package name.graf.emanuel.testfileeditor.ui; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.IAnnotation; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMemberValuePair; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.internal.core.SourceType; import org.eclipse.jdt.internal.junit.model.TestCaseElement; import org.eclipse.jdt.internal.junit.model.TestElement; import org.eclipse.jdt.internal.junit.model.TestSuiteElement; import org.eclipse.jdt.internal.junit.ui.TestRunnerViewPart; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorDescriptor; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.editors.text.TextFileDocumentProvider; import org.eclipse.ui.handlers.HandlerUtil; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.texteditor.IDocumentProvider; import name.graf.emanuel.testfileeditor.model.TestFile; import name.graf.emanuel.testfileeditor.model.node.Test; @SuppressWarnings("restriction") public class JumpToRTSHandler extends AbstractHandler { private static final Pattern TEST_NAME_PATTERN = Pattern.compile(".*\\[(.*)\\].*"); private String className; private IJavaProject project; private Shell shell; private String testName; @Override public Object execute(ExecutionEvent event) throws ExecutionException { IStructuredSelection selection = HandlerUtil.getCurrentStructuredSelection(event); if (selection instanceof TreeSelection) { shell = HandlerUtil.getActiveShell(event); getProject(event); getTestInfo((TestElement) selection.getFirstElement()); jump(); } return null; } private String getPathViaAnnotation(IType classType) throws JavaModelException { IAnnotation runFor = classType.getAnnotation("RunFor"); if (runFor.exists()) { IMemberValuePair[] values = runFor.getMemberValuePairs(); if (values.length == 1) { return (String) values[0].getValue(); } } return null; } private IFile findFileInContainer(IContainer container, String filename) { try { for (IResource resource : container.members()) { if (resource instanceof IContainer) { IFile found = findFileInContainer((IContainer) resource, filename); if (found != null) { return found; } } else if (resource instanceof IFile) { if (((IFile) resource).getName().equals(filename)) { return (IFile) resource; } } } } catch (CoreException e) { e.printStackTrace(); } return null; } private String guessPath() throws CoreException { int lastDot = className.lastIndexOf('.'); String testFileName = className.substring(lastDot + 1) + ".rts"; IResource file = findFileInContainer(project.getProject(), testFileName); if (file != null) { return file.getProjectRelativePath().toString(); } return null; } private void getProject(ExecutionEvent event) { TestRunnerViewPart view = (TestRunnerViewPart) HandlerUtil.getActivePart(event); project = view.getLaunchedProject(); } private String getTestFileName(IType classType) throws CoreException { if (!(classType instanceof SourceType)) { return null; } String filePath = getPathViaAnnotation(classType); return filePath != null ? filePath : guessPath(); } private void getTestInfo(TestElement entry) { if (entry instanceof TestCaseElement) { className = entry.getClassName(); TestCaseElement testCase = (TestCaseElement) entry; Matcher matcher = TEST_NAME_PATTERN.matcher(testCase.getTestMethodName()); if (matcher.matches()) { testName = matcher.group(1); } } else if (entry instanceof TestSuiteElement) { TestSuiteElement testSuite = (TestSuiteElement) entry; if (!testSuite.getClassName().contains(".")) { className = testSuite.getParent().getClassName(); } else { className = testSuite.getTestName(); } testName = testSuite.getTestName(); } } private void jump() { if (className != null) { IType cls = null; try { cls = project.findType(className); } catch (JavaModelException e) { return; } try { IFile file = project.getProject().getFile(getTestFileName(cls)); IWorkbench workbench = PlatformUI.getWorkbench(); IWorkbenchPage page = workbench.getActiveWorkbenchWindow().getActivePage(); FileEditorInput input = new FileEditorInput(file); IDocumentProvider provider = new TextFileDocumentProvider(); provider.connect(input); IDocument document = provider.getDocument(input); TestFile testFile = new TestFile(input, provider); testFile.parse(); IEditorDescriptor defaultEditor = workbench.getEditorRegistry().getDefaultEditor(file.getName()); String editorId = defaultEditor.getId(); if (!className.equals(testName)) { for (Test test : testFile.getTests()) { if (test.toString().equals(testName)) { int line = document.getLineOfOffset(test.getPosition().getOffset()); IMarker lineMarker = file.createMarker(IMarker.TEXT); lineMarker.setAttribute(IMarker.LINE_NUMBER, line + 1); lineMarker.setAttribute(IDE.EDITOR_ID_ATTR, editorId); IDE.openEditor(page, lineMarker); lineMarker.delete(); return; } } } else { IDE.openEditor(page, file); } } catch (CoreException | BadLocationException | NullPointerException e) { e.printStackTrace(); MessageDialog.openError(shell, "Jump to RTS", "Failed to find associated RTS file."); } } } }