Automatically remove explicit package declarations with import statements in Java

By | December 14, 2017
Questions:

I have a project created by others that includes thousands of class files and has the package names explicitly typed out for every reference to any of their classes. It looks like the code was reverse engineered. Is there a good tool for Java that refactors the code so that the explicitly typed package prefixes are removed from class references and moved into import statements.

Thank you in advance.

EDIT:

I think an example will help. I want to have the imports at the top, and I don’t care how many imports there are.

javax.swing.JButton button1 = new javax.swing.JButton();

Imagine the code above but absolutely everywhere in thousands upon thousands of lines of code amongst thousands of class files. I would like to be able to remove all of the prefixes and just have a nice import javax.swing.JButton; at the top of each class file.

Answers:

I don’t know a tool for this use case, but I had to do something similar a few month ago.

  • Write a script or do a search replace with regex to get rid of the explicitly typed package prefixes.

  • Than let eclipse do the rest using “organize imports”. Ctrl-1

Hint: to avoid ambiguities, setup the classpath with no more than the required libs.
For sround about 800 classes I was done in 2 hours.

  • Or get someone who deserved it to do this job.

EDIT: You should know that in Prefeneces/Java/Editor/Save Actions, Organize imports can be configured as save action.

Questions:
Answers:

For a single type, eclipse offers the ‘Add import’ action (Shift+Ctrl+M). It does exactly what you want – with the big, big limitation: you have to place the cursor on a type and it will only affect that ‘selected’ occurrence.

But maybe this action can be used in a scripted/global method. A JDT plugin could crawl through the AST and call this action on every type it finds.

Questions:
Answers:

This thread says:

select the package explorer view, right click on your project, choose source then organise imports. Bobs your uncle – all unwanted imports are removed

To make it better formatted:

Right click project > Source > Organize imports

Now, what remains, is to find a way to strip the fully-qualified names from the code. You may think of some regular expression. Take a look at this library – it seems helpful. This article should also be useful.

Questions:
Answers:

I use an Eclipse plugin by Michael Ernst that does what you want. It converts references such as java.util.Collection to Collection with the addition of an import java.util.Collection; at the top of the file.

It is effectively the same thing as using “Source -> Add Import” for a fully-qualified reference except that it lets you do it for an entire .java file at once.

Even better, it lets you batch-process all the .java files you have selected in the Package Explorer. Simply right-click on the selection and select “Source -> Clean qualified Type Declarations” form the contextual menu.

Eclipse update site: http://cqtp.sourceforge.net/eclipse/

Questions:
Answers:

IntelliJ Idea has tools to do this on a per-file basis. You can probably also do it in bulk, but I don’t know how.

Try out a 30 day evaluation and you’ll probably be pleased by more than the import cleanup features.

Questions:
Answers:

I had the same problem with axis generated files, and I wrote a small groovy script to do this. I doesn’t do everything (you have to use organize imports in eclipse after you run it), and I haven’t tested it very well, so use it carefully. It’s also limited to lowercase package names and camel-cased class names, but it may be a good starting point

def replaceExplicitPackageNamesInFile(File javaFile){
 eol = org.codehaus.groovy.tools.Utilities.eol()

 newFile = ""
 explicitImportExpr = /([^\w])(([a-z0-9]+\.)+)([A-Z][a-zA-Z0-9]+)/
 imports = ""
 javaFile.eachLine { 
  line = it.replaceAll(explicitImportExpr, {
   Object [] match ->
   imports += "import ${match[2]+match[-1]};${eol}"
   match[1]+match[-1]
  })
  newFile += line+"${eol}" 
 }
 newFile2 = ""
 newFile.eachLine { line ->
  newFile2 +=
   line.replaceAll(/(^\s*package.*$)/, {
    Object [] match ->
    match[0] + eol + imports
   } ) + eol
 }
 javaFile.setText(newFile2)
}

def replaceExplicitPackageNamesInDir(File dir){
 dir.eachFileRecurse {
  if (it.isFile() && it.name ==~ /.*\.java\z/){
   println "Processing ${it.absolutePath - dir.absolutePath}"
   replaceExplicitPackageNamesInFile(it)
  }
 }
}

Questions:
Answers:

You probably need to replace all javax.swing.. Then do organize imports.

Questions:
Answers:

I have been able to remove all explicit package names in interfaces by running the sed command below on target files, then by reorganize imports in eclipse:

sed -e 's/java\.[^ ]*\.//g;s/com\.[^ ]*\.//g'

Leave a Reply

Your email address will not be published. Required fields are marked *