Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jdt.debug.tests/java8/Bug573547.java63
-rw-r--r--org.eclipse.jdt.debug.tests/java9/Bug575039.java6
-rw-r--r--org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java2
-rw-r--r--org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java4
-rw-r--r--org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/Java9Tests.java54
-rw-r--r--org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DebugHoverTests.java449
-rw-r--r--org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugHover.java91
-rw-r--r--org.eclipse.jdt.debug/.settings/.api_filters11
-rw-r--r--org.eclipse.jdt.debug/META-INF/MANIFEST.MF2
-rw-r--r--org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTEvaluationEngine.java10
-rw-r--r--org.eclipse.jdt.debug/pom.xml2
-rw-r--r--org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java4
-rw-r--r--pom.xml2
13 files changed, 681 insertions, 19 deletions
diff --git a/org.eclipse.jdt.debug.tests/java8/Bug573547.java b/org.eclipse.jdt.debug.tests/java8/Bug573547.java
new file mode 100644
index 000000000..806dc9a3f
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/java8/Bug573547.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2021 Gayan Perera and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Gayan Perera - initial API and implementation
+ *******************************************************************************/
+
+import java.util.stream.Stream;
+
+public class Bug573547 {
+ private String payload;
+
+ private String[] payloads;
+
+ private static String[] PAYLOADS = new String[] {"1"};
+
+ public Bug573547(String payload) {
+ this.payload = payload;
+ this.payloads = new String[]{payload};
+ }
+
+ public void hoverOverLocal(String[] names) {
+ char[] name = new char[] {'n', 'a', 'm', 'e'};
+ Bug573547 object = new Bug573547("p");
+
+ System.out.println(name.length);
+ System.out.println(object.payload);
+ System.out.println(names.length);
+ /*Root*/System.out.println(object.payloads.length);
+ System.out.println(this.payloads.length);
+ System.out.println(payloads.length);
+
+ Stream.of(name).forEach(a -> {
+ System.out.println(a.length);
+ });
+ nestedHover();
+ }
+
+ public void nestedHover() {
+ String object = "1234";
+ /*Nested1*/System.out.println(object);
+ (new Nest()).nestedHover();
+ }
+ public static void main(String[] args) {
+ new Bug573547("p").hoverOverLocal(new String[] {"name"});
+ }
+
+ private class Nest {
+ /*Nested2*/private String payload = "np";
+
+ public void nestedHover() {
+ String object = "1234n";
+ /*Nested2*/System.out.println(object);
+ }
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.jdt.debug.tests/java9/Bug575039.java b/org.eclipse.jdt.debug.tests/java9/Bug575039.java
new file mode 100644
index 000000000..26168b1fe
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/java9/Bug575039.java
@@ -0,0 +1,6 @@
+public class Bug575039 {
+ public static void main(String[] args) {
+ Thread t = new Thread("Hello bug 575039");
+ t.start();
+ }
+} \ No newline at end of file
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 685087aad..b879fab5c 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
@@ -498,6 +498,7 @@ public abstract class AbstractDebugTest extends TestCase implements IEvaluation
cfgs.add(createLaunchConfiguration(jp, "Bug573589"));
cfgs.add(createLaunchConfiguration(jp, "Bug574395"));
cfgs.add(createLaunchConfiguration(jp, "Bug571310"));
+ cfgs.add(createLaunchConfiguration(jp, "Bug573547"));
loaded18 = true;
waitForBuild();
}
@@ -528,6 +529,7 @@ public abstract class AbstractDebugTest extends TestCase implements IEvaluation
if (!loaded9) {
jp = createProject(NINE_PROJECT_NAME, JavaProjectHelper.TEST_9_SRC_DIR.toString(), JavaProjectHelper.JAVA_SE_9_EE_NAME, false);
cfgs.add(createLaunchConfiguration(jp, "LogicalStructures"));
+ cfgs.add(createLaunchConfiguration(jp, "Bug575039"));
loaded9 = 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 7f93c69d1..08d2977db 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
@@ -96,6 +96,7 @@ import org.eclipse.jdt.debug.tests.eval.ExpressionEvalTest;
import org.eclipse.jdt.debug.tests.eval.GeneralEvalTests;
import org.eclipse.jdt.debug.tests.eval.GenericsEval17Test;
import org.eclipse.jdt.debug.tests.eval.GenericsEvalTests;
+import org.eclipse.jdt.debug.tests.eval.Java9Tests;
import org.eclipse.jdt.debug.tests.eval.LambdaVariableTest;
import org.eclipse.jdt.debug.tests.eval.SyntheticVariableTests;
import org.eclipse.jdt.debug.tests.launching.ClasspathShortenerTests;
@@ -339,6 +340,9 @@ public class AutomatedSuite extends DebugSuite {
addTest(new TestSuite(LambdaVariableTest.class));
}
//addTest(EvalTestSuite.suite());
+ if (JavaProjectHelper.isJava9Compatible()) {
+ addTest(new TestSuite(Java9Tests.class));
+ }
// long classpath tests
addTest(new TestSuite(ClasspathShortenerTests.class));
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/Java9Tests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/Java9Tests.java
new file mode 100644
index 000000000..1b1784f2d
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/Java9Tests.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2021 Gayan Perera and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Gayan Perera - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.debug.tests.eval;
+
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.debug.core.IJavaThread;
+import org.eclipse.jdt.debug.tests.AbstractDebugTest;
+
+public class Java9Tests extends AbstractDebugTest {
+
+ private IJavaThread thread;
+
+ public Java9Tests(String name) {
+ super(name);
+ }
+
+ @Override
+ protected IJavaProject getProjectContext() {
+ return super.get9Project();
+ }
+
+ public void testBug575039_methodBreakpointOnJavaBaseModuleClass_expectSuccessfulEval() throws Exception {
+ String type = "Bug575039";
+ createMethodBreakpoint("java.lang.Thread", "<init>", "(Ljava/lang/ThreadGroup;Ljava/lang/Runnable;Ljava/lang/String;JLjava/security/AccessControlContext;Z)V",
+ true, false);
+ thread = launchToBreakpoint(type);
+ assertNotNull("The program did not suspend", thread);
+
+ String snippet = "name != null";
+ IValue value = doEval(thread, snippet);
+
+ assertNotNull("value is null", value);
+ assertEquals("true", value.getValueString());
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ removeAllBreakpoints();
+ terminateAndRemove(thread);
+ super.tearDown();
+ }
+}
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DebugHoverTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DebugHoverTests.java
index f21e89cc3..50f724854 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DebugHoverTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DebugHoverTests.java
@@ -25,6 +25,8 @@ import org.eclipse.debug.core.model.ILineBreakpoint;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IVariable;
import org.eclipse.debug.internal.ui.views.console.ProcessConsole;
+import org.eclipse.debug.internal.ui.views.launch.LaunchView;
+import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.jdi.internal.StringReferenceImpl;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.debug.core.IJavaArray;
@@ -43,6 +45,8 @@ import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.Region;
+import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.test.OrderedTestSuite;
import junit.framework.Test;
@@ -954,6 +958,434 @@ public class DebugHoverTests extends AbstractDebugUiTests {
}
}
+ public void testBug573547_insideLambda_onOuterScopeLocalVariableChain() throws Exception {
+ sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
+
+ final String typeName = "Bug573547";
+ final String expectedMethod = "lambda$0";
+ final int frameNumber = 6;
+ final int bpLine = 41;
+ final int hoverLine = 34;
+
+ IJavaBreakpoint bp = createLineBreakpoint(bpLine, "", typeName + ".java", typeName);
+ bp.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+ IFile file = (IFile) bp.getMarker().getResource();
+ assertEquals(typeName + ".java", file.getName());
+
+ IJavaThread thread = null;
+ try {
+ thread = launchToBreakpoint(typeName);
+ CompilationUnitEditor part = openEditorAndValidateStack(expectedMethod, frameNumber, file, thread);
+
+ JavaDebugHover hover = new JavaDebugHover();
+ hover.setEditor(part);
+
+ String variableName = "payload";
+ int offset = part.getViewer().getDocument().get().indexOf("System.out.println(object.payload")
+ + "System.out.println(object.".length();
+ IRegion region = new Region(offset, "payload".length());
+ String text = selectAndReveal(part, hoverLine, region);
+ assertEquals(variableName, text);
+ IVariable info = (IVariable) sync(() -> hover.getHoverInfo2(part.getViewer(), region));
+
+ assertNotNull(info);
+ assertEquals("object.payload", info.getName());
+ assertEquals("p", info.getValue().getValueString());
+ } finally {
+ terminateAndRemove(thread);
+ removeAllBreakpoints();
+ }
+ }
+
+ public void testBug573547_insideLambda_onOuterScopeMemberVariable() throws Exception {
+ sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
+ final String typeName = "Bug573547";
+ final String expectedMethod = "lambda$0";
+ final int frameNumber = 6;
+ final int bpLine = 41;
+ final int hoverLine = 38;
+
+ IJavaBreakpoint bp = createLineBreakpoint(bpLine, "", typeName + ".java", typeName);
+ bp.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+ IFile file = (IFile) bp.getMarker().getResource();
+ assertEquals(typeName + ".java", file.getName());
+
+ IJavaThread thread = null;
+ try {
+ thread = launchToBreakpoint(typeName);
+ CompilationUnitEditor part = openEditorAndValidateStack(expectedMethod, frameNumber, file, thread);
+
+ JavaDebugHover hover = new JavaDebugHover();
+ hover.setEditor(part);
+
+ String variableName = "payloads";
+ int offset = part.getViewer().getDocument().get().lastIndexOf("System.out.println(payloads") + "System.out.println(".length();
+ IRegion region = new Region(offset, "payloads".length());
+ String text = selectAndReveal(part, hoverLine, region);
+ assertEquals(variableName, text);
+ IVariable info = (IVariable) sync(() -> hover.getHoverInfo2(part.getViewer(), region));
+
+ assertNotNull(info);
+ assertEquals("payloads", info.getName());
+ assertTrue("Not an array variable", info.getValue() instanceof IJavaArray);
+ } finally {
+ terminateAndRemove(thread);
+ removeAllBreakpoints();
+ }
+ }
+
+ public void testBug573547_insideLambda_onOuterScopeMemberVariable_withThis() throws Exception {
+ sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
+ final String typeName = "Bug573547";
+ final String expectedMethod = "lambda$0";
+ final int frameNumber = 6;
+ final int bpLine = 41;
+ final int hoverLine = 37;
+
+ IJavaBreakpoint bp = createLineBreakpoint(bpLine, "", typeName + ".java", typeName);
+ bp.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+ IFile file = (IFile) bp.getMarker().getResource();
+ assertEquals(typeName + ".java", file.getName());
+
+ IJavaThread thread = null;
+ try {
+ thread = launchToBreakpoint(typeName);
+ CompilationUnitEditor part = openEditorAndValidateStack(expectedMethod, frameNumber, file, thread);
+
+ JavaDebugHover hover = new JavaDebugHover();
+ hover.setEditor(part);
+
+ String variableName = "payloads";
+ int offset = part.getViewer().getDocument().get().lastIndexOf("System.out.println(this.payloads") + "System.out.println(this.".length();
+ IRegion region = new Region(offset, "payloads".length());
+ String text = selectAndReveal(part, hoverLine, region);
+ assertEquals(variableName, text);
+ IVariable info = (IVariable) sync(() -> hover.getHoverInfo2(part.getViewer(), region));
+
+ assertNotNull(info);
+ assertEquals("payloads", info.getName());
+ assertTrue("Not an array variable", info.getValue() instanceof IJavaArray);
+ } finally {
+ terminateAndRemove(thread);
+ removeAllBreakpoints();
+ }
+ }
+
+ public void testBug573547_insideLambda_onOuterScopeStaticVariable() throws Exception {
+ sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
+ final String typeName = "Bug573547";
+ final String expectedMethod = "lambda$0";
+ final int frameNumber = 6;
+ final int bpLine = 41;
+ final int hoverLine = 22;
+
+ IJavaBreakpoint bp = createLineBreakpoint(bpLine, "", typeName + ".java", typeName);
+ bp.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+ IFile file = (IFile) bp.getMarker().getResource();
+ assertEquals(typeName + ".java", file.getName());
+
+ IJavaThread thread = null;
+ try {
+ thread = launchToBreakpoint(typeName);
+ CompilationUnitEditor part = openEditorAndValidateStack(expectedMethod, frameNumber, file, thread);
+
+ JavaDebugHover hover = new JavaDebugHover();
+ hover.setEditor(part);
+
+ String variableName = "PAYLOADS";
+ int offset = part.getViewer().getDocument().get().lastIndexOf("private static String[] PAYLOADS") + "private static String[] ".length();
+ IRegion region = new Region(offset, "payloads".length());
+ String text = selectAndReveal(part, hoverLine, region);
+ assertEquals(variableName, text);
+ IVariable info = (IVariable) sync(() -> hover.getHoverInfo2(part.getViewer(), region));
+
+ assertNotNull(info);
+ assertEquals("PAYLOADS", info.getName());
+ assertTrue("Not an array variable", info.getValue() instanceof IJavaArray);
+ } finally {
+ terminateAndRemove(thread);
+ removeAllBreakpoints();
+ }
+ }
+
+ public void testBug573547_insideLambda_onOuterScopeMemberVariable_onLength() throws Exception {
+ sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
+ final String typeName = "Bug573547";
+ final String expectedMethod = "lambda$0";
+ final int frameNumber = 6;
+ final int bpLine = 41;
+ final int hoverLine = 38;
+
+ IJavaBreakpoint bp = createLineBreakpoint(bpLine, "", typeName + ".java", typeName);
+ bp.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+ IFile file = (IFile) bp.getMarker().getResource();
+ assertEquals(typeName + ".java", file.getName());
+
+ IJavaThread thread = null;
+ try {
+ thread = launchToBreakpoint(typeName);
+ CompilationUnitEditor part = openEditorAndValidateStack(expectedMethod, frameNumber, file, thread);
+
+ JavaDebugHover hover = new JavaDebugHover();
+ hover.setEditor(part);
+
+ String variableName = "length";
+ int offset = part.getViewer().getDocument().get().lastIndexOf("System.out.println(payloads.length")
+ + "System.out.println(payloads.".length();
+ IRegion region = new Region(offset, "length".length());
+ String text = selectAndReveal(part, hoverLine, region);
+ assertEquals(variableName, text);
+ IVariable info = (IVariable) sync(() -> hover.getHoverInfo2(part.getViewer(), region));
+
+ assertNotNull(info);
+ assertEquals("payloads.length", info.getName());
+ assertEquals("1", info.getValue().getValueString());
+ } finally {
+ terminateAndRemove(thread);
+ removeAllBreakpoints();
+ }
+ }
+
+ public void testBug573547_insideLambda_onOuterScopeMemberVariable_withThis_onLength() throws Exception {
+ sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
+ final String typeName = "Bug573547";
+ final String expectedMethod = "lambda$0";
+ final int frameNumber = 6;
+ final int bpLine = 41;
+ final int hoverLine = 37;
+
+ IJavaBreakpoint bp = createLineBreakpoint(bpLine, "", typeName + ".java", typeName);
+ bp.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+ IFile file = (IFile) bp.getMarker().getResource();
+ assertEquals(typeName + ".java", file.getName());
+
+ IJavaThread thread = null;
+ try {
+ thread = launchToBreakpoint(typeName);
+ CompilationUnitEditor part = openEditorAndValidateStack(expectedMethod, frameNumber, file, thread);
+
+ JavaDebugHover hover = new JavaDebugHover();
+ hover.setEditor(part);
+
+ String variableName = "length";
+ int offset = part.getViewer().getDocument().get().lastIndexOf("System.out.println(this.payloads.length")
+ + "System.out.println(this.payloads.".length();
+ IRegion region = new Region(offset, "length".length());
+ String text = selectAndReveal(part, hoverLine, region);
+ assertEquals(variableName, text);
+ IVariable info = (IVariable) sync(() -> hover.getHoverInfo2(part.getViewer(), region));
+
+ assertNotNull(info);
+ assertEquals("this.payloads.length", info.getName());
+ assertEquals("1", info.getValue().getValueString());
+ } finally {
+ terminateAndRemove(thread);
+ removeAllBreakpoints();
+ }
+ }
+
+ public void testBug573547_insideLambda_onOuterScopeLocalVariable_onLength() throws Exception {
+ sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
+ final String typeName = "Bug573547";
+ final String expectedMethod = "lambda$0";
+ final int frameNumber = 6;
+ final int bpLine = 41;
+ final int hoverLine = 36;
+
+ IJavaBreakpoint bp = createLineBreakpoint(bpLine, "", typeName + ".java", typeName);
+ bp.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+ IFile file = (IFile) bp.getMarker().getResource();
+ assertEquals(typeName + ".java", file.getName());
+
+ IJavaThread thread = null;
+ try {
+ thread = launchToBreakpoint(typeName);
+ CompilationUnitEditor part = openEditorAndValidateStack(expectedMethod, frameNumber, file, thread);
+
+ JavaDebugHover hover = new JavaDebugHover();
+ hover.setEditor(part);
+
+ String variableName = "length";
+ int offset = part.getViewer().getDocument().get().lastIndexOf("System.out.println(object.payloads.length")
+ + "System.out.println(object.payloads.".length();
+ IRegion region = new Region(offset, "length".length());
+ String text = selectAndReveal(part, hoverLine, region);
+ assertEquals(variableName, text);
+ IVariable info = (IVariable) sync(() -> hover.getHoverInfo2(part.getViewer(), region));
+
+ assertNotNull(info);
+ assertEquals("object.payloads.length", info.getName());
+ assertEquals("1", info.getValue().getValueString());
+ } finally {
+ terminateAndRemove(thread);
+ removeAllBreakpoints();
+ }
+ }
+
+ public void testBug573547_insideLambda_onOuterScopeVariable_whileOnPreviousFrame() throws Exception {
+ sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
+ final String typeName = "Bug573547";
+ final String expectedMethod = "lambda$0";
+ final int frameNumber = 6;
+ final int bpLine = 41;
+ final int hoverLine = 36;
+
+ IJavaBreakpoint bp = createLineBreakpoint(bpLine, "", typeName + ".java", typeName);
+ bp.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+ IFile file = (IFile) bp.getMarker().getResource();
+ assertEquals(typeName + ".java", file.getName());
+
+ IJavaThread thread = null;
+ try {
+ thread = launchToBreakpoint(typeName);
+ CompilationUnitEditor part = openEditorAndValidateStack(expectedMethod, frameNumber, file, thread);
+
+ selectFrame(thread.getStackFrames()[4]);
+
+ JavaDebugHover hover = new JavaDebugHover();
+ hover.setEditor(part);
+
+ String variableName = "object";
+ int offset = part.getViewer().getDocument().get().lastIndexOf("/*Root*/System.out.println(object")
+ + "/*Root*/System.out.println(".length();
+ IRegion region = new Region(offset, "object".length());
+ String text = selectAndReveal(part, hoverLine, region);
+ assertEquals(variableName, text);
+ IVariable info = (IVariable) sync(() -> hover.getHoverInfo2(part.getViewer(), region));
+
+ assertNotNull(info);
+ assertEquals("object", info.getName());
+ assertEquals("Bug573547", info.getValue().getReferenceTypeName());
+ } finally {
+ terminateAndRemove(thread);
+ removeAllBreakpoints();
+ }
+ }
+
+ public void testBug573547_inNestedMethodInvocation_useCorrectFrameForSelectedVariable() throws Exception {
+ sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
+ final String typeName = "Bug573547";
+ final String expectedMethod = "nestedHover";
+ final int frameNumber = 3;
+ final int bpLine = 48;
+ final int hoverLine = 48;
+
+ IJavaBreakpoint bp = createLineBreakpoint(bpLine, "", typeName + ".java", typeName);
+ bp.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+ IFile file = (IFile) bp.getMarker().getResource();
+ assertEquals(typeName + ".java", file.getName());
+
+ IJavaThread thread = null;
+ try {
+ thread = launchToBreakpoint(typeName);
+ CompilationUnitEditor part = openEditorAndValidateStack(expectedMethod, frameNumber, file, thread);
+ JavaDebugHover hover = new JavaDebugHover();
+ hover.setEditor(part);
+
+ String variableName = "object";
+ int offset = part.getViewer().getDocument().get().lastIndexOf("/*Nested1*/System.out.println(object")
+ + "/*Nested1*/System.out.println(".length();
+ IRegion region = new Region(offset, "object".length());
+ String text = selectAndReveal(part, hoverLine, region);
+ assertEquals(variableName, text);
+ IVariable info = (IVariable) sync(() -> hover.getHoverInfo2(part.getViewer(), region));
+
+ assertNotNull(info);
+ assertEquals("object", info.getName());
+ assertEquals("1234", info.getValue().getValueString());
+ } finally {
+ terminateAndRemove(thread);
+ removeAllBreakpoints();
+ }
+ }
+
+ public void testBug573547_onVariableOutOfExecutionStack_expectNoHoverInfo() throws Exception {
+ sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
+ final String typeName = "Bug573547";
+ final String expectedMethod = "nestedHover";
+ final int frameNumber = 3;
+ final int bpLine = 48;
+ final int hoverLine = 60;
+
+ IJavaBreakpoint bp = createLineBreakpoint(bpLine, "", typeName + ".java", typeName);
+ bp.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+ IFile file = (IFile) bp.getMarker().getResource();
+ assertEquals(typeName + ".java", file.getName());
+
+ IJavaThread thread = null;
+ try {
+ thread = launchToBreakpoint(typeName);
+ CompilationUnitEditor part = openEditorAndValidateStack(expectedMethod, frameNumber, file, thread);
+ JavaDebugHover hover = new JavaDebugHover();
+ hover.setEditor(part);
+
+ String variableName = "object";
+ int offset = part.getViewer().getDocument().get().lastIndexOf("/*Nested2*/System.out.println(object")
+ + "/*Nested2*/System.out.println(".length();
+ IRegion region = new Region(offset, "object".length());
+ String text = selectAndReveal(part, hoverLine, region);
+ assertEquals(variableName, text);
+ IVariable info = (IVariable) sync(() -> hover.getHoverInfo2(part.getViewer(), region));
+
+ assertNull(info);
+ } finally {
+ terminateAndRemove(thread);
+ removeAllBreakpoints();
+ }
+ }
+
+ public void testBug573547_inNestedMethodInvocation_inNestedClasses_useCorrectFrameForSelectedVariables() throws Exception {
+ sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
+ final String typeName = "Bug573547";
+ final String expectedMethod = "nestedHover";
+ final int frameNumber = 4;
+ final int bpLine = 60;
+ final int hoverLineVar = 60;
+ final int hoverLineField = 56;
+
+ IJavaBreakpoint bp = createLineBreakpoint(bpLine, "", typeName + ".java", typeName);
+ bp.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+ IFile file = (IFile) bp.getMarker().getResource();
+ assertEquals(typeName + ".java", file.getName());
+
+ IJavaThread thread = null;
+ try {
+ thread = launchToBreakpoint(typeName);
+ CompilationUnitEditor part = openEditorAndValidateStack(expectedMethod, frameNumber, file, thread);
+ JavaDebugHover hover = new JavaDebugHover();
+ hover.setEditor(part);
+
+ // local variable
+ String variableNameVar = "object";
+ int offsetVar = part.getViewer().getDocument().get().lastIndexOf("/*Nested2*/System.out.println(object")
+ + "/*Nested1*/System.out.println(".length();
+ IRegion regionVar = new Region(offsetVar, "object".length());
+ String textVar = selectAndReveal(part, hoverLineVar, regionVar);
+ assertEquals(variableNameVar, textVar);
+ IVariable infoVar = (IVariable) sync(() -> hover.getHoverInfo2(part.getViewer(), regionVar));
+
+ assertNotNull(infoVar);
+ assertEquals("object", infoVar.getName());
+ assertEquals("1234n", infoVar.getValue().getValueString());
+
+ // field
+ String variableNameField = "payload";
+ int offsetField = part.getViewer().getDocument().get().lastIndexOf("/*Nested2*/private String payload")
+ + "/*Nested2*/private String ".length();
+ IRegion regionField = new Region(offsetField, "payload".length());
+ String textField = selectAndReveal(part, hoverLineField, regionField);
+ assertEquals(variableNameField, textField);
+ IVariable infoField = (IVariable) sync(() -> hover.getHoverInfo2(part.getViewer(), regionField));
+
+ assertNotNull(infoField);
+ assertEquals("payload", infoField.getName());
+ assertEquals("np", infoField.getValue().getValueString());
+ } finally {
+ terminateAndRemove(thread);
+ removeAllBreakpoints();
+ }
+ }
+
private CompilationUnitEditor openEditorAndValidateStack(final String expectedMethod, final int expectedFramesNumber, IFile file, IJavaThread thread) throws Exception, DebugException {
// Let now all pending jobs proceed, ignore console jobs
sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
@@ -1021,6 +1453,23 @@ public class DebugHoverTests extends AbstractDebugUiTests {
return sync(() -> selection.getText());
}
+ private void selectFrame(IStackFrame frame) throws Exception {
+ LaunchView debugView = sync(() -> (LaunchView) getActivePage().findView(IDebugUIConstants.ID_DEBUG_VIEW));
+ assertNotNull("expected Debug View to be open", debugView);
+
+ TreeSelection selection = sync(() -> (TreeSelection) debugView.getViewer().getSelection());
+ TreePath path = selection.getPaths()[0];
+ TreePath newPath = path.getParentPath().createChildPath(frame);
+ TreeSelection newSelection = new TreeSelection(newPath);
+ sync(() -> debugView.getViewer().setSelection(newSelection, true));
+ processUiEvents(100);
+ }
+
+ @Override
+ protected boolean enableUIEventLoopProcessingInWaiter() {
+ return true;
+ }
+
public void testResolveIn2Lambdas() throws Exception {
sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugHover.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugHover.java
index 32ccf1613..3a1b53032 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugHover.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugHover.java
@@ -19,11 +19,13 @@ import java.util.Optional;
import java.util.StringJoiner;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
+import java.util.function.Predicate;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IVariable;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
@@ -63,6 +65,7 @@ import org.eclipse.jdt.debug.eval.IEvaluationListener;
import org.eclipse.jdt.debug.eval.IEvaluationResult;
import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
import org.eclipse.jdt.internal.debug.core.logicalstructures.JDIPlaceholderVariable;
+import org.eclipse.jdt.internal.debug.core.model.JDIThisVariable;
import org.eclipse.jdt.internal.debug.eval.ast.engine.ASTEvaluationEngine;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.text.java.hover.IJavaEditorTextHover;
@@ -80,7 +83,8 @@ import org.eclipse.ui.IEditorPart;
public class JavaDebugHover implements IJavaEditorTextHover, ITextHoverExtension, ITextHoverExtension2 {
- private IEditorPart fEditor;
+ private static final String THIS = "this"; //$NON-NLS-1$
+ private IEditorPart fEditor;
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.text.java.hover.IJavaEditorTextHover#setEditor(org.eclipse.ui.IEditorPart)
@@ -267,7 +271,7 @@ public class JavaDebugHover implements IJavaEditorTextHover, ITextHoverExtension
if (document != null) {
try {
String variableName= document.get(hoverRegion.getOffset(), hoverRegion.getLength());
- if (variableName.equals("this")) { //$NON-NLS-1$
+ if (variableName.equals(THIS)) {
try {
IJavaVariable variable = frame.findVariable(variableName);
if (variable != null) {
@@ -373,15 +377,15 @@ public class JavaDebugHover implements IJavaEditorTextHover, ITextHoverExtension
StructuralPropertyDescriptor locationInParent = node.getLocationInParent();
if (locationInParent == FieldAccess.NAME_PROPERTY) {
FieldAccess fieldAccess = (FieldAccess) node.getParent();
- if (fieldAccess.getExpression() instanceof ThisExpression) {
- variable = evaluateField(frame, field);
+ if (fieldAccess.getExpression() instanceof ThisExpression && !onArrayLength) {
+ variable = evaluateField(findFirstFrameForVariable(frame, forField(field)), field);
} else {
- variable = evaluateQualifiedNode(fieldAccess, frame, typeRoot.getJavaProject());
+ variable = evaluateQualifiedNode(fieldAccess, frame, typeRoot.getJavaProject(), forField(field));
}
} else if (locationInParent == QualifiedName.NAME_PROPERTY) {
- variable = evaluateQualifiedNode(node.getParent(), frame, typeRoot.getJavaProject());
+ variable = evaluateQualifiedNode(node.getParent(), frame, typeRoot.getJavaProject(), forField(field));
} else {
- variable = evaluateField(frame, field);
+ variable = evaluateField(findFirstFrameForVariable(frame, forField(field)), field);
}
}
}
@@ -391,6 +395,7 @@ public class JavaDebugHover implements IJavaEditorTextHover, ITextHoverExtension
break;
}
if (javaElement instanceof ILocalVariable) {
+ ILocalVariable var = (ILocalVariable) javaElement;
// if we are on a array, regardless where we are send it to evaluation engine
if (onArrayLength) {
if (!(codeAssist instanceof ITypeRoot)) {
@@ -401,10 +406,9 @@ public class JavaDebugHover implements IJavaEditorTextHover, ITextHoverExtension
if (node == null) {
return null;
}
- return evaluateQualifiedNode(node.getParent(), frame, typeRoot.getJavaProject());
+ return evaluateQualifiedNode(node.getParent(), frame, typeRoot.getJavaProject(), forLocalVariable(var));
}
- ILocalVariable var = (ILocalVariable)javaElement;
IJavaElement parent = var.getParent();
while (!(parent instanceof IMethod) && !(parent instanceof IInitializer) && parent != null) {
parent = parent.getParent();
@@ -462,7 +466,7 @@ public class JavaDebugHover implements IJavaEditorTextHover, ITextHoverExtension
}
// find variable if equal or method is a Lambda Method
if (equal || method.isLambdaMethod()) {
- return findLocalVariable(frame, var.getElementName());
+ return findLocalVariable(findFirstFrameForVariable(frame, forLocalVariable(var)), var.getElementName());
}
}
break;
@@ -530,7 +534,7 @@ public class JavaDebugHover implements IJavaEditorTextHover, ITextHoverExtension
return null;
}
- private IJavaVariable evaluateQualifiedNode(ASTNode node, IJavaStackFrame frame, IJavaProject project) {
+ private IJavaVariable evaluateQualifiedNode(ASTNode node, IJavaStackFrame frame, IJavaProject project, Predicate<IJavaStackFrame> framePredicate) {
StringBuilder snippetBuilder = new StringBuilder();
if (node instanceof QualifiedName) {
snippetBuilder.append(((QualifiedName) node).getFullyQualifiedName());
@@ -545,7 +549,7 @@ public class JavaDebugHover implements IJavaEditorTextHover, ITextHoverExtension
@Override
public boolean visit(ThisExpression node) {
- segments.add("this"); //$NON-NLS-1$
+ segments.add(THIS);
return true;
}
@@ -556,6 +560,7 @@ public class JavaDebugHover implements IJavaEditorTextHover, ITextHoverExtension
}
final String snippet = snippetBuilder.toString();
+
class Evaluator implements IEvaluationListener {
private CompletableFuture<IEvaluationResult> result = new CompletableFuture<>();
@@ -566,7 +571,7 @@ public class JavaDebugHover implements IJavaEditorTextHover, ITextHoverExtension
public void run() throws DebugException {
IAstEvaluationEngine engine = JDIDebugPlugin.getDefault().getEvaluationEngine(project, (IJavaDebugTarget) frame.getDebugTarget());
- engine.evaluate(snippet, frame, this, DebugEvent.EVALUATION_IMPLICIT, false);
+ engine.evaluate(snippet, findFirstFrameForVariable(frame, framePredicate), this, DebugEvent.EVALUATION_IMPLICIT, false);
}
public Optional<IEvaluationResult> getResult() {
@@ -593,4 +598,64 @@ public class JavaDebugHover implements IJavaEditorTextHover, ITextHoverExtension
public IInformationControlCreator getInformationPresenterControlCreator() {
return new ExpressionInformationControlCreator();
}
+
+ private static IJavaStackFrame findFirstFrameForVariable(IJavaStackFrame currentFrame, Predicate<IJavaStackFrame> framePredicate) throws DebugException {
+ // check the current frame first
+ if (framePredicate.test(currentFrame)) {
+ return currentFrame;
+ }
+
+ for (IStackFrame stackFrame : currentFrame.getThread().getStackFrames()) {
+ IJavaStackFrame javaStackFrame = (IJavaStackFrame) stackFrame;
+ if (currentFrame != javaStackFrame && framePredicate.test(javaStackFrame)) {
+ return javaStackFrame;
+ }
+ }
+
+ // we couldn't find a frame, so return the current frame, this is highly unlikely we endup here.
+ return currentFrame;
+ }
+
+ private static boolean containsVariable(IStackFrame frame, String variableName) throws DebugException {
+ for (IVariable variable : frame.getVariables()) {
+ if (variable instanceof JDIThisVariable) {
+ for (IVariable fieldVar : variable.getValue().getVariables()) {
+ if (variableName.equals(fieldVar.getName())) {
+ return true;
+ }
+ }
+ } else if (variableName.equals(variable.getName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // the following two predicates will make sure to find correct frame according the java element's enclosing parent.
+ private static Predicate<IJavaStackFrame> forLocalVariable(ILocalVariable variable) {
+ return frame -> {
+ try {
+ return variable.getDeclaringMember() != null && variable.getDeclaringMember().getElementName().equals(frame.getMethodName())
+ && containsVariable(frame, variable.getElementName());
+ } catch (DebugException e) {
+ JDIDebugUIPlugin.log(e);
+ return false;
+ }
+ };
+
+ }
+
+ private static Predicate<IJavaStackFrame> forField(IField field) {
+ return frame -> {
+ try {
+ return frame.getThis() != null && frame.getThis().getJavaType().getName().equals(field.getDeclaringType().getFullyQualifiedName())
+ && containsVariable(frame, field.getElementName());
+ } catch (DebugException e) {
+ JDIDebugUIPlugin.log(e);
+ return false;
+ }
+ };
+
+ }
+
}
diff --git a/org.eclipse.jdt.debug/.settings/.api_filters b/org.eclipse.jdt.debug/.settings/.api_filters
new file mode 100644
index 000000000..87ceb52a6
--- /dev/null
+++ b/org.eclipse.jdt.debug/.settings/.api_filters
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<component id="org.eclipse.jdt.debug" version="2">
+ <resource path="META-INF/MANIFEST.MF">
+ <filter comment="Reverted bug 574170" id="926941240">
+ <message_arguments>
+ <message_argument value="3.18.0"/>
+ <message_argument value="3.17.200"/>
+ </message_arguments>
+ </filter>
+ </resource>
+</component>
diff --git a/org.eclipse.jdt.debug/META-INF/MANIFEST.MF b/org.eclipse.jdt.debug/META-INF/MANIFEST.MF
index d7c6bff6c..ad977cfc0 100644
--- a/org.eclipse.jdt.debug/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.debug/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jdt.debug; singleton:=true
-Bundle-Version: 3.17.300.qualifier
+Bundle-Version: 3.18.0.qualifier
Bundle-ClassPath: jdimodel.jar
Bundle-Activator: org.eclipse.jdt.internal.debug.core.JDIDebugPlugin
Bundle-Vendor: %providerName
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 d9dc4ae48..dc3a3eef3 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
@@ -41,6 +41,7 @@ import org.eclipse.debug.core.model.ITerminate;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.core.model.IVariable;
import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.IProblem;
@@ -62,6 +63,7 @@ import org.eclipse.jdt.debug.eval.IAstEvaluationEngine;
import org.eclipse.jdt.debug.eval.ICompiledExpression;
import org.eclipse.jdt.debug.eval.IEvaluationListener;
import org.eclipse.jdt.debug.eval.IEvaluationResult;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.debug.core.JDIDebugOptions;
import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
import org.eclipse.jdt.internal.debug.core.logicalstructures.JDILambdaVariable;
@@ -384,10 +386,16 @@ public class ASTEvaluationEngine implements IAstEvaluationEngine {
// frame.getThis().getJavaType();
// }
+ Map<String, String> extraOptions = Collections.emptyMap();
+ // if target runtime is above java 1.8 then switch the compiler to debug mode to ignore java 9 module system
+ if (JavaCore.compareJavaVersions(((IJavaDebugTarget) frame.getDebugTarget()).getVersion(), JavaCore.VERSION_1_8) > 0) {
+ extraOptions = Collections.singletonMap(CompilerOptions.OPTION_JdtDebugCompileMode, JavaCore.ENABLED);
+ }
+
unit = parseCompilationUnit(
mapper.getSource(receivingType, frame.getLineNumber(), javaProject,
frame.isStatic()).toCharArray(),
- mapper.getCompilationUnitName(), javaProject);
+ mapper.getCompilationUnitName(), javaProject, extraOptions);
} catch (CoreException e) {
InstructionSequence expression = new InstructionSequence(snippet);
expression.addError(e.getStatus().getMessage());
diff --git a/org.eclipse.jdt.debug/pom.xml b/org.eclipse.jdt.debug/pom.xml
index 99fb860dc..b18485312 100644
--- a/org.eclipse.jdt.debug/pom.xml
+++ b/org.eclipse.jdt.debug/pom.xml
@@ -18,6 +18,6 @@
</parent>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.debug</artifactId>
- <version>3.17.300-SNAPSHOT</version>
+ <version>3.18.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
index b9f2d8a06..1cd98630d 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
@@ -1679,13 +1679,13 @@ public final class JavaRuntime {
} else {
// Add all entries except the one from JRE itself
IPackageFragmentRoot jreContainer = findJreContainer(project);
- IPath canonicalJrePath = jreContainer != null ? JavaProject.canonicalizedPath(jreContainer.getPath()) : null;
+ IPath jrePath = jreContainer != null ? jreContainer.getPath() : null;
for (IRuntimeClasspathEntry entry : entries1) {
switch (entry.getClasspathEntry().getEntryKind()) {
case IClasspathEntry.CPE_LIBRARY:
if (!entry.getPath().lastSegment().contains("jrt-fs.jar") //$NON-NLS-1$
- && (canonicalJrePath == null || !canonicalJrePath.equals(JavaProject.canonicalizedPath(entry.getPath())))) {
+ && (jrePath == null || !jrePath.equals(entry.getPath()))) {
entries2.add(entry);
}
break;
diff --git a/pom.xml b/pom.xml
index 7daf1601f..8308b92a0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,7 +24,7 @@
<packaging>pom</packaging>
<properties>
- <tycho.scmUrl>scm:git:git://git.eclipse.org/gitroot/jdt/eclipse.jdt.debug.git</tycho.scmUrl>
+ <tycho.scmUrl>scm:git:https://git.eclipse.org/r/jdt/eclipse.jdt.debug.git</tycho.scmUrl>
</properties>
<!--

Back to the top