emptyList() : Collections.unmodifiableList(result);
}
}
diff --git a/src/core/lombok/core/TypeResolver.java b/src/core/lombok/core/TypeResolver.java
index ecc042a0..e5c3fac8 100644
--- a/src/core/lombok/core/TypeResolver.java
+++ b/src/core/lombok/core/TypeResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Project Lombok Authors.
+ * Copyright (C) 2009-2011 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -30,17 +30,17 @@ import lombok.core.AST.Kind;
/**
* Capable of resolving a simple type name such as 'String' into 'java.lang.String'.
+ *
+ * NB: This resolver gives wrong answers when there's a class in the local package with the same name as a class in a star-import,
+ * and this importer also can't find inner types from superclasses/interfaces.
*/
public class TypeResolver {
- private final TypeLibrary library;
private Collection imports;
/**
- * Creates a new TypeResolver that can be used to resolve types in a given library, encountered in
- * a source file with the provided package and import statements.
+ * Creates a new TypeResolver that can be used to resolve types in a source file with the given package and import statements.
*/
- public TypeResolver(TypeLibrary library, String packageString, Collection importStrings) {
- this.library = library;
+ public TypeResolver(String packageString, Collection importStrings) {
this.imports = makeImportList(packageString, importStrings);
}
@@ -51,41 +51,76 @@ public class TypeResolver {
return imports;
}
+ public boolean typeMatches(LombokNode, ?, ?> context, String fqn, String typeRef) {
+ return !findTypeMatches(context, TypeLibrary.createLibraryForSingleType(fqn), typeRef).isEmpty();
+ }
+
/**
* Finds type matches for the stated type reference. The provided context is scanned for local type names
* that shadow type names listed in import statements. If such a shadowing occurs, no matches are returned
* for any shadowed types, as you would expect.
*/
- public Collection findTypeMatches(LombokNode, ?, ?> context, String typeRef) {
+ public Collection findTypeMatches(LombokNode, ?, ?> context, TypeLibrary library, String typeRef) {
+ // When asking if 'Foo' could possibly be referring to 'bar.Baz', the answer is obviously no.
Collection potentialMatches = library.findCompatible(typeRef);
if (potentialMatches.isEmpty()) return Collections.emptyList();
+ // If input type appears to be fully qualified, we found a winner.
int idx = typeRef.indexOf('.');
if (idx > -1) return potentialMatches;
- String simpleName = typeRef.substring(idx+1);
- //If there's an import statement that explicitly imports a 'Getter' that isn't any of our potentials, return no matches.
- if (nameConflictInImportList(simpleName, potentialMatches)) return Collections.emptyList();
+ // If there's an import statement that explicitly imports a 'Getter' that isn't any of our potentials, return no matches,
+ // because if you want to know if 'Foo' could refer to 'bar.Foo' when 'baz.Foo' is explicitly imported, the answer is no.
+ if (nameConflictInImportList(typeRef, potentialMatches)) return Collections.emptyList();
- //Check if any of our potentials is even imported in the first place. If not: no matches.
- potentialMatches = eliminateImpossibleMatches(potentialMatches);
+ // Check if any of our potentials are even imported in the first place. If not: no matches.
+ // Note that (ourPackage.*) is added to the imports.
+ potentialMatches = eliminateImpossibleMatches(potentialMatches, library);
if (potentialMatches.isEmpty()) return Collections.emptyList();
- //Find a lexically accessible type of the same simple name in the same Compilation Unit. If it exists: no matches.
+ // Now the hard part - inner classes or method local classes in our own scope.
+ // For method locals, this refers to any statements that are 'above' the type reference with the same name.
+ // For inners, this refers to siblings of us or any parent node that are type declarations.
LombokNode, ?, ?> n = context;
+
+ mainLoop:
while (n != null) {
- if (n.getKind() == Kind.TYPE) {
- String name = n.getName();
- if (name != null && name.equals(simpleName)) return Collections.emptyList();
+ if (n.getKind() == Kind.TYPE && typeRef.equals(n.getName())) {
+ // Our own class or one of our outer classes is named 'typeRef' so that's what 'typeRef' is referring to, not one of our type library classes.
+ return Collections.emptyList();
}
- n = n.up();
+
+ if (n.getKind() == Kind.STATEMENT || n.getKind() == Kind.LOCAL) {
+ LombokNode, ?, ?> newN = n.directUp();
+ if (newN == null) break mainLoop;
+
+ if (newN.getKind() == Kind.STATEMENT || newN.getKind() == Kind.INITIALIZER || newN.getKind() == Kind.METHOD) {
+ for (LombokNode, ?, ?> child : newN.down()) {
+ // We found a method local with the same name above our code. That's the one 'typeRef' is referring to, not
+ // anything in the type library we're trying to find, so, no matches.
+ if (child.getKind() == Kind.TYPE && typeRef.equals(child.getName())) return Collections.emptyList();
+ if (child == n) break;
+ }
+ }
+ n = newN;
+ continue mainLoop;
+ }
+
+ if (n.getKind() == Kind.TYPE || n.getKind() == Kind.COMPILATION_UNIT) {
+ for (LombokNode, ?, ?> child : n.down()) {
+ // Inner class that's visible to us has 'typeRef' as name, so that's the one being referred to, not one of our type library classes.
+ if (child.getKind() == Kind.TYPE && typeRef.equals(child.getName())) return Collections.emptyList();
+ }
+ }
+
+ n = n.directUp();
}
- // The potential matches we found by comparing the import statements is our matching set. Return it.
+ // No class in this source file is a match, therefore the potential matches found via the import statements must be it. Return those.
return potentialMatches;
}
- private Collection eliminateImpossibleMatches(Collection potentialMatches) {
+ private Collection eliminateImpossibleMatches(Collection potentialMatches, TypeLibrary library) {
Set results = new HashSet();
for (String importedType : imports) {
diff --git a/src/core/lombok/eclipse/HandlerLibrary.java b/src/core/lombok/eclipse/HandlerLibrary.java
index 197d7a7e..5c75c071 100644
--- a/src/core/lombok/eclipse/HandlerLibrary.java
+++ b/src/core/lombok/eclipse/HandlerLibrary.java
@@ -173,11 +173,11 @@ public class HandlerLibrary {
String pkgName = annotationNode.getPackageDeclaration();
Collection imports = annotationNode.getImportStatements();
- TypeResolver resolver = new TypeResolver(typeLibrary, pkgName, imports);
+ TypeResolver resolver = new TypeResolver(pkgName, imports);
TypeReference rawType = annotation.type;
if (rawType == null) return;
- for (String fqn : resolver.findTypeMatches(annotationNode, toQualifiedName(annotation.type.getTypeName()))) {
+ for (String fqn : resolver.findTypeMatches(annotationNode, typeLibrary, toQualifiedName(annotation.type.getTypeName()))) {
boolean isPrintAST = fqn.equals(PrintAST.class.getName());
if (isPrintAST == skipPrintAst) continue;
AnnotationHandlerContainer> container = annotationHandlers.get(fqn);
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
index 5130c7de..c6d7eb41 100644
--- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
+++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
@@ -30,7 +30,6 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -46,7 +45,6 @@ import lombok.core.AnnotationValues.AnnotationValue;
import lombok.eclipse.EclipseAST;
import lombok.eclipse.EclipseNode;
import lombok.core.TransformationsUtil;
-import lombok.core.TypeLibrary;
import lombok.core.TypeResolver;
import org.eclipse.core.runtime.ILog;
@@ -260,16 +258,9 @@ public class EclipseHandlerUtil {
if (!lastPartA.equals(lastPartB)) return false;
String typeName = toQualifiedName(typeRef.getTypeName());
- TypeLibrary library = new TypeLibrary();
- library.addType(type.getName());
- TypeResolver resolver = new TypeResolver(library, node.getPackageDeclaration(), node.getImportStatements());
- Collection typeMatches = resolver.findTypeMatches(node, typeName);
+ TypeResolver resolver = new TypeResolver(node.getPackageDeclaration(), node.getImportStatements());
+ return resolver.typeMatches(node, type.getName(), typeName);
- for (String match : typeMatches) {
- if (match.equals(type.getName())) return true;
- }
-
- return false;
}
public static Annotation copyAnnotation(Annotation annotation, ASTNode source) {
diff --git a/src/core/lombok/javac/HandlerLibrary.java b/src/core/lombok/javac/HandlerLibrary.java
index 17684a7e..cba318e2 100644
--- a/src/core/lombok/javac/HandlerLibrary.java
+++ b/src/core/lombok/javac/HandlerLibrary.java
@@ -171,9 +171,9 @@ public class HandlerLibrary {
* @param annotation 'node.get()' - convenience parameter.
*/
public void handleAnnotation(JCCompilationUnit unit, JavacNode node, JCAnnotation annotation) {
- TypeResolver resolver = new TypeResolver(typeLibrary, node.getPackageDeclaration(), node.getImportStatements());
+ TypeResolver resolver = new TypeResolver(node.getPackageDeclaration(), node.getImportStatements());
String rawType = annotation.annotationType.toString();
- for (String fqn : resolver.findTypeMatches(node, rawType)) {
+ for (String fqn : resolver.findTypeMatches(node, typeLibrary, rawType)) {
boolean isPrintAST = fqn.equals(PrintAST.class.getName());
if (isPrintAST && phase != 2) continue;
if (!isPrintAST && phase == 2) continue;
diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
index 2bf6c4ec..244f7d38 100644
--- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
+++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
@@ -28,7 +28,6 @@ import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
@@ -38,7 +37,6 @@ import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
import lombok.core.AnnotationValues;
-import lombok.core.TypeLibrary;
import lombok.core.TypeResolver;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues.AnnotationValue;
@@ -139,16 +137,8 @@ public class JavacHandlerUtil {
public static boolean typeMatches(Class> type, JavacNode node, JCTree typeNode) {
String typeName = typeNode.toString();
- TypeLibrary library = new TypeLibrary();
- library.addType(type.getName());
- TypeResolver resolver = new TypeResolver(library, node.getPackageDeclaration(), node.getImportStatements());
- Collection typeMatches = resolver.findTypeMatches(node, typeName);
-
- for (String match : typeMatches) {
- if (match.equals(type.getName())) return true;
- }
-
- return false;
+ TypeResolver resolver = new TypeResolver(node.getPackageDeclaration(), node.getImportStatements());
+ return resolver.typeMatches(node, type.getName(), typeName);
}
/**
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java b/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java
index cc72c206..e027b09d 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java
@@ -108,6 +108,7 @@ public class PatchDelegate {
for (Annotation ann : field.annotations) {
if (ann.type == null) continue;
TypeBinding tb = ann.type.resolveType(decl.initializerScope);
+ if (tb == null) continue;
if (!charArrayEquals("lombok", tb.qualifiedPackageName())) continue;
if (!charArrayEquals("Delegate", tb.qualifiedSourceName())) continue;
return true;
diff --git a/test/transform/resource/after-delombok/SimpleTypeResolution.java b/test/transform/resource/after-delombok/SimpleTypeResolution.java
new file mode 100644
index 00000000..c6e08d70
--- /dev/null
+++ b/test/transform/resource/after-delombok/SimpleTypeResolution.java
@@ -0,0 +1,11 @@
+class SimpleTypeResolutionFail {
+ @Getter
+ private int x;
+}
+class SimpleTypeResolutionSuccess {
+ private int x;
+ @java.lang.SuppressWarnings("all")
+ public int getX() {
+ return this.x;
+ }
+}
diff --git a/test/transform/resource/after-delombok/TrickyTypeResolution.java b/test/transform/resource/after-delombok/TrickyTypeResolution.java
new file mode 100644
index 00000000..9a5aae16
--- /dev/null
+++ b/test/transform/resource/after-delombok/TrickyTypeResolution.java
@@ -0,0 +1,54 @@
+import lombok.*;
+class TrickyDoNothing {
+ @interface Getter {
+ }
+ @Getter
+ int x;
+}
+class TrickyDoNothing2 {
+ @Getter
+ int x;
+ @interface Getter {
+ }
+}
+class TrickySuccess {
+ int x;
+ @java.lang.SuppressWarnings("all")
+ public int getX() {
+ return this.x;
+ }
+}
+class TrickyDoNothing3 {
+ void test() {
+ class val {
+ }
+ val x = null;
+ }
+}
+class TrickyDoSomething {
+ void test() {
+ final java.lang.Object x = null;
+ class val {
+ }
+ }
+}
+class DoubleTrickyDoNothing {
+ void test() {
+ class val {
+ }
+ for (int i = 10; i < 20; i++) {
+ val y = null;
+ }
+ }
+}
+class DoubleTrickyDoSomething {
+ void test() {
+ for (int j = 10; j < 20; j++) {
+ class val {
+ }
+ }
+ for (int i = 10; i < 20; i++) {
+ final java.lang.Object y = null;
+ }
+ }
+}
diff --git a/test/transform/resource/after-delombok/TrickyTypeResolution2.java b/test/transform/resource/after-delombok/TrickyTypeResolution2.java
new file mode 100644
index 00000000..9118767f
--- /dev/null
+++ b/test/transform/resource/after-delombok/TrickyTypeResolution2.java
@@ -0,0 +1,8 @@
+import lombok.*;
+class DoNothingDueToTopLevel {
+ void test() {
+ val x = null;
+ }
+}
+class val {
+}
diff --git a/test/transform/resource/after-ecj/SimpleTypeResolution.java b/test/transform/resource/after-ecj/SimpleTypeResolution.java
new file mode 100644
index 00000000..a0997c67
--- /dev/null
+++ b/test/transform/resource/after-ecj/SimpleTypeResolution.java
@@ -0,0 +1,15 @@
+class SimpleTypeResolutionFail {
+ private @Getter int x;
+ SimpleTypeResolutionFail() {
+ super();
+ }
+}
+class SimpleTypeResolutionSuccess {
+ private @lombok.Getter int x;
+ public @java.lang.SuppressWarnings("all") int getX() {
+ return this.x;
+ }
+ SimpleTypeResolutionSuccess() {
+ super();
+ }
+}
diff --git a/test/transform/resource/after-ecj/TrickyTypeResolution.java b/test/transform/resource/after-ecj/TrickyTypeResolution.java
new file mode 100644
index 00000000..cb06d3c1
--- /dev/null
+++ b/test/transform/resource/after-ecj/TrickyTypeResolution.java
@@ -0,0 +1 @@
+//ignore
\ No newline at end of file
diff --git a/test/transform/resource/after-ecj/TrickyTypeResolution2.java b/test/transform/resource/after-ecj/TrickyTypeResolution2.java
new file mode 100644
index 00000000..cb06d3c1
--- /dev/null
+++ b/test/transform/resource/after-ecj/TrickyTypeResolution2.java
@@ -0,0 +1 @@
+//ignore
\ No newline at end of file
diff --git a/test/transform/resource/after-eclipse/SimpleTypeResolution.java b/test/transform/resource/after-eclipse/SimpleTypeResolution.java
new file mode 100644
index 00000000..a0997c67
--- /dev/null
+++ b/test/transform/resource/after-eclipse/SimpleTypeResolution.java
@@ -0,0 +1,15 @@
+class SimpleTypeResolutionFail {
+ private @Getter int x;
+ SimpleTypeResolutionFail() {
+ super();
+ }
+}
+class SimpleTypeResolutionSuccess {
+ private @lombok.Getter int x;
+ public @java.lang.SuppressWarnings("all") int getX() {
+ return this.x;
+ }
+ SimpleTypeResolutionSuccess() {
+ super();
+ }
+}
diff --git a/test/transform/resource/after-eclipse/TrickyTypeResolution.java b/test/transform/resource/after-eclipse/TrickyTypeResolution.java
new file mode 100644
index 00000000..cb06d3c1
--- /dev/null
+++ b/test/transform/resource/after-eclipse/TrickyTypeResolution.java
@@ -0,0 +1 @@
+//ignore
\ No newline at end of file
diff --git a/test/transform/resource/after-eclipse/TrickyTypeResolution2.java b/test/transform/resource/after-eclipse/TrickyTypeResolution2.java
new file mode 100644
index 00000000..cb06d3c1
--- /dev/null
+++ b/test/transform/resource/after-eclipse/TrickyTypeResolution2.java
@@ -0,0 +1 @@
+//ignore
\ No newline at end of file
diff --git a/test/transform/resource/before/SimpleTypeResolution.java b/test/transform/resource/before/SimpleTypeResolution.java
new file mode 100644
index 00000000..ef5ddef2
--- /dev/null
+++ b/test/transform/resource/before/SimpleTypeResolution.java
@@ -0,0 +1,7 @@
+class SimpleTypeResolutionFail {
+ @Getter private int x;
+}
+
+class SimpleTypeResolutionSuccess {
+ @lombok.Getter private int x;
+}
diff --git a/test/transform/resource/before/TrickyTypeResolution.java b/test/transform/resource/before/TrickyTypeResolution.java
new file mode 100644
index 00000000..94d97fe0
--- /dev/null
+++ b/test/transform/resource/before/TrickyTypeResolution.java
@@ -0,0 +1,49 @@
+import lombok.*;
+class TrickyDoNothing {
+ @interface Getter {}
+ @Getter int x;
+}
+
+class TrickyDoNothing2 {
+ @Getter int x;
+ @interface Getter {}
+}
+
+class TrickySuccess {
+ @Getter int x;
+}
+
+class TrickyDoNothing3 {
+ void test() {
+ class val {}
+ val x = null;
+ }
+}
+
+class TrickyDoSomething {
+ void test() {
+ val x = null;
+ class val {}
+ }
+}
+
+class DoubleTrickyDoNothing {
+ void test() {
+ class val {}
+ for (int i = 10; i < 20; i++) {
+ val y = null;
+ }
+ }
+}
+
+class DoubleTrickyDoSomething {
+ void test() {
+ for (int j = 10; j < 20; j++) {
+ class val {}
+ }
+
+ for (int i = 10; i < 20; i++) {
+ val y = null;
+ }
+ }
+}
diff --git a/test/transform/resource/before/TrickyTypeResolution2.java b/test/transform/resource/before/TrickyTypeResolution2.java
new file mode 100644
index 00000000..00f2ac39
--- /dev/null
+++ b/test/transform/resource/before/TrickyTypeResolution2.java
@@ -0,0 +1,8 @@
+import lombok.*;
+class DoNothingDueToTopLevel {
+ void test() {
+ val x = null;
+ }
+}
+
+class val {}
diff --git a/test/transform/resource/messages-delombok/SimpleTypeResolution.java.messages b/test/transform/resource/messages-delombok/SimpleTypeResolution.java.messages
new file mode 100644
index 00000000..3a345d06
--- /dev/null
+++ b/test/transform/resource/messages-delombok/SimpleTypeResolution.java.messages
@@ -0,0 +1,9 @@
+2:10 ERROR cannot find symbol
+symbol : class Getter
+location: class SimpleTypeResolutionFail
+2:10 ERROR cannot find symbol
+symbol : class Getter
+location: class SimpleTypeResolutionFail
+2:10 ERROR cannot find symbol
+symbol : class Getter
+location: class SimpleTypeResolutionFail
diff --git a/test/transform/resource/messages-eclipse/SimpleTypeResolution.java.messages b/test/transform/resource/messages-eclipse/SimpleTypeResolution.java.messages
new file mode 100644
index 00000000..a5ad71f3
--- /dev/null
+++ b/test/transform/resource/messages-eclipse/SimpleTypeResolution.java.messages
@@ -0,0 +1 @@
+2 error Getter cannot be resolved to a type
diff --git a/test/transform/resource/messages-idempotent/SimpleTypeResolution.java.messages b/test/transform/resource/messages-idempotent/SimpleTypeResolution.java.messages
new file mode 100644
index 00000000..3a345d06
--- /dev/null
+++ b/test/transform/resource/messages-idempotent/SimpleTypeResolution.java.messages
@@ -0,0 +1,9 @@
+2:10 ERROR cannot find symbol
+symbol : class Getter
+location: class SimpleTypeResolutionFail
+2:10 ERROR cannot find symbol
+symbol : class Getter
+location: class SimpleTypeResolutionFail
+2:10 ERROR cannot find symbol
+symbol : class Getter
+location: class SimpleTypeResolutionFail