package krasa.console; import krasa.actions.AutotestUtils; import org.jetbrains.annotations.*; import com.intellij.execution.filters.*; import com.intellij.lang.xml.XMLLanguage; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diff.*; import com.intellij.openapi.diff.ex.DiffContentFactory; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.search.PsiShortNamesCache; import com.intellij.testFramework.LightVirtualFile; import com.intellij.ui.awt.RelativePoint; public class RequestComparatorFilter implements Filter { public static final String REQUEST_DOES_NOT_MATCH_EXPECTED_CONTENT_FOR = "Request does not match expected content for"; Data data; @Nullable @Override public Result applyFilter(String line, int entireLength) { if (line == null) { return null; } if (line.substring(0, Math.min(line.length(), 100)).contains("RequestComparator")) { int path = line.indexOf(REQUEST_DOES_NOT_MATCH_EXPECTED_CONTENT_FOR); int actual = actualIndex(line); if (path > 0) { data = new Data(); data.path = line.substring(path + REQUEST_DOES_NOT_MATCH_EXPECTED_CONTENT_FOR.length()).trim(); data.hyperlinkInfoBase = new MyHyperlinkInfoBase(data); } else if (actual > 0 && data != null) { String substring = line.substring(actual + "Actual: ".length()); data.actual = substring.trim(); Result result = new Result(entireLength - line.length(), entireLength, data.hyperlinkInfoBase); data = null; return result; } } return null; } private int actualIndex(String line) { int i = line.indexOf("Actual: "); if (i <= 0) { i = line.indexOf("actual: "); } return i; } private static class MyHyperlinkInfoBase extends HyperlinkInfoBase { private Data data; public MyHyperlinkInfoBase(Data data) { this.data = data; } @Override public void navigate(@NotNull final Project project, @Nullable RelativePoint hyperlinkLocationPoint) { VirtualFile expected = findFile(project); if (expected == null) { ConsoleFilterProvider.notificationGroup.createNotification( "File not found " + data.path, MessageType.ERROR).notify(project); return; } final String actual = data.actual; String text = FormatUtils.reformat(project, actual); VirtualFile actualVF = new LightVirtualFile("Actual", XMLLanguage.INSTANCE, text); SimpleDiffRequest diffData = DiffContentFactory.compareVirtualFiles(project, actualVF, expected, data.path); // noinspection ConstantConditions diffData.setContentTitles("Actual", expected.getPath()); final DiffContent[] contents = diffData.getContents(); ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { for (DiffContent content : contents) { Document document = content.getDocument(); if (document != null) { FileDocumentManager.getInstance().saveDocument(document); } } } }); DiffManager.getInstance().getDiffTool().show(diffData); } private VirtualFile findFile(Project project) { VirtualFile file = null; PsiShortNamesCache instance = PsiShortNamesCache.getInstance(project); String fileName = AutotestUtils.getFileName(data.path); PsiFile[] filesByName = getFilesByName(instance, fileName); String expectedPath = data.path; if (!expectedPath.startsWith("/")) { expectedPath = "/" + expectedPath; } for (PsiFile psiFile : filesByName) { VirtualFile virtualFile = psiFile.getVirtualFile(); String path = virtualFile.getPath(); if (path.contains(expectedPath) && path.contains("dummy-requests")) { file = virtualFile; } } return file; } private PsiFile[] getFilesByName(PsiShortNamesCache instance, String fileName) { PsiFile[] filesByName = instance.getFilesByName(fileName); if (filesByName.length == 0) { filesByName = instance.getFilesByName(fileName + ".xml"); } if (filesByName.length == 0) { filesByName = instance.getFilesByName(fileName + ".json"); } return filesByName; } } private static class Data { String path; String actual; HyperlinkInfoBase hyperlinkInfoBase; @Override public String toString() { final StringBuilder sb = new StringBuilder("Data{"); sb.append("path='").append(path).append('\''); sb.append(", actual='").append(actual).append('\''); sb.append('}'); return sb.toString(); } } }