View | Details | Raw Unified | Return to bug 372588 | Differences between
and this patch

Collapse All | Expand All

(-)a/org.eclipse.jdt.junit.core/.gitignore (+1 lines)
Added Link Here
1
/bin/
(-)a/org.eclipse.jdt.junit.core/src/org/eclipse/jdt/internal/junit/model/TestCaseElement.java (-2 / +81 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Xavier Coulon <xcoulon@redhat.com> - https://bugs.eclipse.org/bugs/show_bug.cgi?id=102512 - [JUnit] test method name cut off before (
10
 *     Xavier Coulon <xcoulon@redhat.com> 
11
 *         - [JUnit] test method name cut off before '(' - https://bugs.eclipse.org/bugs/show_bug.cgi?id=102512
12
 *         - [JUnit] Add "Link with Editor" to JUnit view - https://bugs.eclipse.org/bugs/show_bug.cgi?id=372588 
11
 *******************************************************************************/
13
 *******************************************************************************/
12
14
13
package org.eclipse.jdt.internal.junit.model;
15
package org.eclipse.jdt.internal.junit.model;
Lines 15-29 Link Here
15
import org.eclipse.jdt.junit.model.ITestCaseElement;
17
import org.eclipse.jdt.junit.model.ITestCaseElement;
16
18
17
import org.eclipse.core.runtime.Assert;
19
import org.eclipse.core.runtime.Assert;
20
import org.eclipse.core.runtime.IAdaptable;
18
21
22
import org.eclipse.jdt.core.IJavaElement;
23
import org.eclipse.jdt.core.IMethod;
24
import org.eclipse.jdt.core.IType;
25
import org.eclipse.jdt.core.JavaModelException;
19
26
20
public class TestCaseElement extends TestElement implements ITestCaseElement {
27
import org.eclipse.jdt.internal.junit.JUnitCorePlugin;
28
29
/**
30
 * 
31
 * @since 3.7 implements {@link IAdaptable}
32
 */
33
public class TestCaseElement extends TestElement implements ITestCaseElement, IAdaptable {
34
35
	private IMethod fJavaMethod= null;
36
37
	private boolean fJavaMethodResolved= false;
21
38
22
	private boolean fIgnored;
39
	private boolean fIgnored;
23
40
24
	public TestCaseElement(TestSuiteElement parent, String id, String testName) {
41
	public TestCaseElement(TestSuiteElement parent, String id, String testName) {
25
		super(parent, id, testName);
42
		super(parent, id, testName);
26
		Assert.isNotNull(parent);
43
		Assert.isNotNull(parent);
44
	}
45
46
	/**
47
	 * @return the name of the Java Method associated with this {@link TestCaseElement}, ie, it
48
	 *         returns the valid java identifier part of the name (in particular, it removes the
49
	 *         brackets suffix for Parameterized JUnit tests).
50
	 * 
51
	 * 
52
	 */
53
	private String getJavaTestMethodName() {
54
		String testMethodName= getTestMethodName();
55
		for (int i= 0; i < testMethodName.length(); i++) {
56
			if (!Character.isJavaIdentifierPart(testMethodName.charAt(i))) {
57
				return testMethodName.substring(0, i);
58
			}
59
		}
60
		return testMethodName;
27
	}
61
	}
28
62
29
	/**
63
	/**
Lines 41-46 Link Here
41
		if (index > 0)
75
		if (index > 0)
42
			return testName.substring(0, index);
76
			return testName.substring(0, index);
43
		return testName;
77
		return testName;
78
	}
79
80
	/**
81
	 * Finds and returns the {@link IMethod} associated with this {@link TestCaseElement}.
82
	 * 
83
	 * @return the corresponding Java method element or null if not found.
84
	 * @since 3.7
85
	 */
86
	public IMethod getJavaMethod() {
87
		if (!fJavaMethodResolved) {
88
			try {
89
				final IType type= getJavaType();
90
				if (type != null) {
91
					final IMethod[] methods= type.getMethods();
92
					String testMethodName= getJavaTestMethodName();
93
					for (int i= 0; i < methods.length; i++) {
94
						if (methods[i].getElementName().equals(testMethodName)) {
95
							fJavaMethod= methods[i];
96
							return methods[i];
97
						}
98
					}
99
				}
100
				return null;
101
			} catch (JavaModelException e) {
102
				JUnitCorePlugin.log(e);
103
			} finally {
104
				fJavaMethodResolved= true;
105
			}
106
		}
107
		return fJavaMethod;
44
	}
108
	}
45
109
46
	/**
110
	/**
Lines 73-76 Link Here
73
	public String toString() {
137
	public String toString() {
74
		return "TestCase: " + getTestClassName() + "." + getTestMethodName() + " : " + super.toString(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
138
		return "TestCase: " + getTestClassName() + "." + getTestMethodName() + " : " + super.toString(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
75
	}
139
	}
140
141
	/**
142
	 * Provides support for converting this {@link TestCaseElement} into an {@link IMethod} when the
143
	 * given adapter class is {@link IJavaElement}.
144
	 * 
145
	 * @param adapter the class in which this {@link TestCaseElement} should be adapted.
146
	 * @return an object in the request type, or null if it could not be adapted.
147
	 * @since 3.7
148
	 */
149
	public Object getAdapter(Class adapter) {
150
		if (adapter != null && adapter.equals(IJavaElement.class)) {
151
			return getJavaMethod();
152
		}
153
		return null;
154
	}
76
}
155
}
(-)a/org.eclipse.jdt.junit.core/src/org/eclipse/jdt/internal/junit/model/TestElement.java (-1 / +31 lines)
Lines 9-15 Link Here
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Brock Janiczak (brockj@tpg.com.au)
10
 *     Brock Janiczak (brockj@tpg.com.au)
11
 *         - https://bugs.eclipse.org/bugs/show_bug.cgi?id=102236: [JUnit] display execution time next to each test
