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 (+28 lines)
Lines 20-25 Link Here
20
20
21
import org.eclipse.core.runtime.Assert;
21
import org.eclipse.core.runtime.Assert;
22
22
23
import org.eclipse.jdt.core.IType;
24
import org.eclipse.jdt.core.JavaModelException;
25
26
import org.eclipse.jdt.internal.junit.JUnitCorePlugin;
27
23
28
24
public abstract class TestElement implements ITestElement {
29
public abstract class TestElement implements ITestElement {
25
	public final static class Status {
30
	public final static class Status {
Lines 175-180 Link Here
175
180
176
	private boolean fAssumptionFailed;
181
	private boolean fAssumptionFailed;
177
182
183
	private IType fJavaType= null;
184
185
	private boolean fJavaTypeResolved= false;
186
178
	/**
187
	/**
179
	 * Running time in seconds. Contents depend on the current {@link #getProgressState()}:
188
	 * Running time in seconds. Contents depend on the current {@link #getProgressState()}:
180
	 * <ul>
189
	 * <ul>
Lines 324-329 Link Here
324
		return extractClassName(getTestName());
333
		return extractClassName(getTestName());
325
	}
334
	}
326
335
336
	/**
337
	 * @return the Java {@link IType} associated with this {@link TestElement}.
338
	 * @since 3.7
339
	 */
340
	public IType getJavaType() {
341
		if (!fJavaTypeResolved) {
342
			try {
343
				fJavaType= getTestRunSession().getLaunchedProject().findType(getClassName());
344
			} catch (JavaModelException e) {
345
				JUnitCorePlugin.log(e);
346
			} finally {
347
				fJavaTypeResolved= true;
348
			}
349
		}
350
		return fJavaType;
351
	}
352
353
354
327
	private static String extractClassName(String testNameString) {
355
	private static String extractClassName(String testNameString) {
328
		testNameString= extractRawClassName(testNameString);
356
		testNameString= extractRawClassName(testNameString);
329
		testNameString= testNameString.replace('$', '.'); // see bug 178503
357
		testNameString= testNameString.replace('$', '.'); // see bug 178503
(-)a/org.eclipse.jdt.junit.core/src/org/eclipse/jdt/internal/junit/model/TestSuiteElement.java (-2 / +69 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
	 * @see TestElement#getJavaType()
189
	 */
190
	public IJavaElement getJavaElement() {
191
		if (!fJavaElementResolved) {
192
			// 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.
193
			fJavaElementResolved= true;
194
			fJavaElement= super.getJavaType();
195
			if (fJavaElement == null) {
196
				if (getChildren().length == 1 && getChildren()[0] instanceof TestCaseElement) {
197
					fJavaElement= ((TestCaseElement)getChildren()[0]).getJavaMethod();
198
				}
199
			}
200
		}
201
		return fJavaElement;
202
	}
203
204
	/**
205
	 * Returns the {@link IType} associated with the given {@link TestSuiteElement}, or uses the
206
	 * work-around in {@link TestSuiteElement#getJavaElement()} to retrieve the {@link IType}
207
	 * associated with the single child {@link TestCaseElement} if this {@link TestSuiteElement}
208
	 * matches a Parameterized JUnit Test.
209
	 * 
210
	 * @see TestElement#getJavaType()
211
	 */
212
	public IType getJavaType() {
213
		final IType javaType= super.getJavaType();
214
		if (javaType != null) {
215
			return javaType;
216
		} else if (getJavaElement() != null) {
217
			return (IType)fJavaElement.getAncestor(IJavaElement.TYPE);
218
		}
219
		return null;
220
	}
154
}
221
}
(-)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 (+108 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 96-101 Link Here
96
import org.eclipse.jface.dialogs.MessageDialog;
97
import org.eclipse.jface.dialogs.MessageDialog;
97
import org.eclipse.jface.operation.IRunnableWithProgress;
98
import org.eclipse.jface.operation.IRunnableWithProgress;
98
import org.eclipse.jface.resource.ImageDescriptor;
99
import org.eclipse.jface.resource.ImageDescriptor;
100
import org.eclipse.jface.viewers.ISelection;
99
101
100
import org.eclipse.ui.IActionBars;
102
import org.eclipse.ui.IActionBars;
101
import org.eclipse.ui.IEditorActionBarContributor;
103
import org.eclipse.ui.IEditorActionBarContributor;
Lines 149-154 Link Here
149
151
150
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
152
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
151
153
154
import org.eclipse.jdt.internal.ui.JavaPluginImages;
155
import org.eclipse.jdt.internal.ui.actions.AbstractToggleLinkingAction;
152
import org.eclipse.jdt.internal.ui.viewsupport.ViewHistory;
156
import org.eclipse.jdt.internal.ui.viewsupport.ViewHistory;
153
157
154
/**
158
/**
Lines 210-215 Link Here
210
	private Action fPreviousAction;
214
	private Action fPreviousAction;
211
215
212
	private StopAction fStopAction;
216
	private StopAction fStopAction;
217
218
219
	/**
220
	 * Helper to open and activate editors.
221
	 * 
222
	 * @since 3.7
223
	 */
224
	private LinkWithEditorAction fLinkWithEditorAction;
225
213
	private JUnitCopyAction fCopyAction;
226
	private JUnitCopyAction fCopyAction;
214
	private Action fPasteAction;
227
	private Action fPasteAction;
215
228
Lines 732-737 Link Here
732
						JavaCore.addElementChangedListener(fDirtyListener);
745
						JavaCore.addElementChangedListener(fDirtyListener);
733
					}
746
					}
734
					warnOfContentChange();
747
					warnOfContentChange();
748
					fLinkWithEditorAction.setEnabled(fTestRunSession != null);
749
					setLinkingWithEditorActive(fTestRunSession != null);
735
				}
750
				}
736
			});
