Merge remote-tracking branch 'origin/master' into BETA_JAVA_12
diff --git a/org.eclipse.jdt.debug.tests/META-INF/MANIFEST.MF b/org.eclipse.jdt.debug.tests/META-INF/MANIFEST.MF
index 8a8c16a..138e475 100644
--- a/org.eclipse.jdt.debug.tests/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.debug.tests/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jdt.debug.tests; singleton:=true
-Bundle-Version: 3.11.300.qualifier
+Bundle-Version: 3.11.400.qualifier
Bundle-ClassPath: javadebugtests.jar
Bundle-Activator: org.eclipse.jdt.debug.testplugin.JavaTestPlugin
Bundle-Vendor: %providerName
diff --git a/org.eclipse.jdt.debug.tests/java8/Bug404097BreakpointInAnonymousLocalClass.java b/org.eclipse.jdt.debug.tests/java8/Bug404097BreakpointInAnonymousLocalClass.java
new file mode 100644
index 0000000..08b6a64
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/java8/Bug404097BreakpointInAnonymousLocalClass.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Simeon Andreev 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:
+ * Simeon Andreev - initial API and implementation
+ *******************************************************************************/
+
+import java.util.function.Consumer;
+
+public class Bug404097BreakpointInAnonymousLocalClass {
+
+ public static void breakpointMethod(final String methodParameter) {
+ // StringBuilder to make sure the compiler doesn't optimize "methodVariable" out of the compiled code.
+ final StringBuilder methodVariable = new StringBuilder("methodVariable");
+ Consumer<String> r = new Consumer<String>() {
+ public void accept(String lambdaParameter) {
+ String lambdaVariable = "lambdaVariable";
+ System.out.println("method parameter: " + methodParameter);
+ System.out.println("method variable: " + methodVariable);
+ System.out.println("lambda parameter: " + lambdaParameter);
+ System.out.println("lambda variable: " + lambdaVariable);
+ }
+ };
+ r.accept("lambdaParameter");
+ }
+
+ public static void main(String[] args) {
+ breakpointMethod("methodParameter");
+ }
+}
diff --git a/org.eclipse.jdt.debug.tests/java8/Bug404097BreakpointInLambda.java b/org.eclipse.jdt.debug.tests/java8/Bug404097BreakpointInLambda.java
new file mode 100644
index 0000000..158f975
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/java8/Bug404097BreakpointInLambda.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Simeon Andreev 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:
+ * Simeon Andreev - initial API and implementation
+ *******************************************************************************/
+
+import java.util.function.Consumer;
+
+public class Bug404097BreakpointInLambda {
+
+ public static void breakpointMethod(final String methodParameter) {
+ // StringBuilder to make sure the compiler doesn't optimize "methodVariable" out of the compiled code.
+ final StringBuilder methodVariable = new StringBuilder("methodVariable");
+ Consumer<String> r = lambdaParameter -> {
+ String lambdaVariable = "lambdaVariable";
+ System.out.println("method parameter: " + methodParameter);
+ System.out.println("method variable: " + methodVariable);
+ System.out.println("lambda parameter: " + lambdaParameter);
+ System.out.println("lambda variable: " + lambdaVariable);
+ };
+ r.accept("lambdaParameter");
+ }
+
+ public static void main(String[] args) {
+ breakpointMethod("methodParameter");
+ }
+}
diff --git a/org.eclipse.jdt.debug.tests/java8/Bug404097BreakpointInLocalClass.java b/org.eclipse.jdt.debug.tests/java8/Bug404097BreakpointInLocalClass.java
new file mode 100644
index 0000000..029692c
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/java8/Bug404097BreakpointInLocalClass.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Simeon Andreev 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:
+ * Simeon Andreev - initial API and implementation
+ *******************************************************************************/
+
+import java.util.function.Consumer;
+
+public class Bug404097BreakpointInLocalClass {
+
+ public static void breakpointMethod(final String methodParameter) {
+ // StringBuilder to make sure the compiler doesn't optimize "methodVariable" out of the compiled code.
+ final StringBuilder methodVariable = new StringBuilder("methodVariable");
+ class SomeConsumer implements Consumer<String> {
+ public void accept(String lambdaParameter) {
+ String lambdaVariable = "lambdaVariable";
+ System.out.println("method parameter: " + methodParameter);
+ System.out.println("method variable: " + methodVariable);
+ System.out.println("lambda parameter: " + lambdaParameter);
+ System.out.println("lambda variable: " + lambdaVariable);
+ }
+ };
+ Consumer<String> r = new SomeConsumer();
+ r.accept("lambdaParameter");
+ }
+
+ public static void main(String[] args) {
+ breakpointMethod("methodParameter");
+ }
+}
diff --git a/org.eclipse.jdt.debug.tests/java8/Bug404097BreakpointUsingInnerClass.java b/org.eclipse.jdt.debug.tests/java8/Bug404097BreakpointUsingInnerClass.java
new file mode 100644
index 0000000..224a73c
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/java8/Bug404097BreakpointUsingInnerClass.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Simeon Andreev 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:
+ * Simeon Andreev - initial API and implementation
+ *******************************************************************************/
+
+public class Bug404097BreakpointUsingInnerClass {
+
+ static class InnerClass {
+ int i;
+ }
+
+ public static void breakpointMethod() {
+ InnerClass object = new InnerClass();
+ object.i = 0;
+ System.out.println(object.i);
+ }
+
+ public static void main(String[] args) {
+ breakpointMethod();
+ }
+}
diff --git a/org.eclipse.jdt.debug.tests/java8/Bug404097BreakpointUsingLocalClass.java b/org.eclipse.jdt.debug.tests/java8/Bug404097BreakpointUsingLocalClass.java
new file mode 100644
index 0000000..10b84b6
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/java8/Bug404097BreakpointUsingLocalClass.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Simeon Andreev 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:
+ * Simeon Andreev - initial API and implementation
+ *******************************************************************************/
+
+public class Bug404097BreakpointUsingLocalClass {
+
+ public static void breakpointMethod() {
+ class LocalClass {
+ int i;
+ }
+ LocalClass object = new LocalClass();
+ object.i = 0;
+ System.out.println(object.i);
+ }
+
+ public static void main(String[] args) {
+ breakpointMethod();
+ }
+}
diff --git a/org.eclipse.jdt.debug.tests/java8/ClosureVariableTest_Bug542989.java b/org.eclipse.jdt.debug.tests/java8/ClosureVariableTest_Bug542989.java
new file mode 100644
index 0000000..5a24fae
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/java8/ClosureVariableTest_Bug542989.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2019 IBM Corporation 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:
+ * Paul Pazderski - initial API and implementation
+ *******************************************************************************/
+public class ClosureVariableTest_Bug542989 {
+ public static void main(String[] args) {
+ java.io.PrintStream out = System.out;
+ java.util.function.Consumer<String> printer = (msg) -> {
+ out.println(msg); //set breakpoint here
+ };
+ printer.accept("Hallo World!");
+ }
+}
diff --git a/org.eclipse.jdt.debug.tests/pom.xml b/org.eclipse.jdt.debug.tests/pom.xml
index 47c0287..88b3780 100644
--- a/org.eclipse.jdt.debug.tests/pom.xml
+++ b/org.eclipse.jdt.debug.tests/pom.xml
@@ -18,7 +18,7 @@
</parent>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.debug.tests</artifactId>
- <version>3.11.300-SNAPSHOT</version>
+ <version>3.11.400-SNAPSHOT</version>
<packaging>eclipse-test-plugin</packaging>
<properties>
<code.ignoredWarnings>${tests.ignoredWarnings}</code.ignoredWarnings>
diff --git a/org.eclipse.jdt.debug.tests/testprograms/Bug540243.java b/org.eclipse.jdt.debug.tests/testprograms/Bug540243.java
new file mode 100644
index 0000000..ed31664
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/testprograms/Bug540243.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Simeon Andreev 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:
+ * Simeon Andreev - initial API and implementation
+ *******************************************************************************/
+
+public class Bug540243 {
+
+ public static void main(String[] args) throws InterruptedException {
+ Thread t = new Thread(new Runnable() {
+ // method must be synchronized, so that the thread owns a monitor
+ public synchronized void run() {
+ breakpointMethod();
+ }
+ });
+ t.start();
+ t.join();
+ }
+
+ public static void breakpointMethod() {
+ System.out.println("set a breakpoint here");
+ }
+}
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 2eed4e0..874c9a3 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
@@ -193,7 +193,7 @@
public static final String CLONE_SUFFIX = "Clone";
final String[] LAUNCH_CONFIG_NAMES_1_4 = {"LargeSourceFile", "LotsOfFields", "Breakpoints", "InstanceVariablesTests", "LocalVariablesTests", "LocalVariableTests2", "StaticVariablesTests",
- "DropTests", "ThrowsNPE", "ThrowsException", "org.eclipse.debug.tests.targets.Watchpoint",
+ "DropTests", "ThrowsNPE", "ThrowsException", "org.eclipse.debug.tests.targets.Watchpoint",
"org.eclipse.debug.tests.targets.BreakpointsLocationBug344984", "org.eclipse.debug.tests.targets.CallLoop", "A",
"HitCountLooper", "CompileError", "MultiThreadedLoop", "HitCountException", "MultiThreadedException", "MultiThreadedList", "MethodLoop", "StepFilterOne",
"StepFilterFour", "EvalArrayTests", "EvalSimpleTests", "EvalTypeTests", "EvalNestedTypeTests", "EvalTypeHierarchyTests",
@@ -207,7 +207,7 @@
"org.eclipse.debug.tests.targets.HcrClass5", "org.eclipse.debug.tests.targets.HcrClass6", "org.eclipse.debug.tests.targets.HcrClass7", "org.eclipse.debug.tests.targets.HcrClass8",
"org.eclipse.debug.tests.targets.HcrClass9", "TestContributedStepFilterClass", "TerminateAll_01", "TerminateAll_02", "StepResult1",
"StepResult2", "StepResult3", "StepUncaught", "TriggerPoint_01", "BulkThreadCreationTest", "MethodExitAndException",
- "Bug534319earlyStart", "Bug534319lateStart", "Bug534319singleThread", "Bug534319startBetwen", "MethodCall", "Bug538303" };
+ "Bug534319earlyStart", "Bug534319lateStart", "Bug534319singleThread", "Bug534319startBetwen", "MethodCall", "Bug538303", "Bug540243" };
/**
* the default timeout
@@ -470,6 +470,12 @@
cfgs.add(createLaunchConfiguration(jp, "EvalIntfSuperDefault"));
cfgs.add(createLaunchConfiguration(jp, "DebugHoverTest18"));
cfgs.add(createLaunchConfiguration(jp, "Bug541110"));
+ cfgs.add(createLaunchConfiguration(jp, "ClosureVariableTest_Bug542989"));
+ cfgs.add(createLaunchConfiguration(jp, "Bug404097BreakpointInLocalClass"));
+ cfgs.add(createLaunchConfiguration(jp, "Bug404097BreakpointInAnonymousLocalClass"));
+ cfgs.add(createLaunchConfiguration(jp, "Bug404097BreakpointInLambda"));
+ cfgs.add(createLaunchConfiguration(jp, "Bug404097BreakpointUsingInnerClass"));
+ cfgs.add(createLaunchConfiguration(jp, "Bug404097BreakpointUsingLocalClass"));
loaded18 = 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 7ef5057..1828248 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
@@ -23,6 +23,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.ConditionalBreakpointsInJava8Tests;
import org.eclipse.jdt.debug.tests.breakpoints.ConditionalBreakpointsTests;
import org.eclipse.jdt.debug.tests.breakpoints.ConditionalBreakpointsWithGenerics;
import org.eclipse.jdt.debug.tests.breakpoints.DeferredBreakpointTests;
@@ -131,6 +132,7 @@
import org.eclipse.jdt.debug.tests.ui.OpenFromClipboardTests;
import org.eclipse.jdt.debug.tests.ui.ViewManagementTests;
import org.eclipse.jdt.debug.tests.ui.presentation.ModelPresentationTests;
+import org.eclipse.jdt.debug.tests.ui.presentation.ModelPresentationTests18;
import org.eclipse.jdt.debug.tests.variables.DetailFormatterTests;
import org.eclipse.jdt.debug.tests.variables.TestAnonymousInspect;
import org.eclipse.jdt.debug.tests.variables.TestInstanceRetrieval;
@@ -347,6 +349,8 @@
if (JavaProjectHelper.isJava8Compatible()) {
addTest(new TestSuite(TestToggleBreakpointsTarget8.class));
+ addTest(new TestSuite(ModelPresentationTests18.class));
+ addTest(new TestSuite(ConditionalBreakpointsInJava8Tests.class));
}
if (JavaProjectHelper.isJava5Compatible()) {
addTest(new TestSuite(MethodBreakpointTests15.class));
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/ConditionalBreakpointsInJava8Tests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/ConditionalBreakpointsInJava8Tests.java
new file mode 100644
index 0000000..2f967cf
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/ConditionalBreakpointsInJava8Tests.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Simeon Andreev 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:
+ * Simeon Andreev - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.debug.tests.breakpoints;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.internal.ui.views.console.ProcessConsole;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.debug.core.IJavaDebugTarget;
+import org.eclipse.jdt.debug.testplugin.DebugEventWaiter;
+import org.eclipse.jdt.debug.tests.AbstractDebugTest;
+import org.eclipse.jdt.debug.tests.TestUtil;
+
+/**
+ * Tests conditional breakpoints.
+ */
+public class ConditionalBreakpointsInJava8Tests extends AbstractDebugTest {
+
+ public ConditionalBreakpointsInJava8Tests(String name) {
+ super(name);
+ }
+
+ @Override
+ protected IJavaProject getProjectContext() {
+ return get18Project();
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ assertNoErrorMarkersExist();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ terminateAndRemoveJavaLaunches();
+ removeAllBreakpoints();
+ super.tearDown();
+ }
+
+ /**
+ * Test for Bug 541110 - ClassCastException in Instruction.popValue and a zombie EventDispatcher$1 job afterwards
+ *
+ * We check that a specific conditional breakpoint on a line with a lambda expression does not cause a {@link ClassCastException}.
+ */
+ public void testBug541110() throws Exception {
+ String typeName = "Bug541110";
+ String breakpointCondition = "map.get(key) != null";
+ int breakpointLineNumber = 22;
+
+ // The class cast exception causes a job which runs forever. So we will timeout when waiting for debug events, if the exception occurs.
+ assertNoBreakpointHit(typeName, breakpointLineNumber, breakpointCondition);
+ }
+
+ /**
+ * Test for Bug 541110 - Cannot display or set conditional breakpoint using local class reference or field
+ *
+ * We check that a conditional breakpoint inside a locally defined anonymous class can access visbile variables.
+ */
+ public void testBug404097BreakpointInAnonymousLocalClass() throws Exception {
+ String typeName = "Bug404097BreakpointInAnonymousLocalClass";
+ int breakpointLineNumber = 25;
+ doTestVariableVisibility(typeName, breakpointLineNumber);
+ }
+
+ /**
+ * Test for Bug 541110 - Cannot display or set conditional breakpoint using local class reference or field
+ *
+ * We check that a conditional breakpoint inside a lambda can access visible variables.
+ */
+ public void testBug404097BreakpointInLambda() throws Exception {
+ String typeName = "Bug404097BreakpointInLambda";
+ int breakpointLineNumber = 24;
+ doTestVariableVisibility(typeName, breakpointLineNumber);
+ }
+
+ /**
+ * Test for Bug 541110 - Cannot display or set conditional breakpoint using local class reference or field
+ *
+ * We check that a conditional breakpoint inside a locally defined class can access visible variables.
+ */
+ public void testBug404097BreakpointInLocalClass() throws Exception {
+ String typeName = "Bug404097BreakpointInLocalClass";
+ int breakpointLineNumber = 25;
+ doTestVariableVisibility(typeName, breakpointLineNumber);
+ }
+
+ /**
+ * Test for Bug 541110 - Cannot display or set conditional breakpoint using local class reference or field
+ *
+ * We check that a conditional breakpoint can access members of a static inner class.
+ */
+ public void testBug404097BreakpointUsingInnerClass() throws Exception {
+ String typeName = "Bug404097BreakpointUsingInnerClass";
+ int breakpointLineNumber = 24;
+ doTestClassMemberVisibility(typeName, breakpointLineNumber);
+ }
+
+ /**
+ * Test for Bug 541110 - Cannot display or set conditional breakpoint using local class reference or field
+ *
+ * We check that a conditional breakpoint can access members of a class which is defined locally.
+ *
+ * TODO: disabled until a fix is available
+ */
+ public void disabled_testBug404097BreakpointUsingLocalClass() throws Exception {
+ String typeName = "Bug404097BreakpointUsingLocalClass";
+ int breakpointLineNumber = 23;
+ doTestClassMemberVisibility(typeName, breakpointLineNumber);
+ }
+
+ private void doTestVariableVisibility(String typeName, int breakpointLineNumber) throws Exception {
+ /*
+ * We create a condition which does not evaluate to true and expect to not hit the breakpoint.
+ * If condition evaluation runs into a compile error, either the breakpoint becomes unconditional and is therefore always hit.
+ */
+ String breakpointCondition = String.join(" || ", Arrays.asList(
+ "!\"methodParameter\".equals(methodParameter)",
+ "methodVariable == null", "!\"methodVariable\".equals(methodVariable.toString())",
+ "!\"lambdaParameter\".equals(lambdaParameter)",
+ "!\"lambdaVariable\".equals(lambdaVariable)"));
+ assertNoBreakpointHit(typeName, breakpointLineNumber, breakpointCondition);
+ }
+
+ private void doTestClassMemberVisibility(String typeName, int breakpointLineNumber) throws Exception {
+ /*
+ * We create a condition which does not evaluate to true and expect to not hit the breakpoint. If condition evaluation runs into a compile
+ * error, the breakpoint becomes unconditional and is therefore always hit.
+ */
+ String breakpointCondition = "object.i != 0";
+ assertNoBreakpointHit(typeName, breakpointLineNumber, breakpointCondition);
+ }
+
+ private void assertNoBreakpointHit(String typeName, int breakpointLineNumber, String breakpointCondition) throws Exception {
+ boolean suspendOnTrue = true;
+ createConditionalLineBreakpoint(breakpointLineNumber, typeName, breakpointCondition, suspendOnTrue);
+ ILaunchConfiguration config = getLaunchConfiguration(typeName);
+ DebugEventWaiter waiter = new DebugTargetTerminateWaiter();
+ launchAndWait(config, waiter);
+ TestUtil.waitForJobs(getName(), 1_000, 30_000, ProcessConsole.class);
+
+ }
+
+ private void terminateAndRemoveJavaLaunches() {
+ ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
+ List<ILaunch> launches = Arrays.asList(launchManager.getLaunches());
+ for (ILaunch launch : launches) {
+ IDebugTarget debugTarget = launch.getDebugTarget();
+ if (debugTarget instanceof IJavaDebugTarget) {
+ terminateAndRemove((IJavaDebugTarget) debugTarget);
+ }
+ }
+ }
+
+ private static class DebugTargetTerminateWaiter extends DebugEventWaiter {
+
+ public DebugTargetTerminateWaiter() {
+ super(DebugEvent.TERMINATE);
+ }
+
+ @Override
+ public boolean accept(DebugEvent event) {
+ if (super.accept(event)) {
+ Object source = event.getSource();
+ return source instanceof IDebugTarget;
+ }
+ return false;
+ }
+ }
+}
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/LambdaBreakpointsTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/LambdaBreakpointsTests.java
deleted file mode 100644
index 6d9f336..0000000
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/LambdaBreakpointsTests.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2018 Simeon Andreev 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:
- * Simeon Andreev - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.debug.tests.breakpoints;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.eclipse.debug.core.DebugEvent;
-import org.eclipse.debug.core.DebugPlugin;
-import org.eclipse.debug.core.ILaunch;
-import org.eclipse.debug.core.ILaunchConfiguration;
-import org.eclipse.debug.core.ILaunchManager;
-import org.eclipse.debug.core.model.IDebugTarget;
-import org.eclipse.debug.internal.ui.views.console.ProcessConsole;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.debug.core.IJavaDebugTarget;
-import org.eclipse.jdt.debug.testplugin.DebugEventWaiter;
-import org.eclipse.jdt.debug.tests.AbstractDebugTest;
-import org.eclipse.jdt.debug.tests.TestUtil;
-
-/**
- * Tests conditional breakpoints.
- */
-public class LambdaBreakpointsTests extends AbstractDebugTest {
-
- /**
- * Constructor
- * @param name
- */
- public LambdaBreakpointsTests(String name) {
- super(name);
- }
-
- @Override
- protected IJavaProject getProjectContext() {
- return get18Project();
- }
-
-
- /**
- * Test for Bug 541110 - ClassCastException in Instruction.popValue and a zombie EventDispatcher$1 job afterwards
- *
- * We check that a specific conditional breakpoint on a line with a lambda expression does not cause a {@link ClassCastException}.
- */
- public void testBug541110() throws Exception {
- assertNoErrorMarkersExist();
-
- String typeName = "Bug541110";
- createConditionalLineBreakpoint(22, typeName, "map.get(key) != null", true);
-
- try {
- // The class cast exception causes a job which runs forever. So we will timeout when waiting for debug events, if the exception occurs.
- ILaunchConfiguration config = getLaunchConfiguration(typeName);
- DebugEventWaiter waiter = new DebugEventWaiter(DebugEvent.TERMINATE);
- launchAndWait(config, waiter);
- // Join running jobs in case the launch did go through, but we have the endless job.
- TestUtil.waitForJobs(getName(), 1_000, 30_000, ProcessConsole.class);
- } finally {
- terminateAndRemoveJavaLaunches();
- removeAllBreakpoints();
- }
- }
-
- private void terminateAndRemoveJavaLaunches() {
- ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
- List<ILaunch> launches = Arrays.asList(launchManager.getLaunches());
- for (ILaunch launch : launches) {
- IDebugTarget debugTarget = launch.getDebugTarget();
- if (debugTarget instanceof IJavaDebugTarget) {
- terminateAndRemove((IJavaDebugTarget) debugTarget);
- }
- }
- }
-}
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/AbstractDebugViewTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/AbstractDebugViewTests.java
index ac6f7ea..843f239 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/AbstractDebugViewTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/AbstractDebugViewTests.java
@@ -55,13 +55,15 @@
}
private LaunchView debugView;
- private boolean showMonitorsOriginal;
+ private Boolean showMonitorsOriginal;
+ private Boolean showSystemThreadsOriginal;
@Override
protected void setUp() throws Exception {
super.setUp();
IPreferenceStore jdiUIPreferences = JDIDebugUIPlugin.getDefault().getPreferenceStore();
showMonitorsOriginal = jdiUIPreferences.getBoolean(IJavaDebugUIConstants.PREF_SHOW_MONITOR_THREAD_INFO);
+ showSystemThreadsOriginal = jdiUIPreferences.getBoolean(IJavaDebugUIConstants.PREF_SHOW_SYSTEM_THREADS);
jdiUIPreferences.setValue(IJavaDebugUIConstants.PREF_SHOW_MONITOR_THREAD_INFO, true);
resetPerspective(DebugViewPerspectiveFactory.ID);
debugView = sync(() -> (LaunchView) getActivePage().showView(IDebugUIConstants.ID_DEBUG_VIEW));
@@ -72,6 +74,7 @@
protected void tearDown() throws Exception {
IPreferenceStore jdiUIPreferences = JDIDebugUIPlugin.getDefault().getPreferenceStore();
jdiUIPreferences.setValue(IJavaDebugUIConstants.PREF_SHOW_MONITOR_THREAD_INFO, showMonitorsOriginal);
+ jdiUIPreferences.setValue(IJavaDebugUIConstants.PREF_SHOW_SYSTEM_THREADS, showSystemThreadsOriginal);
sync(() -> getActivePage().closeAllEditors(false));
processUiEvents(100);
super.tearDown();
@@ -118,6 +121,7 @@
try {
thread = launchToBreakpoint(typeName, breakpointMethodName, expectedBreakpointHitsCount);
+ assertDebugViewIsOpen();
assertStackFrameIsSelected(breakpointMethodName);
} catch (AssertionError assertionError) {
failedAssertions.add(assertionError);
@@ -272,8 +276,13 @@
sync(() -> getActivePage().activate(debugView));
}
+ protected void assertDebugViewIsOpen() throws Exception {
+ debugView = sync(() -> (LaunchView) getActivePage().findView(IDebugUIConstants.ID_DEBUG_VIEW));
+ assertNotNull("expected Debug View to be open", debugView);
+ }
+
protected void assertDebugViewIsActive() throws Exception {
- assertEquals("expected Debug View to activate after resuming thread", debugView, sync(() -> getActivePage().getActivePart()));
+ assertEquals("expected Debug View to be activate", debugView, sync(() -> getActivePage().getActivePart()));
}
protected static class BreakpointWaiter extends DebugElementKindEventDetailWaiter {
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DebugViewTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DebugViewTests.java
index 779348d..ed315d8 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DebugViewTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DebugViewTests.java
@@ -17,9 +17,13 @@
import org.eclipse.core.runtime.Platform;
import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.tests.TestAgainException;
+import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants;
+import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
+import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.test.OrderedTestSuite;
import org.eclipse.ui.IViewPart;
@@ -194,6 +198,36 @@
}
/**
+ * Test for Bug 540243 - Wrong selection when first opening view due to breakpoint
+ *
+ * When hitting a breakpoint, if the Debug View is open at all, and we show Java thread owned monitors, its possible to see a wrong selection in
+ * the Debug View. To ensure this doesn't occur, this test does the following:
+ *
+ * <ol>
+ * <li>ensures the Debug View is showing owned monitors for threads</li>
+ * <li>close the Debug View</li>
+ * <li>create a Java snippet which starts a thread</li>
+ * <li>set a break point in the code executed by the thread</li>
+ * <li>debug the snippet until the break point is reached</li>
+ * <li>validate that the selection in the Debug View contains is exactly the method with a break point</li>
+ * </ol>
+ */
+ public void testWrongSelectionBug540243() throws Exception {
+ IPreferenceStore jdiUIPreferences = JDIDebugUIPlugin.getDefault().getPreferenceStore();
+ Boolean isShowingMonitorThreadInfo = jdiUIPreferences.getBoolean(IJavaDebugUIConstants.PREF_SHOW_MONITOR_THREAD_INFO);
+ assertNotNull("Preference to show thread owned monitors must be set but is not", isShowingMonitorThreadInfo);
+ assertTrue("Preference to show thread owned monitors must be enabled but is not", isShowingMonitorThreadInfo);
+
+ sync(() -> getActivePage().hideView(getActivePage().findView(IDebugUIConstants.ID_DEBUG_VIEW)));
+
+ int iterations = 1;
+ String typeName = "Bug540243";
+ String breakpointMethodName = "breakpointMethod";
+ int expectedBreakpointHitsCount = 1;
+ doTestWrongSelection(iterations, typeName, breakpointMethodName, expectedBreakpointHitsCount);
+ }
+
+ /**
* Test for Bug 534319 - Debug View shows wrong information due to threads with short lifetime
*
* We observe that e.g. starting new threads from the debugged JVM can cause incorrect selections in the Debug View. To assure this doesn't occur,
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/presentation/ModelPresentationTests18.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/presentation/ModelPresentationTests18.java
new file mode 100644
index 0000000..8592def
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/presentation/ModelPresentationTests18.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2019 IBM Corporation 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:
+ * Paul Pazderski - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.debug.tests.ui.presentation;
+
+import org.eclipse.debug.core.model.ILineBreakpoint;
+import org.eclipse.debug.core.model.IVariable;
+import org.eclipse.debug.ui.IDebugModelPresentation;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.debug.core.IJavaStackFrame;
+import org.eclipse.jdt.debug.core.IJavaThread;
+import org.eclipse.jdt.debug.tests.AbstractDebugTest;
+import org.eclipse.jdt.internal.debug.core.logicalstructures.JDILambdaVariable;
+import org.eclipse.jdt.internal.debug.core.model.LambdaUtils;
+import org.eclipse.jdt.internal.debug.ui.JDIModelPresentation;
+
+/**
+ * Tests for some of the methods of the model presentation requiring/using Java 1.8 features.
+ *
+ * @see JDIModelPresentation
+ * @see ModelPresentationTests
+ */
+public class ModelPresentationTests18 extends AbstractDebugTest {
+
+ /**
+ * Constructor
+ */
+ public ModelPresentationTests18() {
+ super("Model Presentation tests using Java 1.8 features");
+ }
+
+ @Override
+ protected IJavaProject getProjectContext() {
+ return get18Project();
+ }
+
+ /**
+ * Tests a closure/lambda variable text including variable type name.
+ *
+ * Test for Bug 542989.
+ *
+ * @throws Exception
+ */
+ public void testClosureVariableText() throws Exception {
+ String typeName = "ClosureVariableTest_Bug542989";
+ ILineBreakpoint bp = createLineBreakpoint(18, typeName);
+
+ JDIModelPresentation pres = new JDIModelPresentation();
+ IJavaThread thread = null;
+ try {
+ thread = launchToLineBreakpoint(typeName, bp);
+
+ IJavaStackFrame frame = (IJavaStackFrame) thread.getTopStackFrame();
+ assertTrue("Did not stopped in lambda context.", LambdaUtils.isLambdaFrame(frame));
+ String closureVariableName = new JDILambdaVariable(null).getName();
+ IVariable closure = findVariable(frame, closureVariableName);
+ assertNotNull("Could not find variable '" + closureVariableName + "'", closure);
+
+ pres.setAttribute(IDebugModelPresentation.DISPLAY_VARIABLE_TYPE_NAMES, Boolean.TRUE);
+ String text = pres.getText(closure);
+ assertNotNull(text);
+ } finally {
+ terminateAndRemove(thread);
+ removeAllBreakpoints();
+ pres.dispose();
+ }
+ }
+}
diff --git a/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF b/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF
index 08163ba..d57c604 100644
--- a/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jdt.debug.ui; singleton:=true
-Bundle-Version: 3.10.100.qualifier
+Bundle-Version: 3.10.200.qualifier
Bundle-Activator: org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
diff --git a/org.eclipse.jdt.debug.ui/plugin.xml b/org.eclipse.jdt.debug.ui/plugin.xml
index a680465..9f68823 100644
--- a/org.eclipse.jdt.debug.ui/plugin.xml
+++ b/org.eclipse.jdt.debug.ui/plugin.xml
@@ -1419,6 +1419,10 @@
name="PrimitiveVariableActionFilter"
value="isPrimitive">
</objectState>
+ <objectState
+ name="JavaVariableFilter"
+ value="isObjectValue">
+ </objectState>
<not>
<objectState
name="JavaVariableFilter"
diff --git a/org.eclipse.jdt.debug.ui/pom.xml b/org.eclipse.jdt.debug.ui/pom.xml
index af78e1d..ea497b6 100644
--- a/org.eclipse.jdt.debug.ui/pom.xml
+++ b/org.eclipse.jdt.debug.ui/pom.xml
@@ -18,7 +18,7 @@
</parent>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.debug.ui</artifactId>
- <version>3.10.100-SNAPSHOT</version>
+ <version>3.10.200-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
<properties>
<code.ignoredWarnings>-warn:+resource,-deprecation,unavoidableGenericProblems</code.ignoredWarnings>
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java
index 2545132..dac12ec 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -264,6 +264,8 @@
public static String DetailFormatterDialog_Select_type_6;
public static String DetailFormatterDialog_Could_not_open_type_selection_dialog_for_detail_formatters_7;
public static String DetailFormatterDialog_Select_type_8;
+ public static String DetailFormatterDialog_Select_type_9;
+ public static String DetailFormatterDialog_Select_type_10;
public static String DetailFormatterDialog_Select_a_type_to_format_when_displaying_its_detail_9;
public static String DetailFormatterDialog_Edit_Detail_Formatter_1;
public static String DetailFormatterDialog_Add_Detail_Formatter_2;
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties
index ec50283..c2e8452 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2000, 2018 IBM Corporation and others.
+# Copyright (c) 2000, 2019 IBM Corporation and others.
#
# This program and the accompanying materials
# are made available under the terms of the Eclipse Public License 2.0
@@ -220,6 +220,8 @@
DetailFormatterDialog_Select_type_6=Select Type
DetailFormatterDialog_Could_not_open_type_selection_dialog_for_detail_formatters_7=Could not open type selection dialog for detail formatters
DetailFormatterDialog_Select_type_8=Select Type
+DetailFormatterDialog_Select_type_9=Browse Type
+DetailFormatterDialog_Select_type_10=In order to browse a type, a project needs to be present and accessible.
DetailFormatterDialog_Select_a_type_to_format_when_displaying_its_detail_9=&Select a type to format when displaying its detail:
DetailFormatterDialog_Edit_Detail_Formatter_1=Edit Detail Formatter
DetailFormatterDialog_Add_Detail_Formatter_2=Add Detail Formatter
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/EditLogicalStructureDialog.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/EditLogicalStructureDialog.java
index fc138f6..ac3aed6 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/EditLogicalStructureDialog.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/EditLogicalStructureDialog.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2015 IBM Corporation and others.
+ * Copyright (c) 2004, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -21,6 +21,8 @@
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
@@ -46,6 +48,7 @@
import org.eclipse.jdt.ui.text.IJavaPartitions;
import org.eclipse.jdt.ui.text.JavaTextTools;
import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.StatusDialog;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.DocumentEvent;
@@ -622,7 +625,24 @@
* Open the 'select type' dialog, and set the user choice into the formatter.
*/
private void selectType() {
- Shell shell= getShell();
+ Shell shell = getShell();
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ if (projects.length == 0) {
+ MessageDialog.openInformation(shell, DebugUIMessages.DetailFormatterDialog_Select_type_9, DebugUIMessages.DetailFormatterDialog_Select_type_10);
+ return;
+ }
+ boolean allClosed = true;
+ for (IProject iProject : projects) {
+ if (iProject.isOpen()) {
+ allClosed = false;
+ break;
+ }
+ }
+
+ if (allClosed) {
+ MessageDialog.openInformation(shell, DebugUIMessages.DetailFormatterDialog_Select_type_9, DebugUIMessages.DetailFormatterDialog_Select_type_10);
+ return;
+ }
SelectionDialog dialog= null;
try {
dialog= JavaUI.createTypeDialog(shell, PlatformUI.getWorkbench().getProgressService(),
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaVarActionFilter.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaVarActionFilter.java
index 7cea28f..bbf67e4 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaVarActionFilter.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaVarActionFilter.java
@@ -25,6 +25,7 @@
import org.eclipse.jdt.debug.core.IJavaType;
import org.eclipse.jdt.debug.core.IJavaVariable;
import org.eclipse.jdt.internal.debug.core.model.JDINullValue;
+import org.eclipse.jdt.internal.debug.core.model.JDIObjectValue;
import org.eclipse.jdt.internal.debug.core.model.JDIPlaceholderValue;
import org.eclipse.jdt.internal.debug.core.model.JDIReferenceListVariable;
import org.eclipse.jdt.internal.debug.ui.display.JavaInspectExpression;
@@ -191,6 +192,9 @@
if (value.equals("isPlaceholderValue")) { //$NON-NLS-1$
return varValue instanceof JDIPlaceholderValue;
}
+ if (value.equals("isObjectValue")) { //$NON-NLS-1$
+ return varValue != null && JDIObjectValue.class.isAssignableFrom(varValue.getClass());
+ }
}
else if (name.equals("ConcreteVariableActionFilter") && value.equals("isConcrete")) { //$NON-NLS-1$ //$NON-NLS-2$
return isDeclaredSameAsConcrete(var);
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/contentassist/CurrentFrameContext.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/contentassist/CurrentFrameContext.java
index 49742d2..ed71f21 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/contentassist/CurrentFrameContext.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/contentassist/CurrentFrameContext.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2017 IBM Corporation and others.
+ * Copyright (c) 2005, 2018 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -22,7 +22,7 @@
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.debug.core.IJavaVariable;
import org.eclipse.jdt.internal.debug.core.JavaDebugUtils;
-import org.eclipse.jdt.internal.debug.core.logicalstructures.JDIReturnValueVariable;
+import org.eclipse.jdt.internal.debug.core.logicalstructures.JDIPlaceholderVariable;
import org.eclipse.jdt.internal.debug.core.model.JDIThisVariable;
@@ -65,7 +65,8 @@
if (frame != null) {
IVariable[] variables = frame.getVariables();
int index = 0;
- while (index < variables.length && (variables[index] instanceof JDIThisVariable || variables[index] instanceof JDIReturnValueVariable)) {
+ while (index < variables.length
+ && (variables[index] instanceof JDIThisVariable || JDIPlaceholderVariable.class.isAssignableFrom(variables[index].getClass()))) {
index++;
}
String[][] locals = new String[2][variables.length - index];
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/threadgroups/JavaDebugTargetProxy.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/threadgroups/JavaDebugTargetProxy.java
index b013a0a..5fd7379 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/threadgroups/JavaDebugTargetProxy.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/threadgroups/JavaDebugTargetProxy.java
@@ -21,7 +21,10 @@
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.model.IDebugElement;
import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
import org.eclipse.debug.internal.ui.viewers.update.DebugEventHandler;
@@ -29,6 +32,7 @@
import org.eclipse.debug.internal.ui.viewers.update.DebugTargetProxy;
import org.eclipse.debug.internal.ui.viewers.update.StackFrameEventHandler;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
+import org.eclipse.jdt.debug.ui.JavaDebugUtils;
import org.eclipse.jdt.internal.debug.ui.monitors.JavaElementContentProvider;
import org.eclipse.jdt.internal.debug.ui.snippeteditor.ScrapbookLauncher;
import org.eclipse.jface.viewers.Viewer;
@@ -141,4 +145,18 @@
return 0;
}
+ @Override
+ protected int getStackFrameIndex(IStackFrame stackFrame) {
+ int stackFrameIndex = 0;
+ if (((IJavaDebugTarget) fDebugTarget).supportsMonitorInformation()) {
+ IThread thread = stackFrame.getThread();
+ IDebugElement[] ownedMonitors = JavaDebugUtils.getOwnedMonitors(thread);
+ stackFrameIndex += ownedMonitors.length;
+ IDebugElement contendedMonitor = JavaDebugUtils.getContendedMonitor(thread);
+ if (contendedMonitor != null) {
+ stackFrameIndex++;
+ }
+ }
+ return stackFrameIndex;
+ }
}
diff --git a/org.eclipse.jdt.debug/META-INF/MANIFEST.MF b/org.eclipse.jdt.debug/META-INF/MANIFEST.MF
index eaa9d49..44df683 100644
--- a/org.eclipse.jdt.debug/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.debug/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jdt.debug; singleton:=true
-Bundle-Version: 3.12.100.qualifier
+Bundle-Version: 3.12.200.qualifier
Bundle-ClassPath: jdi.jar,
jdimodel.jar,
tools.jar
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 d3b92c5..4a5f6ae 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
@@ -15,8 +15,11 @@
*******************************************************************************/
package org.eclipse.jdt.internal.debug.eval.ast.engine;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
@@ -57,9 +60,13 @@
import org.eclipse.jdt.debug.eval.IEvaluationResult;
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;
+import org.eclipse.jdt.internal.debug.core.logicalstructures.JDIReturnValueVariable;
import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
+import org.eclipse.jdt.internal.debug.core.model.JDIThisVariable;
import org.eclipse.jdt.internal.debug.core.model.JDIThread;
import org.eclipse.jdt.internal.debug.core.model.JDIValue;
+import org.eclipse.jdt.internal.debug.core.model.LambdaUtils;
import org.eclipse.jdt.internal.debug.eval.EvaluationResult;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.InstructionSequence;
@@ -284,7 +291,8 @@
EvaluationSourceGenerator mapper = null;
CompilationUnit unit = null;
try {
- IJavaVariable[] localsVar = context.getLocals();
+ List<IJavaVariable> localsVar = new ArrayList<>();
+ localsVar.addAll(Arrays.asList(context.getLocals()));
IJavaObject thisClass = context.getThis();
IVariable[] innerClassFields; // For anonymous classes, getting variables from outer class
if (null != thisClass) {
@@ -292,22 +300,41 @@
} else {
innerClassFields = new IVariable[0];
}
- int numLocalsVar = localsVar.length;
+ List<IVariable> lambdaFrameVariables = LambdaUtils.getLambdaFrameVariables(frame);
+ int numLocalsVar = localsVar.size();
Set<String> names = new HashSet<>();
// ******
// to hide problems with local variable declare as instance of Local
// Types
// and to remove locals with duplicate names
// IJavaVariable[] locals = new IJavaVariable[numLocalsVar];
- IJavaVariable[] locals = new IJavaVariable[numLocalsVar + innerClassFields.length];
- String[] localVariablesWithNull = new String[numLocalsVar + innerClassFields.length];
+ IJavaVariable[] locals = new IJavaVariable[numLocalsVar + innerClassFields.length + lambdaFrameVariables.size()];
+ String[] localVariablesWithNull = new String[numLocalsVar + innerClassFields.length + lambdaFrameVariables.size()];
int numLocals = 0;
for (int i = 0; i < numLocalsVar; i++) {
- if (!isLocalType(localsVar[i].getSignature())
- && !names.contains(localsVar[i].getName())) {
- locals[numLocals] = localsVar[i];
- names.add(localsVar[i].getName());
- localVariablesWithNull[numLocals++] = localsVar[i].getName();
+ IJavaVariable variable = localsVar.get(i);
+ if (!isLocalType(variable.getSignature()) && !names.contains(variable.getName())) {
+ locals[numLocals] = variable;
+ names.add(variable.getName());
+ localVariablesWithNull[numLocals++] = variable.getName();
+ }
+ }
+ /*
+ * If we are in a lambda frame, the variable context is not complete; names of outer-scope variables are mangled by the compiler. So we
+ * check variables one stack frame above the lambda frames, in order to also include outer-scope variables. This is necessary to use local
+ * variables defined in a method, within a breakpoint condition inside a lambda also defined in that method.
+ */
+ for (IVariable variable : lambdaFrameVariables) {
+ if (variable instanceof IJavaVariable && !isLambdaOrImplicitVariable(variable)) {
+ IJavaVariable javaVariable = (IJavaVariable) variable;
+ String variableName = variable.getName();
+ if (variableName != null && !variableName.contains("$")) { //$NON-NLS-1$
+ if (!isLocalType(javaVariable.getSignature()) && !names.contains(variableName)) {
+ locals[numLocals] = javaVariable;
+ names.add(variable.getName());
+ localVariablesWithNull[numLocals++] = variable.getName();
+ }
+ }
}
}
// Adding outer class variables to inner class scope
@@ -839,4 +866,10 @@
}
return updatedSnippet.toString();
}
+
+ private static boolean isLambdaOrImplicitVariable(IVariable variable) {
+ boolean isLambdaOrImplicitVariable = variable instanceof JDILambdaVariable || variable instanceof JDIReturnValueVariable
+ || variable instanceof JDIThisVariable;
+ return isLambdaOrImplicitVariable;
+ }
}
diff --git a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/instructions/PushLocalVariable.java b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/instructions/PushLocalVariable.java
index 69c1689..f7c3cee 100644
--- a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/instructions/PushLocalVariable.java
+++ b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/instructions/PushLocalVariable.java
@@ -22,6 +22,7 @@
import org.eclipse.jdt.debug.core.IJavaObject;
import org.eclipse.jdt.debug.core.IJavaVariable;
import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
+import org.eclipse.jdt.internal.debug.core.model.LambdaUtils;
import org.eclipse.jdt.internal.debug.eval.ast.engine.ASTEvaluationEngine;
import org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext;
import org.eclipse.osgi.util.NLS;
@@ -64,6 +65,11 @@
return;
}
}
+ IVariable variable = LambdaUtils.findLambdaFrameVariable(context, getName());
+ if (variable != null) {
+ push(variable);
+ return;
+ }
throw new CoreException(
new Status(
IStatus.ERROR,
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/logicalstructures/JDILambdaVariable.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/logicalstructures/JDILambdaVariable.java
index 034d018..055455d 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/logicalstructures/JDILambdaVariable.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/logicalstructures/JDILambdaVariable.java
@@ -10,61 +10,23 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Paul Pazderski - Bug 542989 - inherit from {@link JDIPlaceholderVariable} to prevent NPEs
*******************************************************************************/
package org.eclipse.jdt.internal.debug.core.logicalstructures;
-import org.eclipse.debug.core.DebugException;
-import org.eclipse.debug.core.model.IVariable;
-import org.eclipse.jdt.debug.core.IJavaStackFrame;
-import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
-import org.eclipse.jdt.internal.debug.core.model.JDIVariable;
-
-import com.sun.jdi.ObjectReference;
-import com.sun.jdi.Type;
-import com.sun.jdi.Value;
+import org.eclipse.jdt.debug.core.IJavaValue;
/**
- * Represents the return value after a "step-return".
+ * Represents the closure context inside a lambda expression.
*/
-public class JDILambdaVariable extends JDIVariable {
+public class JDILambdaVariable extends JDIPlaceholderVariable {
- private ObjectReference fObject;
-
- public JDILambdaVariable(JDIDebugTarget target, IJavaStackFrame frame, ObjectReference object) {
- super(target);
- this.fObject = object;
+ public JDILambdaVariable(IJavaValue value) {
+ super("Lambda", value); //$NON-NLS-1$
}
@Override
- protected Value retrieveValue() {
- return fObject;
- }
-
- /**
- * @see IVariable#getName()
- */
- @Override
- public String getName() {
- return "Lambda"; //$NON-NLS-1$
- }
-
- @Override
- public String getSignature() throws DebugException {
- return null;
- }
-
- @Override
- public String getGenericSignature() throws DebugException {
- return null;
- }
-
- @Override
- public String getReferenceTypeName() throws DebugException {
- return null;
- }
-
- @Override
- protected Type getUnderlyingType() throws DebugException {
- return null;
+ public boolean isSynthetic() {
+ return true;
}
}
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIStackFrame.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIStackFrame.java
index b5970c5..e292189 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIStackFrame.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIStackFrame.java
@@ -362,13 +362,14 @@
}
}
if (LambdaUtils.isLambdaFrame(this)) {
- List<IJavaStackFrame> frames = fThread.computeStackFrames();
- int previousIndex = frames.indexOf(this) + 1;
- if (previousIndex > 0 && previousIndex < frames.size()) {
- IJavaStackFrame previousFrame = frames.get(previousIndex);
- fVariables.add(new JDILambdaVariable((JDIDebugTarget) getDebugTarget(), previousFrame, ((JDIStackFrame) previousFrame).getUnderlyingThisObject()));
- }
+ List<IJavaStackFrame> frames = fThread.computeStackFrames();
+ int previousIndex = frames.indexOf(this) + 1;
+ if (previousIndex > 0 && previousIndex < frames.size()) {
+ IJavaStackFrame previousFrame = frames.get(previousIndex);
+ IJavaValue closureValue = JDIValue.createValue((JDIDebugTarget) getDebugTarget(), ((JDIStackFrame) previousFrame).getUnderlyingThisObject());
+ fVariables.add(new JDILambdaVariable(closureValue));
}
+ }
addStepReturnValue(fVariables);
// add locals
Iterator<LocalVariable> variables = getUnderlyingVisibleVariables()
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIValue.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIValue.java
index ccce91c..e3cc969 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIValue.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIValue.java
@@ -22,7 +22,6 @@
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IValue;
import org.eclipse.debug.core.model.IVariable;
-
import org.eclipse.jdt.debug.core.IJavaType;
import org.eclipse.jdt.debug.core.IJavaValue;
import org.eclipse.jdt.debug.core.IJavaVariable;
@@ -39,6 +38,7 @@
import com.sun.jdi.Type;
import com.sun.jdi.VMDisconnectedException;
import com.sun.jdi.Value;
+import com.sun.jdi.VoidValue;
/**
* Represents the value of a java variable
@@ -95,7 +95,7 @@
/**
* Creates the appropriate kind of value - i.e. a primitive value, object,
- * class object, array, or <code>null</code>.
+ * class object, array, <code>null</code> or void.
*/
public static JDIValue createValue(JDIDebugTarget target, Value value) {
if (value == null) {
@@ -113,6 +113,9 @@
if (value instanceof PrimitiveValue) {
return new JDIPrimitiveValue(target, value);
}
+ if (value instanceof VoidValue) {
+ return new JDIVoidValue(target);
+ }
return new JDIValue(target, value);
}
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/LambdaUtils.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/LambdaUtils.java
index aeea804..851bc81 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/LambdaUtils.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/LambdaUtils.java
@@ -14,8 +14,18 @@
package org.eclipse.jdt.internal.debug.core.model;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.debug.core.model.IThread;
+import org.eclipse.debug.core.model.IVariable;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
+import org.eclipse.jdt.debug.core.IJavaThread;
+import org.eclipse.jdt.internal.debug.eval.ast.engine.IRuntimeContext;
/**
* Utility class for Lambda Expressions and Stack frames Place holder for all Lambda operation encapsulation.
@@ -23,6 +33,77 @@
public class LambdaUtils {
/**
+ * Inspects the top stack frame of the context; if that frame is a lambda frame, looks for a variable with the specified name in that frame and
+ * two frames below that frame.
+ *
+ * Inside a lambda expression, variable names are mangled by the compiler. Its therefore necessary to check the outer frame when at a lambda
+ * frame, in order to find a variable with its name. The lambda expression itself is called by a synthetic static method, which is the first frame
+ * below the lambda frame. So in total we check 3 stack frames for the variable with the specified name.
+ *
+ * @param context
+ * The context in which to check.
+ * @param variableName
+ * The name of the variable.
+ * @return The variable with the specified name if found, {@code null} otherwise. Also returns {@code null} if no thread or top stack frame is
+ * available. If there are multiple variables with the same name in the lambda context, the most local one is returned.
+ * @throws DebugException
+ * If accessing the top stack frame or the local variables on stack frames fails, due to failure to communicate with the debug target.
+ */
+ public static IVariable findLambdaFrameVariable(IRuntimeContext context, String variableName) throws DebugException {
+ IJavaThread thread = context.getThread();
+ if (thread != null) {
+ IStackFrame topStackFrame = thread.getTopStackFrame();
+ List<IVariable> variables = getLambdaFrameVariables(topStackFrame);
+ for (IVariable variable : variables) {
+ if (variable.getName().equals(variableName)) {
+ return variable;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Collects variables visible from a lambda stack frame. I.e. inspects the specified stack frame; if that frame is a lambda frame, collects all
+ * variables in that frame and two frames below that frame.
+ *
+ * Inside a lambda expression, variable names are mangled by the compiler. Its therefore necessary to check the outer frame when at a lambda
+ * frame, in order to find a variable with its name. The lambda expression itself is called by a synthetic static method, which is the first frame
+ * below the lambda frame. So in total we collect variables from 3 stack frames.
+ *
+ * @param frame
+ * The lambda frame at which to check.
+ * @return The variables visible from the stack frame. An empty list if the specified stack frame is not a lambda frame. The variables are ordered
+ * top-down, i.e. if shadowing occurs, the more local variable will be first in the resulting list.
+ * @throws DebugException
+ * If accessing the top stack frame or the local variables on stack frames fails, due to failure to communicate with the debug target.
+ */
+ public static List<IVariable> getLambdaFrameVariables(IStackFrame frame) throws DebugException {
+ List<IVariable> variables = new ArrayList<>();
+ if (LambdaUtils.isLambdaFrame(frame)) {
+ IThread thread = frame.getThread();
+ IStackFrame[] stackFrames = thread.getStackFrames();
+ for (int i = 0; i < Math.min(3, stackFrames.length); ++i) {
+ IStackFrame stackFrame = stackFrames[i];
+ IVariable[] stackFrameVariables = stackFrame.getVariables();
+ variables.addAll(Arrays.asList(stackFrameVariables));
+ }
+ }
+ return Collections.unmodifiableList(variables);
+ }
+
+ /**
+ * Evaluates if the input frame is a lambda frame.
+ *
+ * @param frame
+ * the frame which needs to be evaluated
+ * @return <code>True</code> if the frame is a lambda frame else return <code>False</Code>
+ */
+ public static boolean isLambdaFrame(IStackFrame frame) throws DebugException {
+ return frame instanceof IJavaStackFrame && isLambdaFrame((IJavaStackFrame) frame);
+ }
+
+ /**
* Evaluates if the input frame is a lambda frame.
*
* @param frame
@@ -33,5 +114,4 @@
public static boolean isLambdaFrame(IJavaStackFrame frame) throws DebugException {
return frame.isSynthetic() && frame.getName().startsWith("lambda$"); //$NON-NLS-1$
}
-
- }
+}
diff --git a/org.eclipse.jdt.debug/pom.xml b/org.eclipse.jdt.debug/pom.xml
index eccb2dd..68d6fea 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.12.100-SNAPSHOT</version>
+ <version>3.12.200-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
diff --git a/org.eclipse.jdt.launching/META-INF/MANIFEST.MF b/org.eclipse.jdt.launching/META-INF/MANIFEST.MF
index 81987a5..6fcb96d 100644
--- a/org.eclipse.jdt.launching/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.launching/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jdt.launching; singleton:=true
-Bundle-Version: 3.12.0.qualifier
+Bundle-Version: 3.12.100.qualifier
Bundle-Activator: org.eclipse.jdt.internal.launching.LaunchingPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
@@ -16,7 +16,7 @@
org.eclipse.jdt.launching.sourcelookup.containers
Require-Bundle: org.eclipse.core.resources;bundle-version="[3.5.0,4.0.0)",
org.eclipse.jdt.core;bundle-version="[3.15.0,4.0.0)",
- org.eclipse.debug.core;bundle-version="[3.13.0,4.0.0)",
+ org.eclipse.debug.core;bundle-version="[3.13.200,4.0.0)",
org.eclipse.jdt.debug;bundle-version="[3.11.0,4.0.0)",
org.eclipse.core.variables;bundle-version="[3.2.0,4.0.0)",
org.eclipse.core.runtime;bundle-version="[3.11.0,4.0.0)",
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMType.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMType.java
index afe5b6e..94e64da 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMType.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMType.java
@@ -56,7 +56,9 @@
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.Launch;
import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.debug.core.model.IStreamMonitor;
import org.eclipse.debug.core.model.IStreamsProxy;
+import org.eclipse.debug.internal.core.OutputStreamMonitor;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.launching.AbstractVMInstallType;
import org.eclipse.jdt.launching.ILibraryLocationResolver;
@@ -700,9 +702,11 @@
p = DebugPlugin.exec(cmdLine, null, envp);
IProcess process = DebugPlugin.newProcess(new Launch(null, ILaunchManager.RUN_MODE, null), p, "Library Detection"); //$NON-NLS-1$
process.setAttribute(IProcess.ATTR_CMDLINE, String.join(" ", cmdLine)); //$NON-NLS-1$
+ IStreamMonitor outputStreamMonitor = process.getStreamsProxy().getOutputStreamMonitor();
for (int i= 0; i < 600; i++) {
- // Wait no more than 30 seconds (600 * 50 milliseconds)
- if (process.isTerminated()) {
+ // Wait no more than 30 seconds (600 * 50 milliseconds),
+ // also ensure we are done reading the process stream, if we have a OutputStreamMonitor
+ if (process.isTerminated() && isReadingDone(outputStreamMonitor)) {
break;
}
try {
@@ -728,6 +732,14 @@
return info;
}
+ @SuppressWarnings("restriction")
+ private boolean isReadingDone(IStreamMonitor monitor) {
+ if (monitor instanceof OutputStreamMonitor) {
+ return ((OutputStreamMonitor) monitor).isReadingDone();
+ }
+ return true;
+ }
+
/**
* Parses the output from 'LibraryDetector'.
*
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/AdvancedSourceLookup.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/AdvancedSourceLookup.java
index 77e721c..eefa06c 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/AdvancedSourceLookup.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/AdvancedSourceLookup.java
@@ -60,13 +60,21 @@
final Map<File, IPackageFragmentRoot> classpath = new LinkedHashMap<>();
for (IPackageFragmentRoot fragment : project.getPackageFragmentRoots()) {
if (fragment.getKind() == IPackageFragmentRoot.K_BINARY) {
- File classpathLocation;
+ File classpathLocation = null;
if (fragment.isExternal()) {
classpathLocation = fragment.getPath().toFile();
} else {
- classpathLocation = fragment.getResource().getLocation().toFile();
+ IResource resource = fragment.getResource();
+ if (resource != null) {
+ IPath location = resource.getLocation();
+ if (location != null) {
+ classpathLocation = location.toFile();
+ }
+ }
}
- classpath.put(classpathLocation, fragment);
+ if (classpathLocation != null) {
+ classpath.put(classpathLocation, fragment);
+ }
}
}
return classpath;
diff --git a/org.eclipse.jdt.launching/pom.xml b/org.eclipse.jdt.launching/pom.xml
index 50b420b..b98ef87 100644
--- a/org.eclipse.jdt.launching/pom.xml
+++ b/org.eclipse.jdt.launching/pom.xml
@@ -18,7 +18,7 @@
</parent>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.launching</artifactId>
- <version>3.12.0-SNAPSHOT</version>
+ <version>3.12.100-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
<build>