11
 *         - https://bugs.eclipse.org/bugs/show_bug.cgi?id=102236: [JUnit] display execution time next to each test
12
 *     Xavier Coulon <xcoulon@redhat.com> - https://bugs.eclipse.org/bugs/show_bug.cgi?id=102512 - [JUnit] test method name cut off before (
12
 *     Xavier Coulon <xcoulon@redhat.com> 
13
 *         - [JUnit] test method name cut off before '(' - https://bugs.eclipse.org/bugs/show_bug.cgi?id=102512
14
 *         - [JUnit] Add "Link with Editor" to JUnit view - https://bugs.eclipse.org/bugs/show_bug.cgi?id=372588 
13
 *******************************************************************************/
15
 *******************************************************************************/
14
16
15
package org.eclipse.jdt.internal.junit.model;
17
package org.eclipse.jdt.internal.junit.model;
Lines 19-24 Link Here
19
import org.eclipse.jdt.junit.model.ITestRunSession;
21
import org.eclipse.jdt.junit.model.ITestRunSession;
20
22
21
import org.eclipse.core.runtime.Assert;
23
import org.eclipse.core.runtime.Assert;
24
25
import org.eclipse.jdt.core.IType;
26
import org.eclipse.jdt.core.JavaModelException;
27
28
import org.eclipse.jdt.internal.junit.JUnitCorePlugin;
22
29
23
30
24
public abstract class TestElement implements ITestElement {
31
public abstract class TestElement implements ITestElement {
Lines 175-180 Link Here
175
182
176
	private boolean fAssumptionFailed;
183
	private boolean fAssumptionFailed;
177
184
185
	private IType fJavaType= null;
186
187
	private boolean fJavaTypeResolved= false;
188
178
	/**
189
	/**
179
	 * Running time in seconds. Contents depend on the current {@link #getProgressState()}:
190
	 * Running time in seconds. Contents depend on the current {@link #getProgressState()}:
180
	 * <ul>
191
	 * <ul>
Lines 324-329 Link Here
324
		return extractClassName(getTestName());
335
		return extractClassName(getTestName());
325
	}
336
	}
326
337
338
	/**
339
	 * @return the Java {@link IType} associated with this {@link TestElement}.
340
	 * @since 3.7
341
	 */
342
	public IType getJavaType() {
343
		if (!fJavaTypeResolved) {
344
			try {
345
				fJavaType= getTestRunSession().getLaunchedProject().findType(getClassName());
346
			} catch (JavaModelException e) {
347
				JUnitCorePlugin.log(e);
348
			} finally {
349
				fJavaTypeResolved= true;
350
			}
351
		}
352
		return fJavaType;
353
	}
354
355
356
327
	private static String extractClassName(String testNameString) {
357
	private static String extractClassName(String testNameString) {
328
		testNameString= extractRawClassName(testNameString);
358
		testNameString= extractRawClassName(testNameString);
329
		testNameString= testNameString.replace('$', '.'); // see bug 178503
359
		testNameString= testNameString.replace('$', '.'); // see bug 178503
(-)a/org.eclipse.jdt.junit.core/src/org/eclipse/jdt/internal/junit/model/TestSuiteElement.java (-2 / +71 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2008 IBM Corporation and others.
2
 * Copyright (c) 2000, 2014 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Xavier Coulon <xcoulon@redhat.com> -  [JUnit] Add "Link with Editor" to JUnit view - https://bugs.eclipse.org/bugs/show_bug.cgi?id=372588
10
 *******************************************************************************/
11
 *******************************************************************************/
11
12
12
package org.eclipse.jdt.internal.junit.model;
13
package org.eclipse.jdt.internal.junit.model;
Lines 17-24 Link Here
17
import org.eclipse.jdt.junit.model.ITestElement;
18
import org.eclipse.jdt.junit.model.ITestElement;
18
import org.eclipse.jdt.junit.model.ITestSuiteElement;
19
import org.eclipse.jdt.junit.model.ITestSuiteElement;
19
20
21
import org.eclipse.core.runtime.IAdaptable;
20
22
21
public class TestSuiteElement extends TestElement implements ITestSuiteElement {
23
import org.eclipse.jdt.core.IJavaElement;
24
import org.eclipse.jdt.core.IMethod;
25
import org.eclipse.jdt.core.IType;
26
27
28
public class TestSuiteElement extends TestElement implements ITestSuiteElement, IAdaptable {
29
30
	private IJavaElement fJavaElement= null;
31
32
	private boolean fJavaElementResolved= false;
22
33
23
	private List/*<TestElement>*/ fChildren;
34
	private List/*<TestElement>*/ fChildren;
24
	private Status fChildrenStatus;
35
	private Status fChildrenStatus;
Lines 151-154 Link Here
151
		return "TestSuite: " + getSuiteTypeName() + " : " + super.toString() + " (" + fChildren.size() + ")";   //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
162
		return "TestSuite: " + getSuiteTypeName() + " : " + super.toString() + " (" + fChildren.size() + ")";   //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
152
	}
163
	}
153
164
165
	/**
166
	 * Provides support for converting this {@link TestSuiteElement} into an {@link IType} (or an
167
	 * {@link IMethod} when this {@link TestSuiteElement} matches a JUnit Parameterized Test) when
168
	 * the given adapter class is {@link IJavaElement}.
169
	 * 
170
	 * @param adapter the class in which this {@link TestSuiteElement} should be adapted.
171
	 * @return an object in the request type, or null if it could not be adapted.
172
	 * @since 3.7
173
	 */
174
	public Object getAdapter(Class adapter) {
175
		if (adapter != null && adapter.equals(IJavaElement.class)) {
176
			return getJavaElement();
177
		}
178
		return null;
179
	}
180
181
	/**
182
	 * Returns the closest {@link IJavaElement} for the given {@link TestSuiteElement}, including
183
	 * with a work-around for Parameterized tests by looking at the child elements: if there's only
184
	 * one, return its Java {@link IMethod}. Otherwise, return the {@link IType}
185
	 * 
186
	 * @return the {@link IJavaElement} found for this {@link TestSuiteElement}.
187
	 * 
188
	 * @since 3.7
189
	 * @see TestElement#getJavaType()
190
	 */
191
	public IJavaElement getJavaElement() {
192
		if (!fJavaElementResolved) {
193
			// whatever happens, let's consider that the Java Type has been resolved, to make sure we don't come back here again for this TestSuitElement.
194
			fJavaElementResolved= true;
195
			fJavaElement= super.getJavaType();
196
			if (fJavaElement == null) {
197
				if (getChildren().length == 1 && getChildren()[0] instanceof TestCaseElement) {
198
					fJavaElement= ((TestCaseElement)getChildren()[0]).getJavaMethod();
199
				}
200
			}
201
		}
202
		return fJavaElement;
203
	}
204
205
	/**
206
	 * Returns the {@link IType} associated with the given {@link TestSuiteElement}, or uses the
207
	 * work-around in {@link TestSuiteElement#getJavaElement()} to retrieve the {@link IType}
208
	 * associated with the single child {@link TestCaseElement} if this {@link TestSuiteElement}
209
	 * matches a Parameterized JUnit Test.
210
	 * 
211
	 * @since 3.7
212
	 * @see TestElement#getJavaType()
213
	 */
214
	public IType getJavaType() {
215
		final IType javaType= super.getJavaType();
216
		if (javaType != null) {
217
			return javaType;
218
		} else if (getJavaElement() != null) {
219
			return (IType)fJavaElement.getAncestor(IJavaElement.TYPE);
220
		}
221
		return null;
222
	}
154
}
223
}
(-)a/org.eclipse.jdt.junit/.gitignore (+1 lines)
Added Link Here
1
/bin/
(-)a/org.eclipse.jdt.junit/src/org/eclipse/jdt/internal/junit/ui/TestRunnerViewPart.java (-1 / +128 lines)
Lines 16-21 Link Here
16
 *     Andrew Eisenberg <andrew@eisenberg.as> - [JUnit] Rerun failed first does not work with JUnit4 - https://bugs.eclipse.org/bugs/show_bug.cgi?id=140392
16
 *     Andrew Eisenberg <andrew@eisenberg.as> - [JUnit] Rerun failed first does not work with JUnit4 - https://bugs.eclipse.org/bugs/show_bug.cgi?id=140392
17
 *     Thirumala Reddy Mutchukota <thirumala@google.com> - [JUnit] Avoid rerun test launch on UI thread - https://bugs.eclipse.org/bugs/show_bug.cgi?id=411841
17
 *     Thirumala Reddy Mutchukota <thirumala@google.com> - [JUnit] Avoid rerun test launch on UI thread - https://bugs.eclipse.org/bugs/show_bug.cgi?id=411841
18
 *     Andrew Eisenberg <andrew@eisenberg.as> - [JUnit] Add a monospace font option for the junit results view - https://bugs.eclipse.org/bugs/show_bug.cgi?id=411794
18
 *     Andrew Eisenberg <andrew@eisenberg.as> - [JUnit] Add a monospace font option for the junit results view - https://bugs.eclipse.org/bugs/show_bug.cgi?id=411794
19
 *     Xavier Coulon <xcoulon@redhat.com> -  [JUnit] Add "Link with Editor" to JUnit view - https://bugs.eclipse.org/bugs/show_bug.cgi?id=372588
19
 *******************************************************************************/
20
 *******************************************************************************/
20
package org.eclipse.jdt.internal.junit.ui;
21
package org.eclipse.jdt.internal.junit.ui;
21
22
Lines 36-41 Link Here
36
import java.util.Iterator;
37
import java.util.Iterator;
37
import java.util.List;
38
import java.util.List;
38
39
40
import org.eclipse.jdt.junit.model.ITestElement.ProgressState;
39
import org.eclipse.jdt.junit.model.ITestElement.Result;
41
import org.eclipse.jdt.junit.model.ITestElement.Result;
40
42
41
import org.eclipse.swt.SWT;
43
import org.eclipse.swt.SWT;
Lines 96-101 Link Here
96
import org.eclipse.jface.dialogs.MessageDialog;
98
import org.eclipse.jface.dialogs.MessageDialog;
97
import org.eclipse.jface.operation.IRunnableWithProgress;
99
import org.eclipse.jface.operation.IRunnableWithProgress;
98
import org.eclipse.jface.resource.ImageDescriptor;
100
import org.eclipse.jface.resource.ImageDescriptor;
101
import org.eclipse.jface.viewers.ISelection;
99
102
100
import org.eclipse.ui.IActionBars;
103
import org.eclipse.ui.IActionBars;
101
import org.eclipse.ui.IEditorActionBarContributor;
104
import org.eclipse.ui.IEditorActionBarContributor;
Lines 149-154 Link Here
149
152
150
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
153
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
151
154
155
import org.eclipse.jdt.internal.ui.JavaPluginImages;
156
import org.eclipse.jdt.internal.ui.actions.AbstractToggleLinkingAction;
152
import org.eclipse.jdt.internal.ui.viewsupport.ViewHistory;
157
import org.eclipse.jdt.internal.ui.viewsupport.ViewHistory;
153
158
154
/**
159
/**
Lines 210-215 Link Here
210
	private Action fPreviousAction;
215
	private Action fPreviousAction;
211
216
212
	private StopAction fStopAction;
217
	private StopAction fStopAction;
218
	private LinkWithEditorAction fLinkWithEditorAction;
213
	private JUnitCopyAction fCopyAction;
219
	private JUnitCopyAction fCopyAction;
214
	private Action fPasteAction;
220
	private Action fPasteAction;
215
221
Lines 899-904 Link Here
899
		}
905
		}
900
	}
906
	}
901
907
908
	/**
909
	 * This action toggles whether this {@link TestRunnerViewPart} links its selection to the active
910
	 * editor.
911
	 *
912
	 */
913
	private class LinkWithEditorAction extends AbstractToggleLinkingAction {
914
915
		/** Image to use when the sync is on.*/
916
		private static final String SYNCED_GIF= "synced.gif"; //$NON-NLS-1$
917
		
918
		/** Image to use when the sync is broken.*/
919
		private static final String SYNC_BROKEN_GIF= "sync_broken.gif"; //$NON-NLS-1$
920
		
921
		/**
922
		 * Default image when the action is created (as defined in the constructor of the
923
		 * superclass).
924
		 */
925
		private String fIconName= SYNCED_GIF;
926
		
927
		LinkWithEditorAction() {
928
			super();
929
			// enable by default
930
			setChecked(true);
931
		}
932
933
		@Override
934
		public void run() {
935
			setLinkingWithEditorActive(isChecked());
936
		}
937
		
938
		/**
939
		 * Updates the Link image with a "normal link" image if parameter is true, or a
940
		 * "broken link" image otherwise
941
		 * 
942
		 * @param isInSync the state of synchronization
943
		 */
944
		public void updateLinkImage(boolean isInSync) {
945
			String iconName= isInSync ? SYNCED_GIF : SYNC_BROKEN_GIF;
946
			if (!iconName.equals(fIconName)) {
947
				fIconName= iconName;
948
				refreshIcon();
949
			}
950
		}
951
952
		private void refreshIcon() {
953
			JavaPluginImages.setLocalImageDescriptors(this, fIconName);
954
		}
955
956
	}
957
958
	/**
959
	 * @return {@code true} if the {@link LinkWithEditorAction} is checked, {@code false} otherwise.
960
	 * @since 3.8
961
	 */
962
	public boolean isLinkWithEditorActive() {
963
		return fLinkWithEditorAction.isChecked();
964
	}
965
966
	/**
967
	 * @return the {@link ProgressState} of the current {@link TestRunSession}, or
968
	 *         {@link ProgressState#NOT_STARTED} if there's no {@link TestRunSession} yet.
969
	 * @since 3.8
970
	 */
971
	public ProgressState getCurrentProgressState() {
972
		if (fTestRunSession == null) {
973
			return ProgressState.NOT_STARTED;
974
		}
975
		return fTestRunSession.getProgressState();
976
	}
977
978
902
	private class RerunLastAction extends Action {
979
	private class RerunLastAction extends Action {
903
		public RerunLastAction() {
980
		public RerunLastAction() {
904
			setText(JUnitMessages.TestRunnerViewPart_rerunaction_label);
981
			setText(JUnitMessages.TestRunnerViewPart_rerunaction_label);
Lines 1200-1205 Link Here
1200
		}
1277
		}
1201
	}
1278
	}
1202
1279
1280
	/**
1281
	 * Activate the 'Link with Editor' in the current {@link IWorkbenchPage}. (The
1282
	 * {@link TestViewer} will respond to {@link ISelection} changes.)
1283
	 * 
1284
	 * @param active boolean to indicate if the link with editor is active ({@code true}) or not (
1285
	 *            {@code false})
1286
	 * 
1287
	 * @since 3.8
1288
	 */
1289
	public void setLinkingWithEditorActive(final boolean active) {
1290
		if (active) {
1291
			getSite().getPage().addPostSelectionListener(fTestViewer);
1292
			fTestViewer.setSelection(getSite().getPage().getActiveEditor());
1293
		} else {
1294
			getSite().getPage().removePostSelectionListener(fTestViewer);
1295
			// force the icon to 'synced' mode
1296
			setLinkingWithEditorInSync(true);
1297
		}
1298
	}
1299
	
1300
1301
1302
	/**
1303
	 * Updates the Link image with a "normal link" image if parameter is true, or a "broken link"
1304
	 * image otherwise
1305
	 * 
1306
	 * @param isInSync the state of synchronization
1307
	 * 
1308
	 * @since 3.8
1309
	 */
1310
	public void setLinkingWithEditorInSync(final boolean isInSync) {
1311
		fLinkWithEditorAction.updateLinkImage(isInSync);
1312
	}
1313
1203
	private void startUpdateJobs() {
1314
	private void startUpdateJobs() {
1204
		postSyncProcessChanges();
1315
		postSyncProcessChanges();
1205
1316
Lines 1245-1251 Link Here
1245
		boolean hasErrorsOrFailures= hasErrorsOrFailures();
1356
		boolean hasErrorsOrFailures= hasErrorsOrFailures();
1246
		fNextAction.setEnabled(hasErrorsOrFailures);
1357
		fNextAction.setEnabled(hasErrorsOrFailures);
1247
		fPreviousAction.setEnabled(hasErrorsOrFailures);
1358
		fPreviousAction.setEnabled(hasErrorsOrFailures);
1248
1359
		fLinkWithEditorAction.setEnabled(fTestRunSession != null);
1249
		fTestViewer.processChangesInUI();
1360
		fTestViewer.processChangesInUI();
1250
	}
1361
	}
1251
1362
Lines 1512-1517 Link Here
1512
				stopUpdateJobs();
1623
				stopUpdateJobs();
1513
1624
1514
				fStopAction.setEnabled(fTestRunSession.isKeptAlive());
1625
				fStopAction.setEnabled(fTestRunSession.isKeptAlive());
1626
				// if "Link with Editor" is active, register the listener
1627
				if (isLinkWithEditorActive()) {
1628
					getSite().getPage().addPostSelectionListener(fTestViewer);
1629
					fTestViewer.setSelection(getSite().getPage().getActiveEditor());
1630
				}
1631
1515
				fTestViewer.expandFirstLevel();
1632
				fTestViewer.expandFirstLevel();
1516
			}
1633
			}
1517
		}
