Bug 341232 - Eclipse is not able to set the simplest of conditional
breakpoints and reports that the condition has compilation errors when
it doesn't
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java
index fc3c7d6..ef43203 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Jesper Steen Moller - bug 341232
*******************************************************************************/
package org.eclipse.jdt.debug.tests;
@@ -360,6 +361,7 @@
cfgs.add(createLaunchConfiguration(jp, "a.b.c.MethodBreakpoints"));
cfgs.add(createLaunchConfiguration(jp, "a.b.c.IntegerAccess"));
cfgs.add(createLaunchConfiguration(jp, "a.b.c.StepIntoSelectionWithGenerics"));
+ cfgs.add(createLaunchConfiguration(jp, "a.b.c.ConditionalsNearGenerics"));
loaded15 = true;
waitForBuild();
}
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
index af076ff..1c336f5 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
@@ -22,6 +22,7 @@
import org.eclipse.jdt.debug.tests.breakpoints.BreakpointListenerTests;
import org.eclipse.jdt.debug.tests.breakpoints.BreakpointLocationVerificationTests;
import org.eclipse.jdt.debug.tests.breakpoints.BreakpointWorkingSetTests;
+import org.eclipse.jdt.debug.tests.breakpoints.ConditionalBreakpoints15Tests;
import org.eclipse.jdt.debug.tests.breakpoints.ConditionalBreakpointsTests;
import org.eclipse.jdt.debug.tests.breakpoints.DeferredBreakpointTests;
import org.eclipse.jdt.debug.tests.breakpoints.ExceptionBreakpointTests;
@@ -182,6 +183,7 @@
addTest(new TestSuite(MethodBreakpointTests15.class));
addTest(new TestSuite(TestIntegerAccessUnboxing15.class));
addTest(new TestSuite(StepIntoSelectionWithGenerics.class));
+ addTest(new TestSuite(ConditionalBreakpoints15Tests.class));
}
//Sourcelookup tests
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/ConditionalBreakpoints15Tests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/ConditionalBreakpoints15Tests.java
new file mode 100644
index 0000000..af41b34
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/ConditionalBreakpoints15Tests.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Jesper Steen Moller and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Jesper Steen Moller - initial API and implementation, adapted from
+ * Stefan Mandels contribution in bug 341232, and existing debug tests
+ *******************************************************************************/
+package org.eclipse.jdt.debug.tests.breakpoints;
+
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.debug.core.IJavaLineBreakpoint;
+import org.eclipse.jdt.debug.core.IJavaThread;
+import org.eclipse.jdt.debug.tests.AbstractDebugTest;
+
+/**
+ * Tests conditional breakpoints.
+ */
+public class ConditionalBreakpoints15Tests extends AbstractDebugTest {
+
+ /**
+ * Constructor
+ * @param name
+ */
+ public ConditionalBreakpoints15Tests(String name) {
+ super(name);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.debug.tests.AbstractDebugTest#getProjectContext()
+ */
+ @Override
+ protected IJavaProject getProjectContext() {
+ return get15Project();
+ }
+
+ /**
+ * Tests a breakpoint with a simple condition
+ * @throws Exception
+ */
+ public void testSimpleConditionalBreakpointOnParameterizedType() throws Exception {
+ String typeName = "a.b.c.ConditionalsNearGenerics";
+ String innerTypeName = "a.b.c.ConditionalsNearGenerics.ItemIterator";
+ IJavaLineBreakpoint bp1 = createConditionalLineBreakpoint(33, typeName, "false", true);
+ IJavaLineBreakpoint bp2 = createConditionalLineBreakpoint(39, typeName, "false", true);
+ IJavaLineBreakpoint bp3 = createConditionalLineBreakpoint(52, innerTypeName, "false", true);
+ IJavaLineBreakpoint bp4 = createConditionalLineBreakpoint(53, innerTypeName, "true", true);
+
+ IJavaThread thread= null;
+ try {
+ thread= launchToLineBreakpoint(typeName, bp4); // If compiled correctly, this will jump over bp1-bp3 !!
+
+ bp1.delete();
+ bp2.delete();
+ bp3.delete();
+ bp4.delete();
+ } finally {
+ terminateAndRemove(thread);
+ removeAllBreakpoints();
+ }
+ }
+
+ }
diff --git a/org.eclipse.jdt.debug.tests/testsource-j2se-1.5/a/b/c/ConditionalsNearGenerics.java b/org.eclipse.jdt.debug.tests/testsource-j2se-1.5/a/b/c/ConditionalsNearGenerics.java
new file mode 100644
index 0000000..93565a0
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/testsource-j2se-1.5/a/b/c/ConditionalsNearGenerics.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Jesper Steen Moller and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Jesper Steen Moller - initial API and implementation, adapted from
+ * Stefan Mandels contribution in bug 341232
+ *******************************************************************************/
+package a.b.c;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+public class ConditionalsNearGenerics {
+
+ private String name;
+
+ public ConditionalsNearGenerics() {
+ // set a conditional breakpoint in next line: use true as expression
+ this.name = "bug";
+ }
+
+ public static void main(String[] args) throws Exception {
+ new ConditionalsNearGenerics().bug();
+ }
+
+ public void bug() throws Exception {
+ char[] chars = name.toCharArray();
+ System.out.println(chars);
+ tokenize(Arrays.asList(1,2,3), name);
+ }
+
+ //FIXME delete following method, then the breakpoint shall work
+ public <T extends Number> Iterator<T> tokenize(List<T> list, String input) {
+ new ItemIterator<Item>(input);
+ return list.iterator();
+ }
+
+ public interface Item {
+
+ }
+
+ private class ItemIterator<T extends Item> implements Iterator<T> {
+
+ private String input;
+
+ public ItemIterator(String input) {
+ this.input = input;
+ System.out.println("From ItemIterator!");
+ }
+
+ @Override
+ public boolean hasNext() {
+ return false;
+ }
+
+ @Override
+ public T next() {
+ return null;
+ }
+
+ @Override
+ public void remove() {
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTEvaluationEngine.java b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTEvaluationEngine.java
index 165fb7a..f35e2da 100644
--- a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTEvaluationEngine.java
+++ b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTEvaluationEngine.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Jesper Steen Moller - bug 341232
*******************************************************************************/
package org.eclipse.jdt.internal.debug.eval.ast.engine;
@@ -336,7 +337,7 @@
// }
unit = parseCompilationUnit(
- mapper.getSource(receivingType, javaProject,
+ mapper.getSource(receivingType, frame.getLineNumber(), javaProject,
frame.isStatic()).toCharArray(),
mapper.getCompilationUnitName(), javaProject);
} catch (CoreException e) {
@@ -428,7 +429,7 @@
if (javaTypes.length > 0) {
IJavaReferenceType recType = (IJavaReferenceType) javaTypes[0];
unit = parseCompilationUnit(
- mapper.getSource(recType, getJavaProject(), false)
+ mapper.getSource(recType, -1, getJavaProject(), false)
.toCharArray(),
mapper.getCompilationUnitName(), javaProject);
} else {
@@ -493,7 +494,7 @@
try {
unit = parseCompilationUnit(
- mapper.getSource(type, javaProject, false).toCharArray(),
+ mapper.getSource(type, -1, javaProject, false).toCharArray(),
mapper.getCompilationUnitName(), javaProject);
} catch (CoreException e) {
InstructionSequence expression = new InstructionSequence(snippet);
diff --git a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/EvaluationSourceGenerator.java b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/EvaluationSourceGenerator.java
index f21a3b9..d752a0f 100644
--- a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/EvaluationSourceGenerator.java
+++ b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/EvaluationSourceGenerator.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Jesper Steen Moller - bug 341232
*******************************************************************************/
package org.eclipse.jdt.internal.debug.eval.ast.engine;
@@ -137,7 +138,7 @@
}
private void createEvaluationSourceFromSource(String source, IType type,
- boolean createInAStaticMethod, IJavaProject project)
+ int line, boolean createInAStaticMethod, IJavaProject project)
throws DebugException {
ASTParser parser = ASTParser.newParser(AST.JLS4);
parser.setSource(source.toCharArray());
@@ -146,7 +147,7 @@
parser.setCompilerOptions(options);
CompilationUnit unit = (CompilationUnit) parser.createAST(null);
SourceBasedSourceGenerator visitor = new SourceBasedSourceGenerator(
- type, createInAStaticMethod, fLocalVariableTypeNames,
+ type, line, createInAStaticMethod, fLocalVariableTypeNames,
fLocalVariableNames, fCodeSnippet, sourceLevel);
unit.accept(visitor);
@@ -217,7 +218,7 @@
return objectToEvaluationSourceMapper;
}
- public String getSource(IJavaReferenceType type, IJavaProject javaProject,
+ public String getSource(IJavaReferenceType type, int line, IJavaProject javaProject,
boolean isStatic) throws CoreException {
if (fSource == null) {
IType iType = JavaDebugUtils.resolveType(type);
@@ -230,7 +231,7 @@
}
if (baseSource != null) {
createEvaluationSourceFromSource(baseSource, iType,
- isStatic, javaProject);
+ line, isStatic, javaProject);
}
}
if (fSource == null) {
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 dbbd7d9..837bac0 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,13 +7,17 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Jesper Steen Moller - bug 341232
*******************************************************************************/
package org.eclipse.jdt.internal.debug.eval.ast.engine;
-import java.util.HashSet;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
-import java.util.Set;
+import java.util.Map;
+import java.util.Stack;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IType;
@@ -131,6 +135,7 @@
private String fError;
private IType fType;
+ private int fLine;
private StringBuffer fSource;
@@ -149,7 +154,12 @@
private int fSourceMajorLevel;
private int fSourceMinorLevel;
- private Set<String> fTypeParameters = new HashSet<String>();
+ private Stack<Map<String, String>> fTypeParameterStack = new Stack<Map<String, String>>();
+ private Map<String, String> fMatchingTypeParameters = null;
+ private CompilationUnit fCompilationUnit;
+ {
+ fTypeParameterStack.push(Collections.<String,String>emptyMap());
+ }
/**
* if the <code>createInAnInstanceMethod</code> flag is set, the method
@@ -158,6 +168,8 @@
*
* @param type
* the root {@link IType}
+ * @param sourcePosition
+ * the reference position in the type's source
* @param createInAStaticMethod
* if the source should be generated
* @param localTypesNames
@@ -170,10 +182,11 @@
* the desired source level
*/
public SourceBasedSourceGenerator(IType type,
- boolean createInAStaticMethod, String[] localTypesNames,
+ int line, boolean createInAStaticMethod, String[] localTypesNames,
String[] localVariables, String codeSnippet, String sourceLevel) {
fRightTypeFound = false;
fType = type;
+ fLine = line;
fLocalVariableTypeNames = localTypesNames;
fLocalVariableNames = localVariables;
fCodeSnippet = codeSnippet;
@@ -243,8 +256,9 @@
// add type parameters as required
if (isSourceLevelGreaterOrEqual(1, 5)) {
- if (!fTypeParameters.isEmpty()) {
- Iterator<String> iterator = fTypeParameters.iterator();
+ 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();
@@ -740,7 +754,7 @@
if (type.isSimpleType()) {
String name = getQualifiedIdentifier(((SimpleType) type).getName());
if (!isSourceLevelGreaterOrEqual(1, 5)
- && fTypeParameters.contains(name)) {
+ && fTypeParameterStack.peek().containsKey(name)) {
return "Object"; //$NON-NLS-1$
}
return name;
@@ -1008,6 +1022,13 @@
}
}
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ASTVisitor#endVisit(org.eclipse.jdt.core.dom.MethodDeclaration)
+ */
+ public void endVisit(MethodDeclaration node) {
+ fTypeParameterStack.pop();
+ }
+
/**
* @see ASTVisitor#endVisit(TypeDeclaration)
*/
@@ -1015,6 +1036,7 @@
public void endVisit(TypeDeclaration node) {
if (hasError()) {
+ fTypeParameterStack.pop();
return;
}
@@ -1027,6 +1049,7 @@
if (!fEvaluateNextEndTypeDeclaration) {
fEvaluateNextEndTypeDeclaration = true;
+ fTypeParameterStack.pop();
return;
}
@@ -1060,6 +1083,7 @@
fLastTypeName = node.getName().getIdentifier();
}
}
+ fTypeParameterStack.pop();
}
/*
@@ -1254,6 +1278,7 @@
*/
@Override
public boolean visit(CompilationUnit node) {
+ fCompilationUnit = node;
if (rightTypeFound()) {
return false;
}
@@ -1532,13 +1557,15 @@
*/
@Override
public boolean visit(MethodDeclaration node) {
+ String name = node.getName().toString();
+ System.out.println(name);
+ int firstLine = fCompilationUnit.getLineNumber(node.getStartPosition());
+ int lastLine = fCompilationUnit.getLineNumber(node.getStartPosition() + node.getLength());
+
List<TypeParameter> typeParameters = node.typeParameters();
- if (!typeParameters.isEmpty()) {
- Iterator<TypeParameter> iterator = typeParameters.iterator();
- while (iterator.hasNext()) {
- TypeParameter typeParameter = iterator.next();
- fTypeParameters.add(typeParameter.toString());
- }
+ pushTypeParameters(typeParameters);
+ if (isRightType(node.getParent()) && firstLine <= fLine && fLine <= lastLine) {
+ fMatchingTypeParameters = fTypeParameterStack.peek();
}
if (rightTypeFound()) {
return false;
@@ -1546,6 +1573,21 @@
return true;
}
+ private void pushTypeParameters(List<TypeParameter> typeParameters) {
+ if (!typeParameters.isEmpty()) {
+ HashMap<String,String> newTypeParameters = new HashMap<String,String>(fTypeParameterStack.peek());
+ Iterator<TypeParameter> iterator = typeParameters.iterator();
+ while (iterator.hasNext()) {
+ TypeParameter typeParameter = iterator.next();
+ String boundName = typeParameter.getName().getIdentifier();
+ newTypeParameters.put(boundName, typeParameter.toString());
+ }
+ fTypeParameterStack.push(newTypeParameters); // Push the new "scope"
+ } else {
+ fTypeParameterStack.push(fTypeParameterStack.peek()); // Push the same
+ }
+ }
+
/**
* @see ASTVisitor#visit(MethodInvocation)
*/
@@ -1925,13 +1967,7 @@
@Override
public boolean visit(TypeDeclaration node) {
List<TypeParameter> typeParameters = node.typeParameters();
- if (!typeParameters.isEmpty()) {
- Iterator<TypeParameter> iterator = typeParameters.iterator();
- while (iterator.hasNext()) {
- TypeParameter typeParameter = iterator.next();
- fTypeParameters.add(typeParameter.getName().getIdentifier());
- }
- }
+ pushTypeParameters(typeParameters);
if (rightTypeFound()) {
fEvaluateNextEndTypeDeclaration = false;
return false;