| package com.intellij.coverage; |
| |
| import com.intellij.codeInspection.export.ExportToHTMLDialog; |
| import com.intellij.coverage.view.CoverageViewExtension; |
| import com.intellij.coverage.view.CoverageViewManager; |
| import com.intellij.execution.configurations.RunConfigurationBase; |
| import com.intellij.execution.configurations.coverage.CoverageEnabledConfiguration; |
| import com.intellij.execution.testframework.AbstractTestProxy; |
| import com.intellij.openapi.actionSystem.DataContext; |
| import com.intellij.openapi.editor.Editor; |
| import com.intellij.openapi.extensions.ExtensionPointName; |
| import com.intellij.openapi.module.Module; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.roots.ProjectFileIndex; |
| import com.intellij.openapi.roots.ProjectRootManager; |
| import com.intellij.openapi.vfs.LocalFileSystem; |
| import com.intellij.openapi.vfs.VfsUtilCore; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.psi.PsiElement; |
| import com.intellij.psi.PsiFile; |
| import com.intellij.rt.coverage.data.LineData; |
| import com.intellij.util.Function; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.io.File; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.TreeMap; |
| |
| /** |
| * @author Roman.Chernyatchik |
| * <p/> |
| * Coverage engine provide coverage support for different languages or coverage runner classes. |
| * E.g. engine for JVM languages, Ruby, Python |
| * <p/> |
| * Each coverage engine may work with several coverage runner. E.g. Java coverage engine supports IDEA/EMMA/Cobertura, |
| * Ruby engine works with RCov |
| */ |
| public abstract class CoverageEngine { |
| public static final ExtensionPointName<CoverageEngine> EP_NAME = ExtensionPointName.create("com.intellij.coverageEngine"); |
| |
| /** |
| * Checks whether coverage feature is supported by this engine for given configuration or not. |
| * |
| * @param conf Run Configuration |
| * @return True if coverage for given run configuration is supported by this engine |
| */ |
| public abstract boolean isApplicableTo(@Nullable final RunConfigurationBase conf); |
| |
| public abstract boolean canHavePerTestCoverage(@Nullable final RunConfigurationBase conf); |
| |
| /** |
| * Creates coverage enabled configuration for given RunConfiguration. It is supposed that one run configuration may be associated |
| * not more than one coverage engine. |
| * |
| * @param conf Run Configuration |
| * @return Coverage enabled configuration with engine specific settings |
| */ |
| @NotNull |
| public abstract CoverageEnabledConfiguration createCoverageEnabledConfiguration(@Nullable final RunConfigurationBase conf); |
| |
| /** |
| * Coverage suite is coverage settings & coverage data gather by coverage runner (for suites provided by TeamCity server) |
| * |
| * @param covRunner Coverage Runner |
| * @param name Suite name |
| * @param coverageDataFileProvider Coverage raw data file provider |
| * @param filters Coverage data filters |
| * @param lastCoverageTimeStamp timestamp |
| * @param suiteToMerge Suite to merge this coverage data with |
| * @param coverageByTestEnabled Collect coverage for test option |
| * @param tracingEnabled Tracing option |
| * @param trackTestFolders Track test folders option |
| * @return Suite |
| */ |
| @Nullable |
| public CoverageSuite createCoverageSuite(@NotNull final CoverageRunner covRunner, |
| @NotNull final String name, |
| @NotNull final CoverageFileProvider coverageDataFileProvider, |
| @Nullable final String[] filters, |
| final long lastCoverageTimeStamp, |
| @Nullable final String suiteToMerge, |
| final boolean coverageByTestEnabled, |
| final boolean tracingEnabled, |
| final boolean trackTestFolders) { |
| return createCoverageSuite(covRunner, name, coverageDataFileProvider, filters, lastCoverageTimeStamp, suiteToMerge, |
| coverageByTestEnabled, tracingEnabled, trackTestFolders, null); |
| } |
| |
| /** |
| * Coverage suite is coverage settings & coverage data gather by coverage runner (for suites provided by TeamCity server) |
| * |
| * |
| * @param covRunner Coverage Runner |
| * @param name Suite name |
| * @param coverageDataFileProvider Coverage raw data file provider |
| * @param filters Coverage data filters |
| * @param lastCoverageTimeStamp timestamp |
| * @param suiteToMerge Suite to merge this coverage data with |
| * @param coverageByTestEnabled Collect coverage for test option |
| * @param tracingEnabled Tracing option |
| * @param trackTestFolders Track test folders option |
| * @param project |
| * @return Suite |
| */ |
| @Nullable |
| public abstract CoverageSuite createCoverageSuite(@NotNull final CoverageRunner covRunner, |
| @NotNull final String name, |
| @NotNull final CoverageFileProvider coverageDataFileProvider, |
| @Nullable final String[] filters, |
| final long lastCoverageTimeStamp, |
| @Nullable final String suiteToMerge, |
| final boolean coverageByTestEnabled, |
| final boolean tracingEnabled, |
| final boolean trackTestFolders, Project project); |
| |
| /** |
| * Coverage suite is coverage settings & coverage data gather by coverage runner |
| * |
| * @param covRunner Coverage Runner |
| * @param name Suite name |
| * @param coverageDataFileProvider |
| * @param config Coverage engine configuration |
| * @return Suite |
| */ |
| @Nullable |
| public abstract CoverageSuite createCoverageSuite(@NotNull final CoverageRunner covRunner, |
| @NotNull final String name, |
| @NotNull final CoverageFileProvider coverageDataFileProvider, |
| @NotNull final CoverageEnabledConfiguration config); |
| |
| @Nullable |
| public abstract CoverageSuite createEmptyCoverageSuite(@NotNull final CoverageRunner coverageRunner); |
| |
| /** |
| * Coverage annotator which annotates smth(e.g. Project view nodes / editor) with coverage information |
| * |
| * @param project Project |
| * @return Annotator |
| */ |
| @NotNull |
| public abstract CoverageAnnotator getCoverageAnnotator(Project project); |
| |
| /** |
| * Determines if coverage information should be displayed for given file. E.g. coverage may be applicable |
| * only to user source files or only for files of specific types |
| * |
| * @param psiFile file |
| * @return false if coverage N/A for given file |
| */ |
| public abstract boolean coverageEditorHighlightingApplicableTo(@NotNull final PsiFile psiFile); |
| |
| /** |
| * Checks whether file is accepted by coverage filters or not. Is used in Project View Nodes annotator. |
| * |
| * @param psiFile Psi file |
| * @param suite Coverage suite |
| * @return true if included in coverage |
| */ |
| public abstract boolean acceptedByFilters(@NotNull final PsiFile psiFile, @NotNull final CoverageSuitesBundle suite); |
| |
| /** |
| * E.g. all *.class files for java source file with several classes |
| * |
| * |
| * @param srcFile |
| * @param module |
| * @return files |
| */ |
| @NotNull |
| public Set<File> getCorrespondingOutputFiles(@NotNull final PsiFile srcFile, |
| @Nullable final Module module, |
| @NotNull final CoverageSuitesBundle suite) { |
| final VirtualFile virtualFile = srcFile.getVirtualFile(); |
| return virtualFile == null ? Collections.<File>emptySet() : Collections.singleton(VfsUtilCore.virtualToIoFile(virtualFile)); |
| } |
| |
| /** |
| * When output directory is empty we probably should recompile source and then choose suite again |
| * |
| * @param module |
| * @param chooseSuiteAction @return True if should stop and wait compilation (e.g. for Java). False if we can ignore output (e.g. for Ruby) |
| */ |
| public abstract boolean recompileProjectAndRerunAction(@NotNull final Module module, @NotNull final CoverageSuitesBundle suite, |
| @NotNull final Runnable chooseSuiteAction); |
| |
| /** |
| * Qualified name same as in coverage raw project data |
| * E.g. java class qualified name by *.class file of some Java class in corresponding source file |
| * |
| * @param outputFile |
| * @param sourceFile |
| * @return |
| */ |
| @Nullable |
| public String getQualifiedName(@NotNull final File outputFile, |
| @NotNull final PsiFile sourceFile) { |
| final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(outputFile); |
| if (virtualFile != null) { |
| return getQualifiedName(virtualFile, sourceFile); |
| } |
| return null; |
| } |
| |
| @Deprecated |
| @Nullable |
| public String getQualifiedName(@NotNull final VirtualFile outputFile, |
| @NotNull final PsiFile sourceFile) { |
| return null; |
| } |
| |
| @NotNull |
| public abstract Set<String> getQualifiedNames(@NotNull final PsiFile sourceFile); |
| |
| /** |
| * Decide include a file or not in coverage report if coverage data isn't available for the file. E.g file wasn't touched by coverage |
| * util |
| * |
| * @param qualifiedName |
| * @param outputFile |
| * @param sourceFile |
| * @param suite |
| * @return |
| */ |
| public boolean includeUntouchedFileInCoverage(@NotNull final String qualifiedName, |
| @NotNull final File outputFile, |
| @NotNull final PsiFile sourceFile, |
| @NotNull final CoverageSuitesBundle suite) { |
| final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(outputFile); |
| if (virtualFile != null) { |
| return includeUntouchedFileInCoverage(qualifiedName, virtualFile, sourceFile, suite); |
| } |
| return false; |
| } |
| |
| @Deprecated |
| public boolean includeUntouchedFileInCoverage(@NotNull final String qualifiedName, |
| @NotNull final VirtualFile outputFile, |
| @NotNull final PsiFile sourceFile, |
| @NotNull final CoverageSuitesBundle suite) { |
| return false; |
| } |
| |
| /** |
| * Collect code lines if untouched file should be included in coverage information. These lines will be marked as uncovered. |
| * |
| * @param suite |
| * @return List (probably empty) of code lines or null if all lines should be marked as uncovered |
| */ |
| @Nullable |
| public List<Integer> collectSrcLinesForUntouchedFile(@NotNull final File classFile, |
| @NotNull final CoverageSuitesBundle suite) { |
| final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(classFile); |
| if (virtualFile != null) { |
| return collectSrcLinesForUntouchedFile(virtualFile, suite); |
| } |
| return null; |
| } |
| |
| @Deprecated |
| @Nullable |
| public List<Integer> collectSrcLinesForUntouchedFile(@NotNull final VirtualFile classFile, |
| @NotNull final CoverageSuitesBundle suite) { |
| return null; |
| } |
| |
| /** |
| * Content of brief report which will be shown by click on coverage icon |
| * |
| * @param editor |
| * @param psiFile |
| * @param lineNumber |
| * @param startOffset |
| * @param endOffset |
| * @param lineData |
| * @return |
| */ |
| public String generateBriefReport(@NotNull Editor editor, |
| @NotNull PsiFile psiFile, |
| int lineNumber, |
| int startOffset, |
| int endOffset, |
| @Nullable LineData lineData) { |
| final int hits = lineData == null ? 0 : lineData.getHits(); |
| return "Hits: " + hits; |
| } |
| |
| public abstract List<PsiElement> findTestsByNames(@NotNull final String[] testNames, @NotNull final Project project); |
| |
| @Nullable |
| public abstract String getTestMethodName(@NotNull final PsiElement element, @NotNull final AbstractTestProxy testProxy); |
| |
| /** |
| * @return true to enable 'Generate Coverage Report...' action |
| */ |
| public boolean isReportGenerationAvailable(@NotNull Project project, |
| @NotNull DataContext dataContext, |
| @NotNull CoverageSuitesBundle currentSuite) { |
| return false; |
| } |
| |
| public void generateReport(@NotNull final Project project, |
| @NotNull final DataContext dataContext, |
| @NotNull final CoverageSuitesBundle currentSuite) { |
| } |
| |
| @NotNull |
| public ExportToHTMLDialog createGenerateReportDialog(@NotNull final Project project, |
| @NotNull final DataContext dataContext, |
| @NotNull final CoverageSuitesBundle currentSuite) { |
| final ExportToHTMLDialog dialog = new ExportToHTMLDialog(project, true); |
| dialog.setTitle("Generate Coverage Report for: \'" + currentSuite.getPresentableName() + "\'"); |
| |
| return dialog; |
| } |
| |
| public abstract String getPresentableText(); |
| |
| public boolean coverageProjectViewStatisticsApplicableTo(VirtualFile fileOrDir) { |
| return false; |
| } |
| |
| public Object[] postProcessExecutableLines(Object[] lines, Editor editor) { |
| return lines; |
| } |
| |
| public CoverageLineMarkerRenderer getLineMarkerRenderer(int lineNumber, |
| @Nullable final String className, |
| final TreeMap<Integer, LineData> lines, |
| final boolean coverageByTestApplicable, |
| @NotNull final CoverageSuitesBundle coverageSuite, |
| final Function<Integer, Integer> newToOldConverter, |
| final Function<Integer, Integer> oldToNewConverter, boolean subCoverageActive) { |
| return CoverageLineMarkerRenderer |
| .getRenderer(lineNumber, className, lines, coverageByTestApplicable, coverageSuite, newToOldConverter, oldToNewConverter, |
| subCoverageActive); |
| } |
| |
| public boolean shouldHighlightFullLines() { |
| return false; |
| } |
| |
| public static String getEditorTitle() { |
| return "Code Coverage"; |
| } |
| |
| public CoverageViewExtension createCoverageViewExtension(Project project, |
| CoverageSuitesBundle suiteBundle, |
| CoverageViewManager.StateBean stateBean) { |
| return null; |
| } |
| |
| public boolean isInLibraryClasses(Project project, VirtualFile file) { |
| final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex(); |
| |
| return projectFileIndex.isInLibraryClasses(file); |
| } |
| } |