split editor for before/after files in testdata
[fedora-idea.git] / plugins / IdeaTestAssistant / src / com / intellij / testAssistant / TestDataLineMarkerProvider.java
blob6d1e795fb7c51d860a3e7bacb2adbac1958cf067
1 package com.intellij.testAssistant;
3 import com.intellij.codeHighlighting.Pass;
4 import com.intellij.codeInsight.AnnotationUtil;
5 import com.intellij.codeInsight.daemon.GutterIconNavigationHandler;
6 import com.intellij.codeInsight.daemon.LineMarkerInfo;
7 import com.intellij.codeInsight.daemon.LineMarkerProvider;
8 import com.intellij.openapi.fileEditor.OpenFileDescriptor;
9 import com.intellij.openapi.fileTypes.FileType;
10 import com.intellij.openapi.fileTypes.FileTypeManager;
11 import com.intellij.openapi.project.Project;
12 import com.intellij.openapi.roots.ProjectFileIndex;
13 import com.intellij.openapi.roots.ProjectRootManager;
14 import com.intellij.openapi.ui.popup.PopupChooserBuilder;
15 import com.intellij.openapi.util.text.StringUtil;
16 import com.intellij.openapi.vfs.LocalFileSystem;
17 import com.intellij.openapi.vfs.VirtualFile;
18 import com.intellij.psi.*;
19 import com.intellij.ui.ColoredListCellRenderer;
20 import com.intellij.ui.awt.RelativePoint;
21 import com.intellij.util.Icons;
22 import org.jetbrains.annotations.Nullable;
24 import javax.swing.*;
25 import java.awt.event.MouseEvent;
26 import java.io.File;
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.List;
32 /**
33 * @author yole
35 public class TestDataLineMarkerProvider implements LineMarkerProvider {
36 public LineMarkerInfo getLineMarkerInfo(PsiElement element) {
37 if (!(element instanceof PsiMethod)) {
38 return null;
40 final PsiMethod method = (PsiMethod)element;
41 String name = method.getName();
42 if (!name.startsWith("test")) {
43 return null;
45 String testDataPath = getTestDataBasePath(method.getContainingClass());
46 if (testDataPath != null) {
47 List<String> fileNames = new TestDataReferenceCollector(testDataPath, name.substring(4)).collectTestDataReferences(method);
48 if (fileNames.size() > 0) {
49 return new LineMarkerInfo<PsiMethod>(method, method.getTextOffset(), Icons.TEST_SOURCE_FOLDER, Pass.UPDATE_ALL, null,
50 new TestDataNavigationHandler(fileNames));
53 return null;
56 public void collectSlowLineMarkers(List<PsiElement> elements, Collection<LineMarkerInfo> result) {
59 @Nullable
60 private static String getTestDataBasePath(PsiClass psiClass) {
61 final PsiAnnotation annotation = AnnotationUtil.findAnnotationInHierarchy(psiClass, Collections.singleton("com.intellij.testFramework.TestDataPath"));
62 if (annotation != null) {
63 final PsiAnnotationMemberValue value = annotation.findAttributeValue(PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME);
64 if (value instanceof PsiExpression) {
65 final PsiConstantEvaluationHelper evaluationHelper = JavaPsiFacade.getInstance(value.getProject()).getConstantEvaluationHelper();
66 final Object constantValue = evaluationHelper.computeConstantExpression(value, false);
67 if (constantValue instanceof String) {
68 String path = (String) constantValue;
69 if (path.indexOf("$CONTENT_ROOT") >= 0) {
70 final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(psiClass.getProject()).getFileIndex();
71 final VirtualFile contentRoot = fileIndex.getContentRootForFile(psiClass.getContainingFile().getVirtualFile());
72 if (contentRoot == null) return null;
73 path = path.replace("$CONTENT_ROOT", contentRoot.getPath());
75 return path;
79 return null;
82 private static class TestDataNavigationHandler implements GutterIconNavigationHandler<PsiMethod> {
83 private List<String> myFileNames;
85 public TestDataNavigationHandler(List<String> fileNames) {
86 myFileNames = fileNames;
89 public void navigate(MouseEvent e, final PsiMethod elt) {
90 if (myFileNames.size() == 1) {
91 openFileByIndex(elt.getProject(), 0);
93 else {
94 TestDataGroupVirtualFile groupFile = getTestDataGroup();
95 if (groupFile != null) {
96 new OpenFileDescriptor(elt.getProject(), groupFile).navigate(true);
98 else {
99 showNavigationPopup(elt.getProject(), e);
104 @Nullable
105 private TestDataGroupVirtualFile getTestDataGroup() {
106 if (myFileNames.size() != 2) {
107 return null;
109 VirtualFile file1 = LocalFileSystem.getInstance().findFileByPath(myFileNames.get(0));
110 VirtualFile file2 = LocalFileSystem.getInstance().findFileByPath(myFileNames.get(1));
111 if (file1 == null || file2 == null) {
112 return null;
114 final int commonPrefixLength = StringUtil.commonPrefixLength(file1.getName(), file2.getName());
115 if (file1.getName().substring(commonPrefixLength).toLowerCase().contains("after")) {
116 return new TestDataGroupVirtualFile(file2, file1);
118 if (file2.getName().substring(commonPrefixLength).toLowerCase().contains("after")) {
119 return new TestDataGroupVirtualFile(file1, file2);
121 return null;
124 private void showNavigationPopup(final Project project, MouseEvent e) {
125 List<String> shortNames = new ArrayList<String>();
126 for (String fileName : myFileNames) {
127 shortNames.add(new File(fileName).getName());
129 final JList list = new JList(shortNames.toArray(new String[shortNames.size()]));
130 list.setCellRenderer(new ColoredListCellRenderer() {
131 @Override
132 protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
133 String fileName = (String)value;
134 final FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(fileName);
135 setIcon(fileType.getIcon());
136 append(fileName);
139 PopupChooserBuilder builder = new PopupChooserBuilder(list);
140 builder.setItemChoosenCallback(new Runnable() {
141 public void run() {
142 final int[] indices = list.getSelectedIndices();
143 for (int index : indices) {
144 openFileByIndex(project, index);
147 }).createPopup().show(new RelativePoint(e));
150 private void openFileByIndex(final Project project, final int index) {
151 final VirtualFile file = LocalFileSystem.getInstance().findFileByPath(myFileNames.get(index));
152 if (file != null) {
153 new OpenFileDescriptor(project, file).navigate(true);