package com.intellij.javascript.karma.coverage; import com.intellij.coverage.CoverageDataManager; import com.intellij.coverage.CoverageExecutor; import com.intellij.coverage.CoverageHelper; import com.intellij.coverage.CoverageRunnerData; import com.intellij.execution.ExecutionException; import com.intellij.execution.ExecutionResult; import com.intellij.execution.configurations.ConfigurationInfoProvider; import com.intellij.execution.configurations.RunProfile; import com.intellij.execution.configurations.RunProfileState; import com.intellij.execution.configurations.RunnerSettings; import com.intellij.execution.configurations.coverage.CoverageEnabledConfiguration; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ExecutionUtil; import com.intellij.execution.runners.GenericProgramRunner; import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.javascript.karma.execution.KarmaConsoleView; import com.intellij.javascript.karma.execution.KarmaRunConfiguration; import com.intellij.javascript.karma.server.KarmaServer; import com.intellij.javascript.karma.util.KarmaUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; import java.util.Objects; public class KarmaCoverageProgramRunner extends GenericProgramRunner { private static final Logger LOG = Logger.getInstance(KarmaCoverageProgramRunner.class); private static final String COVERAGE_RUNNER_ID = KarmaCoverageProgramRunner.class.getSimpleName(); @NotNull @Override public String getRunnerId() { return COVERAGE_RUNNER_ID; } @Override public boolean canRun(@NotNull String executorId, @NotNull RunProfile profile) { return CoverageExecutor.EXECUTOR_ID.equals(executorId) && profile instanceof KarmaRunConfiguration; } @Override public RunnerSettings createConfigurationData(final ConfigurationInfoProvider settingsProvider) { return new CoverageRunnerData(); } @Override protected RunContentDescriptor doExecute(@NotNull RunProfileState state, @NotNull final ExecutionEnvironment env) throws ExecutionException { FileDocumentManager.getInstance().saveAllDocuments(); ExecutionResult executionResult = state.execute(env.getExecutor(), this); if (executionResult == null) { return null; } RunContentDescriptor descriptor = KarmaUtil.createDefaultDescriptor(executionResult, env); KarmaConsoleView consoleView = KarmaConsoleView.get(executionResult, state); if (consoleView == null) { return descriptor; } KarmaServer server = consoleView.getKarmaExecutionSession().getKarmaServer(); if (server.areBrowsersReady()) { listenForCoverageFile(env, server); } else { server.onBrowsersReady(() -> ExecutionUtil.restartIfActive(descriptor)); } return descriptor; } private static void listenForCoverageFile(@NotNull ExecutionEnvironment env, @NotNull KarmaServer server) throws ExecutionException { KarmaRunConfiguration runConfiguration = (KarmaRunConfiguration) env.getRunProfile(); CoverageEnabledConfiguration coverageEnabledConfiguration = CoverageEnabledConfiguration.getOrCreate(runConfiguration); CoverageHelper.resetCoverageSuit(runConfiguration); String coverageFilePath = coverageEnabledConfiguration.getCoverageFilePath(); if (coverageFilePath != null) { KarmaCoveragePeer coveragePeer = server.getCoveragePeer(); Objects.requireNonNull(coveragePeer); coveragePeer.startCoverageSession(new KarmaCoverageSession() { @Override public void onCoverageSessionFinished(@Nullable File lcovFile) { LOG.info("Processing karma coverage file: " + lcovFile); UIUtil.invokeLaterIfNeeded(() -> { Project project = env.getProject(); if (project.isDisposed()) return; if (lcovFile != null) { processLcovInfoFile(lcovFile, coverageFilePath, env, server, runConfiguration); } else { int response = Messages.showYesNoDialog(project, "Cannot find karma test coverage report - lcov.info", "Missing Karma Coverage Report", "Select lcov.info", "Cancel", Messages.getWarningIcon()); if (response == Messages.YES) { FileChooser.chooseFile(FileChooserDescriptorFactory.createSingleFileDescriptor(), project, null, null, file -> { File selected = file != null ? VfsUtilCore.virtualToIoFile(file) : null; if (selected != null) { processLcovInfoFile(selected, coverageFilePath, env, server, runConfiguration); } }); } } }); } }); } } private static void processLcovInfoFile(@NotNull File lcovInfoFile, @NotNull String toCoverageFilePath, @NotNull ExecutionEnvironment env, @NotNull KarmaServer karmaServer, @NotNull KarmaRunConfiguration runConfiguration) { try { FileUtil.copy(lcovInfoFile, new File(toCoverageFilePath)); } catch (IOException e) { LOG.error("Cannot copy " + lcovInfoFile.getAbsolutePath() + " to " + toCoverageFilePath, e); return; } RunnerSettings runnerSettings = env.getRunnerSettings(); if (runnerSettings != null) { KarmaCoverageRunner coverageRunner = KarmaCoverageRunner.getInstance(); coverageRunner.setKarmaServer(karmaServer); CoverageDataManager.getInstance(env.getProject()).processGatheredCoverage(runConfiguration, runnerSettings); } } }