1634
		}
Lines 1579-1584 Link Here
1579
		if (fFailureTrace != null) {
1696
		if (fFailureTrace != null) {
1580
			fFailureTrace.dispose();
1697
			fFailureTrace.dispose();
1581
		}
1698
		}
1699
		getSite().getPage().removePostSelectionListener(fTestViewer);
1582
	}
1700
	}
1583
1701
1584
	private void disposeImages() {
1702
	private void disposeImages() {
Lines 1783-1788 Link Here
1783
		if (!testRunSessions.isEmpty()) {
1901
		if (!testRunSessions.isEmpty()) {
1784
			fTestRunSessionListener.sessionAdded(testRunSessions.get(0));
1902
			fTestRunSessionListener.sessionAdded(testRunSessions.get(0));
1785
		}
1903
		}
1904
		fLinkWithEditorAction.setChecked(true);
1905
		setLinkingWithEditorActive(true);
1906
		setLinkingWithEditorInSync(true);
1786
	}
1907
	}
1787
1908
1788
	private void addDropAdapter(Composite parent) {
1909
	private void addDropAdapter(Composite parent) {
Lines 1887-1892 Link Here
1887
		fStopAction= new StopAction();
2008
		fStopAction= new StopAction();
1888
		fStopAction.setEnabled(false);
2009
		fStopAction.setEnabled(false);
1889
2010
2011
		fLinkWithEditorAction= new LinkWithEditorAction();
2012
		fLinkWithEditorAction.setChecked(false);
2013
		fLinkWithEditorAction.setEnabled(false);
2014
1890
		fRerunLastTestAction= new RerunLastAction();
2015
		fRerunLastTestAction= new RerunLastAction();
1891
		IHandlerService handlerService= getSite().getWorkbenchWindow().getService(IHandlerService.class);
2016
		IHandlerService handlerService= getSite().getWorkbenchWindow().getService(IHandlerService.class);
1892
		IHandler handler = new AbstractHandler() {
2017
		IHandler handler = new AbstractHandler() {
Lines 1937-1942 Link Here
1937
		toolBar.add(fRerunFailedFirstAction);
2062
		toolBar.add(fRerunFailedFirstAction);
1938
		toolBar.add(fStopAction);
2063
		toolBar.add(fStopAction);
1939
		toolBar.add(fViewHistory.createHistoryDropDownAction());
2064
		toolBar.add(fViewHistory.createHistoryDropDownAction());
2065
		toolBar.add(new Separator());
2066
		toolBar.add(fLinkWithEditorAction);
1940
2067
1941
2068
1942
		viewMenu.add(fShowTestHierarchyAction);
2069
		viewMenu.add(fShowTestHierarchyAction);
(-)a/org.eclipse.jdt.junit/src/org/eclipse/jdt/internal/junit/ui/TestViewer.java (-4 / +293 lines)
Lines 9-16 Link Here
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Brock Janiczak (brockj@tpg.com.au)
10
 *     Brock Janiczak (brockj@tpg.com.au)
11
 *         - https://bugs.eclipse.org/bugs/show_bug.cgi?id=102236: [JUnit] display execution time next to each test
11
 *         - https://bugs.eclipse.org/bugs/show_bug.cgi?id=102236: [JUnit] display execution time next to each test
12
 *     Xavier Coulon <xcoulon@redhat.com> - https://bugs.eclipse.org/bugs/show_bug.cgi?id=102512 - [JUnit] test method name cut off before (
12
 *     Xavier Coulon <xcoulon@redhat.com>
13
13
 *         - https://bugs.eclipse.org/bugs/show_bug.cgi?id=102512 - [JUnit] test method name cut off before (
14
 *         - https://bugs.eclipse.org/bugs/show_bug.cgi?id=372588 - [JUnit] Add "Link with Editor" to JUnit view
14
 *******************************************************************************/
15
 *******************************************************************************/
15
16
16
package org.eclipse.jdt.internal.junit.ui;
17
package org.eclipse.jdt.internal.junit.ui;
Lines 23-29 Link Here
23
import java.util.List;
24
import java.util.List;
24
import java.util.ListIterator;
25
import java.util.ListIterator;
25
26
27
import org.eclipse.jdt.junit.model.ITestCaseElement;
26
import org.eclipse.jdt.junit.model.ITestElement;
28
import org.eclipse.jdt.junit.model.ITestElement;
29
import org.eclipse.jdt.junit.model.ITestElement.ProgressState;
30
import org.eclipse.jdt.junit.model.ITestSuiteElement;
27
31
28
import org.eclipse.swt.SWT;
32
import org.eclipse.swt.SWT;
29
import org.eclipse.swt.dnd.Clipboard;
33
import org.eclipse.swt.dnd.Clipboard;
Lines 42-49 Link Here
42
import org.eclipse.jface.action.MenuManager;
46
import org.eclipse.jface.action.MenuManager;
43
import org.eclipse.jface.action.Separator;
47
import org.eclipse.jface.action.Separator;
44
import org.eclipse.jface.viewers.AbstractTreeViewer;
48
import org.eclipse.jface.viewers.AbstractTreeViewer;
49
import org.eclipse.jface.viewers.ISelection;
45
import org.eclipse.jface.viewers.ISelectionChangedListener;
50
import org.eclipse.jface.viewers.ISelectionChangedListener;
46
import org.eclipse.jface.viewers.IStructuredSelection;
51
import org.eclipse.jface.viewers.IStructuredSelection;
52
import org.eclipse.jface.viewers.ITreeSelection;
47
import org.eclipse.jface.viewers.SelectionChangedEvent;
53
import org.eclipse.jface.viewers.SelectionChangedEvent;
48
import org.eclipse.jface.viewers.StructuredSelection;
54
import org.eclipse.jface.viewers.StructuredSelection;
49
import org.eclipse.jface.viewers.StructuredViewer;
55
import org.eclipse.jface.viewers.StructuredViewer;
Lines 52-64 Link Here
52
import org.eclipse.jface.viewers.Viewer;
58
import org.eclipse.jface.viewers.Viewer;
53
import org.eclipse.jface.viewers.ViewerFilter;
59
import org.eclipse.jface.viewers.ViewerFilter;
54
60
61
import org.eclipse.jface.text.ITextSelection;
62
63
import org.eclipse.ui.IEditorPart;
64
import org.eclipse.ui.ISelectionListener;
55
import org.eclipse.ui.IWorkbenchActionConstants;
65
import org.eclipse.ui.IWorkbenchActionConstants;
66
import org.eclipse.ui.IWorkbenchPart;
67
import org.eclipse.ui.PartInitException;
56
import org.eclipse.ui.part.PageBook;
68
import org.eclipse.ui.part.PageBook;
69
import org.eclipse.ui.views.contentoutline.ContentOutline;
57
70
58
import org.eclipse.debug.core.ILaunchConfiguration;
71
import org.eclipse.debug.core.ILaunchConfiguration;
59
import org.eclipse.debug.core.ILaunchManager;
72
import org.eclipse.debug.core.ILaunchManager;
60
73
74
import org.eclipse.jdt.core.IClassFile;
75
import org.eclipse.jdt.core.ICompilationUnit;
76
import org.eclipse.jdt.core.IJavaElement;
61
import org.eclipse.jdt.core.IJavaProject;
77
import org.eclipse.jdt.core.IJavaProject;
78
import org.eclipse.jdt.core.IMethod;
62
import org.eclipse.jdt.core.IType;
79
import org.eclipse.jdt.core.IType;
63
import org.eclipse.jdt.core.JavaModelException;
80
import org.eclipse.jdt.core.JavaModelException;
64
81
Lines 72-82 Link Here
72
89
73
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
90
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
74
91
92
import org.eclipse.jdt.ui.JavaUI;
93
94
import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor;
95
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
96
import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
75
import org.eclipse.jdt.internal.ui.viewsupport.ColoringLabelProvider;
97
import org.eclipse.jdt.internal.ui.viewsupport.ColoringLabelProvider;
76
import org.eclipse.jdt.internal.ui.viewsupport.SelectionProviderMediator;
98
import org.eclipse.jdt.internal.ui.viewsupport.SelectionProviderMediator;
77
99
78
100
79
public class TestViewer {
101
public class TestViewer implements ISelectionListener {
80
	private final class TestSelectionListener implements ISelectionChangedListener {
102
	private final class TestSelectionListener implements ISelectionChangedListener {
81
		public void selectionChanged(SelectionChangedEvent event) {
103
		public void selectionChanged(SelectionChangedEvent event) {
82
			handleSelected();
104
			handleSelected();
Lines 343-348 Link Here
343
			testElement= (TestElement) selection.getFirstElement();
365
			testElement= (TestElement) selection.getFirstElement();
344
		}
366
		}
345
		fTestRunnerPart.handleTestSelected(testElement);
367
		fTestRunnerPart.handleTestSelected(testElement);
368
		// if LinkWithEditor is active, reveal the JavaEditor and select the java type or method
369
		// matching the selected test element, even if the JavaEditor is opened by not active.
370
		if (fTestRunnerPart.isLinkWithEditorActive()) {
371
			handleTestElementSelected(testElement);
372
		}
346
	}
373
	}
347
374
348
	public synchronized void setShowTime(boolean showTime) {
375
	public synchronized void setShowTime(boolean showTime) {
Lines 609-614 Link Here
609
			fTreeViewer.reveal(current);
636
			fTreeViewer.reveal(current);
610
	}
637
	}
611
638
639
	/**
640
	 * Sets the current selection from the given {@link IEditorPart} (if it is a
641
	 * {@link CompilationUnitEditor}) and its selection.
642
	 * 
643
	 * @param editor the selected Java Element in the active Compilation Unit Editor
644
	 * 
645
	 * @since 3.8
646
	 */
647
	public void setSelection(final IEditorPart editor) {
648
		if (editor != null) {
649
			final IJavaElement selectedJavaElement= getSelectedJavaElementInEditor(editor);
650
			setSelection(selectedJavaElement);
651
		}
652
	}
653
	
654
	/**
655
	 * Sets the current selection from the given {@link IJavaElement} if it matches an
656
	 * {@link ITestCaseElement} and updates the LinkWithEditorAction image in the associated
657
	 * {@link TestRunnerViewPart}.
658
	 * 
659
	 * @param activeJavaElement the selected Java Element (or null) in the active
660
	 *            {@link IWorkbenchPart}
661
	 * 
662
	 */
663
	private void setSelection(final IJavaElement activeJavaElement) {
664
		final ITestElement activeTestCaseElement= findTestElement(activeJavaElement);
665
		if (activeTestCaseElement != null) {
666
			// update the current selection in the viewer if it does not match with the java element selected in the given part (if it's not the parent TestViewerPart)
667
			final Object currentSelection= getCurrentViewerSelection();
668
			if ((currentSelection instanceof TestCaseElement && ((TestCaseElement)currentSelection).getJavaMethod() != null && !((TestCaseElement)currentSelection).getJavaMethod().equals(
669
					activeJavaElement))
670
					|| (currentSelection instanceof TestSuiteElement && ((TestSuiteElement)currentSelection).getJavaType() != null && !((TestSuiteElement)currentSelection).getJavaType().equals(
671
							activeJavaElement))) {
672
				final IStructuredSelection selection= new StructuredSelection(activeTestCaseElement);
673
				fSelectionProvider.setSelection(selection, true);
674
			}
675
			// ensure link with editor is in 'synced' mode
676
			fTestRunnerPart.setLinkingWithEditorInSync(true);
677
		}
678
		else {
679
			// selection is out-of-sync: show a different icon on the button.
680
			fTestRunnerPart.setLinkingWithEditorInSync(false);
681
		}
682
	}
683
684
	/**
685
	 * @return the current selection in the JUnit Viewer (provided by the underlying selection
686
	 *         provider), or {@code null} if the kind of selection is not an {@link ITreeSelection}
687
	 *         nor an {@link IStructuredSelection}.
688
	 */
689
	private Object getCurrentViewerSelection() {
690
		final ISelection currentSelection= fSelectionProvider.getSelection();
691
		if (currentSelection instanceof ITreeSelection) {
692
			return ((ITreeSelection)currentSelection).getFirstElement();
693
		} else if (currentSelection instanceof IStructuredSelection) {
694
			return ((IStructuredSelection)currentSelection).getFirstElement();
695
		}
696
		return null;
697
	}
698
699
	/**
700
	 * Finds the {@link ITestElement} from the given {@link IJavaElement}
701
	 * 
702
	 * @param javaElement the java element associated with the {@link ITestElement} to find.
703
	 * @return the {@link ITestElement} or null if it could not be found.
704
	 */
705
	private ITestElement findTestElement(final IJavaElement javaElement) {
706
		// skip if JUnit is still running or if no Java element was selected
707
		if (fTestRunnerPart.getCurrentProgressState() != ProgressState.COMPLETED || javaElement == null) {
708
			return null;
709
		}
710
		switch (javaElement.getElementType()) {
711
			case IJavaElement.METHOD:
712
				final IMethod javaMethod= (IMethod)javaElement;
713
				final IType javaType= (IType)javaMethod.getAncestor(IJavaElement.TYPE);
714
				final String testClassName= javaType.getFullyQualifiedName();
715
				final String testMethodName= javaMethod.getElementName();
716
				return findTestCaseElement(fTestRunSession.getTestRoot(), testClassName, testMethodName);
717
			case IJavaElement.TYPE:
718
				return findTestSuiteElement(fTestRunSession.getTestRoot(), ((IType)javaElement).getFullyQualifiedName());
719
			default:
720
				return null;
721
		}
722
	}
723
724
	/**
725
	 * Finds the {@link ITestCaseElement} with the given test class name and test method name in the
726
	 * given {@link ITestSuiteElement}
727
	 * 
728
	 * @param parentElement the parent Test Suite
729
	 * @param testClassName the name of the test class
730
	 * @param testMethodName the name of the test method
731
	 * 
732
	 * @return the {@link ITestCaseElement} or null if it could not be found.
733
	 */
734
	private ITestCaseElement findTestCaseElement(final ITestSuiteElement parentElement, final String testClassName, final String testMethodName) {
735
		for (ITestElement childElement : parentElement.getChildren()) {
736
			if (childElement instanceof ITestCaseElement) {
737
				final TestCaseElement testCaseElement= (TestCaseElement)childElement;
738
				if (testCaseElement.getJavaType() != null && testCaseElement.getJavaType().getFullyQualifiedName().equals(testClassName) && testCaseElement.getJavaMethod() != null
739
						&& testCaseElement.getJavaMethod() != null && testCaseElement.getJavaMethod().getElementName().equals(testMethodName)) {
740
					return testCaseElement;
741
				}
742
			} else if (childElement instanceof ITestSuiteElement) {
743
				final ITestCaseElement localResult= findTestCaseElement((ITestSuiteElement)childElement, testClassName, testMethodName);
744
				if (localResult != null) {
745
					return localResult;
746
				}
747
			}
748
		}
749
		return null;
750
	}
751
752
	/**
753
	 * Finds the {@link ITestSuiteElement} with the given test class name in the given
754
	 * {@link ITestSuiteElement}
755
	 * 
756
	 * @param parentElement the parent Test Suite
757
	 * @param testClassName the name of the test class
758
	 * 
759
	 * @return the {@link ITestSuiteElement} or null if it could not be found.
760
	 */
761
	private ITestSuiteElement findTestSuiteElement(final ITestSuiteElement parentElement, final String testClassName) {
762
		for (ITestElement childElement : parentElement.getChildren()) {
763
			if (childElement instanceof ITestSuiteElement) {
764
				final ITestSuiteElement childTestSuite= (ITestSuiteElement)childElement;
765
				if (childTestSuite.getSuiteTypeName().equals(testClassName)) {
766
					return childTestSuite;
767
				}
768
				final ITestSuiteElement matchingNestedTestSuiteElement= findTestSuiteElement(childTestSuite, testClassName);
769
				if (matchingNestedTestSuiteElement != null) {
770
					return matchingNestedTestSuiteElement;
771
				}
772
			}
773
		}
774
		return null;
775
	}
776
612
	public void selectFirstFailure() {
777
	public void selectFirstFailure() {
613
		TestCaseElement firstFailure= getNextChildFailure(fTestRunSession.getTestRoot(), true);
778
		TestCaseElement firstFailure= getNextChildFailure(fTestRunSession.getTestRoot(), true);
614
		if (firstFailure != null)
779
		if (firstFailure != null)
Lines 722-726 Link Here
722
		fTreeViewer.expandToLevel(2);
887
		fTreeViewer.expandToLevel(2);
723
	}
888
	}
724
889
725
}
890
	/**
891
	 * Reacts to a selection change in the active {@link IWorkbenchPart} (or when another part
892
	 * received the focus).
893
	 * 
894
	 * @param part the {@link IWorkbenchPart} in which the selection change occurred
895
	 * @param selection the selection in the given part
896
	 * @since 3.8
897
	 */
898
	public void selectionChanged(IWorkbenchPart part, ISelection selection) {
899
		if (part instanceof IEditorPart) {
900
			setSelection((IEditorPart)part);
901
		} else if (part instanceof ContentOutline) {
902
			final ITreeSelection outlineSelection= (ITreeSelection) ((ContentOutline) part).getSelection();
903
			if (outlineSelection.size() == 1) {
904
				setSelection((IJavaElement) outlineSelection.getFirstElement());
905
			}
906
		}
907
	}
726
908
909
	/**
910
	 * @return the selected {@link IJavaElement} in the current editor if it is a {@link CompilationUnitEditor}, null otherwise.
911
	 * @param editor the editor
912
	 */
913
	private IJavaElement getSelectedJavaElementInEditor(final IEditorPart editor) {
914
		if (editor instanceof JavaEditor) {
915
			final JavaEditor javaEditor= (JavaEditor) editor;
916
			try {
917
				final IJavaElement inputJavaElement= JavaUI.getEditorInputJavaElement(editor.getEditorInput());
918
				// when the editor is opened on a .class file, not a .java source file
919
				if (inputJavaElement.getElementType() == IJavaElement.CLASS_FILE) {
920
					final IClassFile classFile= (IClassFile) inputJavaElement;
921
					return classFile.getType();
922
				}
923
				final ITextSelection selection= (ITextSelection) javaEditor.getSelectionProvider().getSelection();
924
				final ICompilationUnit compilationUnit= (ICompilationUnit)inputJavaElement.getAncestor(IJavaElement.COMPILATION_UNIT);
925
				final IJavaElement selectedElement= compilationUnit.getElementAt(selection.getOffset());
926
				// valid results
927
				if (selectedElement == null || selectedElement.getElementType() == IJavaElement.METHOD || selectedElement.getElementType() == IJavaElement.TYPE) {
928
					return selectedElement;
929
				}
930
				// if the selected element is not a Method or a Type, let's return something meaningful
931
				if (selectedElement.getElementType() == IJavaElement.FIELD) {
932
					return selectedElement.getAncestor(IJavaElement.TYPE);
933
				}
934
				if (selectedElement.getElementType() == IJavaElement.PACKAGE_DECLARATION) {
935
					return ((ICompilationUnit) selectedElement.getAncestor(IJavaElement.COMPILATION_UNIT)).findPrimaryType();
936
				}
937
				if (selectedElement.getElementType() == IJavaElement.IMPORT_CONTAINER || selectedElement.getElementType() == IJavaElement.IMPORT_DECLARATION) {
938
					return ((ICompilationUnit) selectedElement.getAncestor(IJavaElement.COMPILATION_UNIT)).findPrimaryType();
939
				}
940
				return selectedElement;
941
			} catch (JavaModelException e) {
942
				JUnitPlugin.log(e);
943
			}
944
		}
945
		return null;
946
	}
947
948
	/**
949
	 * Handles the case when a {@link TestCaseElement} has been selected, unless there's a
950
	 * {@link TestRunSession} in progress.
951
	 * 
952
	 * @param testElement the new selected {@link TestCaseElement}
953
	 */
954
	private void handleTestElementSelected(final ITestElement testElement) {
955
		if (fTestRunnerPart.getCurrentProgressState().equals(ProgressState.RUNNING)) {
956
			return;
957
		}
958
		if (testElement instanceof TestCaseElement) {
959
			final IMethod selectedMethod= ((TestCaseElement)testElement).getJavaMethod();
960
			handleJavaElementSelected(selectedMethod);
961
		} else if (testElement instanceof TestSuiteElement) {
962
			final IJavaElement selectedElement= ((TestSuiteElement)testElement).getJavaElement();
963
			handleJavaElementSelected(selectedElement);
964
		}
965
	}
966
967
	/**
968
	 * Reveals the given {@link IJavaElement} in its associated Editor if this later is already
969
	 * open, and sets the "Link with Editor" button state accordingly.
970
	 * 
971
	 * @param selectedJavaElement the selected {@link IJavaElement} in the {@link TestViewer} that
972
	 *            should be revealed in its Java Editor.
973
	 */
974
	private void handleJavaElementSelected(final IJavaElement selectedJavaElement) {
975
		// skip if there's no editor open (yet)
976
		if (fTestRunnerPart.getSite().getPage().getActiveEditor() == null) {
977
			return;
978
		}
979
		try {
980
			final IEditorPart editor= EditorUtility.isOpenInEditor(selectedJavaElement);
981
			if (selectedJavaElement != null && editor != null && editor instanceof JavaEditor) {
982
				final JavaEditor javaEditor= (JavaEditor)editor;
983
				final ITextSelection javaEditorSelection= (ITextSelection)javaEditor.getSelectionProvider().getSelection();
984
				final IEditorPart selectedMethodEditor= EditorUtility.isOpenInEditor(selectedJavaElement);
985
				// checks if the editor is already open or not
986
				if (selectedMethodEditor != null) {
987
					// Retrieve the current active editor
988
					final IEditorPart activeEditor= fTestRunnerPart.getSite().getPage().getActiveEditor();
989
					// open the required editor if it is not the active one
990
					if (!selectedMethodEditor.equals(activeEditor)) {
991
						EditorUtility.openInEditor(selectedJavaElement, false);
992
					}
993
					// retrieve the current java element (unless the associated compilation unit cannot be retrieved)
994
					final ICompilationUnit compilationUnit= (ICompilationUnit)selectedJavaElement.getAncestor(IJavaElement.COMPILATION_UNIT);
995
					fTestRunnerPart.setLinkingWithEditorInSync(true);
996
					if (compilationUnit != null) {
997
						final IJavaElement javaEditorSelectedElement= compilationUnit.getElementAt(javaEditorSelection.getOffset());
998
						// force to reveal the selected element in case where the editor was not active
999
						if (!selectedMethodEditor.equals(activeEditor) || !selectedJavaElement.equals(javaEditorSelectedElement)) {
1000
							EditorUtility.revealInEditor(selectedMethodEditor, selectedJavaElement);
1001
						}
1002
					}
1003
					return;
1004
				}
1005
			}
1006
		} catch (JavaModelException e) {
1007
			JUnitPlugin.log(e);
1008
		} catch (PartInitException e) {
1009
			// occurs if the editor could not be opened or the input element is not valid Status code
1010
			JUnitPlugin.log(e);
1011
		}
1012
		fTestRunnerPart.setLinkingWithEditorInSync(false);
1013
	}
1014
1015
}
(-)a/org.eclipse.jdt.ui/.gitignore (+1 lines)
Line 1 Link Here
1
/bin-jar-in-jar-loader/
1
/bin-jar-in-jar-loader/
2
/bin/

Return to bug 372588