751
			});
737
			stopUpdateJobs();
752
			stopUpdateJobs();
Lines 897-902 Link Here
897
			stopTest();
912
			stopTest();
898
			setEnabled(false);
913
			setEnabled(false);
899
		}
914
		}
915
	}
916
917
	/**
918
	 * This action toggles whether this {@link TestRunnerViewPart} links its selection to the active
919
	 * editor.
920
	 *
921
	 */
922
	private class LinkWithEditorAction extends AbstractToggleLinkingAction {
923
924
		/** Image to use when the sync is on.*/
925
		private static final String SYNCED_GIF= "synced.gif"; //$NON-NLS-1$
926
		
927
		/** Image to use when the sync is broken.*/
928
		private static final String SYNC_BROKEN_GIF= "sync_broken.gif"; //$NON-NLS-1$
929
		
930
		private String fIconName = SYNC_BROKEN_GIF;
931
		
932
		LinkWithEditorAction() {
933
			// enable by default
934
			setChecked(true);
935
		}
936
937
		@Override
938
		public void run() {
939
			setLinkingWithEditorActive(isChecked());
940
		}
941
		
942
		/**
943
		 * Updates the Link image with a "normal link" image if parameter is true, or a
944
		 * "broken link" image otherwise
945
		 * 
946
		 * @param isInSync the state of synchronization
947
		 */
948
		public void updateLinkImage(boolean isInSync) {
949
			String iconName= isInSync ? SYNCED_GIF : SYNC_BROKEN_GIF;
950
			if (!iconName.equals(fIconName)) {
951
				JavaPluginImages.setLocalImageDescriptors(fLinkWithEditorAction, iconName);
952
				fIconName= iconName;
953
			}
954
		}
955
956
	}
957
958
	/**
959
	 * @return {@code true} if the {@link LinkWithEditorAction} is checked, false otherwise.
960
	 * @since 3.7
961
	 */
962
	public boolean isLinkWithEditorActive() {
963
		return fLinkWithEditorAction.isChecked();
900
	}
964
	}
901
965
902
	private class RerunLastAction extends Action {
966
	private class RerunLastAction extends Action {
Lines 1198-1203 Link Here
1198
			}
1262
			}
1199
			fTestRunSession.stopTestRun();
1263
			fTestRunSession.stopTestRun();
1200
		}
1264
		}
1265
	}
1266
1267
	/**
1268
	 * Activate the 'Link with Editor' in the current {@link IWorkbenchPage}. (The
1269
	 * {@link TestViewer} will respond to {@link ISelection} changes.)
1270
	 * 
1271
	 * @param active boolean to indicate if the link with editor is active ({@code true}) or not (
1272
	 *            {@code false})
1273
	 * 
1274
	 * @since 3.8
1275
	 */
