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 |
} |