diff --git a/debug/org.eclipse.debug.tests/plugin.properties b/debug/org.eclipse.debug.tests/plugin.properties
index 56ca2e3b1bb..64495cd2370 100755
--- a/debug/org.eclipse.debug.tests/plugin.properties
+++ b/debug/org.eclipse.debug.tests/plugin.properties
@@ -22,4 +22,5 @@ launchConfigurationType.name = Test Launch Type
extension.name = Debug File System
launchConfigurationType.name.0 = Cancelling Launch Type
launchConfigurationType.name.1 = Throwing Launch Type
-testBreakpoint.name = Test Breakpoint
\ No newline at end of file
+testBreakpoint.name = Test Breakpoint
+launchConfigurationType.name.2 = Example launch
\ No newline at end of file
diff --git a/debug/org.eclipse.debug.tests/plugin.xml b/debug/org.eclipse.debug.tests/plugin.xml
index 3738652a0cb..f8395ed7e27 100644
--- a/debug/org.eclipse.debug.tests/plugin.xml
+++ b/debug/org.eclipse.debug.tests/plugin.xml
@@ -163,4 +163,20 @@
priority="-1"
class="org.eclipse.debug.tests.ui.TestVariableValueEditor3"/>
+
+
+
+
+
+
+
+
+
diff --git a/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java b/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java
index 5e5e9ba65f6..2e91df5d59f 100644
--- a/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java
+++ b/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java
@@ -44,6 +44,7 @@
import org.eclipse.debug.tests.sourcelookup.SourceLookupFacilityTests;
import org.eclipse.debug.tests.statushandlers.StatusHandlerTests;
import org.eclipse.debug.tests.stepfilters.StepFiltersTests;
+import org.eclipse.debug.tests.ui.LaunchConfigurationTabGroupViewerTest;
import org.eclipse.debug.tests.ui.VariableValueEditorManagerTests;
import org.eclipse.debug.tests.view.memory.MemoryRenderingTests;
import org.eclipse.debug.tests.view.memory.TableRenderingTests;
@@ -131,6 +132,7 @@
// Launch Groups
LaunchGroupTests.class,
+ LaunchConfigurationTabGroupViewerTest.class,
// Logical structure
LogicalStructureCacheTest.class,
diff --git a/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/ui/LaunchConfigurationTabGroupViewerTest.java b/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/ui/LaunchConfigurationTabGroupViewerTest.java
new file mode 100644
index 00000000000..2e966e0b96a
--- /dev/null
+++ b/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/ui/LaunchConfigurationTabGroupViewerTest.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2018, 2019 SAP SE and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SAP SE - initial version
+ *******************************************************************************/
+
+package org.eclipse.debug.tests.ui;
+
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunchConfigurationType;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.internal.ui.DebugUIPlugin;
+import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationPresentationManager;
+import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationsDialog;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.debug.ui.ILaunchConfigurationDialog;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+import org.eclipse.debug.ui.ILaunchConfigurationTabGroup;
+import org.eclipse.swt.widgets.Display;
+import org.junit.Before;
+import org.junit.Test;
+
+public class LaunchConfigurationTabGroupViewerTest {
+
+ private static interface ThrowingRunnable {
+ void run() throws T;
+ }
+
+ private static final String LAUNCH_CONFIG_TYPE_ID = "org.eclipse.debug.ui.tests.launchConfigurationType1";
+ private static final String LAUNCH_CONFIG_MODE = ILaunchManager.RUN_MODE;
+ private ILaunchConfigurationType fLaunchConfigurationType;
+ private LaunchConfigurationsDialog fLaunchConfigurationsDialog;
+
+ @Before
+ public void createDialog() throws CoreException {
+ fLaunchConfigurationType = getLaunchManager().getLaunchConfigurationType(LAUNCH_CONFIG_TYPE_ID);
+ ILaunchConfigurationTabGroup tabGroup = getLaunchConfigurationTabGroup(fLaunchConfigurationType);
+
+ fLaunchConfigurationsDialog = (LaunchConfigurationsDialog) createLaunchConfigurationDialog();
+ tabGroup.createTabs(fLaunchConfigurationsDialog, ILaunchManager.RUN_MODE);
+ }
+
+ @Test
+ public void tesAllTabsAreInitializedByDefault() throws CoreException {
+ // Create a launch configuration with a unique name
+ ThrowingRunnable createAndSelect1LaunchConfig = () -> {
+ fLaunchConfigurationsDialog.getTabViewer().setInput(createLaunchConfigurationInstance());
+ };
+
+ final ILaunchConfigurationTab[] tabs = runOnDialog(createAndSelect1LaunchConfig);
+
+ for (int i = 0; i < tabs.length; i++) {
+ assertThat("Tab " + i + " was not initialized", ((SpyTab) tabs[i]).isInitialized());
+ }
+ }
+
+ @Test
+ public void testFirstTabIsActivatedByDefault() throws CoreException {
+ // Create a launch configuration with a unique name
+ ThrowingRunnable createAndSelect1LaunchConfig = () -> {
+ fLaunchConfigurationsDialog.getTabViewer().setInput(createLaunchConfigurationInstance());
+ };
+
+ final ILaunchConfigurationTab[] tabs = runOnDialog(createAndSelect1LaunchConfig);
+ assertThat("The 1st tab was not activated", ((SpyTab) tabs[0]).isActivated());
+ }
+
+ @Test
+ public void testOtherTabInOtherConfigIsActivated() throws CoreException {
+ int secondTabIndex = 1;
+
+ ThrowingRunnable setActiveTab = () -> {
+ // Create and select launch config
+ fLaunchConfigurationsDialog.getTabViewer().setInput(createLaunchConfigurationInstance());
+
+ // Select another tab
+ fLaunchConfigurationsDialog.getTabViewer().setActiveTab(secondTabIndex);
+
+ // Create a new launch config. This one should activate the same tab by default.
+ fLaunchConfigurationsDialog.getTabViewer().setInput(createLaunchConfigurationInstance());
+ };
+
+ final ILaunchConfigurationTab[] tabs = runOnDialog(setActiveTab);
+
+ assertThat("The 1st tab of the other launch configuration shouldn't have been activated",
+ not(((SpyTab) tabs[0]).isActivated()));
+ assertThat("The tab was not activated", ((SpyTab) tabs[secondTabIndex]).isActivated());
+ }
+
+ @Test
+ public void testOtherTabIsActivated() throws CoreException {
+ int secondTabIndex = 1;
+
+ ThrowingRunnable setActiveTab = () -> {
+ // Create and select launch config
+ fLaunchConfigurationsDialog.getTabViewer().setInput(createLaunchConfigurationInstance());
+
+ // Select another tab
+ fLaunchConfigurationsDialog.getTabViewer().setActiveTab(secondTabIndex);
+ };
+
+ final ILaunchConfigurationTab[] tabs = runOnDialog(setActiveTab);
+
+ assertThat("The tab was not activated", ((SpyTab) tabs[secondTabIndex]).isActivated());
+ }
+
+ private ILaunchConfigurationWorkingCopy createLaunchConfigurationInstance() throws CoreException {
+ return fLaunchConfigurationType.newInstance(null, "MyLaunchConfiguration_" + System.currentTimeMillis());
+ }
+
+ private ILaunchConfigurationTab[] runOnDialog(ThrowingRunnable runnable) {
+ AtomicReference tabsRef = new AtomicReference<>();
+ AtomicReference throwableRef = new AtomicReference<>();
+
+ Display.getCurrent().asyncExec(() -> {
+ try {
+
+ runnable.run();
+
+ // I need to store the tabs here because the tab viewer (and all its tabs) are
+ // gone as soon as the dialog is closed
+ tabsRef.set(fLaunchConfigurationsDialog.getTabs());
+
+ } catch (Throwable e) {
+ // neither calling "fail" not throwing an exception will let the test fail so I
+ // need to store this and check it outside of the runnable
+ throwableRef.set(e);
+ DebugPlugin.log(e);
+ } finally {
+ fLaunchConfigurationsDialog.close();
+ }
+ });
+
+ fLaunchConfigurationsDialog.open();
+
+ if (throwableRef.get() != null) {
+ throw new AssertionError("An exception occurred while executing the runnable.", throwableRef.get());
+ }
+
+ return tabsRef.get();
+ }
+
+ /**
+ * Returns the standard java launch tab group
+ *
+ * @return the standard java launch tab group
+ * @throws CoreException
+ *
+ */
+ protected ILaunchConfigurationTabGroup getLaunchConfigurationTabGroup(
+ ILaunchConfigurationType launchConfigurationType) throws CoreException {
+ return LaunchConfigurationPresentationManager.getDefault().getTabGroup(launchConfigurationType,
+ LAUNCH_CONFIG_MODE);
+ }
+
+ /**
+ * Returns an instance of the launch configuration dialog on the the specified
+ * launch mode
+ *
+ * @return an new instance of IlaunchConfigurationDialog
+ *
+ */
+ protected ILaunchConfigurationDialog createLaunchConfigurationDialog() {
+ return new LaunchConfigurationsDialog(null, DebugUIPlugin.getDefault().getLaunchConfigurationManager()
+ .getLaunchGroup(IDebugUIConstants.ID_DEBUG_LAUNCH_GROUP));
+ }
+
+ /**
+ * Returns the launch manager
+ *
+ * @return launch manager
+ */
+ protected ILaunchManager getLaunchManager() {
+ return DebugPlugin.getDefault().getLaunchManager();
+ }
+}
diff --git a/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/ui/SpyTab.java b/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/ui/SpyTab.java
new file mode 100644
index 00000000000..c51c7eeb338
--- /dev/null
+++ b/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/ui/SpyTab.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2018, 2019 SAP SE and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SAP SE - initial version
+ *******************************************************************************/
+
+package org.eclipse.debug.tests.ui;
+
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * A Tab whose sole purpose is to say if it was initialized and activated
+ * properly
+ */
+public abstract class SpyTab extends AbstractLaunchConfigurationTab {
+
+ private boolean initialized;
+ private boolean activated;
+
+ @Override
+ public void createControl(Composite parent) {
+ }
+
+ @Override
+ public String getName() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void initializeFrom(ILaunchConfiguration configuration) {
+ initialized = true;
+ }
+
+ @Override
+ public void activated(ILaunchConfigurationWorkingCopy workingCopy) {
+ activated = true;
+ }
+
+ @Override
+ public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+ }
+
+ @Override
+ public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
+ }
+
+ public boolean isInitialized() {
+ return initialized;
+ }
+
+ public boolean isActivated() {
+ return activated;
+ }
+
+ // These 3 are necessary because I need 3 tabs in the launch config and using
+ // always the same kind of tab produces incorrect results
+ public static class SpyTabA extends SpyTab {
+ }
+
+ public static class SpyTabB extends SpyTab {
+ }
+
+ public static class SpyTabC extends SpyTab {
+ }
+}
diff --git a/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/ui/SpyTabGroup.java b/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/ui/SpyTabGroup.java
new file mode 100644
index 00000000000..ae760398229
--- /dev/null
+++ b/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/ui/SpyTabGroup.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2018, 2019 SAP SE and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SAP SE - initial version
+ *******************************************************************************/
+
+package org.eclipse.debug.tests.ui;
+
+import org.eclipse.debug.tests.ui.SpyTab.SpyTabA;
+import org.eclipse.debug.tests.ui.SpyTab.SpyTabB;
+import org.eclipse.debug.tests.ui.SpyTab.SpyTabC;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
+import org.eclipse.debug.ui.ILaunchConfigurationDialog;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+
+public class SpyTabGroup extends AbstractLaunchConfigurationTabGroup {
+
+ @Override
+ public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
+ setTabs(new ILaunchConfigurationTab[] { new SpyTabA(), new SpyTabB(), new SpyTabC() });
+ }
+
+}
\ No newline at end of file
diff --git a/debug/org.eclipse.debug.ui/META-INF/MANIFEST.MF b/debug/org.eclipse.debug.ui/META-INF/MANIFEST.MF
index 35261b4ac26..248d1bd2a89 100644
--- a/debug/org.eclipse.debug.ui/META-INF/MANIFEST.MF
+++ b/debug/org.eclipse.debug.ui/META-INF/MANIFEST.MF
@@ -13,7 +13,8 @@ Export-Package: org.eclipse.debug.internal.ui;
org.eclipse.debug.tests,
org.eclipse.debug.examples.ui,
org.eclipse.debug.examples.mixedmode,
- org.eclipse.debug.ui.launchview",
+ org.eclipse.debug.ui.launchview,
+ org.eclipse.debug.ui.tests",
org.eclipse.debug.internal.ui.actions;x-internal:=true,
org.eclipse.debug.internal.ui.actions.breakpointGroups;x-internal:=true,
org.eclipse.debug.internal.ui.actions.breakpointSortBy;x-internal:=true,
@@ -35,7 +36,7 @@ Export-Package: org.eclipse.debug.internal.ui;
org.eclipse.debug.internal.ui.hover;x-internal:=true,
org.eclipse.debug.internal.ui.importexport.breakpoints;x-internal:=true,
org.eclipse.debug.internal.ui.importexport.launchconfigurations;x-internal:=true,
- org.eclipse.debug.internal.ui.launchConfigurations;x-friends:="org.eclipse.debug.tests",
+ org.eclipse.debug.internal.ui.launchConfigurations;x-friends:="org.eclipse.debug.tests,org.eclipse.debug.ui.tests",
org.eclipse.debug.internal.ui.memory;x-internal:=true,
org.eclipse.debug.internal.ui.memory.provisional;x-internal:=true,
org.eclipse.debug.internal.ui.model.elements;x-friends:="org.eclipse.debug.examples.ui,org.eclipse.jdt.debug.ui,org.eclipse.wst.jsdt.debug.ui",
diff --git a/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationTabGroupViewer.java b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationTabGroupViewer.java
index 2ba0dd7e72c..c3f8c32f4cc 100644
--- a/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationTabGroupViewer.java
+++ b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationTabGroupViewer.java
@@ -22,6 +22,7 @@
import java.text.MessageFormat;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import org.eclipse.core.resources.IFile;
@@ -722,7 +723,9 @@ protected void inputChanged(Object input) {
if (finput instanceof ILaunchConfiguration configuration) {
boolean refreshTabs = true;
if (fWorkingCopy != null
- && fWorkingCopy.getOriginal().equals(configuration.getWorkingCopy().getOriginal())) {
+ && fWorkingCopy.getOriginal() != null //
+ && Objects.equals(fWorkingCopy.getOriginal(),
+ configuration.getWorkingCopy().getOriginal())) {
refreshTabs = false;
}
fOriginal = configuration;
@@ -1449,19 +1452,39 @@ protected void handleTabSelected() {
if (fDisposingTabs || fInitializingTabs) {
return;
}
+ int oldCurrentTabIndex = fCurrentTabIndex;
+ fCurrentTabIndex = fTabFolder.getSelectionIndex();
+
ILaunchConfigurationTab[] tabs = getTabs();
- if (fCurrentTabIndex == fTabFolder.getSelectionIndex() || tabs == null || tabs.length == 0 || fCurrentTabIndex > (tabs.length - 1)) {
+ if (oldCurrentTabIndex == fCurrentTabIndex || tabs == null || tabs.length == 0
+ || oldCurrentTabIndex > (tabs.length - 1)) {
return;
}
- if (fCurrentTabIndex != -1) {
- ILaunchConfigurationTab tab = tabs[fCurrentTabIndex];
- ILaunchConfigurationWorkingCopy wc = getWorkingCopy();
- if (wc != null) {
- tab.deactivated(wc);
- getActiveTab().activated(wc);
- }
+
+ deactivateTab(oldCurrentTabIndex);
+
+ activateCurrentlyActiveTab();
+ }
+
+ private void deactivateTab(int tabIndex) {
+ ILaunchConfigurationWorkingCopy wc = getWorkingCopy();
+
+ if (tabIndex < 0 || wc == null) {
+ return;
}
- fCurrentTabIndex = fTabFolder.getSelectionIndex();
+
+ getTabs()[tabIndex].deactivated(wc);
+ }
+
+ private void activateCurrentlyActiveTab() {
+ ILaunchConfigurationWorkingCopy wc = getWorkingCopy();
+ ILaunchConfigurationTab activeTab = getActiveTab();
+
+ if (wc == null || activeTab == null) {
+ return;
+ }
+
+ activeTab.activated(wc);
}
/**
diff --git a/debug/pom.xml b/debug/pom.xml
index e0e30f92cdd..a9ef91c731e 100644
--- a/debug/pom.xml
+++ b/debug/pom.xml
@@ -34,6 +34,7 @@
org.eclipse.debug.ui
org.eclipse.debug.ui.launchview
org.eclipse.debug.ui.launchview.tests
+ org.eclipse.debug.ui.tests
org.eclipse.ui.console
org.eclipse.ui.externaltools
org.eclipse.unittest.ui