1276
	public void setLinkingWithEditorActive(final boolean active) {
1277
		if (active) {
1278
			getSite().getPage().addPostSelectionListener(fTestViewer);
1279
			fTestViewer.setSelection(getSite().getPage().getActiveEditor());
1280
		} else {
1281
			getSite().getPage().removePostSelectionListener(fTestViewer);
1282
		}
1283
	}
1284
	
1285
	/**
1286
	 * Updates the Link image with a "normal link" image if parameter is true, or a "broken link"
1287
	 * image otherwise
1288
	 * 
1289
	 * @param isInSync the state of synchronization
1290
	 * 
1291
	 * @since 3.7
1292
	 */
1293
	public void setLinkingWithEditorInSync(final boolean isInSync) {
1294
		fLinkWithEditorAction.updateLinkImage(isInSync);
1201
	}
1295
	}
1202
1296
1203
	private void startUpdateJobs() {
1297
	private void startUpdateJobs() {
Lines 1507-1517 Link Here
1507
				startUpdateJobs();
1601
				startUpdateJobs();
1508
1602
1509
				fStopAction.setEnabled(true);
1603
				fStopAction.setEnabled(true);
1604
				fLinkWithEditorAction.setEnabled(true);
1510
1605
1511
			} else /* old or fresh session: don't want jobs at this stage */ {
1606
			} else /* old or fresh session: don't want jobs at this stage */ {
1512
				stopUpdateJobs();
1607
				stopUpdateJobs();
1513
1608
1514
				fStopAction.setEnabled(fTestRunSession.isKeptAlive());
1609
				fStopAction.setEnabled(fTestRunSession.isKeptAlive());
1610
				fLinkWithEditorAction.setEnabled(fTestRunSession != null);
1611
				// if "Link with Editor" is active, register the listener
1612
				if (isLinkWithEditorActive()) {
1613
					getSite().getPage().addPostSelectionListener(fTestViewer);
1614
					fTestViewer.setSelection(getSite().getPage().getActiveEditor());
1615
				}
1616
1515
				fTestViewer.expandFirstLevel();
1617
				fTestViewer.expandFirstLevel();
1516
			}
1618
			}
1517
		}
1619
		}
Lines 1579-1584 Link Here
1579
		if (fFailureTrace != null) {
1681
		if (fFailureTrace != null) {
1580
			fFailureTrace.dispose();
1682
			fFailureTrace.dispose();
1581
		}
1683
		}
1684
		getSite().getPage().removePostSelectionListener(fTestViewer);
1582
	}
1685
	}
