From e5860edabe31f3b6ceabd91f9cbcadf3d4d0315a Mon Sep 17 00:00:00 2001
From: Reinier Zwitserloot <reinier@zwitserloot.com>
Date: Sun, 1 Feb 2015 06:52:52 +0100
Subject: Fixed issues with val in inner classes, and re-enabled a test that
 caught it that we ignored earlier.

---
 src/core/lombok/javac/JavacResolution.java  | 55 +++++++++++++++++++++++++++--
 src/utils/lombok/javac/TreeMirrorMaker.java | 13 ++++---
 2 files changed, 60 insertions(+), 8 deletions(-)

(limited to 'src')

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) {
-- 
cgit