| /* |
| * Copyright 2000-2013 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.jetbrains.idea.devkit.testAssistant; |
| |
| import com.intellij.codeInsight.daemon.GutterIconNavigationHandler; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.fileEditor.OpenFileDescriptor; |
| import com.intellij.openapi.fileTypes.FileType; |
| import com.intellij.openapi.fileTypes.FileTypeManager; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.ui.Messages; |
| import com.intellij.openapi.ui.popup.PopupChooserBuilder; |
| import com.intellij.openapi.util.Computable; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.openapi.vfs.LocalFileSystem; |
| import com.intellij.openapi.vfs.VfsUtil; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.psi.PsiMethod; |
| import com.intellij.ui.ColoredListCellRenderer; |
| import com.intellij.ui.awt.RelativePoint; |
| import com.intellij.ui.components.JBList; |
| import com.intellij.util.ArrayUtil; |
| import com.intellij.util.PathUtil; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import java.awt.event.MouseEvent; |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * @author yole |
| */ |
| public class TestDataNavigationHandler implements GutterIconNavigationHandler<PsiMethod> { |
| public void navigate(MouseEvent e, final PsiMethod elt) { |
| navigate(elt, new RelativePoint(e)); |
| } |
| |
| public static void navigate(PsiMethod method, final RelativePoint point) { |
| List<String> fileNames = null; |
| String testDataPath = TestDataLineMarkerProvider.getTestDataBasePath(method.getContainingClass()); |
| if (testDataPath != null) { |
| fileNames = new TestDataReferenceCollector(testDataPath, method.getName().substring(4)).collectTestDataReferences(method); |
| } |
| |
| if (fileNames == null || fileNames.isEmpty()) { |
| fileNames = TestDataGuessByExistingFilesUtil.collectTestDataByExistingFiles(method); |
| } |
| |
| if (fileNames == null || fileNames.isEmpty()) { |
| return; |
| } |
| navigate(point, fileNames, method.getProject()); |
| } |
| |
| public static void navigate(@NotNull final RelativePoint point, |
| @NotNull List<String> testDataFiles, |
| final Project project) { |
| if (testDataFiles.size() == 1) { |
| openFileByIndex(project, testDataFiles, 0); |
| } |
| else if (testDataFiles.size() > 1) { |
| TestDataGroupVirtualFile groupFile = getTestDataGroup(testDataFiles); |
| if (groupFile != null) { |
| new OpenFileDescriptor(project, groupFile).navigate(true); |
| } |
| else { |
| showNavigationPopup(project, testDataFiles, point); |
| } |
| } |
| } |
| |
| @Nullable |
| private static TestDataGroupVirtualFile getTestDataGroup(List<String> fileNames) { |
| if (fileNames.size() != 2) { |
| return null; |
| } |
| VirtualFile file1 = LocalFileSystem.getInstance().refreshAndFindFileByPath(fileNames.get(0)); |
| VirtualFile file2 = LocalFileSystem.getInstance().refreshAndFindFileByPath(fileNames.get(1)); |
| if (file1 == null || file2 == null) { |
| return null; |
| } |
| final int commonPrefixLength = StringUtil.commonPrefixLength(file1.getName(), file2.getName()); |
| if (file1.getName().substring(commonPrefixLength).toLowerCase().contains("after")) { |
| return new TestDataGroupVirtualFile(file2, file1); |
| } |
| if (file2.getName().substring(commonPrefixLength).toLowerCase().contains("after")) { |
| return new TestDataGroupVirtualFile(file1, file2); |
| } |
| return null; |
| } |
| |
| private static void showNavigationPopup(final Project project, final List<String> fileNames, final RelativePoint point) { |
| List<String> listPaths = new ArrayList<String>(fileNames); |
| final String CREATE_MISSING_OPTION = "Create Missing Files"; |
| if (fileNames.size() == 2) { |
| VirtualFile file1 = LocalFileSystem.getInstance().refreshAndFindFileByPath(fileNames.get(0)); |
| VirtualFile file2 = LocalFileSystem.getInstance().refreshAndFindFileByPath(fileNames.get(1)); |
| if (file1 == null || file2 == null) { |
| listPaths.add(CREATE_MISSING_OPTION); |
| } |
| } |
| final JList list = new JBList(ArrayUtil.toStringArray(listPaths)); |
| list.setCellRenderer(new ColoredListCellRenderer() { |
| @Override |
| protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { |
| String path = (String)value; |
| String fileName = PathUtil.getFileName(path); |
| if (!fileName.equals(CREATE_MISSING_OPTION)) { |
| final FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(fileName); |
| setIcon(fileType.getIcon()); |
| } |
| append(String.format("%s (%s)", fileName, PathUtil.getParentPath(path))); |
| } |
| }); |
| PopupChooserBuilder builder = new PopupChooserBuilder(list); |
| builder.setItemChoosenCallback(new Runnable() { |
| public void run() { |
| final int[] indices = list.getSelectedIndices(); |
| if (ArrayUtil.indexOf(indices, fileNames.size()) >= 0) { |
| createMissingFiles(project, fileNames); |
| } |
| else { |
| for (int index : indices) { |
| openFileByIndex(project, fileNames, index); |
| } |
| } |
| } |
| }).createPopup().show(point); |
| } |
| |
| private static void createMissingFiles(Project project, List<String> fileNames) { |
| for (String name : fileNames) { |
| if (LocalFileSystem.getInstance().refreshAndFindFileByPath(name) == null) { |
| createFileByName(project, name); |
| } |
| } |
| final TestDataGroupVirtualFile testDataGroup = getTestDataGroup(fileNames); |
| if (testDataGroup != null) { |
| new OpenFileDescriptor(project, testDataGroup).navigate(true); |
| } |
| } |
| |
| private static void openFileByIndex(final Project project, final List<String> fileNames, final int index) { |
| final String path = fileNames.get(index); |
| final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(path); |
| if (file != null) { |
| new OpenFileDescriptor(project, file).navigate(true); |
| } |
| else { |
| int rc = Messages.showYesNoDialog(project, "The referenced testdata file " + path + " does not exist. Would you like to create it?", |
| "Create Testdata File", Messages.getQuestionIcon()); |
| if (rc == Messages.YES) { |
| VirtualFile vFile = createFileByName(project, path); |
| new OpenFileDescriptor(project, vFile).navigate(true); |
| } |
| } |
| } |
| |
| private static VirtualFile createFileByName(final Project project, final String path) { |
| return ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() { |
| public VirtualFile compute() { |
| try { |
| final File file = new File(path); |
| final VirtualFile parent = VfsUtil.createDirectories(file.getParent()); |
| return parent.createChildData(this, file.getName()); |
| } |
| catch (IOException e) { |
| Messages.showErrorDialog(project, e.getMessage(), "Create Testdata File"); |
| return null; |
| } |
| } |
| }); |
| } |
| } |