diff options
author | Sarika Sinha | 2021-08-17 09:05:11 +0000 |
---|---|---|
committer | Sarika Sinha | 2021-08-17 10:28:55 +0000 |
commit | fbbababc23b6aaff5eb1887fd8d01c8a11c6a324 (patch) | |
tree | 59399fcbbb6cff2d02c53a30daa0b5cfe60e17f6 | |
parent | 2f8db6460f84b5e3a4e8e896c775a15033046a58 (diff) | |
parent | 14ccbcea70acbd8dfe9fef53140df158fc5060db (diff) | |
download | eclipse.jdt.debug-fbbababc23b6aaff5eb1887fd8d01c8a11c6a324.tar.gz eclipse.jdt.debug-fbbababc23b6aaff5eb1887fd8d01c8a11c6a324.tar.xz eclipse.jdt.debug-fbbababc23b6aaff5eb1887fd8d01c8a11c6a324.zip |
Bug 573521 : Merge remote-tracking branch 'origin/master' into BETA_JAVA17Y20210907-0830Y20210907-0800Y20210906-0920Y20210904-0800Y20210903-0800Y20210902-0850Y20210902-0350Y20210901-0420Y20210831-0840Y20210826-0800Y20210824-0940Y20210824-0840Y20210822-0440Y20210820-0230Y20210819-0800Y20210819-0340Y20210818-0520Y20210817-1030P20210907-0320P20210907-0250P20210831-0130P20210827-0040P20210825-0220P20210825-0200P20210820-1100
Change-Id: I7eda581a1e0ec7ccb9ebb11d233b7d8db2da4cff
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; @@ -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> <!-- |