sort the imports
default to import all classes but no package


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@948 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent e20a0bdc50
commit 584f72c35f
  1. 141
      jode/jode/decompiler/ImportHandler.java

@ -20,13 +20,40 @@
package jode.decompiler;
import jode.GlobalOptions;
import jode.bytecode.ClassInfo;
import jode.bytecode.InnerClassInfo;
import jode.type.*;
///#ifdef JDK12
///import java.util.SortedMap;
///import java.util.TreeMap;
///import java.util.List;
///import java.util.LinkedList;
///import java.util.Comparator;
///import java.util.Iterator;
///#else
import jode.util.SortedMap;
import jode.util.TreeMap;
import jode.util.List;
import jode.util.LinkedList;
import jode.util.Comparator;
import jode.util.Iterator;
///#endif
import java.io.IOException;
import java.util.*;
import java.util.Hashtable;
public class ImportHandler {
Hashtable imports;
/**
* The default package limit. MAX_VALUE means, do not import
* packages at all.
*/
public final static int DEFAULT_PACKAGE_LIMIT = Integer.MAX_VALUE;
/**
* The default class limit. 1 means, import every class used here.
*/
public final static int DEFAULT_CLASS_LIMIT = 1;
SortedMap imports;
/* Classes that doesn't need to be qualified. */
Hashtable cachedClassNames = null;
ClassAnalyzer main;
@ -36,8 +63,26 @@ public class ImportHandler {
int importPackageLimit;
int importClassLimit;
/**
* A comparator to sort the imports. We want java.* and javax.*
* imports first. java.lang.* should precede java.lang.ref.*, but
* that is already guaranteed by ascii ordering.
*/
static Comparator comparator = new Comparator() {
public int compare(Object o1, Object o2) {
String s1 = (String) o1;
String s2 = (String) o2;
boolean java1 = s1.startsWith("java");
boolean java2 = s2.startsWith("java");
if (java1 != java2)
return java1 ? -1 : 1;
return s1.compareTo(s2);
}
};
public ImportHandler() {
this(3,3);
this(DEFAULT_PACKAGE_LIMIT, DEFAULT_CLASS_LIMIT);
}
public ImportHandler(int packageLimit, int classLimit) {
@ -70,21 +115,31 @@ public class ImportHandler {
name = name.substring(pkgdelim);
if (pkg.length() != 0) {
/* Does this conflict with a class in this package? */
if (ClassInfo.exists(pkg+name))
return true;
} else {
/* Does this conflict with a class in this unnamed
* package? */
if (ClassInfo.exists(name.substring(1)))
return true;
}
Enumeration enum = imports.keys();
while (enum.hasMoreElements()) {
String importName = (String) enum.nextElement();
Iterator iter = imports.keySet().iterator();
while (iter.hasNext()) {
String importName = (String) iter.next();
if (importName.endsWith(".*")) {
/* strip the "*" */
importName = importName.substring
(0, importName.length()-2);
if (!importName.equals(pkgName)) {
if (ClassInfo.exists(importName))
if (ClassInfo.exists(importName+name))
return true;
}
} else {
/* Is this a class import with same name? */
if (importName.endsWith(name))
return true;
}
}
}
@ -93,26 +148,29 @@ public class ImportHandler {
private void cleanUpImports() {
Integer dummyVote = new Integer(Integer.MAX_VALUE);
Hashtable newImports = new Hashtable();
Vector classImports = new Vector();
Enumeration enum = imports.keys();
while (enum.hasMoreElements()) {
String importName = (String) enum.nextElement();
SortedMap newImports = new TreeMap(comparator);
List classImports = new LinkedList();
Iterator iter = imports.keySet().iterator();
while (iter.hasNext()) {
String importName = (String) iter.next();
Integer vote = (Integer) imports.get(importName);
if (!importName.endsWith(".*")) {
if (vote.intValue() < importClassLimit)
continue;
int delim = importName.lastIndexOf(".");
Integer pkgvote = (Integer)
imports.get(importName.substring(0, delim)+".*");
if (pkgvote.intValue() >= importPackageLimit)
/* Since the imports are sorted, newImports already
* contains the package if it should be imported.
*/
if (newImports.containsKey
(importName.substring(0, delim)+".*"))
continue;
/* This is a single Class import, that is not
* superseeded by a package import. Mark it for
* importation, but don't put it in newImports, yet.
*/
classImports.addElement(importName);
classImports.add(importName);
} else {
if (vote.intValue() < importPackageLimit)
continue;
@ -125,17 +183,17 @@ public class ImportHandler {
/* Now check if the class import conflict with any of the
* package imports.
*/
enum = classImports.elements();
while (enum.hasMoreElements()) {
iter = classImports.iterator();
while (iter.hasNext()) {
/* If there are more than one single class imports with
* the same name, exactly the first (in hash order) will
* the same name, exactly the first (in sorted order) will
* be imported. */
String className = (String) enum.nextElement();
if (!conflictsImport(className)) {
imports.put(className, dummyVote);
String classFQName = (String) iter.next();
if (!conflictsImport(classFQName)) {
imports.put(classFQName, dummyVote);
String name =
className.substring(className.lastIndexOf('.')+1);
cachedClassNames.put(className, name);
classFQName.substring(classFQName.lastIndexOf('.')+1);
cachedClassNames.put(classFQName, name);
}
}
}
@ -153,12 +211,23 @@ public class ImportHandler {
writer.println("package "+pkg+";");
cleanUpImports();
Enumeration enum = imports.keys();
while (enum.hasMoreElements()) {
String pkgName = (String)enum.nextElement();
if (!pkgName.equals("java.lang.*"))
Iterator iter = imports.keySet().iterator();
String lastFirstPart = null;
while (iter.hasNext()) {
String pkgName = (String)iter.next();
if (!pkgName.equals("java.lang.*")) {
int firstDot = pkgName.indexOf('.');
if (firstDot != -1) {
String firstPart = pkgName.substring(0, firstDot);
if (lastFirstPart != null
&& !lastFirstPart.equals(firstPart)) {
writer.println("");
}
lastFirstPart = firstPart;
}
writer.println("import "+pkgName+";");
}
}
writer.println("");
}
@ -167,7 +236,7 @@ public class ImportHandler {
}
public void init(String className) {
imports = new Hashtable();
imports = new TreeMap(comparator);
/* java.lang is always imported */
imports.put("java.lang.*", new Integer(Integer.MAX_VALUE));
@ -181,6 +250,20 @@ public class ImportHandler {
* enough.
*/
public void useClass(ClassInfo clazz) {
for (;;) {
/* First handle inner classes: For class scoped classes
* import outer class instead; for method scoped classes
* we don't import anything.
*/
InnerClassInfo[] outerInfo = clazz.getOuterClasses();
if (outerInfo == null)
break;
if (outerInfo[0].name == null || outerInfo[0].outer == null)
return;
clazz = ClassInfo.forName(outerInfo[0].outer);
}
String name = clazz.getName();
int pkgdelim = name.lastIndexOf('.');
if (pkgdelim != -1) {

Loading…
Cancel
Save