1583
1686
1584
	private void disposeImages() {
1687
	private void disposeImages() {
Lines 1887-1892 Link Here
1887
		fStopAction= new StopAction();
1990
		fStopAction= new StopAction();
1888
		fStopAction.setEnabled(false);
1991
		fStopAction.setEnabled(false);
1889
1992
1993
		fLinkWithEditorAction= new LinkWithEditorAction();
1994
		fLinkWithEditorAction.setEnabled(false);
1995
1890
		fRerunLastTestAction= new RerunLastAction();
1996
		fRerunLastTestAction= new RerunLastAction();
1891
		IHandlerService handlerService= getSite().getWorkbenchWindow().getService(IHandlerService.class);
1997
		IHandlerService handlerService= getSite().getWorkbenchWindow().getService(IHandlerService.class);
1892
		IHandler handler = new AbstractHandler() {
1998
		IHandler handler = new AbstractHandler() {
Lines 1937-1942 Link Here
1937
		toolBar.add(fRerunFailedFirstAction);
2043
		toolBar.add(fRerunFailedFirstAction);
1938
		toolBar.add(fStopAction);
2044
		toolBar.add(fStopAction);
1939
		toolBar.add(fViewHistory.createHistoryDropDownAction());
2045
		toolBar.add(fViewHistory.createHistoryDropDownAction());
2046
		toolBar.add(new Separator());
2047
		toolBar.add(fLinkWithEditorAction);
1940
2048
1941
2049
1942
		viewMenu.add(fShowTestHierarchyAction);
2050
		viewMenu.add(fShowTestHierarchyAction);
(-)a/org.eclipse.jdt.junit/src/org/eclipse/jdt/internal/junit/ui/TestViewer.java (-4 / +253 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.ITestSuiteElement;
27
30
28
import org.eclipse.swt.SWT;
31
import org.eclipse.swt.SWT;
29
import org.eclipse.swt.dnd.Clipboard;
32
import org.eclipse.swt.dnd.Clipboard;
Lines 42-49 Link Here
42
import org.eclipse.jface.action.MenuManager;
45
import org.eclipse.jface.action.MenuManager;
43
import org.eclipse.jface.action.Separator;
46
import org.eclipse.jface.action.Separator;
44
import org.eclipse.jface.viewers.AbstractTreeViewer;
47
import org.eclipse.jface.viewers.AbstractTreeViewer;
48
import org.eclipse.jface.viewers.ISelection;
45
import org.eclipse.jface.viewers.ISelectionChangedListener;
49
import org.eclipse.jface.viewers.ISelectionChangedListener;
46
import org.eclipse.jface.viewers.IStructuredSelection;
50
import org.eclipse.jface.viewers.IStructuredSelection;
51
import org.eclipse.jface.viewers.ITreeSelection;
47
import org.eclipse.jface.viewers.SelectionChangedEvent;
52
import org.eclipse.jface.viewers.SelectionChangedEvent;
48
import org.eclipse.jface.viewers.StructuredSelection;
53
import org.eclipse.jface.viewers.StructuredSelection;
49
import org.eclipse.jface.viewers.StructuredViewer;
54
import org.eclipse.jface.viewers.StructuredViewer;
Lines 52-64 Link Here
52
import org.eclipse.jface.viewers.Viewer;
57
import org.eclipse.jface.viewers.Viewer;
53
import org.eclipse.jface.viewers.ViewerFilter;
58
import org.eclipse.jface.viewers.ViewerFilter;
54
59
60
import org.eclipse.jface.text.ITextSelection;
61
62
import org.eclipse.ui.IEditorPart;
63
import org.eclipse.ui.ISelectionListener;
55
import org.eclipse.ui.IWorkbenchActionConstants;
64
import org.eclipse.ui.IWorkbenchActionConstants;
65
import org.eclipse.ui.IWorkbenchPart;
66
import org.eclipse.ui.PartInitException;
56
import org.eclipse.ui.part.PageBook;
67
import org.eclipse.ui.part.PageBook;
57
68
58
import org.eclipse.debug.core.ILaunchConfiguration;
69
import org.eclipse.debug.core.ILaunchConfiguration;
59
import org.eclipse.debug.core.ILaunchManager;
70
import org.eclipse.debug.core.ILaunchManager;
60
71
72
import org.eclipse.jdt.core.ICompilationUnit;
73
import org.eclipse.jdt.core.IJavaElement;
61
import org.eclipse.jdt.core.IJavaProject;
74
import org.eclipse.jdt.core.IJavaProject;
75
import org.eclipse.jdt.core.IMethod;
62
import org.eclipse.jdt.core.IType;
76
import org.eclipse.jdt.core.IType;
63
import org.eclipse.jdt.core.JavaModelException;
77
import org.eclipse.jdt.core.JavaModelException;
64
78
Lines 72-82 Link Here
72
86
73
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
87
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
74
88
89
import org.eclipse.jdt.ui.JavaUI;
90
91
import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor;
92
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
93
import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
75
import org.eclipse.jdt.internal.ui.viewsupport.ColoringLabelProvider;
94
import org.eclipse.jdt.internal.ui.viewsupport.ColoringLabelProvider;
76
import org.eclipse.jdt.internal.ui.viewsupport.SelectionProviderMediator;
95
import org.eclipse.jdt.internal.ui.viewsupport.SelectionProviderMediator;
77
96
78
97
79
public class TestViewer {
98
public class TestViewer implements ISelectionListener {
80
	private final class TestSelectionListener implements ISelectionChangedListener {
99
	private final class TestSelectionListener implements ISelectionChangedListener {
81
		public void selectionChanged(SelectionChangedEvent event) {
100
		public void selectionChanged(SelectionChangedEvent event) {
82
			handleSelected();
101
			handleSelected();
Lines 343-348 Link Here
343
			testElement= (TestElement) selection.getFirstElement();
362
			testElement= (TestElement) selection.getFirstElement();
344
		}
363
		}
345
		fTestRunnerPart.handleTestSelected(testElement);
364
		fTestRunnerPart.handleTestSelected(testElement);
365
		// if LinkWithEditor is active, reveal the JavaEditor and select the java type or method 
366
		// matching the selected test element, even if the JavaEditor is opened by not active.
367
		if (fTestRunnerPart.isLinkWithEditorActive()) {
368
			handleTestElementSelected(testElement);
369
		}
346
	}
370
	}
347
371
348
	public synchronized void setShowTime(boolean showTime) {
372
	public synchronized void setShowTime(boolean showTime) {
Lines 609-614 Link Here
609
			fTreeViewer.reveal(current);
633
			fTreeViewer.reveal(current);
610
	}
634
	}
611
635
636
	/**
637
	 * Sets the current selection from the given {@link IEditorPart} (if it is a
638
	 * {@link CompilationUnitEditor}) and its selection.
639
	 * 
640
	 * @param editor the selected Java Element in the active Compilation Unit Editor
641
	 * 
642
	 * @since 3.8
643
	 */
644
	public void setSelection(final IEditorPart editor) {
645
		final IJavaElement selectedJavaElement= getSelectedJavaElementInEditor(editor);
646
		setSelection(selectedJavaElement);
647
	}
648
	
649
	/**
650
	 * Sets the current selection from the given {@link IJavaElement} if it matches an
651
	 * {@link ITestCaseElement} and updates the LinkWithEditorAction image in the associated
652
	 * {@link TestRunnerViewPart}.
653
	 * 
654
	 * @param activeJavaElement the selected Java Element (or null) in the active
655
	 *            {@link IWorkbenchPart}
656
	 * 
657
	 */
658
	private void setSelection(final IJavaElement activeJavaElement) {
659
		final ITestElement activeTestCaseElement= findTestElement(activeJavaElement);
660
		if (activeTestCaseElement != null) {
661
			// selection is in-sync
662
			fTestRunnerPart.setLinkingWithEditorInSync(true);
663
			// 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)
664
			final Object currentSelection= getCurrentViewerSelection();
665
			if ((currentSelection instanceof TestCaseElement && ((TestCaseElement)currentSelection).getJavaMethod() != null && !((TestCaseElement)currentSelection).getJavaMethod().equals(
666
					activeJavaElement))
667
					|| (currentSelection instanceof TestSuiteElement && ((TestSuiteElement)currentSelection).getJavaType() != null && !((TestSuiteElement)currentSelection).getJavaType().equals(
668
							activeJavaElement))) {
669
				final IStructuredSelection selection= new StructuredSelection(activeTestCaseElement);
670
				fSelectionProvider.setSelection(selection, true);
671
			}
672
		}
673
		else {
674
			// selection is out-of-sync: show a different icon on the button.
675
			fTestRunnerPart.setLinkingWithEditorInSync(false);
676
		}
677
	}
678
679
	/**
680
	 * @return the current selection in the JUnit Viewer (provided by the underlying selection
681
	 *         provider), or {@code null} if the kind of selection is not an {@link ITreeSelection}
682
	 *         nor an {@link IStructuredSelection}.
683
	 */
684
	private Object getCurrentViewerSelection() {
685
		final ISelection currentSelection= fSelectionProvider.getSelection();
686
		if (currentSelection instanceof ITreeSelection) {
687
			return ((ITreeSelection)currentSelection).getFirstElement();
688
		} else if (currentSelection instanceof IStructuredSelection) {
689
			return ((IStructuredSelection)currentSelection).getFirstElement();
690
		}
691
		return null;
692
	}
693
694
	/**
695
	 * Finds the {@link ITestElement} from the given {@link IJavaElement}
696
	 * 
697
	 * @param javaElement the java element associated with the {@link ITestElement} to find.
698
	 * @return the {@link ITestElement} or null if it could not be found.
699
	 */
700
	private ITestElement findTestElement(final IJavaElement javaElement) {
701
		if (fTestRunSession == null || javaElement == null) {
702
			return null;
703
		}
704
		switch (javaElement.getElementType()) {
705
			case IJavaElement.METHOD:
706
				final IMethod javaMethod= (IMethod)javaElement;
707
				final IType javaType= (IType)javaMethod.getAncestor(IJavaElement.TYPE);
708
				final String testClassName= javaType.getFullyQualifiedName();
709
				final String testMethodName= javaMethod.getElementName();
710
				return findTestCaseElement(fTestRunSession.getTestRoot(), testClassName, testMethodName);
711
			case IJavaElement.TYPE:
712
				return findTestSuiteElement(fTestRunSession.getTestRoot(), ((IType)javaElement).getFullyQualifiedName());
713
			default:
714
				return null;
715
		}
716
	}
717
718
	/**
719
	 * Finds the {@link ITestCaseElement} with the given test class name and test method name in the
720
	 * given {@link ITestSuiteElement}
721
	 * 
722
	 * @param parentElement the parent Test Suite
723
	 * @param testClassName the name of the test class
724
	 * @param testMethodName the name of the test method
725
	 * 
726
	 * @return the {@link ITestCaseElement} or null if it could not be found.
727
	 */
728
	private ITestCaseElement findTestCaseElement(final ITestSuiteElement parentElement, final String testClassName, final String testMethodName) {
729
		for (ITestElement childElement : parentElement.getChildren()) {
730
			if (childElement instanceof ITestCaseElement) {
731
				final TestCaseElement testCaseElement= (TestCaseElement)childElement;
732
				if (testCaseElement.getJavaType() != null && testCaseElement.getJavaType().getFullyQualifiedName().equals(testClassName) && testCaseElement.getJavaMethod() != null
733
						&& testCaseElement.getJavaMethod() != null && testCaseElement.getJavaMethod().getElementName().equals(testMethodName)) {
734
					return testCaseElement;
735
				}
736
			} else if (childElement instanceof ITestSuiteElement) {
737
				final ITestCaseElement localResult= findTestCaseElement((ITestSuiteElement)childElement, testClassName, testMethodName);
738
				if (localResult != null) {
739
					return localResult;
740
				}
741
			}
742
		}
743
		return null;
744
	}
745
746
	/**
747
	 * Finds the {@link ITestSuiteElement} with the given test class name in the given
748
	 * {@link ITestSuiteElement}
749
	 * 
750
	 * @param parentElement the parent Test Suite
751
	 * @param testClassName the name of the test class
752
	 * 
753
	 * @return the {@link ITestSuiteElement} or null if it could not be found.
754
	 */
755
	private ITestSuiteElement findTestSuiteElement(final ITestSuiteElement parentElement, final String testClassName) {
756
		for (ITestElement childElement : parentElement.getChildren()) {
757
			if (childElement instanceof ITestSuiteElement) {
758
				final ITestSuiteElement childTestSuite= (ITestSuiteElement)childElement;
759
				if (childTestSuite.getSuiteTypeName().equals(testClassName)) {
760
					return childTestSuite;
761
				}
762
			}
763
		}
764
		return null;
765
	}
766
612
	public void selectFirstFailure() {
767
	public void selectFirstFailure() {
613
		TestCaseElement firstFailure= getNextChildFailure(fTestRunSession.getTestRoot(), true);
768
		TestCaseElement firstFailure= getNextChildFailure(fTestRunSession.getTestRoot(), true);
614
		if (firstFailure != null)
769
		if (firstFailure != null)
Lines 722-726 Link Here
722
		fTreeViewer.expandToLevel(2);
877
		fTreeViewer.expandToLevel(2);
723
	}
878
	}
724
879
725
}
880
	/**
881
	 * Reacts to a selection change in the active {@link IWorkbenchPart} (or when another part
882
	 * received the focus).
883
	 * 
884
	 * @param part the {@link IWorkbenchPart} in which the selection change occurred
885
	 * @param selection the selection in the given part
886
	 * @since 3.8
887
	 */
888
	public void selectionChanged(IWorkbenchPart part, ISelection selection) {
889
		if (part instanceof IEditorPart) {
890
			setSelection((IEditorPart)part);
891
		} else if (part instanceof TestRunnerViewPart) {
892
			fTestRunnerPart.setLinkingWithEditorInSync(true);
893
		}
894
	}
726
895
896
	/**
897
	 * @return the selected {@link IJavaElement} in the current editor if it is a {@link CompilationUnitEditor}, null otherwise. 
898
	 * @param editor the editor
899
	 */
900
	private IJavaElement getSelectedJavaElementInEditor(final IEditorPart editor) {
901
		if (editor instanceof CompilationUnitEditor) {
902
			final CompilationUnitEditor compilationUnitEditor = (CompilationUnitEditor)editor;
903
			try {
904
				final IJavaElement inputJavaElement= JavaUI.getEditorInputJavaElement(editor.getEditorInput());
905
				final ITextSelection selection= (ITextSelection)compilationUnitEditor.getSelectionProvider().getSelection();
906
				final ICompilationUnit compilationUnit= (ICompilationUnit)inputJavaElement.getAncestor(IJavaElement.COMPILATION_UNIT);
907
				return compilationUnit.getElementAt(selection.getOffset());
908
			} catch (JavaModelException e) {
909
				JUnitPlugin.log(e);
910
			}
911
		}
912
		return null;
913
	}
914
915
	/**
916
	 * Handles the case when a {@link TestCaseElement} has been selected: open the associated code
917
	 * in the Java Editor
918
	 * 
919
	 * @param testElement the new selected {@link TestCaseElement}
920
	 */
921
	private void handleTestElementSelected(final ITestElement testElement) {
922
		if (testElement instanceof TestCaseElement) {
923
			final IMethod selectedMethod= ((TestCaseElement)testElement).getJavaMethod();
924
			handleJavaElementSelected(selectedMethod);
925
		} else if (testElement instanceof TestSuiteElement) {
926
			final IJavaElement selectedElement= ((TestSuiteElement)testElement).getJavaElement();
927
			handleJavaElementSelected(selectedElement);
928
		}
929
	}
930
931
	/**
932
	 * Reveals the given {@link IJavaElement} in its associated Editor if this later is already
933
	 * open, and sets the "Link with Editor" button state accordingly.
934
	 * 
935
	 * @param selectedJavaElement the selected {@link IJavaElement} in the {@link TestViewer} that
936
	 *            should be revealed in its Java Editor.
937
	 */
938
	private void handleJavaElementSelected(final IJavaElement selectedJavaElement) {
939
		try {
940
			final IEditorPart editor= EditorUtility.isOpenInEditor(selectedJavaElement);
941
			if (selectedJavaElement != null && editor != null && editor instanceof JavaEditor) {
942
				final JavaEditor javaEditor= (JavaEditor)editor;
943
				final ITextSelection javaEditorSelection= (ITextSelection)javaEditor.getSelectionProvider().getSelection();
944
				final IEditorPart selectedMethodEditor= EditorUtility.isOpenInEditor(selectedJavaElement);
945
				// checks if the editor is already open or not
946
				if (selectedMethodEditor != null) {
947
					// Retrieve the current active editor
948
					final IEditorPart activeEditor= fTestRunnerPart.getSite().getPage().getActiveEditor();
949
					// open the required editor if it is not the active one   
950
					if (!selectedMethodEditor.equals(activeEditor)) {
951
						EditorUtility.openInEditor(selectedJavaElement, false);
952
					}
953
					// retrieve the current java element (unless the associated compilation unit cannot be retrieved)
954
					final ICompilationUnit compilationUnit= (ICompilationUnit)selectedJavaElement.getAncestor(IJavaElement.COMPILATION_UNIT);
955
					if (compilationUnit != null) {
956
						final IJavaElement javaEditorSelectedElement= compilationUnit.getElementAt(javaEditorSelection.getOffset());
957
						// force to reveal the selected element in case where the editor was not active
958
						if (!selectedMethodEditor.equals(activeEditor) || !selectedJavaElement.equals(javaEditorSelectedElement)) {
959
							EditorUtility.revealInEditor(selectedMethodEditor, selectedJavaElement);
960
						}
961
						fTestRunnerPart.setLinkingWithEditorInSync(true);
962
						return;
963
					}
964
				}
965
			}
966
		} catch (JavaModelException e) {
967
			JUnitPlugin.log(e);
968
		} catch (PartInitException e) {
969
			// occurs if the editor could not be opened or the input element is not valid Status code
970
			JUnitPlugin.log(e);
971
		}
972
		fTestRunnerPart.setLinkingWithEditorInSync(false);
973
	}
974
975
}
(-)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