Mercurial > hg > graal-compiler
changeset 9221:67bee207f20c
Made import generation more robust.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Sat, 20 Apr 2013 12:17:03 +0200 |
parents | 97ad6d3e7557 |
children | aa9ffb3a715e |
files | graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java |
diffstat | 1 files changed, 151 insertions(+), 184 deletions(-) [+] |
line wrap: on
line diff
--- 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<TypeMirror, Integer> importUsage = new HashMap<>(); - private final Map<TypeMirror, Integer> staticImportUsage = new HashMap<>(); + private final Set<TypeMirror> staticImportUsage = new HashSet<>(); private final Map<String, TypeMirror> 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<TypeElement> 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<String> ambiguousSymbols, Set<String> 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<String> ambiguousSymbols, Set<String> 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<CodeImport> generateImports() { Set<CodeImport> 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<String> importedMethods = new HashSet<>(); List<ExecutableElement> methods = ElementFilter.methodsIn(element.getEnclosedElements()); @@ -217,37 +225,39 @@ return allAmbiguous; } - private static Set<CodeImport> generateImports(CodeTypeElement e, Set<TypeMirror> toGenerate) { - Set<String> 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<Element> elements = Utils.getElementHierarchy(enclosedElement); - // if type is declared inside a super type of this class -> no import - collectSuperTypeImports(e, autoImportedTypes); - collectInnerTypeImports(e, autoImportedTypes); + Set<String> 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<CodeImport> generateImports(Collection<TypeMirror> toGenerate) { TreeSet<CodeImport> 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<CodeImport> generateStaticImports(CodeTypeElement e, Set<TypeMirror> toGenerate) { + private Set<CodeImport> generateStaticImports(Set<TypeMirror> toGenerate) { Set<String> 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<CodeImport> importObjects = new TreeSet<>(); for (TypeMirror importType : toGenerate) { @@ -292,73 +302,52 @@ return importObjects; } - private static void addUsage(TypeMirror type, Map<TypeMirror, Integer> 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<Void, Void> { - - final Map<TypeMirror, Integer> typeReferences = new HashMap<>(); - final Map<TypeMirror, Integer> staticTypeReferences = new HashMap<>(); + private abstract static class TypeReferenceVisitor extends CodeElementScanner<Void, Void> { @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<? extends AnnotationMirror> mirrors) { + private void visitAnnotations(Element enclosingElement, List<? extends AnnotationMirror> 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<? extends ExecutableElement, ? extends AnnotationValue> values = e.getElementValues(); Set<? extends ExecutableElement> 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<Void, Void> { + 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<? extends AnnotationValue> 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<Void, Void> { - - 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<TypeElement> 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); - } - } - }