From ebfaa557d8c74a9e82dec1e91547d2aa303bd152 Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Fri, 25 Jan 2019 15:04:16 +0100 Subject: [PATCH] coverage: move java specific tracking tests to the dedicated module --- .../com/intellij/coverage/CoverageEngine.java | 14 +++ .../actions/ShowCoveringTestsAction.java | 94 ++++--------------- .../intellij/coverage/JavaCoverageEngine.java | 88 ++++++++++++++++- 3 files changed, 115 insertions(+), 81 deletions(-) diff --git a/plugins/coverage-common/src/com/intellij/coverage/CoverageEngine.java b/plugins/coverage-common/src/com/intellij/coverage/CoverageEngine.java index 7ae71ca84536..a2ef0e5ea4fb 100644 --- a/plugins/coverage-common/src/com/intellij/coverage/CoverageEngine.java +++ b/plugins/coverage-common/src/com/intellij/coverage/CoverageEngine.java @@ -51,6 +51,20 @@ public abstract class CoverageEngine { public abstract boolean canHavePerTestCoverage(@Nullable final RunConfigurationBase conf); + /** + * @return tests, which covered specified line. Names should be compatible with {@link CoverageEngine#findTestsByNames(String[], Project)} + */ + public Set getTestsForLine(Project project, String classFQName, int lineNumber) { + return Collections.emptySet(); + } + + /** + * @return true, if test data was collected + */ + public boolean wasTestDataCollected(Project project) { + return false; + } + /** * Creates coverage enabled configuration for given RunConfiguration. It is supposed that one run configuration may be associated * not more than one coverage engine. diff --git a/plugins/coverage-common/src/com/intellij/coverage/actions/ShowCoveringTestsAction.java b/plugins/coverage-common/src/com/intellij/coverage/actions/ShowCoveringTestsAction.java index 201829e847a2..bff4b95b335c 100644 --- a/plugins/coverage-common/src/com/intellij/coverage/actions/ShowCoveringTestsAction.java +++ b/plugins/coverage-common/src/com/intellij/coverage/actions/ShowCoveringTestsAction.java @@ -6,9 +6,12 @@ import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.hint.ImplementationViewComponent; import com.intellij.codeInsight.hint.PsiImplementationViewElement; import com.intellij.coverage.CoverageDataManager; -import com.intellij.coverage.CoverageSuite; +import com.intellij.coverage.CoverageEngine; import com.intellij.coverage.CoverageSuitesBundle; -import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.progress.ProgressManager; @@ -17,8 +20,6 @@ import com.intellij.openapi.ui.PanelWithText; import com.intellij.openapi.ui.popup.ComponentPopupBuilder; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.rt.coverage.data.LineCoverage; @@ -28,14 +29,12 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.PlatformIcons; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.io.DataInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.*; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public class ShowCoveringTestsAction extends AnAction { private static final Logger LOG = Logger.getInstance(ShowCoveringTestsAction.class); @@ -51,7 +50,6 @@ public class ShowCoveringTestsAction extends AnAction { @Override public void actionPerformed(@NotNull final AnActionEvent e) { - final DataContext context = e.getDataContext(); final Project project = e.getProject(); LOG.assertTrue(project != null); final Editor editor = e.getData(CommonDataKeys.EDITOR); @@ -59,39 +57,18 @@ public class ShowCoveringTestsAction extends AnAction { final CoverageSuitesBundle currentSuite = CoverageDataManager.getInstance(project).getCurrentSuitesBundle(); LOG.assertTrue(currentSuite != null); - - final File[] traceFiles = getTraceFiles(project); + final CoverageEngine coverageEngine = currentSuite.getCoverageEngine(); final Set tests = new HashSet<>(); - Runnable runnable = () -> { - for (File traceFile : traceFiles) { - DataInputStream in = null; - try { - in = new DataInputStream(new FileInputStream(traceFile)); - extractTests(traceFile, in, tests); - } - catch (Exception ex) { - LOG.error(traceFile.getName(), ex); - } - finally { - try { - in.close(); - } - catch (IOException ex) { - LOG.error(ex); - } - } - } - }; - - if (ProgressManager.getInstance().runProcessWithProgressSynchronously(runnable, "Extract information about tests", false, project)) { //todo cache them? show nothing found message + if (ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> tests.addAll(coverageEngine.getTestsForLine(project, myClassFQName, myLineData.getLineNumber())), + "Extract Information About Tests", false, project)) { //todo cache them? show nothing found message final String[] testNames = ArrayUtil.toStringArray(tests); Arrays.sort(testNames); if (testNames.length == 0) { HintManager.getInstance().showErrorHint(editor, "Failed to load covered tests"); return; } - final List elements = currentSuite.getCoverageEngine().findTestsByNames(testNames, project); + final List elements = coverageEngine.findTestsByNames(testNames, project); final ImplementationViewComponent component; final String title = "Tests covering line " + myClassFQName + ":" + myLineData.getLineNumber(); final ComponentPopupBuilder popupBuilder; @@ -123,23 +100,6 @@ public class ShowCoveringTestsAction extends AnAction { } } - private void extractTests(final File traceFile, final DataInputStream in, final Set tests) throws IOException { - long traceSize = in.readInt(); - for (int i = 0; i < traceSize; i++) { - final String className = in.readUTF(); - final int linesSize = in.readInt(); - for(int l = 0; l < linesSize; l++) { - final int line = in.readInt(); - if (Comparing.strEqual(className, myClassFQName)) { - if (myLineData.getLineNumber() == line) { - tests.add(FileUtil.getNameWithoutExtension(traceFile)); - return; - } - } - } - } - } - @Override public void update(@NotNull final AnActionEvent e) { final Presentation presentation = e.getPresentation(); @@ -147,32 +107,10 @@ public class ShowCoveringTestsAction extends AnAction { if (myLineData != null && myLineData.getStatus() != LineCoverage.NONE) { final Project project = e.getProject(); if (project != null) { - final File[] files = getTraceFiles(project); - if (files != null && files.length > 0) { - presentation.setEnabled(CoverageDataManager.getInstance(project).getCurrentSuitesBundle().isCoverageByTestEnabled()); - } + CoverageSuitesBundle currentSuitesBundle = CoverageDataManager.getInstance(project).getCurrentSuitesBundle(); + presentation.setEnabled(currentSuitesBundle.isCoverageByTestEnabled() && + currentSuitesBundle.getCoverageEngine().wasTestDataCollected(project)); } } } - - @Nullable - private static File[] getTraceFiles(Project project) { - final CoverageSuitesBundle currentSuite = CoverageDataManager.getInstance(project).getCurrentSuitesBundle(); - if (currentSuite == null) return null; - final List files = new ArrayList<>(); - for (CoverageSuite coverageSuite : currentSuite.getSuites()) { - - final String filePath = coverageSuite.getCoverageDataFileName(); - final String dirName = FileUtil.getNameWithoutExtension(new File(filePath).getName()); - - final File parentDir = new File(filePath).getParentFile(); - final File tracesDir = new File(parentDir, dirName); - final File[] suiteFiles = tracesDir.listFiles(); - if (suiteFiles != null) { - Collections.addAll(files, suiteFiles); - } - } - - return files.isEmpty() ? null : files.toArray(new File[0]); - } } diff --git a/plugins/coverage/src/com/intellij/coverage/JavaCoverageEngine.java b/plugins/coverage/src/com/intellij/coverage/JavaCoverageEngine.java index 47cd2c8c622f..a3de5f1b5fd2 100644 --- a/plugins/coverage/src/com/intellij/coverage/JavaCoverageEngine.java +++ b/plugins/coverage/src/com/intellij/coverage/JavaCoverageEngine.java @@ -3,6 +3,7 @@ package com.intellij.coverage; import com.intellij.CommonBundle; import com.intellij.codeEditor.printing.ExportToHTMLSettings; +import com.intellij.codeInsight.TestFrameworks; import com.intellij.coverage.view.CoverageViewExtension; import com.intellij.coverage.view.CoverageViewManager; import com.intellij.coverage.view.JavaCoverageViewExtension; @@ -32,6 +33,7 @@ import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.roots.TestSourcesFilter; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.text.StringUtil; @@ -45,12 +47,15 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.rt.coverage.data.JumpData; import com.intellij.rt.coverage.data.LineData; import com.intellij.rt.coverage.data.SwitchData; +import com.intellij.testIntegration.TestFramework; import jetbrains.coverage.report.ReportGenerationFailedException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.java.JavaSourceRootType; +import java.io.DataInputStream; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.util.*; @@ -82,6 +87,83 @@ public class JavaCoverageEngine extends CoverageEngine { return !(conf instanceof ApplicationConfiguration) && conf instanceof CommonJavaRunConfigurationParameters; } + @Override + public Set getTestsForLine(Project project, String classFQName, int lineNumber) { + return extractTracedTests(project, classFQName, lineNumber); + } + + @Override + public boolean wasTestDataCollected(Project project) { + File[] files = getTraceFiles(project); + return files != null && files.length > 0; + } + + private static Set extractTracedTests(Project project, final String classFQName, final int lineNumber) { + Set tests = new HashSet<>(); + final File[] traceFiles = getTraceFiles(project); + for (File traceFile : traceFiles) { + DataInputStream in = null; + try { + in = new DataInputStream(new FileInputStream(traceFile)); + extractTests(traceFile, in, tests, classFQName, lineNumber); + } + catch (Exception ex) { + LOG.error(traceFile.getName(), ex); + } + finally { + try { + in.close(); + } + catch (IOException ex) { + LOG.error(ex); + } + } + } + return tests; + } + + private static void extractTests(final File traceFile, + final DataInputStream in, + final Set tests, + final String classFQName, + final int lineNumber) throws IOException { + long traceSize = in.readInt(); + for (int i = 0; i < traceSize; i++) { + final String className = in.readUTF(); + final int linesSize = in.readInt(); + for(int l = 0; l < linesSize; l++) { + final int line = in.readInt(); + if (Comparing.strEqual(className, classFQName)) { + if (lineNumber == line) { + tests.add(FileUtil.getNameWithoutExtension(traceFile)); + return; + } + } + } + } + } + + @Nullable + private static File[] getTraceFiles(Project project) { + final CoverageSuitesBundle currentSuite = CoverageDataManager.getInstance(project).getCurrentSuitesBundle(); + if (currentSuite == null) return null; + final List files = new ArrayList<>(); + for (CoverageSuite coverageSuite : currentSuite.getSuites()) { + + final String filePath = coverageSuite.getCoverageDataFileName(); + final String dirName = FileUtil.getNameWithoutExtension(new File(filePath).getName()); + + final File parentDir = new File(filePath).getParentFile(); + final File tracesDir = new File(parentDir, dirName); + final File[] suiteFiles = tracesDir.listFiles(); + if (suiteFiles != null) { + Collections.addAll(files, suiteFiles); + } + } + + return files.isEmpty() ? null : files.toArray(new File[0]); + } + @NotNull @Override public CoverageEnabledConfiguration createCoverageEnabledConfiguration(@Nullable final RunConfigurationBase conf) { @@ -498,10 +580,10 @@ public class JavaCoverageEngine extends CoverageEngine { } private static void collectTestsByName(List elements, String testName, PsiClass psiClass, int lastIdx) { + TestFramework testFramework = TestFrameworks.detectFramework(psiClass); + if (testFramework == null) return; final PsiMethod[] testsByName = psiClass.findMethodsByName(testName.substring(lastIdx + 1), true); - if (testsByName.length == 1) { - elements.add(testsByName[0]); - } + Arrays.stream(testsByName).filter(test -> testFramework.isTestMethod(test)).forEach(elements::add); }