diff options
8 files changed, 111 insertions, 9 deletions
diff --git a/src/core/lombok/javac/JavacResolution.java b/src/core/lombok/javac/JavacResolution.java index 8063d5e3..6231735c 100644 --- a/src/core/lombok/javac/JavacResolution.java +++ b/src/core/lombok/javac/JavacResolution.java @@ -24,6 +24,7 @@ package lombok.javac; import static lombok.javac.Javac.*; import static lombok.javac.JavacTreeMaker.TypeTag.typeTag; +import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayDeque; @@ -98,7 +99,7 @@ public class JavacResolution { @Override public void visitClassDef(JCClassDecl tree) { if (copyAt != null) return; - env = enter.getClassEnv(tree.sym); + if (tree.sym != null) env = enter.getClassEnv(tree.sym); } @Override public void visitMethodDef(JCMethodDecl tree) { @@ -138,16 +139,64 @@ public class JavacResolution { EnvFinder finder = new EnvFinder(node.getContext()); while (!stack.isEmpty()) stack.pop().accept(finder); - TreeMirrorMaker mirrorMaker = new TreeMirrorMaker(node.getTreeMaker()); + TreeMirrorMaker mirrorMaker = new TreeMirrorMaker(node.getTreeMaker(), node.getContext()); JCTree copy = mirrorMaker.copy(finder.copyAt()); - attrib(copy, finder.get()); + memberEnterAndAttribute(copy, finder.get(), node.getContext()); return mirrorMaker.getOriginalToCopyMap(); } finally { messageSuppressor.enableLoggers(); } } + private static Field memberEnterDotEnv; + + private static Field getMemberEnterDotEnv() { + if (memberEnterDotEnv != null) return memberEnterDotEnv; + try { + Field f = MemberEnter.class.getDeclaredField("env"); + f.setAccessible(true); + memberEnterDotEnv = f; + } catch (NoSuchFieldException e) { + return null; + } + + return memberEnterDotEnv; + } + + @SuppressWarnings("unchecked") + private static Env<AttrContext> getEnvOfMemberEnter(MemberEnter memberEnter) { + Field f = getMemberEnterDotEnv(); + try { + return (Env<AttrContext>) f.get(memberEnter); + } catch (Exception e) { + return null; + } + } + + private static void setEnvOfMemberEnter(MemberEnter memberEnter, Env<AttrContext> env) { + Field f = getMemberEnterDotEnv(); + try { + f.set(memberEnter, env); + } catch (Exception e) { + return; + } + } + + private void memberEnterAndAttribute(JCTree copy, Env<AttrContext> env, Context context) { + MemberEnter memberEnter = MemberEnter.instance(context); + Env<AttrContext> oldEnv = getEnvOfMemberEnter(memberEnter); + setEnvOfMemberEnter(memberEnter, env); + try { + copy.accept(memberEnter); + } catch (Exception ignore) { + // intentionally ignored; usually even if this step fails, val will work (but not for val in method local inner classes and anonymous inner classes). + } finally { + setEnvOfMemberEnter(memberEnter, oldEnv); + } + attrib(copy, env); + } + public void resolveClassMember(JavacNode node) { ArrayDeque<JCTree> stack = new ArrayDeque<JCTree>(); diff --git a/src/utils/lombok/javac/TreeMirrorMaker.java b/src/utils/lombok/javac/TreeMirrorMaker.java index 621e4e00..093839d7 100644 --- a/src/utils/lombok/javac/TreeMirrorMaker.java +++ b/src/utils/lombok/javac/TreeMirrorMaker.java @@ -38,6 +38,7 @@ import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCNewClass; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.tree.TreeCopier; +import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.List; /** @@ -53,7 +54,7 @@ import com.sun.tools.javac.util.List; public class TreeMirrorMaker extends TreeCopier<Void> { private final IdentityHashMap<JCTree, JCTree> originalToCopy = new IdentityHashMap<JCTree, JCTree>(); - public TreeMirrorMaker(JavacTreeMaker maker) { + public TreeMirrorMaker(JavacTreeMaker maker, Context context) { super(maker.getUnderlyingTreeMaker()); } @@ -93,12 +94,14 @@ public class TreeMirrorMaker extends TreeCopier<Void> { return Collections.unmodifiableMap(originalToCopy); } - // Fix for NPE in HandleVal. See http://code.google.com/p/projectlombok/issues/detail?id=205 - // Maybe this should be done elsewhere... + // Monitor issue 205 and issue 694 when making changes here. @Override public JCTree visitVariable(VariableTree node, Void p) { + JCVariableDecl original = node instanceof JCVariableDecl ? (JCVariableDecl) node : null; JCVariableDecl copy = (JCVariableDecl) super.visitVariable(node, p); - copy.sym = ((JCVariableDecl) node).sym; - if (copy.sym != null) copy.type = ((JCVariableDecl) node).type; + if (original == null) return copy; + + copy.sym = original.sym; + if (copy.sym != null) copy.type = original.type; if (copy.type != null) { boolean wipeSymAndType = copy.type.isErroneous(); if (!wipeSymAndType) { diff --git a/test/core/src/lombok/LombokTestSource.java b/test/core/src/lombok/LombokTestSource.java index 9b5607ef..c686bf19 100644 --- a/test/core/src/lombok/LombokTestSource.java +++ b/test/core/src/lombok/LombokTestSource.java @@ -183,6 +183,8 @@ public class LombokTestSource { continue; } + if (lc.startsWith("issue ")) continue; + Assert.fail("Directive line \"" + directive + "\" in '" + file.getAbsolutePath() + "' invalid: unrecognized directive."); throw new RuntimeException(); } diff --git a/test/transform/resource/after-delombok/ValAnonymousSubclassWithGenerics.java b/test/transform/resource/after-delombok/ValAnonymousSubclassWithGenerics.java new file mode 100644 index 00000000..25a9e0ce --- /dev/null +++ b/test/transform/resource/after-delombok/ValAnonymousSubclassWithGenerics.java @@ -0,0 +1,18 @@ +import java.util.*; +public class ValAnonymousSubclassWithGenerics { + Object object = new Object(){ + void foo() { + final int j = 1; + } + }; + void bar() { + final int k = super.hashCode(); + int x = k; + } + java.util.List<String> names = new java.util.ArrayList<String>(){ + public String get(int i) { + final java.lang.String result = super.get(i); + return result; + } + }; +} diff --git a/test/transform/resource/after-ecj/ValAnonymousSubclassWithGenerics.java b/test/transform/resource/after-ecj/ValAnonymousSubclassWithGenerics.java new file mode 100644 index 00000000..989555fc --- /dev/null +++ b/test/transform/resource/after-ecj/ValAnonymousSubclassWithGenerics.java @@ -0,0 +1,28 @@ +import java.util.*; +import lombok.val; +public class ValAnonymousSubclassWithGenerics { + Object object = new Object() { + x() { + super(); + } + void foo() { + final @val int j = 1; + } + }; + java.util.List<String> names = new java.util.ArrayList<String>() { + x() { + super(); + } + public String get(int i) { + final @val java.lang.String result = super.get(i); + return result; + } + }; + public ValAnonymousSubclassWithGenerics() { + super(); + } + void bar() { + final @val int k = super.hashCode(); + int x = k; + } +}
\ No newline at end of file diff --git a/test/transform/resource/before/ValAnonymousSubclassWithGenerics.java b/test/transform/resource/before/ValAnonymousSubclassWithGenerics.java index 49fc86e0..c0f8157a 100644 --- a/test/transform/resource/before/ValAnonymousSubclassWithGenerics.java +++ b/test/transform/resource/before/ValAnonymousSubclassWithGenerics.java @@ -1,4 +1,4 @@ -// ignore +// issue 205: val inside anonymous inner classes is a bit tricky in javac, this test ensures we don't break it. import java.util.*; import lombok.val; diff --git a/test/transform/resource/before/ValWithLocalClasses.java b/test/transform/resource/before/ValWithLocalClasses.java index 8c6be4f9..572a1e7d 100644 --- a/test/transform/resource/before/ValWithLocalClasses.java +++ b/test/transform/resource/before/ValWithLocalClasses.java @@ -1,3 +1,4 @@ +//issue 694: In javac, resolving the RHS (which is what val does) can cause an entire class to be resolved, breaking all usage of val inside that class. This tests that we handle that better. class ValWithLocalClasses1 { { lombok.val f2 = new ValWithLocalClasses2() {}; diff --git a/test/transform/resource/messages-ecj/ValAnonymousSubclassWithGenerics.java.messages b/test/transform/resource/messages-ecj/ValAnonymousSubclassWithGenerics.java.messages new file mode 100644 index 00000000..37f87639 --- /dev/null +++ b/test/transform/resource/messages-ecj/ValAnonymousSubclassWithGenerics.java.messages @@ -0,0 +1 @@ +17 The serializable class does not declare a static final serialVersionUID field of type long
\ No newline at end of file |