blob: 0e32f5c3b60a3fb68ace2bdd48fb390d64fbe855 [file] [log] [blame]
package com.intellij.coverage;
import com.intellij.CommonBundle;
import com.intellij.codeEditor.printing.ExportToHTMLSettings;
import com.intellij.coverage.view.CoverageViewExtension;
import com.intellij.coverage.view.CoverageViewManager;
import com.intellij.coverage.view.JavaCoverageViewExtension;
import com.intellij.execution.CommonJavaRunConfigurationParameters;
import com.intellij.execution.application.ApplicationConfiguration;
import com.intellij.execution.configurations.RunConfigurationBase;
import com.intellij.execution.configurations.coverage.CoverageEnabledConfiguration;
import com.intellij.execution.configurations.coverage.JavaCoverageEnabledConfiguration;
import com.intellij.execution.testframework.AbstractTestProxy;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileStatusNotification;
import com.intellij.openapi.compiler.CompilerManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.CompilerModuleExtension;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.controlFlow.*;
import com.intellij.psi.impl.source.tree.java.PsiSwitchStatementImpl;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.GlobalSearchScopes;
import com.intellij.psi.util.ClassUtil;
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.ProjectData;
import com.intellij.rt.coverage.data.SwitchData;
import com.intellij.rt.coverage.instrumentation.SaveHook;
import com.intellij.util.containers.HashSet;
import jetbrains.coverage.report.ClassInfo;
import jetbrains.coverage.report.ReportBuilderFactory;
import jetbrains.coverage.report.ReportGenerationFailedException;
import jetbrains.coverage.report.SourceCodeProvider;
import jetbrains.coverage.report.html.HTMLReportBuilder;
import jetbrains.coverage.report.idea.IDEACoverageData;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.JavaSourceRootType;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* @author Roman.Chernyatchik
*/
public class JavaCoverageEngine extends CoverageEngine {
private static final Logger LOG = Logger.getInstance(JavaCoverageEngine.class.getName());
@Override
public boolean isApplicableTo(@Nullable final RunConfigurationBase conf) {
if (conf instanceof CommonJavaRunConfigurationParameters) {
return true;
}
for (JavaCoverageEngineExtension extension : Extensions.getExtensions(JavaCoverageEngineExtension.EP_NAME)) {
if (extension.isApplicableTo(conf)) {
return true;
}
}
return false;
}
@Override
public boolean canHavePerTestCoverage(@Nullable RunConfigurationBase conf) {
return !(conf instanceof ApplicationConfiguration) && conf instanceof CommonJavaRunConfigurationParameters;
}
@NotNull
@Override
public CoverageEnabledConfiguration createCoverageEnabledConfiguration(@Nullable final RunConfigurationBase conf) {
return new JavaCoverageEnabledConfiguration(conf, this);
}
@Nullable
@Override
public CoverageSuite createCoverageSuite(@NotNull final CoverageRunner covRunner,
@NotNull final String name,
@NotNull final CoverageFileProvider coverageDataFileProvider,
String[] filters,
long lastCoverageTimeStamp,
String suiteToMerge,
boolean coverageByTestEnabled,
boolean tracingEnabled,
boolean trackTestFolders, Project project) {
return createSuite(covRunner, name, coverageDataFileProvider, filters, lastCoverageTimeStamp, coverageByTestEnabled,
tracingEnabled, trackTestFolders, project);
}
@Override
public CoverageSuite createCoverageSuite(@NotNull final CoverageRunner covRunner,
@NotNull final String name,
@NotNull final CoverageFileProvider coverageDataFileProvider,
@NotNull final CoverageEnabledConfiguration config) {
if (config instanceof JavaCoverageEnabledConfiguration) {
final JavaCoverageEnabledConfiguration javaConfig = (JavaCoverageEnabledConfiguration)config;
return createSuite(covRunner, name, coverageDataFileProvider,
javaConfig.getPatterns(),
new Date().getTime(),
javaConfig.isTrackPerTestCoverage() && !javaConfig.isSampling(),
!javaConfig.isSampling(),
javaConfig.isTrackTestFolders(), config.getConfiguration().getProject());
}
return null;
}
@Nullable
@Override
public CoverageSuite createEmptyCoverageSuite(@NotNull CoverageRunner coverageRunner) {
return new JavaCoverageSuite(this);
}
@NotNull
@Override
public CoverageAnnotator getCoverageAnnotator(Project project) {
return JavaCoverageAnnotator.getInstance(project);
}
/**
* Determines if coverage information should be displayed for given file
* @param psiFile
* @return
*/
public boolean coverageEditorHighlightingApplicableTo(@NotNull final PsiFile psiFile) {
if (!(psiFile instanceof PsiClassOwner)) {
return false;
}
// let's show coverage only for module files
final Module module = ApplicationManager.getApplication().runReadAction(new Computable<Module>() {
@Nullable
public Module compute() {
return ModuleUtil.findModuleForPsiElement(psiFile);
}
});
return module != null;
}
public boolean acceptedByFilters(@NotNull final PsiFile psiFile, @NotNull final CoverageSuitesBundle suite) {
final VirtualFile virtualFile = psiFile.getVirtualFile();
if (virtualFile == null) return false;
final Project project = psiFile.getProject();
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
if (!suite.isTrackTestFolders() && fileIndex.isInTestSourceContent(virtualFile)) {
return false;
}
for (CoverageSuite coverageSuite : suite.getSuites()) {
final JavaCoverageSuite javaSuite = (JavaCoverageSuite)coverageSuite;
final List<PsiPackage> packages = javaSuite.getCurrentSuitePackages(project);
if (isUnderFilteredPackages((PsiClassOwner)psiFile, packages)) {
return true;
} else {
final List<PsiClass> classes = javaSuite.getCurrentSuiteClasses(project);
for (PsiClass aClass : classes) {
final PsiFile containingFile = aClass.getContainingFile();
if (psiFile.equals(containingFile)) {
return true;
}
}
}
}
return false;
}
@Override
public boolean recompileProjectAndRerunAction(@NotNull final Module module, @NotNull final CoverageSuitesBundle suite,
@NotNull final Runnable chooseSuiteAction) {
final VirtualFile outputpath = CompilerModuleExtension.getInstance(module).getCompilerOutputPath();
final VirtualFile testOutputpath = CompilerModuleExtension.getInstance(module).getCompilerOutputPathForTests();
if ((outputpath == null && isModuleOutputNeeded(module, JavaSourceRootType.SOURCE))
|| (suite.isTrackTestFolders() && testOutputpath == null && isModuleOutputNeeded(module, JavaSourceRootType.TEST_SOURCE))) {
final Project project = module.getProject();
if (suite.isModuleChecked(module)) return false;
suite.checkModule(module);
final Runnable runnable = new Runnable() {
public void run() {
if (Messages.showOkCancelDialog(
"Project class files are out of date. Would you like to recompile? The refusal to do it will result in incomplete coverage information",
"Project is out of date", Messages.getWarningIcon()) == Messages.OK) {
final CompilerManager compilerManager = CompilerManager.getInstance(project);
compilerManager.make(compilerManager.createProjectCompileScope(project), new CompileStatusNotification() {
public void finished(final boolean aborted, final int errors, final int warnings, final CompileContext compileContext) {
if (aborted || errors != 0) return;
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
if (project.isDisposed()) return;
CoverageDataManager.getInstance(project).chooseSuitesBundle(suite);
}
});
}
});
} else if (!project.isDisposed()) {
CoverageDataManager.getInstance(project).chooseSuitesBundle(null);
}
}
};
ApplicationManager.getApplication().invokeLater(runnable);
return true;
}
return false;
}
private static boolean isModuleOutputNeeded(Module module, final JavaSourceRootType rootType) {
return !ModuleRootManager.getInstance(module).getSourceRoots(rootType).isEmpty();
}
public static boolean isUnderFilteredPackages(final PsiClassOwner javaFile, final List<PsiPackage> packages) {
final String hisPackageName = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
public String compute() {
return javaFile.getPackageName();
}
});
PsiPackage hisPackage = JavaPsiFacade.getInstance(javaFile.getProject()).findPackage(hisPackageName);
if (hisPackage == null) return false;
for (PsiPackage aPackage : packages) {
if (PsiTreeUtil.isAncestor(aPackage, hisPackage, false)) return true;
}
return false;
}
@Nullable
public List<Integer> collectSrcLinesForUntouchedFile(@NotNull final File classFile, @NotNull final CoverageSuitesBundle suite) {
final List<Integer> uncoveredLines = new ArrayList<Integer>();
final byte[] content;
try {
content = FileUtil.loadFileBytes(classFile);
}
catch (IOException e) {
return null;
}
try {
SourceLineCounterUtil.collectSrcLinesForUntouchedFiles(uncoveredLines, content, suite.isTracingEnabled());
}
catch (Exception e) {
LOG.error("Fail to process class from: " + classFile.getPath(), e);
}
return uncoveredLines;
}
public boolean includeUntouchedFileInCoverage(@NotNull final String qualifiedName,
@NotNull final File outputFile,
@NotNull final PsiFile sourceFile, @NotNull CoverageSuitesBundle suite) {
for (CoverageSuite coverageSuite : suite.getSuites()) {
final JavaCoverageSuite javaSuite = (JavaCoverageSuite)coverageSuite;
if (javaSuite.isClassFiltered(qualifiedName) || javaSuite.isPackageFiltered(getPackageName(sourceFile))) return true;
}
return false;
}
public String getQualifiedName(@NotNull final File outputFile, @NotNull final PsiFile sourceFile) {
final String packageFQName = getPackageName(sourceFile);
return StringUtil.getQualifiedName(packageFQName, FileUtil.getNameWithoutExtension(outputFile));
}
@NotNull
@Override
public Set<String> getQualifiedNames(@NotNull final PsiFile sourceFile) {
final PsiClass[] classes = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass[]>() {
public PsiClass[] compute() {
return ((PsiClassOwner)sourceFile).getClasses();
}
});
final Set<String> qNames = new HashSet<String>();
for (final JavaCoverageEngineExtension nameExtension : Extensions.getExtensions(JavaCoverageEngineExtension.EP_NAME)) {
if (ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
public Boolean compute() {
return nameExtension.suggestQualifiedName(sourceFile, classes, qNames);
}
})) {
return qNames;
}
}
for (final PsiClass aClass : classes) {
final String qName = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Nullable
public String compute() {
return aClass.getQualifiedName();
}
});
if (qName == null) continue;
qNames.add(qName);
}
return qNames;
}
@NotNull
public Set<File> getCorrespondingOutputFiles(@NotNull final PsiFile srcFile,
@Nullable final Module module,
@NotNull final CoverageSuitesBundle suite) {
if (module == null) {
return Collections.emptySet();
}
final Set<File> classFiles = new HashSet<File>();
final VirtualFile outputpath = CompilerModuleExtension.getInstance(module).getCompilerOutputPath();
final VirtualFile testOutputpath = CompilerModuleExtension.getInstance(module).getCompilerOutputPathForTests();
for (JavaCoverageEngineExtension extension : Extensions.getExtensions(JavaCoverageEngineExtension.EP_NAME)) {
if (extension.collectOutputFiles(srcFile, outputpath, testOutputpath, suite, classFiles)) return classFiles;
}
final String packageFQName = getPackageName(srcFile);
final String packageVmName = packageFQName.replace('.', '/');
final List<File> children = new ArrayList<File>();
final File vDir =
outputpath == null
? null : packageVmName.length() > 0
? new File(outputpath.getPath() + File.separator + packageVmName) : VfsUtilCore.virtualToIoFile(outputpath);
if (vDir != null && vDir.exists()) {
Collections.addAll(children, vDir.listFiles());
}
if (suite.isTrackTestFolders()) {
final File testDir =
testOutputpath == null
? null : packageVmName.length() > 0
? new File(testOutputpath.getPath() + File.separator + packageVmName) : VfsUtilCore.virtualToIoFile(testOutputpath);
if (testDir != null && testDir.exists()) {
Collections.addAll(children, testDir.listFiles());
}
}
final PsiClass[] classes = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass[]>() {
public PsiClass[] compute() {
return ((PsiClassOwner)srcFile).getClasses();
}
});
for (final PsiClass psiClass : classes) {
final String className = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
public String compute() {
return psiClass.getName();
}
});
for (File child : children) {
if (FileUtilRt.extensionEquals(child.getName(), StdFileTypes.CLASS.getDefaultExtension())) {
final String childName = FileUtil.getNameWithoutExtension(child);
if (childName.equals(className) || //class or inner
childName.startsWith(className) && childName.charAt(className.length()) == '$') {
classFiles.add(child);
}
}
}
}
return classFiles;
}
public String generateBriefReport(@NotNull Editor editor,
@NotNull PsiFile psiFile,
int lineNumber,
int startOffset,
int endOffset,
@Nullable LineData lineData) {
final StringBuffer buf = new StringBuffer();
buf.append("Hits: ");
if (lineData == null) {
buf.append(0);
return buf.toString();
}
buf.append(lineData.getHits()).append("\n");
final List<PsiExpression> expressions = new ArrayList<PsiExpression>();
final Project project = editor.getProject();
for(int offset = startOffset; offset < endOffset; offset++) {
PsiElement parent = PsiTreeUtil.getParentOfType(psiFile.findElementAt(offset), PsiStatement.class);
PsiElement condition = null;
if (parent instanceof PsiIfStatement) {
condition = ((PsiIfStatement)parent).getCondition();
} else if (parent instanceof PsiSwitchStatement) {
condition = ((PsiSwitchStatement)parent).getExpression();
} else if (parent instanceof PsiDoWhileStatement) {
condition = ((PsiDoWhileStatement)parent).getCondition();
} else if (parent instanceof PsiForStatement) {
condition = ((PsiForStatement)parent).getCondition();
} else if (parent instanceof PsiWhileStatement) {
condition = ((PsiWhileStatement)parent).getCondition();
} else if (parent instanceof PsiForeachStatement) {
condition = ((PsiForeachStatement)parent).getIteratedValue();
} else if (parent instanceof PsiAssertStatement) {
condition = ((PsiAssertStatement)parent).getAssertCondition();
}
if (condition != null && PsiTreeUtil.isAncestor(condition, psiFile.findElementAt(offset), false)) {
try {
final ControlFlow controlFlow = ControlFlowFactory.getInstance(project).getControlFlow(
parent, AllVariablesControlFlowPolicy.getInstance());
for (Instruction instruction : controlFlow.getInstructions()) {
if (instruction instanceof ConditionalBranchingInstruction) {
final PsiExpression expression = ((ConditionalBranchingInstruction)instruction).expression;
if (!expressions.contains(expression)) {
expressions.add(expression);
}
}
}
}
catch (AnalysisCanceledException e) {
return buf.toString();
}
}
}
final String indent = " ";
try {
int idx = 0;
int hits = 0;
if (lineData.getJumps() != null) {
for (Object o : lineData.getJumps()) {
final JumpData jumpData = (JumpData)o;
if (jumpData.getTrueHits() + jumpData.getFalseHits() > 0) {
final PsiExpression expression = expressions.get(idx++);
final PsiElement parentExpression = expression.getParent();
boolean reverse = parentExpression instanceof PsiPolyadicExpression && ((PsiPolyadicExpression)parentExpression).getOperationTokenType() == JavaTokenType.OROR
|| parentExpression instanceof PsiDoWhileStatement || parentExpression instanceof PsiAssertStatement;
buf.append(indent).append(expression.getText()).append("\n");
buf.append(indent).append(indent).append("true hits: ").append(reverse ? jumpData.getFalseHits() : jumpData.getTrueHits()).append("\n");
buf.append(indent).append(indent).append("false hits: ").append(reverse ? jumpData.getTrueHits() : jumpData.getFalseHits()).append("\n");
hits += jumpData.getTrueHits() + jumpData.getFalseHits();
}
}
}
if (lineData.getSwitches() != null) {
for (Object o : lineData.getSwitches()) {
final SwitchData switchData = (SwitchData)o;
final PsiExpression conditionExpression = expressions.get(idx++);
buf.append(indent).append(conditionExpression.getText()).append("\n");
int i = 0;
for (int key : switchData.getKeys()) {
final int switchHits = switchData.getHits()[i++];
buf.append(indent).append(indent).append("case ").append(key).append(": ").append(switchHits).append("\n");
hits += switchHits;
}
int defaultHits = switchData.getDefaultHits();
final boolean hasDefaultLabel = hasDefaultLabel(conditionExpression);
if (hasDefaultLabel || defaultHits > 0) {
if (!hasDefaultLabel) {
defaultHits -= hits;
}
if (hasDefaultLabel || defaultHits > 0) {
buf.append(indent).append(indent).append("default: ").append(defaultHits).append("\n");
hits += defaultHits;
}
}
}
}
if (lineData.getHits() > hits && hits > 0) {
buf.append("Unknown outcome: ").append(lineData.getHits() - hits);
}
}
catch (Exception e) {
LOG.info(e);
return "Hits: " + lineData.getHits();
}
return buf.toString();
}
@Nullable
public String getTestMethodName(@NotNull final PsiElement element,
@NotNull final AbstractTestProxy testProxy) {
return testProxy.toString();
}
@NotNull
public List<PsiElement> findTestsByNames(@NotNull String[] testNames, @NotNull Project project) {
final List<PsiElement> elements = new ArrayList<PsiElement>();
final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
final GlobalSearchScope projectScope = GlobalSearchScope.projectScope(project);
for (String testName : testNames) {
PsiClass psiClass =
facade.findClass(StringUtil.getPackageName(testName, '_').replaceAll("\\_", "\\."), projectScope);
int lastIdx = testName.lastIndexOf("_");
if (psiClass != null) {
collectTestsByName(elements, testName, psiClass, lastIdx);
} else {
String className = testName;
while (lastIdx > 0) {
className = className.substring(0, lastIdx - 1);
psiClass = facade.findClass(StringUtil.getPackageName(className, '_').replaceAll("\\_", "\\."), projectScope);
lastIdx = className.lastIndexOf("_");
if (psiClass != null) {
collectTestsByName(elements, testName, psiClass, lastIdx);
break;
}
}
}
}
return elements;
}
private static void collectTestsByName(List<PsiElement> elements, String testName, PsiClass psiClass, int lastIdx) {
final PsiMethod[] testsByName = psiClass.findMethodsByName(testName.substring(lastIdx + 1), true);
if (testsByName.length == 1) {
elements.add(testsByName[0]);
}
}
private static boolean hasDefaultLabel(final PsiElement conditionExpression) {
boolean hasDefault = false;
final PsiSwitchStatement switchStatement = PsiTreeUtil.getParentOfType(conditionExpression, PsiSwitchStatement.class);
final PsiCodeBlock body = ((PsiSwitchStatementImpl)conditionExpression.getParent()).getBody();
if (body != null) {
final PsiElement bodyElement = body.getFirstBodyElement();
if (bodyElement != null) {
PsiSwitchLabelStatement label = PsiTreeUtil.getNextSiblingOfType(bodyElement, PsiSwitchLabelStatement.class);
while (label != null) {
if (label.getEnclosingSwitchStatement() == switchStatement) {
hasDefault |= label.isDefaultCase();
}
label = PsiTreeUtil.getNextSiblingOfType(label, PsiSwitchLabelStatement.class);
}
}
}
return hasDefault;
}
protected JavaCoverageSuite createSuite(CoverageRunner acceptedCovRunner,
String name, CoverageFileProvider coverageDataFileProvider,
String[] filters,
long lastCoverageTimeStamp,
boolean coverageByTestEnabled,
boolean tracingEnabled,
boolean trackTestFolders, Project project) {
return new JavaCoverageSuite(name, coverageDataFileProvider, filters, lastCoverageTimeStamp, coverageByTestEnabled, tracingEnabled,
trackTestFolders, acceptedCovRunner, this, project);
}
@NotNull
protected static String getPackageName(final PsiFile sourceFile) {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
public String compute() {
return ((PsiClassOwner)sourceFile).getPackageName();
}
});
}
protected static void generateJavaReport(@NotNull final Project project,
final File tempFile,
final CoverageSuitesBundle currentSuite) {
final ExportToHTMLSettings settings = ExportToHTMLSettings.getInstance(project);
final ProjectData projectData = currentSuite.getCoverageData();
ProgressManager.getInstance().run(new Task.Backgroundable(project, "Generating coverage report ...") {
final Exception[] myExceptions = new Exception[1];
public void run(@NotNull final ProgressIndicator indicator) {
try {
new SaveHook(tempFile, true, new IdeaClassFinder(project, currentSuite)).save(projectData);
final HTMLReportBuilder builder = ReportBuilderFactory.createHTMLReportBuilder();
builder.setReportDir(new File(settings.OUTPUT_DIRECTORY));
final SourceCodeProvider sourceCodeProvider = new SourceCodeProvider() {
public String getSourceCode(@NotNull final String classname) throws IOException {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
public String compute() {
final PsiClass psiClass = ClassUtil.findPsiClassByJVMName(PsiManager.getInstance(project), classname);
return psiClass != null ? psiClass.getContainingFile().getText() : "";
}
});
}
};
builder.generateReport(new IDEACoverageData(projectData, sourceCodeProvider) {
@NotNull
@Override
public Collection<ClassInfo> getClasses() {
final Collection<ClassInfo> classes = super.getClasses();
if (!currentSuite.isTrackTestFolders()) {
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
final GlobalSearchScope productionScope = GlobalSearchScopes.projectProductionScope(project);
for (Iterator<ClassInfo> iterator = classes.iterator(); iterator.hasNext();) {
final ClassInfo aClass = iterator.next();
final PsiClass psiClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
public PsiClass compute() {
return psiFacade.findClass(aClass.getFQName(), productionScope);
}
});
if (psiClass == null) {
iterator.remove();
}
}
}
return classes;
}
});
}
catch (IOException e) {
LOG.error(e);
}
catch (ReportGenerationFailedException e) {
myExceptions[0] = e;
}
}
@Override
public void onSuccess() {
if (myExceptions[0] != null) {
Messages.showErrorDialog(project, myExceptions[0].getMessage(), CommonBundle.getErrorTitle());
return;
}
if (settings.OPEN_IN_BROWSER) {
BrowserUtil.browse(new File(settings.OUTPUT_DIRECTORY, "index.html"));
}
}
});
}
@Override
public boolean isReportGenerationAvailable(@NotNull Project project,
@NotNull DataContext dataContext,
@NotNull CoverageSuitesBundle currentSuite) {
Sdk projectSdk = ProjectRootManager.getInstance(project).getProjectSdk();
return projectSdk != null;
}
@Override
public final void generateReport(@NotNull final Project project,
@NotNull final DataContext dataContext,
@NotNull final CoverageSuitesBundle currentSuite) {
try {
final File tempFile = FileUtil.createTempFile("temp", "");
tempFile.deleteOnExit();
generateJavaReport(project, tempFile, currentSuite);
}
catch (IOException e1) {
LOG.error(e1);
}
}
@Override
public String getPresentableText() {
return "Java Coverage";
}
@Override
public CoverageViewExtension createCoverageViewExtension(Project project,
CoverageSuitesBundle suiteBundle,
CoverageViewManager.StateBean stateBean) {
return new JavaCoverageViewExtension((JavaCoverageAnnotator)getCoverageAnnotator(project), project, suiteBundle, stateBean);
}
}