# HG changeset patch # User Christian Humer # Date 1366453023 -7200 # Node ID 67bee207f20c878efa9b1df6d40c52921d3a0c77 # Parent 97ad6d3e75578927e0ea4246b027c22b3a94c024 Made import generation more robust. diff -r 97ad6d3e7557 -r 67bee207f20c graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java Sat Apr 20 12:16:22 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java Sat Apr 20 12:17:03 2013 +0200 @@ -35,8 +35,7 @@ public final class OrganizedImports { - private final Map importUsage = new HashMap<>(); - private final Map staticImportUsage = new HashMap<>(); + private final Set staticImportUsage = new HashSet<>(); private final Map simpleNamesUsed = new HashMap<>(); @@ -53,16 +52,33 @@ public static OrganizedImports organize(CodeTypeElement topLevelClass) { OrganizedImports organized = new OrganizedImports(topLevelClass); - - OrganizedImports.ReferenceCollector reference = new ReferenceCollector(); - topLevelClass.accept(reference, null); - - OrganizedImports.ImportResolver resolver = new ImportResolver(reference, organized); - topLevelClass.accept(resolver, null); + organized.organizeImpl(); return organized; } - public String useImport(TypeMirror type) { + private void organizeImpl() { + ImportTypeReferenceVisitor reference = new ImportTypeReferenceVisitor(); + topLevelClass.accept(reference, null); + + processStaticImports(topLevelClass); + List types = Utils.getSuperTypes(topLevelClass); + for (TypeElement typeElement : types) { + processStaticImports(typeElement); + } + + for (TypeMirror type : staticImportUsage) { + TypeElement element = fromTypeMirror(type); + if (element != null) { + // already processed by supertype + if (types.contains(element)) { + continue; + } + processStaticImports(element); + } + } + } + + public String createTypeReference(Element enclosedElement, TypeMirror type) { switch (type.getKind()) { case BOOLEAN: case BYTE: @@ -75,11 +91,11 @@ case VOID: return Utils.getSimpleName(type); case DECLARED: - return createDeclaredTypeName((DeclaredType) type); + return createDeclaredTypeName(enclosedElement, (DeclaredType) type); case ARRAY: - return useImport(((ArrayType) type).getComponentType()) + "[]"; + return createTypeReference(enclosedElement, ((ArrayType) type).getComponentType()) + "[]"; case WILDCARD: - return createWildcardName((WildcardType) type); + return createWildcardName(enclosedElement, (WildcardType) type); case TYPEVAR: return "?"; default: @@ -87,29 +103,50 @@ } } - private String createWildcardName(WildcardType type) { + public String createStaticFieldReference(Element enclosedElement, TypeMirror type, String fieldName) { + return createStaticReference(enclosedElement, type, fieldName, ambiguousStaticFields, declaredStaticFields); + } + + public String createStaticMethodReference(Element enclosedElement, TypeMirror type, String methodName) { + return createStaticReference(enclosedElement, type, methodName, ambiguousStaticMethods, declaredStaticMethods); + } + + private String createStaticReference(Element enclosedElement, TypeMirror type, String name, Set ambiguousSymbols, Set declaredSymbols) { + if (ambiguousSymbols.contains(name)) { + // ambiguous import + return createTypeReference(enclosedElement, type) + "." + name; + } else if (!declaredSymbols.contains(name)) { + // not imported at all + return createTypeReference(enclosedElement, type) + "." + name; + } else { + // import declared and not ambiguous + return name; + } + } + + private String createWildcardName(Element enclosedElement, WildcardType type) { StringBuilder b = new StringBuilder(); if (type.getExtendsBound() != null) { - b.append("? extends ").append(useImport(type.getExtendsBound())); + b.append("? extends ").append(createTypeReference(enclosedElement, type.getExtendsBound())); } else if (type.getSuperBound() != null) { - b.append("? super ").append(useImport(type.getExtendsBound())); + b.append("? super ").append(createTypeReference(enclosedElement, type.getExtendsBound())); } return b.toString(); } - private String createDeclaredTypeName(DeclaredType type) { + private String createDeclaredTypeName(Element enclosedElement, DeclaredType type) { String name = type.asElement().getSimpleName().toString(); - TypeMirror usedByType = simpleNamesUsed.get(name); - if (usedByType == null) { - simpleNamesUsed.put(name, type); - usedByType = type; - } + if (needsImport(enclosedElement, type)) { + TypeMirror usedByType = simpleNamesUsed.get(name); + if (usedByType == null) { + simpleNamesUsed.put(name, type); + usedByType = type; + } - if (typeEquals(type, usedByType)) { - addUsage(type, importUsage); - } else { - name = getQualifiedName(type); + if (!typeEquals(type, usedByType)) { + name = getQualifiedName(type); + } } if (type.getTypeArguments().size() == 0) { @@ -120,7 +157,7 @@ b.append("<"); if (type.getTypeArguments().size() > 0) { for (int i = 0; i < type.getTypeArguments().size(); i++) { - b.append(useImport(type.getTypeArguments().get(i))); + b.append(createTypeReference(enclosedElement, type.getTypeArguments().get(i))); if (i < type.getTypeArguments().size() - 1) { b.append(", "); } @@ -130,44 +167,15 @@ return b.toString(); } - public String useStaticFieldImport(TypeMirror type, String fieldName) { - return useStaticImport(type, fieldName, ambiguousStaticFields, declaredStaticFields); - } - - public String useStaticMethodImport(TypeMirror type, String methodName) { - return useStaticImport(type, methodName, ambiguousStaticMethods, declaredStaticMethods); - } - - private String useStaticImport(TypeMirror type, String name, Set ambiguousSymbols, Set declaredSymbols) { - if (ambiguousSymbols.contains(name)) { - // ambiguous import - return useImport(type) + "." + name; - } else if (!declaredSymbols.contains(name)) { - // not imported at all - return useImport(type) + "." + name; - } else { - // import declared and not ambiguous - addUsage(type, staticImportUsage); - return name; - } - } - public Set generateImports() { Set imports = new HashSet<>(); - imports.addAll(generateImports(topLevelClass, importUsage.keySet())); - imports.addAll(generateStaticImports(topLevelClass, staticImportUsage.keySet())); + imports.addAll(generateImports(simpleNamesUsed.values())); + imports.addAll(generateStaticImports(staticImportUsage)); return imports; } - void clearStaticImports() { - declaredStaticFields.clear(); - declaredStaticMethods.clear(); - ambiguousStaticFields.clear(); - ambiguousStaticMethods.clear(); - } - boolean processStaticImports(TypeElement element) { Set importedMethods = new HashSet<>(); List methods = ElementFilter.methodsIn(element.getEnclosedElements()); @@ -217,37 +225,39 @@ return allAmbiguous; } - private static Set generateImports(CodeTypeElement e, Set toGenerate) { - Set autoImportedTypes = new HashSet<>(); + private boolean needsImport(Element enclosedElement, TypeMirror importType) { + String importPackagName = getPackageName(importType); + if (importPackagName == null) { + return false; + } else if (importPackagName.equals("java.lang")) { + return false; + } else if (importPackagName.equals(getPackageName(topLevelClass)) && Utils.isTopLevelClass(importType)) { + return false; // same package name -> no import + } + + List elements = Utils.getElementHierarchy(enclosedElement); - // if type is declared inside a super type of this class -> no import - collectSuperTypeImports(e, autoImportedTypes); - collectInnerTypeImports(e, autoImportedTypes); + Set autoImportedTypes = new HashSet<>(); + for (Element element : elements) { + if (element.getKind().isClass()) { + collectSuperTypeImports((TypeElement) element, autoImportedTypes); + collectInnerTypeImports((TypeElement) element, autoImportedTypes); + } + } + String qualifiedName = getQualifiedName(importType); + if (autoImportedTypes.contains(qualifiedName)) { + return false; + } + + return true; + } + + private static Set generateImports(Collection toGenerate) { TreeSet importObjects = new TreeSet<>(); for (TypeMirror importType : toGenerate) { - String importTypePackageName = getPackageName(importType); - if (importTypePackageName == null) { - continue; // no package name -> no import - } - - if (importTypePackageName.equals("java.lang")) { - continue; // java.lang is automatically imported - } - - if (importTypePackageName.equals(getPackageName(e)) && Utils.isTopLevelClass(importType)) { - continue; // same package name -> no import - } - - String qualifiedName = getQualifiedName(importType); - - if (autoImportedTypes.contains(qualifiedName)) { - continue; - } - importObjects.add(new CodeImport(importType, getQualifiedName(importType), false)); } - return importObjects; } @@ -268,12 +278,12 @@ } } - private static Set generateStaticImports(CodeTypeElement e, Set toGenerate) { + private Set generateStaticImports(Set toGenerate) { Set autoImportedStaticTypes = new HashSet<>(); // if type is declared inside a super type of this class -> no import - autoImportedStaticTypes.add(getQualifiedName(e)); - autoImportedStaticTypes.addAll(getQualifiedSuperTypeNames(e)); + autoImportedStaticTypes.add(getQualifiedName(topLevelClass)); + autoImportedStaticTypes.addAll(getQualifiedSuperTypeNames(topLevelClass)); TreeSet importObjects = new TreeSet<>(); for (TypeMirror importType : toGenerate) { @@ -292,73 +302,52 @@ return importObjects; } - private static void addUsage(TypeMirror type, Map usageMap) { - if (type != null) { - Integer value = usageMap.get(type); - if (value == null) { - usageMap.put(type, 1); - } else { - usageMap.put(type, value + 1); - } - } - } - - private static class ReferenceCollector extends CodeElementScanner { - - final Map typeReferences = new HashMap<>(); - final Map staticTypeReferences = new HashMap<>(); + private abstract static class TypeReferenceVisitor extends CodeElementScanner { @Override public void visitTree(CodeTree e, Void p) { if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) { - addStaticImport(e.getType()); + visitStaticFieldReference(e, e.getType(), e.getString()); } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) { - addStaticImport(e.getType()); - } else { - addImport(e.getType()); + visitStaticMethodReference(e, e.getType(), e.getString()); + } else if (e.getType() != null) { + visitTypeReference(e, e.getType()); } super.visitTree(e, p); } @Override public Void visitExecutable(CodeExecutableElement e, Void p) { - visitAnnotations(e.getAnnotationMirrors()); + visitAnnotations(e, e.getAnnotationMirrors()); if (e.getReturnType() != null) { - addImport(e.getReturnType()); + visitTypeReference(e, e.getReturnType()); } for (TypeMirror type : e.getThrownTypes()) { - addImport(type); + visitTypeReference(e, type); } return super.visitExecutable(e, p); } @Override public Void visitType(CodeTypeElement e, Void p) { - visitAnnotations(e.getAnnotationMirrors()); + visitAnnotations(e, e.getAnnotationMirrors()); - addImport(e.getSuperclass()); + visitTypeReference(e, e.getSuperclass()); for (TypeMirror type : e.getImplements()) { - addImport(type); + visitTypeReference(e, type); } return super.visitType(e, p); } - @Override - public Void visitVariable(VariableElement f, Void p) { - visitAnnotations(f.getAnnotationMirrors()); - addImport(f.asType()); - return super.visitVariable(f, p); - } - - private void visitAnnotations(List mirrors) { + private void visitAnnotations(Element enclosingElement, List mirrors) { for (AnnotationMirror mirror : mirrors) { - visitAnnotation(mirror); + visitAnnotation(enclosingElement, mirror); } } - public void visitAnnotation(AnnotationMirror e) { - addImport(e.getAnnotationType()); + public void visitAnnotation(Element enclosingElement, AnnotationMirror e) { + visitTypeReference(enclosingElement, e.getAnnotationType()); if (!e.getElementValues().isEmpty()) { Map values = e.getElementValues(); Set methodsSet = values.keySet(); @@ -372,17 +361,23 @@ for (int i = 0; i < methodsList.size(); i++) { AnnotationValue value = values.get(methodsList.get(i)); - visitAnnotationValue(value); + visitAnnotationValue(enclosingElement, value); } } } - public void visitAnnotationValue(AnnotationValue e) { - e.accept(new AnnotationValueReferenceVisitor(), null); + public void visitAnnotationValue(Element enclosingElement, AnnotationValue e) { + e.accept(new AnnotationValueReferenceVisitor(enclosingElement), null); } private class AnnotationValueReferenceVisitor extends AbstractAnnotationValueVisitor7 { + private final Element enclosingElement; + + public AnnotationValueReferenceVisitor(Element enclosedElement) { + this.enclosingElement = enclosedElement; + } + @Override public Void visitBoolean(boolean b, Void p) { return null; @@ -430,95 +425,67 @@ @Override public Void visitType(TypeMirror t, Void p) { - addImport(t); + visitTypeReference(enclosingElement, t); return null; } @Override public Void visitEnumConstant(VariableElement c, Void p) { - addImport(c.asType()); + visitTypeReference(enclosingElement, c.asType()); return null; } @Override public Void visitAnnotation(AnnotationMirror a, Void p) { - ReferenceCollector.this.visitAnnotation(a); + TypeReferenceVisitor.this.visitAnnotation(enclosingElement, a); return null; } @Override public Void visitArray(List vals, Void p) { for (int i = 0; i < vals.size(); i++) { - ReferenceCollector.this.visitAnnotationValue(vals.get(i)); + TypeReferenceVisitor.this.visitAnnotationValue(enclosingElement, vals.get(i)); } return null; } } @Override + public Void visitVariable(VariableElement f, Void p) { + visitAnnotations(f, f.getAnnotationMirrors()); + visitTypeReference(f, f.asType()); + return super.visitVariable(f, p); + } + + @Override public void visitImport(CodeImport e, Void p) { } - private void addStaticImport(TypeMirror type) { - addUsage(type, staticTypeReferences); + public abstract void visitTypeReference(Element enclosedType, TypeMirror type); + + public abstract void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName); + + public abstract void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName); + + } + + private class ImportTypeReferenceVisitor extends TypeReferenceVisitor { + + @Override + public void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName) { + staticImportUsage.add(type); } - private void addImport(TypeMirror type) { - addUsage(type, typeReferences); + @Override + public void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName) { + staticImportUsage.add(type); + } + + @Override + public void visitTypeReference(Element enclosedType, TypeMirror type) { + createTypeReference(enclosedType, type); } } - private static class ImportResolver extends CodeElementScanner { - - private final ReferenceCollector collector; - private final OrganizedImports organizedImports; - - public ImportResolver(OrganizedImports.ReferenceCollector collector, OrganizedImports organizedImports) { - this.collector = collector; - this.organizedImports = organizedImports; - } - - @Override - public Void visitType(CodeTypeElement e, Void p) { - if (e.isTopLevelClass()) { - organizedImports.clearStaticImports(); - - organizedImports.processStaticImports(e); - List types = Utils.getSuperTypes(e); - for (TypeElement typeElement : types) { - organizedImports.processStaticImports(typeElement); - } - - for (TypeMirror type : collector.staticTypeReferences.keySet()) { - TypeElement element = fromTypeMirror(type); - if (element != null) { - // already processed by supertype - if (types.contains(element)) { - continue; - } - organizedImports.processStaticImports(element); - } - } - - for (TypeMirror imp : collector.typeReferences.keySet()) { - organizedImports.useImport(imp); - } - } - return super.visitType(e, p); - } - - @Override - public void visitTree(CodeTree e, Void p) { - if (e.getCodeKind() == CodeTreeKind.TYPE) { - organizedImports.useImport(e.getType()); - } else if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) { - organizedImports.useStaticFieldImport(e.getType(), e.getString()); - } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) { - organizedImports.useStaticMethodImport(e.getType(), e.getString()); - } - super.visitTree(e, p); - } - } - }