Bug 329294 - "Unable to resolve binding" - handle name ranges better +
enums
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/GenericsEvalTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/GenericsEvalTests.java
index af8bd4a..f7c2c65 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/GenericsEvalTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/GenericsEvalTests.java
@@ -270,7 +270,7 @@
 		IJavaThread thread = null;
 		try {
 			String type = "a.b.c.bug329294WithGenerics";
-			createLineBreakpoint(8, type);
+			createLineBreakpoint(41, type);
 			thread = launchToBreakpoint(type);
 			assertNotNull("The program did not suspend", thread);
 			String snippet = "fInner1.innerBool";
@@ -290,7 +290,7 @@
 		IJavaThread thread = null;
 		try {
 			String type = "a.b.c.bug329294WithGenerics";
-			createLineBreakpoint(23, type);
+			createLineBreakpoint(61, type);
 			thread = launchToBreakpoint(type);
 			assertNotNull("The program did not suspend", thread);
 			String snippet = "inner";
@@ -310,7 +310,7 @@
 		IJavaThread thread = null;
 		try {
 			String type = "a.b.c.bug329294WithGenerics";
-			createLineBreakpoint(27, type);
+			createLineBreakpoint(65, type);
 			thread = launchToBreakpoint(type);
 			assertNotNull("The program did not suspend", thread);
 			String snippet = "fInner1.innerBool";
@@ -330,7 +330,7 @@
 		IJavaThread thread = null;
 		try {
 			String type = "a.b.c.bug329294WithGenerics";
-			createLineBreakpoint(31, type);
+			createLineBreakpoint(69, type);
 			thread = launchToBreakpoint(type);
 			assertNotNull("The program did not suspend", thread);
 			String snippet = "!fInner1.innerBool";
@@ -341,4 +341,104 @@
 			terminateAndRemove(thread);
 		}
 	}
+	
+	/**
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=329294
+	 * @throws Exception
+	 */
+	public void testInnerEnumType1() throws Exception {
+		IJavaThread thread = null;
+		try {
+			String typename = "a.b.c.bug329294WithGenerics";
+			createLineBreakpoint(11, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("The program did not suspend", thread);
+			String snippet = "fInner1.innerBool";
+			doEval(thread, snippet);
+		}
+		finally {
+			removeAllBreakpoints();
+			terminateAndRemove(thread);
+		}
+	}
+	
+	/**
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=329294
+	 * @throws Exception
+	 */
+	public void testInnerEnumType2() throws Exception {
+		IJavaThread thread = null;
+		try {
+			String typename = "a.b.c.bug329294WithGenerics";
+			createLineBreakpoint(14, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("The program did not suspend", thread);
+			String snippet = "!fInner1.innerBool";
+			doEval(thread, snippet);
+		}
+		finally {
+			removeAllBreakpoints();
+			terminateAndRemove(thread);
+		}
+	}
+	
+	/**
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=329294
+	 * @throws Exception
+	 */
+	public void testInnerEnumType3() throws Exception {
+		IJavaThread thread = null;
+		try {
+			String typename = "a.b.c.bug329294WithGenerics";
+			createLineBreakpoint(23, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("The program did not suspend", thread);
+			String snippet = "fInner1.innerBool";
+			doEval(thread, snippet);
+		}
+		finally {
+			removeAllBreakpoints();
+			terminateAndRemove(thread);
+		}
+	}
+	
+	/**
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=329294
+	 * @throws Exception
+	 */
+	public void testInnerEnumType4() throws Exception {
+		IJavaThread thread = null;
+		try {
+			String typename = "a.b.c.bug329294WithGenerics";
+			createLineBreakpoint(28, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("The program did not suspend", thread);
+			String snippet = "i2.fInner1.innerBool";
+			doEval(thread, snippet);
+		}
+		finally {
+			removeAllBreakpoints();
+			terminateAndRemove(thread);
+		}
+	}
+	
+	/**
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=329294
+	 * @throws Exception
+	 */
+	public void testInnerEnumType5() throws Exception {
+		IJavaThread thread = null;
+		try {
+			String typename = "a.b.c.bug329294WithGenerics";
+			createLineBreakpoint(33, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("The program did not suspend", thread);
+			String snippet = "!ei2.fInner1.innerBool";
+			doEval(thread, snippet);
+		}
+		finally {
+			removeAllBreakpoints();
+			terminateAndRemove(thread);
+		}
+	}
 }
diff --git a/org.eclipse.jdt.debug.tests/testsource-j2se-1.5/a/b/c/bug329294WithGenerics.java b/org.eclipse.jdt.debug.tests/testsource-j2se-1.5/a/b/c/bug329294WithGenerics.java
index 55fa081..1254516 100644
--- a/org.eclipse.jdt.debug.tests/testsource-j2se-1.5/a/b/c/bug329294WithGenerics.java
+++ b/org.eclipse.jdt.debug.tests/testsource-j2se-1.5/a/b/c/bug329294WithGenerics.java
@@ -1,6 +1,39 @@
 package a.b.c;
 //breaking line comment
+@SuppressWarnings("rawtypes")
 public class bug329294WithGenerics {
+	//breaking line comment
+	public enum Menum {
+		One;
+		
+		Inner2 ei2 = new Inner2() {
+			boolean isTrue() {
+				return fInner1.innerBool; //bp 
+			};
+			boolean isNotTrue() {
+				return !fInner1.innerBool; //bp
+			};
+		};
+		
+		Menum() {}
+		
+		public <T> boolean eTrue(Inner1<T> i1) {
+			Inner2<T> i2 = new Inner2<T>(i1) {
+				boolean isTrue() {
+					return fInner1.innerBool; //bp
+				}
+			};
+			i2.isTrue();
+			ei2.isTrue();
+			return i2.fInner1.innerBool; //bp
+		}
+		
+		public boolean eIsNotTrue() {
+			ei2.isNotTrue();
+			return !ei2.fInner1.innerBool; //bp
+		}
+	}
+	//breaking line comment
 	public static void main(String[] args) {
 		Inner1<String> i1 = new Inner1<String>();
 		Inner2<String> i2 = new Inner2<String>(i1) {
@@ -12,6 +45,8 @@
 		i2.isNotTrue();
 		i2 = new Inner2<String>(i1);
 		i2.isTrue();
+		Menum.One.eTrue(i1);
+		Menum.One.eIsNotTrue();
 	}
 	private static class Inner1<T> {
 		boolean innerBool;
@@ -19,16 +54,19 @@
 	//breaking line comment
 	private static class Inner2<T> {
 		Inner1<T> fInner1 = null;
+		Inner2() {
+			fInner1 = new Inner1<T>();
+		}
 		Inner2(Inner1<T> inner) {
-			fInner1 = inner;
+			fInner1 = inner; //bp
 		}
 		
 		<E> boolean isTrue() {
-			return fInner1.innerBool;
+			return fInner1.innerBool; //bp
 		}
 		
 		boolean isNotTrue() {
-			return !fInner1.innerBool;
+			return !fInner1.innerBool; //bp
 		}
 	}
 }
diff --git a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/SourceBasedSourceGenerator.java b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/SourceBasedSourceGenerator.java
index 093f04e..b86f289 100644
--- a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/SourceBasedSourceGenerator.java
+++ b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/SourceBasedSourceGenerator.java
@@ -24,6 +24,7 @@
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.SourceRange;
 import org.eclipse.jdt.core.dom.ASTNode;
 import org.eclipse.jdt.core.dom.ASTVisitor;
 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
@@ -254,22 +255,7 @@
 			buffer.append("static "); //$NON-NLS-1$
 		}
 
-		// add type parameters as required
-		if (isSourceLevelGreaterOrEqual(1, 5)) {
-			Collection<String> activeTypeParameters = (fMatchingTypeParameters != null ? fMatchingTypeParameters : fTypeParameterStack.peek()).values();
-			if (!activeTypeParameters.isEmpty()) {
-				Iterator<String> iterator = activeTypeParameters.iterator();
-				buffer.append(Signature.C_GENERIC_START);
-				while (iterator.hasNext()) {
-					String name = iterator.next();
-					buffer.append(name);
-					if (iterator.hasNext()) {
-						buffer.append(", "); //$NON-NLS-1$
-					}
-				}
-				buffer.append(Signature.C_GENERIC_END);
-			}
-		}
+		adddTypeParameters(buffer);
 
 		buffer.append("void "); //$NON-NLS-1$
 		buffer.append(getUniqueMethodName(RUN_METHOD_NAME, bodyDeclarations));
@@ -300,6 +286,31 @@
 	}
 
 	/**
+	 * Adds generic type parameters as needed to the given buffer
+	 * 
+	 * @param buffer
+	 * @since 3.8.0
+	 */
+	void adddTypeParameters(StringBuffer buffer) {
+		if (isSourceLevelGreaterOrEqual(1, 5)) {
+			Collection<String> activeTypeParameters = (fMatchingTypeParameters != null ? fMatchingTypeParameters : fTypeParameterStack.peek()).values();
+			if (!activeTypeParameters.isEmpty()) {
+				Iterator<String> iterator = activeTypeParameters.iterator();
+				buffer.append(Signature.C_GENERIC_START);
+				while (iterator.hasNext()) {
+					String name = iterator.next();
+					buffer.append(name);
+					if (iterator.hasNext()) {
+						buffer.append(", "); //$NON-NLS-1$
+					}
+				}
+				buffer.append(Signature.C_GENERIC_END);
+				buffer.append(' ');
+			}
+		}
+	}
+	
+	/**
 	 * Returns if the specified {@link ASTNode} has the 'correct' parent type to
 	 * match the current type name context
 	 * 
@@ -309,21 +320,31 @@
 	 *         type name context, false otherwise
 	 */
 	private boolean isRightType(ASTNode node) {
-		switch(node.getNodeType()) {
-			case ASTNode.ANNOTATION_TYPE_DECLARATION:
-			case ASTNode.ENUM_DECLARATION:
-			case ASTNode.TYPE_DECLARATION:
-			case ASTNode.CLASS_INSTANCE_CREATION: {
-				try {
-					ISourceRange name = fType.getNameRange();
-					return name.getOffset() >= node.getStartPosition() && 
-							name.getOffset()+name.getLength() <= node.getStartPosition()+node.getLength();
-				} catch (JavaModelException e) {
-					JDIDebugPlugin.log(e.getStatus());
+		try {
+			switch(node.getNodeType()) {
+				case ASTNode.ANNOTATION_TYPE_DECLARATION:
+				case ASTNode.ENUM_DECLARATION:
+				case ASTNode.TYPE_DECLARATION: {
+					AbstractTypeDeclaration decl = (AbstractTypeDeclaration) node;
+					SimpleName name = decl.getName();
+					ISourceRange range = new SourceRange(name.getStartPosition(), name.getLength());
+					return fType.getNameRange().equals(range);
 				}
-				break;
+				case ASTNode.ANONYMOUS_CLASS_DECLARATION: {
+					return isRightType(node.getParent());
+				}
+				case ASTNode.CLASS_INSTANCE_CREATION: {
+					ClassInstanceCreation decl = (ClassInstanceCreation) node;
+					Type type = decl.getType();
+					ISourceRange name = fType.getNameRange();
+					return name.getOffset() >= type.getStartPosition() && 
+							name.getOffset()+name.getLength() <= type.getStartPosition()+type.getLength();
+				}
 			}
 		}
+		catch(JavaModelException jme) {
+			JDIDebugPlugin.log(jme);
+		}
 		return false;
 	}
 
@@ -861,11 +882,11 @@
 				fSource = new StringBuffer();
 
 				if (parent instanceof Initializer) {
-					createAnonymousEvalMethod(true, bodyDeclarations,
+					buildAnonymousEvalMethod(true, bodyDeclarations,
 							getTypeName(node.getType()), source);
 				} else if (parent instanceof MethodDeclaration) {
 					MethodDeclaration enclosingMethodDeclaration = (MethodDeclaration) parent;
-					createAnonymousEvalMethod(
+					buildAnonymousEvalMethod(
 							Flags.isStatic(enclosingMethodDeclaration
 									.getModifiers()), bodyDeclarations,
 							getTypeName(node.getType()), source);
@@ -921,11 +942,12 @@
 	 *            new method
 	 * @since 3.7
 	 */
-	void createAnonymousEvalMethod(boolean isstatic, List<BodyDeclaration> bodydecls,
+	void buildAnonymousEvalMethod(boolean isstatic, List<BodyDeclaration> bodydecls,
 			String typename, StringBuffer body) {
 		if (isstatic) {
 			fSource.append("static "); //$NON-NLS-1$
 		}
+		adddTypeParameters(fSource);
 		fSource.append("void "); //$NON-NLS-1$
 		fSource.append(getUniqueMethodName(EVAL_METHOD_NAME, bodydecls));
 		fSource.append("() {\n"); //$NON-NLS-1$