blob: 143ce0311d1640be5a58ca18707aad41c28a3d52 [file] [log] [blame]
/*
* 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;
}
}
});
}
}