Merge remote-tracking branch 'origin/master' into BETA_JAVA_12
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 874c9a3..605e91e 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
@@ -36,7 +36,6 @@
 import org.eclipse.core.resources.IMarkerDelta;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IWorkspaceRoot;
 import org.eclipse.core.resources.IncrementalProjectBuilder;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
@@ -2834,8 +2833,15 @@
 	}
 
 	protected void assertNoErrorMarkersExist() throws Exception {
-		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
-		IProject[] projects = root.getProjects();
+		IJavaProject javaProject = getProjectContext();
+		assertNotNull("Java test project cannot be null", javaProject);
+		IProject project = javaProject.getProject();
+		assertNotNull("test project cannot be null", project);
+		IProject[] projects = { project };
+		assertNoErrorMarkersExist(projects);
+	}
+
+	protected void assertNoErrorMarkersExist(IProject[] projects) throws Exception {
 		for (IProject project : projects) {
 			assertNoErrorMarkersExist(project);
 		}
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 1828248..652f592 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
@@ -32,6 +32,7 @@
 import org.eclipse.jdt.debug.tests.breakpoints.ImportBreakpointsTest;
 import org.eclipse.jdt.debug.tests.breakpoints.JavaBreakpointListenerTests;
 import org.eclipse.jdt.debug.tests.breakpoints.JavaThreadEventHandlerTests;
+import org.eclipse.jdt.debug.tests.breakpoints.LambdaBreakpointsInJava8Tests;
 import org.eclipse.jdt.debug.tests.breakpoints.MethodBreakpointTests;
 import org.eclipse.jdt.debug.tests.breakpoints.MethodBreakpointTests15;
 import org.eclipse.jdt.debug.tests.breakpoints.MiscBreakpointsTests;
@@ -351,6 +352,7 @@
 			addTest(new TestSuite(TestToggleBreakpointsTarget8.class));
 			addTest(new TestSuite(ModelPresentationTests18.class));
 			addTest(new TestSuite(ConditionalBreakpointsInJava8Tests.class));
+			addTest(new TestSuite(LambdaBreakpointsInJava8Tests.class));
 		}
 		if (JavaProjectHelper.isJava5Compatible()) {
 			addTest(new TestSuite(MethodBreakpointTests15.class));
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/LambdaBreakpointsInJava8Tests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/LambdaBreakpointsInJava8Tests.java
new file mode 100644
index 0000000..29e4572
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/LambdaBreakpointsInJava8Tests.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Andrey Loskutov 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:
+ *     Andrey Loskutov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.debug.tests.breakpoints;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+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.core.IJavaLineBreakpoint;
+import org.eclipse.jdt.debug.core.IJavaThread;
+import org.eclipse.jdt.debug.tests.AbstractDebugTest;
+import org.eclipse.jdt.debug.tests.TestUtil;
+
+/**
+ * Tests lambda breakpoints.
+ */
+public class LambdaBreakpointsInJava8Tests extends AbstractDebugTest {
+
+	public LambdaBreakpointsInJava8Tests(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 543385 - we should stop multiple times on same line with many lambdas
+	 */
+	public void testBug541110_unconditional() throws Exception {
+		String typeName = "Bug541110";
+		int breakpointLineNumber = 22;
+
+		IJavaLineBreakpoint bp = createLineBreakpoint(breakpointLineNumber, typeName);
+
+		IJavaThread thread = null;
+		try {
+			thread = launchToLineBreakpoint(typeName, bp);
+			thread.resume();
+			// now we should stop again in the lambda
+			TestUtil.waitForJobs(getName(), 1000, DEFAULT_TIMEOUT, ProcessConsole.class);
+			assertTrue("Thread should be suspended", thread.isSuspended());
+		} finally {
+			terminateAndRemove(thread);
+			removeAllBreakpoints();
+		}
+	}
+
+	/**
+	 * Test for bug 543385/541110 - we should stop only once if there is a condition.
+	 *
+	 * Note: if we implement proper lambda debugging support some time later, this test will probably fail.
+	 */
+	public void testBug541110_conditional() throws Exception {
+		String typeName = "Bug541110";
+		String breakpointCondition = "true";
+		int breakpointLineNumber = 22;
+
+		IJavaLineBreakpoint bp = createConditionalLineBreakpoint(breakpointLineNumber, typeName, breakpointCondition, true);
+
+		IJavaThread thread = null;
+		try {
+			thread = launchToLineBreakpoint(typeName, bp);
+			thread.resume();
+			// now we should NOT stop again in the lambda (a more complex condition would most likely fail)
+			TestUtil.waitForJobs(getName(), 1000, DEFAULT_TIMEOUT, ProcessConsole.class);
+			assertTrue("Thread should be suspended", thread.isTerminated());
+		} finally {
+			terminateAndRemove(thread);
+			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/DetailPaneManagerTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DetailPaneManagerTests.java
index 3e4855e..51ded11 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DetailPaneManagerTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DetailPaneManagerTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- *  Copyright (c) 2006, 2012 IBM Corporation and others.
+ *  Copyright (c) 2006, 2019 IBM Corporation and others.
  *
  *  This program and the accompanying materials
  *  are made available under the terms of the Eclipse Public License 2.0
@@ -16,24 +16,21 @@
 import java.util.HashSet;
 import java.util.Set;
 
-import junit.framework.Test;
-
+import org.eclipse.debug.internal.ui.views.variables.details.DefaultDetailPane;
+import org.eclipse.debug.internal.ui.views.variables.details.DetailPaneManager;
+import org.eclipse.debug.ui.IDetailPane;
 import org.eclipse.jdt.debug.core.IJavaVariable;
 import org.eclipse.jdt.debug.testplugin.detailpane.SimpleDetailPane;
 import org.eclipse.jdt.debug.testplugin.detailpane.TableDetailPane;
 import org.eclipse.jdt.debug.tests.AbstractDebugTest;
-import org.eclipse.test.OrderedTestSuite;
-
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.viewers.StructuredSelection;
-
-import org.eclipse.debug.internal.ui.views.variables.details.DefaultDetailPane;
-import org.eclipse.debug.internal.ui.views.variables.details.DetailPaneManager;
-
-import org.eclipse.debug.ui.IDetailPane;
-
 import org.eclipse.jdt.internal.debug.core.logicalstructures.JDIPlaceholderVariable;
 import org.eclipse.jdt.internal.debug.core.model.JDIDebugElement;
+import org.eclipse.jdt.internal.debug.ui.variables.JavaVariablesDetailPane;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.test.OrderedTestSuite;
+
+import junit.framework.Test;
 
 /**
  * Tests the detail pane functionality by testing <code>DetailPaneManager</code>.
@@ -142,7 +139,7 @@
 
 		selection = new StructuredSelection(new IJavaVariable[]{new JDIPlaceholderVariable("test var",null)});
 		id = fManager.getPreferredPaneFromSelection(selection);
-		assertEquals("Incorrect pane ID", DefaultDetailPane.ID, id);
+		assertEquals("Incorrect pane ID", JavaVariablesDetailPane.JAVA_VARIABLE_DETAIL_PANE_VARIABLES, id);
 
 		// The factory sets the Table detail pane as the default if the first string is "test pane is default".
 		selection = new StructuredSelection(new String[]{"test pane is default","example selection"});
@@ -182,7 +179,8 @@
 
 		selection = new StructuredSelection(new Object[]{new JDIPlaceholderVariable("test var",null)});
 		result = fManager.getAvailablePaneIDs(selection);
-		assertTrue("Set was incorrect",result.size()==2 && result.contains(DefaultDetailPane.ID) && result.contains(SimpleDetailPane.ID));
+		assertTrue("Set was incorrect", result.size() == 3 && result.contains(DefaultDetailPane.ID) && result.contains(SimpleDetailPane.ID)
+				&& result.contains(JavaVariablesDetailPane.JAVA_VARIABLE_DETAIL_PANE_VARIABLES));
 
 		// Simple detail pane only available if selection has length of 1, containing a java variable
 		selection = new StructuredSelection(new Object[]{"String1",new JDIPlaceholderVariable("test var",null),"String3"});
diff --git a/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF b/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF
index d57c604..b8a192b 100644
--- a/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF
@@ -38,7 +38,7 @@
  org.eclipse.core.variables;bundle-version="[3.2.0,4.0.0)",
  org.eclipse.core.expressions;bundle-version="[3.4.0,4.0.0)",
  org.eclipse.jdt.core;bundle-version="[3.15.0,4.0.0)",
- org.eclipse.debug.ui;bundle-version="[3.13.100,4.0.0)",
+ org.eclipse.debug.ui;bundle-version="[3.13.400,4.0.0)",
  org.eclipse.jdt.debug;bundle-version="[3.11.0,4.0.0)",
  org.eclipse.jdt.launching;bundle-version="[3.11.0,4.0.0)",
  org.eclipse.jdt.ui;bundle-version="[3.15.100,4.0.0)",
diff --git a/org.eclipse.jdt.debug.ui/plugin.properties b/org.eclipse.jdt.debug.ui/plugin.properties
index 5e77de6..3000482 100644
--- a/org.eclipse.jdt.debug.ui/plugin.properties
+++ b/org.eclipse.jdt.debug.ui/plugin.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
@@ -319,3 +319,5 @@
 OpenFromClipboardAction.tooltip = Opens a Java element or Java Stack Trace from Clipboard
 OpenFromClipboardAction.description = Opens a Java element or a Java stack trace from clipboard
 OpenFromClipboardAction.name = Open from Clipboard
+
+VariablesView.name = Variables
\ No newline at end of file
diff --git a/org.eclipse.jdt.debug.ui/plugin.xml b/org.eclipse.jdt.debug.ui/plugin.xml
index 9f68823..2af9c44 100644
--- a/org.eclipse.jdt.debug.ui/plugin.xml
+++ b/org.eclipse.jdt.debug.ui/plugin.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?eclipse version="3.0"?>
 <!--
-     Copyright (c) 2005, 2017 IBM Corporation and others.
+     Copyright (c) 2005, 2019 IBM Corporation and others.
 
      This program and the accompanying materials
      are made available under the terms of the Eclipse Public License 2.0
@@ -3669,6 +3669,25 @@
           </with>
        </enablement>
     </detailFactories>
+    <detailFactories
+          class="org.eclipse.jdt.internal.debug.ui.variables.JavaVariablesDetailPaneFactory"
+          id="org.eclipse.jdt.debug.ui.variables.detailFactories">
+       <enablement>
+          <with
+                variable="selection">
+             <count
+                   value="1">
+             </count>
+             <iterate>
+                <or>
+                   <instanceof
+                         value="org.eclipse.jdt.debug.core.IJavaVariable">
+                   </instanceof>
+                </or>
+             </iterate>
+          </with>
+       </enablement>
+    </detailFactories>
  </extension>
  <extension
        point="org.eclipse.debug.ui.stringVariablePresentations">
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/ExpressionInformationControlCreator.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/ExpressionInformationControlCreator.java
index 83663e1..b1ae6ee 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/ExpressionInformationControlCreator.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/ExpressionInformationControlCreator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2018 IBM Corporation and others.
+ * Copyright (c) 2008, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -494,7 +494,7 @@
 		return foreground;
 	}
 
-	private static Color getSystemBackgroundColor() {
+	public static Color getSystemBackgroundColor() {
 		ColorRegistry colorRegistry = JFaceResources.getColorRegistry();
 		Color background = colorRegistry.get(JFacePreferences.INFORMATION_BACKGROUND_COLOR);
 
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.java
index 1667ebc..2c8c3b1 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2003, 2016 IBM Corporation and others.
+ * Copyright (c) 2003, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -77,6 +77,13 @@
 	public static String ThreadFilterEditor_2;
 	public static String InstanceFilterEditor_0;
 
+	public static String JavaVariableDetailsPane_choosePreviousExpression;
+	public static String JavaVariableDetailsPane_description;
+	public static String JavaVariableDetailsPane_historySeparator;
+	public static String JavaVariableDetailsPane_name;
+	public static String JavaVariableDetailsPane_settings;
+
+
 	static {
 		// load message values from bundle file
 		NLS.initializeMessages(BUNDLE_NAME, PropertyPageMessages.class);
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.properties
index be7b996..c982cb4 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.properties
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2003, 2017 IBM Corporation and others.
+# Copyright (c) 2003, 2019 IBM Corporation and others.
 #
 # This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License 2.0
@@ -47,6 +47,7 @@
 JavaBreakpointPage_7=&Suspend thread
 JavaBreakpointPage_8=Suspend &VM
 JavaBreakpointPage_9=Unable to cancel breakpoint creation
+JavaExceptionBreakpointPage_5=Java Exception Breakpoint
 JavaLineBreakpointPage_2=&Line Number:
 JavaLineBreakpointPage_3=&Member:
 JavaLineBreakpointPage_4=&Method:
@@ -58,10 +59,14 @@
 JavaLineBreakpointPage_18=Line Breakpoint
 JavaLineBreakpointPage_19=Watchpoint
 JavaLineBreakpointPage_20=Method Breakpoint
+JavaVariableDetailsPane_choosePreviousExpression=<Choose a previously entered expression for debugging>
+JavaVariableDetailsPane_description=Java Variable Detail Pane Viewer
+JavaVariableDetailsPane_historySeparator=Global history
+JavaVariableDetailsPane_name=Java Variable Detail Pane Viewer
+JavaVariableDetailsPane_settings=Java Variable Detail Pane Settings
 ThreadFilterEditor_1=&Restrict to Selected Thread(s):
 ThreadFilterEditor_2=Must select a thread in selected targets
 InstanceFilterEditor_0=Restricted to Selected Ob&ject(s)
-JavaExceptionBreakpointPage_5=Java Exception Breakpoint
 VMCapabilitiesPropertyPage_0=The selected debug element does not allow access to the underlying virtual machine.
 VMCapabilitiesPropertyPage_1=&Virtual Machine: 
 VMCapabilitiesPropertyPage_3=Supports synthetic method step filter
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariablesDetailPane.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariablesDetailPane.java
new file mode 100644
index 0000000..41399b1
--- /dev/null
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariablesDetailPane.java
@@ -0,0 +1,336 @@
+/*******************************************************************************
+ *  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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.debug.ui.variables;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Stack;
+import java.util.regex.Pattern;
+
+import org.eclipse.debug.internal.ui.SWTFactory;
+import org.eclipse.debug.internal.ui.views.variables.details.DefaultDetailPane;
+import org.eclipse.jdt.debug.core.IJavaVariable;
+import org.eclipse.jdt.internal.debug.ui.ExpressionInformationControlCreator;
+import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
+import org.eclipse.jdt.internal.debug.ui.propertypages.PropertyPageMessages;
+import org.eclipse.jface.dialogs.DialogSettings;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * Java Variable detail pane.
+ *
+ * @since 3.10
+ */
+public class JavaVariablesDetailPane extends DefaultDetailPane {
+
+	/**
+	 * Identifier for this Java Variable detail pane editor
+	 */
+	public static final String JAVA_VARIABLE_DETAIL_PANE_VARIABLES = JDIDebugUIPlugin.getUniqueIdentifier() + ".JAVA_VARIABLE_DETAIL_PANE_VARIABLES"; //$NON-NLS-1$
+	public static final String NAME = PropertyPageMessages.JavaVariableDetailsPane_name;
+	public static final String DESCRIPTION = PropertyPageMessages.JavaVariableDetailsPane_description;
+
+	private FocusListener focusListener;
+	private Combo fExpressionHistory;
+	private IDialogSettings fExpressionHistoryDialogSettings;
+	private Map<IJavaVariable, Stack<String>> fLocalExpressionHistory;
+	private int fSeparatorIndex;
+	private static final int MAX_HISTORY_SIZE = 10;
+	private static final String DS_SECTION_EXPRESSION_HISTORY = "expressionHistory"; //$NON-NLS-1$
+	private static final String DS_KEY_HISTORY_ENTRY_COUNT = "expressionHistoryEntryCount"; //$NON-NLS-1$
+	private static final String DS_KEY_HISTORY_ENTRY_PREFIX = "expressionHistoryEntry_"; //$NON-NLS-1$
+	private static final Pattern NEWLINE_PATTERN = Pattern.compile("\r\n|\r|\n"); //$NON-NLS-1$ ;
+
+	private IJavaVariable fVariable;
+	public JavaVariablesDetailPane() {
+		fExpressionHistoryDialogSettings = DialogSettings.getOrCreateSection(JDIDebugUIPlugin.getDefault().getDialogSettings(), DS_SECTION_EXPRESSION_HISTORY);
+	}
+
+	@Override
+	public Control createControl(Composite parent) {
+		if (!isInView()) {
+			Control c = super.createControl(parent);
+			c.setBackground(ExpressionInformationControlCreator.getSystemBackgroundColor());
+			return c;
+		}
+		if (fExpressionHistoryDialogSettings != null) {
+			fLocalExpressionHistory = new HashMap<>();
+			fExpressionHistory = SWTFactory.createCombo(parent, SWT.DROP_DOWN | SWT.READ_ONLY, 1, null);
+			fExpressionHistory.addSelectionListener(new SelectionAdapter() {
+				@Override
+				public void widgetSelected(SelectionEvent e) {
+					int historyIndex = fExpressionHistory.getSelectionIndex() - 1;
+					if (historyIndex >= 0 && historyIndex != fSeparatorIndex && getSourceViewer() != null) {
+						getSourceViewer().getDocument().set(getExpressionHistory()[historyIndex]);
+					}
+				}
+			});
+			GridData data = new GridData(GridData.FILL_HORIZONTAL);
+			data.widthHint = 10;
+			fExpressionHistory.setLayoutData(data);
+			fExpressionHistory.setEnabled(false);
+		}
+		Control newControl = super.createControl(parent);
+		SourceViewer viewer = getSourceViewer();
+		focusListener = new FocusListener() {
+
+			@Override
+			public void focusLost(FocusEvent e) {
+				updateExpressionHistories();
+				initializeExpressionHistoryDropDown();
+			}
+
+			@Override
+			public void focusGained(FocusEvent e) {
+
+			}
+		};
+		viewer.getTextWidget().addFocusListener(focusListener);
+		return newControl;
+	}
+
+	/**
+	 * Initializes the Expression history drop-down with values.
+	 */
+	private void initializeExpressionHistoryDropDown() {
+		fExpressionHistory.setItems(getExpressionHistoryLabels());
+		String userHint = PropertyPageMessages.JavaVariableDetailsPane_choosePreviousExpression;
+		fExpressionHistory.add(userHint, 0);
+		fExpressionHistory.setText(userHint);
+	}
+
+	/**
+	 * Returns the Expression history labels for the current variale.
+	 *
+	 * @return an array of strings containing the Expression history labels
+	 */
+	private String[] getExpressionHistoryLabels() {
+		String[] expressions = getExpressionHistory();
+		String[] labels = new String[expressions.length];
+		for (int i = 0; i < expressions.length; i++) {
+			labels[i] = NEWLINE_PATTERN.matcher(expressions[i]).replaceAll(" "); //$NON-NLS-1$
+		}
+		return labels;
+	}
+
+	/**
+	 * Returns the Expression history entries for the current variable.
+	 *
+	 * @return an array of strings containing the history of Expressions
+	 */
+	private String[] getExpressionHistory() {
+		fSeparatorIndex = -1;
+
+		// Get global history
+		String[] globalItems = readExpressionHistory(fExpressionHistoryDialogSettings);
+
+		// Get local history
+		Stack<String> localHistory = fLocalExpressionHistory.get(fVariable);
+		if (localHistory == null) {
+			return globalItems;
+		}
+
+		// Create combined history
+		int localHistorySize = Math.min(localHistory.size(), MAX_HISTORY_SIZE);
+		String[] historyItems = new String[localHistorySize + globalItems.length + 1];
+		for (int i = 0; i < localHistorySize; i++) {
+			historyItems[i] = localHistory.get(localHistory.size() - i - 1);
+		}
+		fSeparatorIndex = localHistorySize;
+		historyItems[localHistorySize] = getSeparatorLabel();
+		System.arraycopy(globalItems, 0, historyItems, localHistorySize + 1, globalItems.length);
+		return historyItems;
+	}
+
+	/**
+	 * Updates the local and global Expression histories.
+	 */
+	private void updateExpressionHistories() {
+		String newItem = getSourceViewer().getDocument().get();
+		if (newItem.length() == 0) {
+			return;
+		}
+
+		// Update local history
+		Stack<String> localHistory = fLocalExpressionHistory.get(fVariable);
+		if (localHistory == null) {
+			localHistory = new Stack<>();
+			fLocalExpressionHistory.put(fVariable, localHistory);
+		}
+
+		localHistory.remove(newItem);
+		localHistory.push(newItem);
+
+		// Update global history
+		String[] globalItems = readExpressionHistory(fExpressionHistoryDialogSettings);
+		if (globalItems.length > 0 && newItem.equals(globalItems[0])) {
+			return;
+		}
+
+		if (globalItems.length == 0) {
+			globalItems = new String[1];
+		} else {
+			String[] tempItems = new String[globalItems.length + 1];
+			System.arraycopy(globalItems, 0, tempItems, 1, globalItems.length);
+			globalItems = tempItems;
+		}
+		globalItems[0] = newItem;
+		storeExpressionHistory(globalItems, fExpressionHistoryDialogSettings);
+	}
+
+	/**
+	 * Reads the Expression history from the given dialog settings.
+	 *
+	 * @param dialogSettings
+	 *            the dialog settings
+	 * @return the Expression history
+	 */
+	private static String[] readExpressionHistory(IDialogSettings dialogSettings) {
+		int count = 0;
+		try {
+			count = dialogSettings.getInt(DS_KEY_HISTORY_ENTRY_COUNT);
+		} catch (NumberFormatException ex) {
+			// No history yet
+		}
+		count = Math.min(count, MAX_HISTORY_SIZE);
+		String[] expressions = new String[count];
+		for (int i = 0; i < count; i++) {
+			expressions[i] = dialogSettings.get(DS_KEY_HISTORY_ENTRY_PREFIX + i);
+		}
+		return expressions;
+	}
+
+	/**
+	 * Writes the given Expressions into the given dialog settings.
+	 *
+	 * @param expressions
+	 *            an array of strings containing the Expressions
+	 * @param dialogSettings
+	 *            the dialog settings
+	 */
+	private static void storeExpressionHistory(String[] expressions, IDialogSettings dialogSettings) {
+		int length = Math.min(expressions.length, MAX_HISTORY_SIZE);
+		int count = 0;
+		outer: for (int i = 0; i < length; i++) {
+			for (int j = 0; j < i; j++) {
+				if (expressions[i].equals(expressions[j])) {
+					break outer;
+				}
+			}
+			dialogSettings.put(DS_KEY_HISTORY_ENTRY_PREFIX + count, expressions[i]);
+			count = count + 1;
+		}
+		dialogSettings.put(DS_KEY_HISTORY_ENTRY_COUNT, count);
+	}
+
+	/**
+	 * Returns the label for the history separator.
+	 *
+	 * @return the label for the history separator
+	 */
+	private String getSeparatorLabel() {
+		int borderWidth = fExpressionHistory.computeTrim(0, 0, 0, 0).width;
+		Rectangle rect = fExpressionHistory.getBounds();
+		int width = rect.width - borderWidth;
+
+		GC gc = new GC(fExpressionHistory);
+		gc.setFont(fExpressionHistory.getFont());
+
+		int fSeparatorWidth = gc.getAdvanceWidth('-');
+		String separatorLabel = PropertyPageMessages.JavaVariableDetailsPane_historySeparator;
+		int fMessageLength = gc.textExtent(separatorLabel).x;
+
+		gc.dispose();
+
+		StringBuilder dashes = new StringBuilder();
+		int chars = (((width - fMessageLength) / fSeparatorWidth) / 2) - 2;
+		for (int i = 0; i < chars; i++) {
+			dashes.append('-');
+		}
+
+		StringBuilder result = new StringBuilder();
+		result.append(dashes);
+		result.append(" " + separatorLabel + " "); //$NON-NLS-1$//$NON-NLS-2$
+		result.append(dashes);
+		return result.toString().trim();
+	}
+
+	@Override
+	public String getDescription() {
+		return DESCRIPTION;
+	}
+
+	@Override
+	public String getID() {
+		return JAVA_VARIABLE_DETAIL_PANE_VARIABLES;
+	}
+
+	@Override
+	public String getName() {
+		return NAME;
+	}
+
+	@Override
+	public void display(IStructuredSelection selection) {
+		if (fExpressionHistory != null && selection != null && selection.getFirstElement() instanceof IJavaVariable) {
+			IJavaVariable variable = (IJavaVariable) (selection.getFirstElement());
+			if (fVariable == null || !fVariable.equals(variable)) {
+				fVariable = variable;
+				fExpressionHistory.setEnabled(true);
+				initializeExpressionHistoryDropDown();
+			}
+		}
+		super.display(selection);
+	}
+
+	/**
+	 * Clears the Java variable detail viewer, removes all text.
+	 */
+	@Override
+	protected void clearSourceViewer(){
+		fVariable = null;
+		if (fExpressionHistory != null) {
+			fExpressionHistory.setEnabled(false);
+		}
+		super.clearSourceViewer();
+	}
+
+	@Override
+	public void dispose() {
+		if (fExpressionHistory != null) {
+			fExpressionHistory.dispose();
+		}
+		if (fLocalExpressionHistory != null) {
+			fLocalExpressionHistory.clear();
+		}
+		if (focusListener != null && getSourceViewer() != null && getSourceViewer().getTextWidget() != null) {
+			getSourceViewer().getTextWidget().removeFocusListener(focusListener);
+		}
+		super.dispose();
+	}
+}
+
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariablesDetailPaneFactory.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariablesDetailPaneFactory.java
new file mode 100644
index 0000000..c057a6d
--- /dev/null
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariablesDetailPaneFactory.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.debug.ui.variables;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.debug.ui.IDetailPane;
+import org.eclipse.debug.ui.IDetailPaneFactory;
+import org.eclipse.jdt.debug.core.IJavaVariable;
+import org.eclipse.jdt.internal.debug.ui.propertypages.PropertyPageMessages;
+import org.eclipse.jface.viewers.IStructuredSelection;
+
+/**
+ * Detail pane factory for Java variable.
+ *
+ * @since 3.10
+ */
+public class JavaVariablesDetailPaneFactory implements IDetailPaneFactory {
+
+	/**
+	 * Maps pane IDs to names
+	 */
+	private Map<String, String> fNameMap;
+
+	@Override
+	public Set<String> getDetailPaneTypes(IStructuredSelection selection) {
+		HashSet<String> set = new HashSet<>();
+		if (selection.size() == 1) {
+			IJavaVariable b = (IJavaVariable) selection.getFirstElement();
+			if (b != null) {
+				set.add(JavaVariablesDetailPane.JAVA_VARIABLE_DETAIL_PANE_VARIABLES);
+			}
+		}
+		return set;
+	}
+
+	@Override
+	public String getDefaultDetailPane(IStructuredSelection selection) {
+		if (selection.size() == 1) {
+			IJavaVariable b = (IJavaVariable) selection.getFirstElement();
+			if (b != null) {
+				return JavaVariablesDetailPane.JAVA_VARIABLE_DETAIL_PANE_VARIABLES;
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public IDetailPane createDetailPane(String paneID) {
+		if (JavaVariablesDetailPane.JAVA_VARIABLE_DETAIL_PANE_VARIABLES.equals(paneID)) {
+			return new JavaVariablesDetailPane();
+		}
+		return null;
+	}
+
+	@Override
+	public String getDetailPaneName(String paneID) {
+		return getNameMap().get(paneID);
+	}
+
+	@Override
+	public String getDetailPaneDescription(String paneID) {
+		return getNameMap().get(paneID);
+	}
+
+	private Map<String, String> getNameMap() {
+		if (fNameMap == null) {
+			fNameMap = new HashMap<>();
+			fNameMap.put(JavaVariablesDetailPane.JAVA_VARIABLE_DETAIL_PANE_VARIABLES, PropertyPageMessages.JavaVariableDetailsPane_settings);
+		}
+		return fNameMap;
+	}
+
+}
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaLineBreakpoint.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaLineBreakpoint.java
index 71ab3ca..c7d8318 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaLineBreakpoint.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaLineBreakpoint.java
@@ -324,6 +324,14 @@
 		if (locations.size() <= 1) {
 			return locations;
 		}
+
+		// JVM has multiple breakpoint locations for this line.
+		// Bug 543385: in case we have no condition, we can allow to stop at every location.
+		// Bug 541110: In case we have condition, it will most likely fail due the wrong context
+		// if evaluated in a lambda where the condition arguments couldn't be resolved.
+		if (!hasCondition()) {
+			return locations;
+		}
 		List<Location> result = new ArrayList<>();
 		for (Location location : locations) {
 			Method method = location.method();
diff --git a/org.eclipse.jdt.launching/.settings/.api_filters b/org.eclipse.jdt.launching/.settings/.api_filters
index 984d02b..d50c85d 100644
--- a/org.eclipse.jdt.launching/.settings/.api_filters
+++ b/org.eclipse.jdt.launching/.settings/.api_filters
@@ -1,5 +1,20 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <component id="org.eclipse.jdt.launching" version="2">
+    <resource path="">
+        <filter comment="No API Changes" id="665845798">
+            <message_arguments>
+                <message_argument value="org.eclipse.jdt.launching"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="META-INF/MANIFEST.MF">
+        <filter comment="No API Changes" id="926941240">
+            <message_arguments>
+                <message_argument value="3.13.0"/>
+                <message_argument value="3.12.0"/>
+            </message_arguments>
+        </filter>
+    </resource>
     <resource path="launching/org/eclipse/jdt/launching/IRuntimeClasspathEntryResolver.java" type="org.eclipse.jdt.launching.IRuntimeClasspathEntryResolver">
         <filter comment="New method is a default method that delegates to an existing method" id="404000815">
             <message_arguments>
diff --git a/org.eclipse.jdt.launching/.settings/org.eclipse.pde.api.tools.prefs b/org.eclipse.jdt.launching/.settings/org.eclipse.pde.api.tools.prefs
index 3cf0ccb..05415eb 100644
--- a/org.eclipse.jdt.launching/.settings/org.eclipse.pde.api.tools.prefs
+++ b/org.eclipse.jdt.launching/.settings/org.eclipse.pde.api.tools.prefs
@@ -88,6 +88,8 @@
 automatically_removed_unused_problem_filters=false
 eclipse.preferences.version=1
 incompatible_api_component_version=Error
+incompatible_api_component_version_report_major_without_breaking_change=Error
+incompatible_api_component_version_report_minor_without_api_change=Error
 incompatible_api_component_version_include_major_without_breaking_change=Disabled
 incompatible_api_component_version_include_minor_without_api_change=Disabled
 invalid_since_tag_version=Error
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java
index 218d2ef..f0abb6d 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.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
@@ -19,6 +19,7 @@
 
 import java.io.File;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
@@ -410,19 +411,19 @@
 		}
 		return bootpathInfo;
 	}
+
 	/**
-	 * Returns the entries that should appear on the user portion of the
-	 * classpath as specified by the given launch configuration, as an array of
-	 * resolved strings. The returned array is empty if no classpath is
-	 * specified.
+	 * Returns the entries that should appear on the user portion of the classpath as specified by the given launch configuration, as an array of
+	 * resolved strings. The returned array is empty if no classpath is specified.
 	 *
 	 * @param configuration
 	 *            launch configuration
-	 * @return the classpath specified by the given launch configuration,
-	 *         possibly an empty array
+	 * @return the classpath specified by the given launch configuration, possibly an empty array
 	 * @exception CoreException
 	 *                if unable to retrieve the attribute
+	 * @deprecated use getClasspathAndModulepath
 	 */
+	@Deprecated
 	public String[] getClasspath(ILaunchConfiguration configuration)
 			throws CoreException {
 		IRuntimeClasspathEntry[] entries = JavaRuntime
@@ -1172,17 +1173,14 @@
 		if (moduleToLocations.isEmpty()) {
 			return moduleCLIOptions;
 		}
-		StringBuilder sb = new StringBuilder(moduleCLIOptions);
+
+		ArrayList<String> list = new ArrayList<>();
+
+		Collections.addAll(list, DebugPlugin.parseArguments(moduleCLIOptions));
 
 		for (Entry<String, String> entry : moduleToLocations.entrySet()) {
-			if (sb.length() > 0) {
-				sb.append(' ');
-			}
-			sb.append("--patch-module"); //$NON-NLS-1$
-			sb.append(' ');
-			sb.append(entry.getKey());
-			sb.append('=');
-			sb.append(entry.getValue());
+			list.add("--patch-module"); //$NON-NLS-1$
+			list.add(entry.getKey() + '=' + entry.getValue());
 		}
 
 		boolean excludeTestCode = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_EXCLUDE_TEST_CODE, false);
@@ -1191,18 +1189,12 @@
 			IJavaProject project = getJavaProject(configuration);
 			if (project != null) {
 				for (String moduleName : project.determineModulesOfProjectsWithNonEmptyClasspath()) {
-					if (sb.length() > 0) {
-						sb.append(' ');
-					}
-					sb.append("--add-reads"); //$NON-NLS-1$
-					sb.append(' ');
-					sb.append(moduleName);
-					sb.append('=');
-					sb.append("ALL-UNNAMED"); //$NON-NLS-1$
+					list.add("--add-reads"); //$NON-NLS-1$
+					list.add(moduleName + '=' + "ALL-UNNAMED"); //$NON-NLS-1$
 				}
 			}
 		}
-		return sb.toString();
+		return DebugPlugin.renderArguments(list.toArray(new String[list.size()]), null);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaLaunchDelegate.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaLaunchDelegate.java
index f4411b3..d2fbe86 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaLaunchDelegate.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaLaunchDelegate.java
@@ -93,10 +93,12 @@
 		// VM-specific attributes
 		Map<String, Object> vmAttributesMap = getVMSpecificAttributesMap(configuration);
 
-		// Bug 522333 :to be used for modulepath only for 4.7.*
 		String[][] paths = getClasspathAndModulepath(configuration);
+		if (paths == null || paths.length == 0) {
+			return null;
+		}
 		// Create VM config
-		VMRunnerConfiguration runConfig = new VMRunnerConfiguration(mainTypeName, getClasspath(configuration));
+		VMRunnerConfiguration runConfig = new VMRunnerConfiguration(mainTypeName, paths[0]);
 		runConfig.setProgramArguments(execArgs.getProgramArgumentsArray());
 		runConfig.setEnvironment(envp);
 		runConfig.setVMArguments(execArgs.getVMArgumentsArray());
@@ -125,7 +127,9 @@
 			runConfig.setBootClassPath(getBootpath(configuration));
 		} else if (supportsModule()) {
 			// module path
-			runConfig.setModulepath(paths[1]);
+			if (paths.length > 1) {
+				runConfig.setModulepath(paths[1]);
+			}
 			if (!configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_MODULE_CLI_OPTIONS, true)) {
 				runConfig.setOverrideDependencies(configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_MODULE_CLI_OPTIONS, "")); //$NON-NLS-1$
 			} else {