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. 147
      jode/jode/decompiler/ImportHandler.java

@ -20,13 +20,40 @@
package jode.decompiler; package jode.decompiler;
import jode.GlobalOptions; import jode.GlobalOptions;
import jode.bytecode.ClassInfo; import jode.bytecode.ClassInfo;
import jode.bytecode.InnerClassInfo;
import jode.type.*; 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.io.IOException;
import java.util.*; import java.util.Hashtable;
public class ImportHandler { 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. */ /* Classes that doesn't need to be qualified. */
Hashtable cachedClassNames = null; Hashtable cachedClassNames = null;
ClassAnalyzer main; ClassAnalyzer main;
@ -36,8 +63,26 @@ public class ImportHandler {
int importPackageLimit; int importPackageLimit;
int importClassLimit; 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() { public ImportHandler() {
this(3,3); this(DEFAULT_PACKAGE_LIMIT, DEFAULT_CLASS_LIMIT);
} }
public ImportHandler(int packageLimit, int classLimit) { public ImportHandler(int packageLimit, int classLimit) {
@ -70,22 +115,32 @@ public class ImportHandler {
name = name.substring(pkgdelim); name = name.substring(pkgdelim);
if (pkg.length() != 0) { if (pkg.length() != 0) {
/* Does this conflict with a class in this package? */
if (ClassInfo.exists(pkg+name)) if (ClassInfo.exists(pkg+name))
return true; return true;
} } else {
/* Does this conflict with a class in this unnamed
Enumeration enum = imports.keys(); * package? */
while (enum.hasMoreElements()) { if (ClassInfo.exists(name.substring(1)))
String importName = (String) enum.nextElement(); return true;
}
Iterator iter = imports.keySet().iterator();
while (iter.hasNext()) {
String importName = (String) iter.next();
if (importName.endsWith(".*")) { if (importName.endsWith(".*")) {
/* strip the "*" */ /* strip the "*" */
importName = importName.substring importName = importName.substring
(0, importName.length()-2); (0, importName.length()-2);
if (!importName.equals(pkgName)) { if (!importName.equals(pkgName)) {
if (ClassInfo.exists(importName)) if (ClassInfo.exists(importName+name))
return true; return true;
} }
} } else {
/* Is this a class import with same name? */
if (importName.endsWith(name))
return true;
}
} }
} }
return false; return false;
@ -93,26 +148,29 @@ public class ImportHandler {
private void cleanUpImports() { private void cleanUpImports() {
Integer dummyVote = new Integer(Integer.MAX_VALUE); Integer dummyVote = new Integer(Integer.MAX_VALUE);
Hashtable newImports = new Hashtable(); SortedMap newImports = new TreeMap(comparator);
Vector classImports = new Vector(); List classImports = new LinkedList();
Enumeration enum = imports.keys(); Iterator iter = imports.keySet().iterator();
while (enum.hasMoreElements()) { while (iter.hasNext()) {
String importName = (String) enum.nextElement(); String importName = (String) iter.next();
Integer vote = (Integer) imports.get(importName); Integer vote = (Integer) imports.get(importName);
if (!importName.endsWith(".*")) { if (!importName.endsWith(".*")) {
if (vote.intValue() < importClassLimit) if (vote.intValue() < importClassLimit)
continue; continue;
int delim = importName.lastIndexOf("."); int delim = importName.lastIndexOf(".");
Integer pkgvote = (Integer)
imports.get(importName.substring(0, delim)+".*"); /* Since the imports are sorted, newImports already
if (pkgvote.intValue() >= importPackageLimit) * contains the package if it should be imported.
*/
if (newImports.containsKey
(importName.substring(0, delim)+".*"))
continue; continue;
/* This is a single Class import, that is not /* This is a single Class import, that is not
* superseeded by a package import. Mark it for * superseeded by a package import. Mark it for
* importation, but don't put it in newImports, yet. * importation, but don't put it in newImports, yet.
*/ */
classImports.addElement(importName); classImports.add(importName);
} else { } else {
if (vote.intValue() < importPackageLimit) if (vote.intValue() < importPackageLimit)
continue; continue;
@ -125,17 +183,17 @@ public class ImportHandler {
/* Now check if the class import conflict with any of the /* Now check if the class import conflict with any of the
* package imports. * package imports.
*/ */
enum = classImports.elements(); iter = classImports.iterator();
while (enum.hasMoreElements()) { while (iter.hasNext()) {
/* If there are more than one single class imports with /* 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. */ * be imported. */
String className = (String) enum.nextElement(); String classFQName = (String) iter.next();
if (!conflictsImport(className)) { if (!conflictsImport(classFQName)) {
imports.put(className, dummyVote); imports.put(classFQName, dummyVote);
String name = String name =
className.substring(className.lastIndexOf('.')+1); classFQName.substring(classFQName.lastIndexOf('.')+1);
cachedClassNames.put(className, name); cachedClassNames.put(classFQName, name);
} }
} }
} }
@ -153,11 +211,22 @@ public class ImportHandler {
writer.println("package "+pkg+";"); writer.println("package "+pkg+";");
cleanUpImports(); cleanUpImports();
Enumeration enum = imports.keys(); Iterator iter = imports.keySet().iterator();
while (enum.hasMoreElements()) { String lastFirstPart = null;
String pkgName = (String)enum.nextElement(); while (iter.hasNext()) {
if (!pkgName.equals("java.lang.*")) 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("import "+pkgName+";");
}
} }
writer.println(""); writer.println("");
} }
@ -167,7 +236,7 @@ public class ImportHandler {
} }
public void init(String className) { public void init(String className) {
imports = new Hashtable(); imports = new TreeMap(comparator);
/* java.lang is always imported */ /* java.lang is always imported */
imports.put("java.lang.*", new Integer(Integer.MAX_VALUE)); imports.put("java.lang.*", new Integer(Integer.MAX_VALUE));
@ -181,6 +250,20 @@ public class ImportHandler {
* enough. * enough.
*/ */
public void useClass(ClassInfo clazz) { 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(); String name = clazz.getName();
int pkgdelim = name.lastIndexOf('.'); int pkgdelim = name.lastIndexOf('.');
if (pkgdelim != -1) { if (pkgdelim != -1) {

Loading…
Cancel
Save