[coverage] IDEA-323740 Fix coverage chooser dialog to be able to choose several suites

GitOrigin-RevId: 69e0687d9355dc2dc38a62a66faf07107011fcf1
This commit is contained in:
Maksim Zuev
2023-10-19 17:55:23 +02:00
committed by intellij-monorepo-bot
parent 6106979688
commit dba486da24
9 changed files with 321 additions and 221 deletions

View File

@@ -107,8 +107,7 @@ public abstract class BaseCoverageSuite implements CoverageSuite, JDOMExternali
final File file = new File(relativePath);
return new DefaultCoverageFileProvider(file.exists() ? file
: new File(PathManager.getSystemPath(), relativePath),
sourceProvider != null ? sourceProvider
: DefaultCoverageFileProvider.class.getName());
sourceProvider != null ? sourceProvider : DefaultCoverageFileProvider.DEFAULT_LOCAL_PROVIDER_KEY);
}
@Override
@@ -180,8 +179,8 @@ public abstract class BaseCoverageSuite implements CoverageSuite, JDOMExternali
element.setAttribute(FILE_PATH, fileName != null ? FileUtil.toSystemIndependentName(fileName) : myCoverageDataFileProvider.getCoverageDataFilePath());
element.setAttribute(NAME_ATTRIBUTE, myName);
element.setAttribute(MODIFIED_STAMP, String.valueOf(myLastCoverageTimeStamp));
element.setAttribute(SOURCE_PROVIDER, myCoverageDataFileProvider instanceof DefaultCoverageFileProvider
? ((DefaultCoverageFileProvider)myCoverageDataFileProvider).getSourceProvider()
element.setAttribute(SOURCE_PROVIDER, myCoverageDataFileProvider instanceof DefaultCoverageFileProvider defaultProvider
? defaultProvider.getSourceProvider()
: myCoverageDataFileProvider.getClass().getName());
// runner
if (getRunner() != null) {

View File

@@ -68,8 +68,8 @@ public interface CoverageSuite extends JDOMExternalizable {
*/
default boolean canRemove() {
CoverageFileProvider provider = getCoverageDataFileProvider();
return provider instanceof DefaultCoverageFileProvider && Comparing.strEqual(((DefaultCoverageFileProvider)provider).getSourceProvider(),
DefaultCoverageFileProvider.class.getName());
return provider instanceof DefaultCoverageFileProvider defaultProvider
&& Comparing.strEqual(defaultProvider.getSourceProvider(), DefaultCoverageFileProvider.DEFAULT_LOCAL_PROVIDER_KEY);
}
/**

View File

@@ -21,15 +21,17 @@ import java.io.File;
* @author Eugene Zhuravlev
*/
public final class DefaultCoverageFileProvider implements CoverageFileProvider{
public static final String DEFAULT_LOCAL_PROVIDER_KEY = DefaultCoverageFileProvider.class.getName();
private final File myFile;
private final String mySourceProvider;
public DefaultCoverageFileProvider(String path) {
this(new File(path), DefaultCoverageFileProvider.class.getName());
this(new File(path), DEFAULT_LOCAL_PROVIDER_KEY);
}
public DefaultCoverageFileProvider(File file) {
this(file, DefaultCoverageFileProvider.class.getName());
this(file, DEFAULT_LOCAL_PROVIDER_KEY);
}
public DefaultCoverageFileProvider(File file, String sourceProvider) {

View File

@@ -5,13 +5,11 @@ import com.intellij.CommonBundle;
import com.intellij.coverage.*;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.ValidationInfo;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
@@ -23,6 +21,7 @@ import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.TreeTraversal;
import com.intellij.util.text.DateFormatUtil;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -30,12 +29,12 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.List;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;
public class CoverageSuiteChooserDialog extends DialogWrapper {
@NonNls private static final String LOCAL = "Local";
@@ -43,7 +42,6 @@ public class CoverageSuiteChooserDialog extends DialogWrapper {
private final CheckboxTree mySuitesTree;
private final CoverageDataManager myCoverageManager;
private final CheckedTreeNode myRootNode;
private CoverageEngine myEngine;
public CoverageSuiteChooserDialog(Project project) {
super(project, true);
@@ -93,7 +91,6 @@ public class CoverageSuiteChooserDialog extends DialogWrapper {
group.add(new AddExternalSuiteAction());
group.add(new RemoveSuiteAction());
group.add(new DeleteSuiteAction());
group.add(new SwitchEngineAction());
final ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar("CoverageSuiteChooser", group, true);
toolbar.setTargetComponent(mySuitesTree);
return toolbar.getComponent();
@@ -102,29 +99,31 @@ public class CoverageSuiteChooserDialog extends DialogWrapper {
@Override
protected void doOKAction() {
final List<CoverageSuite> suites = collectSelectedSuites();
if (!suites.isEmpty()) {
CoverageSuitesBundle bundle = new CoverageSuitesBundle(suites.toArray(new CoverageSuite[0]));
Map<CoverageEngine, List<CoverageSuite>> byEngine = suites.stream().collect(Collectors.groupingBy((suite) -> suite.getCoverageEngine()));
closeBundlesThatAreNotChosen(byEngine);
for (List<CoverageSuite> suiteList : byEngine.values()) {
CoverageSuitesBundle bundle = new CoverageSuitesBundle(suiteList.toArray(new CoverageSuite[0]));
CoverageLogger.logSuiteImport(myProject, bundle);
myCoverageManager.chooseSuitesBundle(bundle);
}
if (!suites.isEmpty()) {
ExternalCoverageWatchManager.getInstance(myProject).addRootsToWatch(suites);
}
super.doOKAction();
}
@NotNull
@Override
protected List<ValidationInfo> doValidateAll() {
CoverageEngine engine = null;
for (CoverageSuite suite : collectSelectedSuites()) {
if (engine == null) {
engine = suite.getCoverageEngine();
continue;
}
if (!Comparing.equal(engine, suite.getCoverageEngine())) {
return Collections.singletonList(new ValidationInfo(CoverageBundle.message("cannot.show.coverage.reports.from.different.engines"), mySuitesTree));
private void closeBundlesThatAreNotChosen(Map<CoverageEngine, List<CoverageSuite>> byEngine) {
Collection<CoverageSuitesBundle> activeSuites = myCoverageManager.activeSuites();
Set<CoverageEngine> activeEngines = activeSuites.stream().map(b -> b.getCoverageEngine()).collect(Collectors.toSet());
activeEngines.removeAll(byEngine.keySet());
for (CoverageSuitesBundle bundle : activeSuites) {
if (activeEngines.contains(bundle.getCoverageEngine())) {
myCoverageManager.closeSuitesBundle(bundle);
}
}
return super.doValidateAll();
}
@Override
@@ -132,14 +131,6 @@ public class CoverageSuiteChooserDialog extends DialogWrapper {
return new Action[]{getOKAction(), new NoCoverageAction(), getCancelAction()};
}
private Set<CoverageEngine> collectEngines() {
final Set<CoverageEngine> engines = new HashSet<>();
for (CoverageSuite suite : myCoverageManager.getSuites()) {
engines.add(suite.getCoverageEngine());
}
return engines;
}
private static String getCoverageRunnerTitle(CoverageRunner coverageRunner) {
return CoverageBundle.message("coverage.data.runner.name", coverageRunner.getPresentableName());
}
@@ -157,10 +148,10 @@ public class CoverageSuiteChooserDialog extends DialogWrapper {
private List<CoverageSuite> collectSelectedSuites() {
final List<CoverageSuite> suites = new ArrayList<>();
TreeUtil.treeNodeTraverser(myRootNode).traverse(TreeTraversal.PRE_ORDER_DFS).processEach(treeNode -> {
if (treeNode instanceof CheckedTreeNode && ((CheckedTreeNode)treeNode).isChecked()) {
final Object userObject = ((CheckedTreeNode)treeNode).getUserObject();
if (userObject instanceof CoverageSuite) {
suites.add((CoverageSuite)userObject);
if (treeNode instanceof CheckedTreeNode checkedTreeNode && checkedTreeNode.isChecked()) {
final Object userObject = checkedTreeNode.getUserObject();
if (userObject instanceof CoverageSuite suite) {
suites.add(suite);
}
}
return true;
@@ -168,106 +159,106 @@ public class CoverageSuiteChooserDialog extends DialogWrapper {
return suites;
}
private void selectSuites(List<CoverageSuite> suites) {
TreeUtil.treeNodeTraverser(myRootNode).traverse(TreeTraversal.PRE_ORDER_DFS).processEach(treeNode -> {
if (treeNode instanceof CheckedTreeNode checkedTreeNode) {
final Object userObject = checkedTreeNode.getUserObject();
checkedTreeNode.setChecked(userObject instanceof CoverageSuite && suites.contains(userObject));
}
return true;
});
}
private void initTree() {
myRootNode.removeAllChildren();
final HashMap<CoverageRunner, Map<String, List<CoverageSuite>>> grouped = new HashMap<>();
groupSuites(grouped, myCoverageManager.getSuites(), myEngine);
groupSuites(grouped, myCoverageManager.getSuites());
final List<CoverageRunner> runners = new ArrayList<>(grouped.keySet());
runners.sort((o1, o2) -> o1.getPresentableName().compareToIgnoreCase(o2.getPresentableName()));
for (CoverageRunner runner : runners) {
final DefaultMutableTreeNode runnerNode = new DefaultMutableTreeNode(getCoverageRunnerTitle(runner));
myRootNode.add(runnerNode);
final Map<String, List<CoverageSuite>> providers = grouped.get(runner);
final DefaultMutableTreeNode remoteNode = new DefaultMutableTreeNode(CoverageBundle.message("remote.suites.node"));
if (providers.size() == 1) {
final String providersKey = providers.keySet().iterator().next();
DefaultMutableTreeNode suitesNode = runnerNode;
if (!Comparing.strEqual(providersKey, DefaultCoverageFileProvider.class.getName())) {
suitesNode = remoteNode;
runnerNode.add(remoteNode);
}
final List<CoverageSuite> suites = providers.get(providersKey);
suites.sort((o1, o2) -> o1.getPresentableName().compareToIgnoreCase(o2.getPresentableName()));
for (CoverageSuite suite : suites) {
final CheckedTreeNode treeNode = new CheckedTreeNode(suite);
treeNode.setChecked(isSuiteActive(suite));
suitesNode.add(treeNode);
String providerKey = providers.keySet().iterator().next();
DefaultMutableTreeNode parent = runnerNode;
if (!isLocalProvider(providerKey)) {
DefaultMutableTreeNode remoteNode = new DefaultMutableTreeNode(CoverageBundle.message("remote.suites.node"));
parent.add(remoteNode);
parent = remoteNode;
}
List<CoverageSuite> suites = providers.get(providerKey);
createSuitesNodes(suites, parent);
}
else {
final DefaultMutableTreeNode localNode = new DefaultMutableTreeNode(LOCAL);
DefaultMutableTreeNode localNode = new DefaultMutableTreeNode(LOCAL);
DefaultMutableTreeNode remoteNode = new DefaultMutableTreeNode(CoverageBundle.message("remote.suites.node"));
runnerNode.add(localNode);
runnerNode.add(remoteNode);
for (String aClass : providers.keySet()) {
DefaultMutableTreeNode node = Comparing.strEqual(aClass, DefaultCoverageFileProvider.class.getName()) ? localNode : remoteNode;
for (CoverageSuite suite : providers.get(aClass)) {
final CheckedTreeNode treeNode = new CheckedTreeNode(suite);
treeNode.setChecked(isSuiteActive(suite));
node.add(treeNode);
}
for (var entry : providers.entrySet()) {
DefaultMutableTreeNode parent = isLocalProvider(entry.getKey()) ? localNode : remoteNode;
createSuitesNodes(entry.getValue(), parent);
}
}
myRootNode.add(runnerNode);
}
}
private void createSuitesNodes(List<CoverageSuite> suites, DefaultMutableTreeNode parent) {
suites.sort((o1, o2) -> o1.getPresentableName().compareToIgnoreCase(o2.getPresentableName()));
for (CoverageSuite suite : suites) {
CheckedTreeNode treeNode = new CheckedTreeNode(suite);
treeNode.setChecked(isSuiteActive(suite));
parent.add(treeNode);
}
}
private static boolean isLocalProvider(String providerKey) {
return Comparing.strEqual(providerKey, DefaultCoverageFileProvider.DEFAULT_LOCAL_PROVIDER_KEY);
}
private boolean isSuiteActive(CoverageSuite suite) {
return ContainerUtil.exists(myCoverageManager.activeSuites(), bundle -> bundle.contains(suite));
}
private static void groupSuites(final HashMap<CoverageRunner, Map<String, List<CoverageSuite>>> grouped,
final CoverageSuite[] suites,
final CoverageEngine engine) {
private static void groupSuites(HashMap<CoverageRunner, Map<String, List<CoverageSuite>>> grouped,
CoverageSuite[] suites) {
for (CoverageSuite suite : suites) {
if (engine != null && suite.getCoverageEngine() != engine) continue;
final CoverageFileProvider provider = suite.getCoverageDataFileProvider();
if (provider instanceof DefaultCoverageFileProvider &&
Comparing.strEqual(((DefaultCoverageFileProvider)provider).getSourceProvider(), DefaultCoverageFileProvider.class.getName())) {
if (!provider.ensureFileExists()) continue;
}
final CoverageRunner runner = suite.getRunner();
Map<String, List<CoverageSuite>> byProviders = grouped.get(runner);
if (byProviders == null) {
byProviders = new HashMap<>();
grouped.put(runner, byProviders);
}
final String sourceProvider = provider instanceof DefaultCoverageFileProvider
? ((DefaultCoverageFileProvider)provider).getSourceProvider()
: provider.getClass().getName();
List<CoverageSuite> list = byProviders.get(sourceProvider);
if (list == null) {
list = new ArrayList<>();
byProviders.put(sourceProvider, list);
CoverageFileProvider provider = suite.getCoverageDataFileProvider();
if (provider instanceof DefaultCoverageFileProvider defaultProvider &&
isLocalProvider(defaultProvider.getSourceProvider())
&& !provider.ensureFileExists()) {
continue;
}
Map<String, List<CoverageSuite>> byProviders = grouped.computeIfAbsent(suite.getRunner(), (unused) -> new HashMap<>());
String sourceProvider = provider instanceof DefaultCoverageFileProvider defaultProvider
? defaultProvider.getSourceProvider()
: provider.getClass().getName();
List<CoverageSuite> list = byProviders.computeIfAbsent(sourceProvider, (unused) -> new ArrayList<>());
list.add(suite);
}
}
private void updateTree() {
((DefaultTreeModel)mySuitesTree.getModel()).reload();
TreeUtil.expandAll(mySuitesTree);
}
private static class SuitesRenderer extends CheckboxTree.CheckboxTreeCellRenderer {
@Override
public void customizeRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
if (value instanceof CheckedTreeNode) {
final Object userObject = ((CheckedTreeNode)value).getUserObject();
if (value instanceof CheckedTreeNode checkedTreeNode) {
final Object userObject = checkedTreeNode.getUserObject();
if (userObject instanceof CoverageSuite suite) {
getTextRenderer().append(suite.getPresentableName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
final String date = " (" + DateFormatUtil.formatPrettyDateTime(suite.getLastCoverageTimeStamp()) + ")";
getTextRenderer().append(date, SimpleTextAttributes.GRAY_ATTRIBUTES);
}
}
else if (value instanceof DefaultMutableTreeNode) {
final Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
if (userObject instanceof String) {
getTextRenderer().append((String)userObject);
else if (value instanceof DefaultMutableTreeNode defaultNode) {
final Object userObject = defaultNode.getUserObject();
if (userObject instanceof @Nls String name) {
getTextRenderer().append(name);
}
}
}
}
private class NoCoverageAction extends DialogWrapperAction {
class NoCoverageAction extends DialogWrapperAction {
NoCoverageAction() {
super(CoverageBundle.message("coverage.data.no.coverage.button"));
}
@@ -307,46 +298,15 @@ public class CoverageSuiteChooserDialog extends DialogWrapper {
continue;
}
final CoverageSuite coverageSuite = myCoverageManager
.addExternalCoverageSuite(file.getName(), file.getTimeStamp(), coverageRunner,
new DefaultCoverageFileProvider(file.getPath()));
CoverageSuite coverageSuite = myCoverageManager.addExternalCoverageSuite(file.getName(), file.getTimeStamp(), coverageRunner,
new DefaultCoverageFileProvider(file.getPath()));
final String coverageRunnerTitle = getCoverageRunnerTitle(coverageRunner);
DefaultMutableTreeNode node = TreeUtil.findNodeWithObject(myRootNode, coverageRunnerTitle);
if (node == null) {
node = new DefaultMutableTreeNode(coverageRunnerTitle);
myRootNode.add(node);
}
if (node.getChildCount() > 0) {
final TreeNode childNode = node.getChildAt(0);
if (!(childNode instanceof CheckedTreeNode)) {
if (LOCAL.equals(((DefaultMutableTreeNode)childNode).getUserObject())) {
node = (DefaultMutableTreeNode)childNode;
}
else {
final DefaultMutableTreeNode localNode = new DefaultMutableTreeNode(LOCAL);
node.add(localNode);
node = localNode;
}
}
}
final CheckedTreeNode suiteNode = new CheckedTreeNode(coverageSuite);
suiteNode.setChecked(true);
node.add(suiteNode);
TreeUtil.sort(node, (o1, o2) -> {
if (o1 instanceof CheckedTreeNode && o2 instanceof CheckedTreeNode) {
final Object userObject1 = ((CheckedTreeNode)o1).getUserObject();
final Object userObject2 = ((CheckedTreeNode)o2).getUserObject();
if (userObject1 instanceof CoverageSuite && userObject2 instanceof CoverageSuite) {
final String presentableName1 = ((CoverageSuite)userObject1).getPresentableName();
final String presentableName2 = ((CoverageSuite)userObject2).getPresentableName();
return presentableName1.compareToIgnoreCase(presentableName2);
}
}
return 0;
});
updateTree();
TreeUtil.selectNode(mySuitesTree, suiteNode);
List<CoverageSuite> currentlySelected = collectSelectedSuites();
currentlySelected.add(coverageSuite);
initTree();
selectSuites(currentlySelected);
((DefaultTreeModel)mySuitesTree.getModel()).reload();
TreeUtil.expandAll(mySuitesTree);
}
}
}
@@ -363,9 +323,9 @@ public class CoverageSuiteChooserDialog extends DialogWrapper {
for (CheckedTreeNode selectedNode : selectedNodes) {
final Object userObject = selectedNode.getUserObject();
if (userObject instanceof CoverageSuite selectedSuite) {
myCoverageManager.unregisterCoverageSuite(selectedSuite);
TreeUtil.removeLastPathComponent(mySuitesTree, new TreePath(selectedNode.getPath()));
}
myCoverageManager.unregisterCoverageSuite(selectedSuite);
TreeUtil.removeLastPathComponent(mySuitesTree, new TreePath(selectedNode.getPath()));
}
}
}
@@ -412,6 +372,7 @@ public class CoverageSuiteChooserDialog extends DialogWrapper {
if (userObject instanceof CoverageSuite selectedSuite) {
if (selectedSuite.canRemove()) {
presentation.setEnabled(true);
return;
}
}
}
@@ -422,34 +383,4 @@ public class CoverageSuiteChooserDialog extends DialogWrapper {
return ActionUpdateThread.BGT;
}
}
private class SwitchEngineAction extends ComboBoxAction {
@NotNull
@Override
protected DefaultActionGroup createPopupActionGroup(@NotNull JComponent button, @NotNull DataContext context) {
final DefaultActionGroup engChooser = new DefaultActionGroup();
for (final CoverageEngine engine : collectEngines()) {
engChooser.add(new AnAction(engine.getPresentableText()) {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
myEngine = engine;
initTree();
updateTree();
}
});
}
return engChooser;
}
@Override
public void update(@NotNull AnActionEvent e) {
super.update(e);
e.getPresentation().setVisible(collectEngines().size() > 1);
}
@Override
public @NotNull ActionUpdateThread getActionUpdateThread() {
return ActionUpdateThread.BGT;
}
}
}

View File

@@ -27,6 +27,8 @@ abstract class CoverageIntegrationBaseTest : JavaModuleTestCase() {
myProject = PlatformTestUtil.loadAndOpenProject(Paths.get(getTestDataPath()), getTestRootDisposable())
}
val manager get() = CoverageDataManager.getInstance(myProject) as CoverageDataManagerImpl
@JvmOverloads
protected fun loadIJSuite(includeFilters: Array<String>? = DEFAULT_FILTER, path: String = SIMPLE_IJ_REPORT_PATH) =
@@ -41,17 +43,17 @@ abstract class CoverageIntegrationBaseTest : JavaModuleTestCase() {
= loadCoverageSuite(XMLReportEngine::class.java, XMLReportRunner::class.java, path, includeFilters)
protected fun closeSuite(bundle: CoverageSuitesBundle) {
CoverageDataManager.getInstance(myProject).closeSuitesBundle(bundle)
manager.closeSuitesBundle(bundle)
}
protected suspend fun openSuiteAndWait(bundle: CoverageSuitesBundle) = waitSuiteProcessing {
CoverageDataManager.getInstance(myProject).chooseSuitesBundle(bundle)
manager.chooseSuitesBundle(bundle)
}
protected suspend fun waitSuiteProcessing(action: () -> Unit) {
var dataCollected = false
val disposable = Disposer.newDisposable()
CoverageDataManager.getInstance(myProject).addSuiteListener(object : CoverageSuiteListener {
manager.addSuiteListener(object : CoverageSuiteListener {
override fun coverageDataCalculated(bundle: CoverageSuitesBundle) {
dataCollected = true
}

View File

@@ -31,7 +31,7 @@ class CoverageIntegrationTest : CoverageIntegrationBaseTest() {
fun testXMLSuite() {
val bundle = loadXMLSuite()
val consumer = PackageAnnotationConsumer()
XMLReportAnnotator.getInstance(myProject).annotate(bundle, CoverageDataManager.getInstance(myProject), consumer)
XMLReportAnnotator.getInstance(myProject).annotate(bundle, manager, consumer)
assertHits(consumer, ignoreConstructor = false)
assertEquals(3, consumer.myDirectoryCoverage.size)
}
@@ -104,7 +104,7 @@ class CoverageIntegrationTest : CoverageIntegrationBaseTest() {
openSuiteAndWait(suite)
waitSuiteProcessing {
CoverageDataManager.getInstance(myProject).selectSubCoverage(suite, listOf("foo.bar.BarTest,testMethod3"))
manager.selectSubCoverage(suite, listOf("foo.bar.BarTest,testMethod3"))
}
run {
val consumer = PackageAnnotationConsumer()
@@ -115,7 +115,7 @@ class CoverageIntegrationTest : CoverageIntegrationBaseTest() {
val fooPartCoverage = intArrayOf(1, 1, 2, 1, 2, 1, 2, 0)
waitSuiteProcessing {
CoverageDataManager.getInstance(myProject).selectSubCoverage(suite, listOf("foo.FooTest,testMethod1"))
manager.selectSubCoverage(suite, listOf("foo.FooTest,testMethod1"))
}
run {
val consumer = PackageAnnotationConsumer()
@@ -125,7 +125,7 @@ class CoverageIntegrationTest : CoverageIntegrationBaseTest() {
}
waitSuiteProcessing {
CoverageDataManager.getInstance(myProject).selectSubCoverage(suite, listOf("foo.FooTest,testMethod2"))
manager.selectSubCoverage(suite, listOf("foo.FooTest,testMethod2"))
}
run {
val consumer = PackageAnnotationConsumer()
@@ -135,7 +135,7 @@ class CoverageIntegrationTest : CoverageIntegrationBaseTest() {
}
waitSuiteProcessing {
CoverageDataManager.getInstance(myProject).restoreMergedCoverage(suite)
manager.restoreMergedCoverage(suite)
}
assertHits(suite)
closeSuite(suite)
@@ -172,7 +172,6 @@ class CoverageIntegrationTest : CoverageIntegrationBaseTest() {
}
private suspend fun assertAnnotator(bundle: CoverageSuitesBundle, loaded: Boolean) {
val manager = CoverageDataManager.getInstance(myProject)
val annotator = bundle.getAnnotator(myProject)
val classes = listOf("foo.FooClass", "foo.bar.UncoveredClass", "foo.bar.BarClass")
for (clazz in classes) {

View File

@@ -11,27 +11,25 @@ import java.io.File
class CoverageSuitesTest : CoverageIntegrationBaseTest() {
fun `test external suite adding`() {
val dataManager = CoverageDataManager.getInstance(myProject)
val path = SIMPLE_IJ_REPORT_PATH
val runner = CoverageRunner.getInstance(IDEACoverageRunner::class.java)
val suite = dataManager.addExternalCoverageSuite(path, -1, runner, createCoverageFileProvider(path))
val suite = manager.addExternalCoverageSuite(path, -1, runner, createCoverageFileProvider(path))
dataManager.suites.run {
manager.suites.run {
Assert.assertEquals(1, size)
Assert.assertSame(suite, this[0])
}
dataManager.unregisterCoverageSuite(suite)
Assert.assertTrue(dataManager.suites.isEmpty())
manager.unregisterCoverageSuite(suite)
Assert.assertTrue(manager.suites.isEmpty())
}
fun `test coverage is closed when a suite is deleted`(): Unit = runBlocking {
val dataManager = CoverageDataManager.getInstance(myProject)
val ijSuite = loadIJSuite().suites[0]
registerSuite(ijSuite)
dataManager.suites.run {
manager.suites.run {
Assert.assertEquals(1, size)
Assert.assertTrue(ijSuite in this)
}
@@ -39,24 +37,23 @@ class CoverageSuitesTest : CoverageIntegrationBaseTest() {
val bundle = CoverageSuitesBundle(ijSuite)
openSuiteAndWait(bundle)
Assert.assertSame(bundle, dataManager.currentSuitesBundle)
Assert.assertSame(bundle, manager.currentSuitesBundle)
dataManager.unregisterCoverageSuite(ijSuite)
manager.unregisterCoverageSuite(ijSuite)
Assert.assertEquals(0, dataManager.suites.size)
Assert.assertNull(dataManager.currentSuitesBundle)
Assert.assertEquals(0, manager.suites.size)
Assert.assertNull(manager.currentSuitesBundle)
}
fun `test coverage reopen if one of the suites is deleted`(): Unit = runBlocking {
val dataManager = CoverageDataManager.getInstance(myProject)
val ijSuite = loadIJSuite().suites[0]
val jacocoSuite = loadJaCoCoSuite().suites[0]
registerSuite(ijSuite)
registerSuite(jacocoSuite)
dataManager.suites.run {
manager.suites.run {
Assert.assertEquals(2, size)
Assert.assertTrue(ijSuite in this)
Assert.assertTrue(jacocoSuite in this)
@@ -65,36 +62,35 @@ class CoverageSuitesTest : CoverageIntegrationBaseTest() {
val bundle = CoverageSuitesBundle(arrayOf(ijSuite, jacocoSuite))
openSuiteAndWait(bundle)
Assert.assertSame(bundle, dataManager.currentSuitesBundle)
Assert.assertSame(bundle, manager.currentSuitesBundle)
waitSuiteProcessing {
dataManager.unregisterCoverageSuite(jacocoSuite)
manager.unregisterCoverageSuite(jacocoSuite)
}
Assert.assertEquals(1, dataManager.suites.size)
dataManager.currentSuitesBundle.also { currentBundle ->
Assert.assertEquals(1, manager.suites.size)
manager.currentSuitesBundle.also { currentBundle ->
Assert.assertNotSame(bundle, currentBundle)
Assert.assertEquals(1, currentBundle.suites.size)
Assert.assertSame(ijSuite, currentBundle.suites[0])
closeSuite(currentBundle)
}
Assert.assertNull(dataManager.currentSuitesBundle)
Assert.assertEquals(1, dataManager.suites.size)
dataManager.unregisterCoverageSuite(ijSuite)
Assert.assertEquals(0, dataManager.suites.size)
Assert.assertNull(manager.currentSuitesBundle)
Assert.assertEquals(1, manager.suites.size)
manager.unregisterCoverageSuite(ijSuite)
Assert.assertEquals(0, manager.suites.size)
}
fun `test suite removal with deletion asks for approval from user`() {
val suite = loadIJSuiteCopy().suites[0]
val dataManager = CoverageDataManager.getInstance(myProject)
val file = File(suite.coverageDataFileName)
registerSuite(suite)
Assert.assertTrue(file.exists())
try {
dataManager.removeCoverageSuite(suite)
manager.removeCoverageSuite(suite)
Assert.fail("Should ask for approval, which was supposed to lead to RuntimeException")
}
catch (e: RuntimeException) {
@@ -104,26 +100,24 @@ class CoverageSuitesTest : CoverageIntegrationBaseTest() {
fun `test suite is not opened if the report file does not exist`() {
val suite = loadIJSuiteCopy()
val dataManager = CoverageDataManager.getInstance(myProject)
val file = File(suite.suites[0].coverageDataFileName)
Assert.assertTrue(file.exists())
file.delete()
dataManager.chooseSuitesBundle(suite)
Assert.assertNull(dataManager.currentSuitesBundle)
Assert.assertEquals(0, dataManager.suites.size)
manager.chooseSuitesBundle(suite)
Assert.assertNull(manager.currentSuitesBundle)
Assert.assertEquals(0, manager.suites.size)
}
fun `test opening several suites`(): Unit = runBlocking {
val dataManager = CoverageDataManager.getInstance(myProject)
val ijSuite = loadIJSuite()
val xmlSuite = loadXMLSuite()
openSuiteAndWait(ijSuite)
openSuiteAndWait(xmlSuite)
Assert.assertSame(xmlSuite, dataManager.currentSuitesBundle)
dataManager.activeSuites().also { activeSuites ->
Assert.assertSame(xmlSuite, manager.currentSuitesBundle)
manager.activeSuites().also { activeSuites ->
Assert.assertEquals(2, activeSuites.count())
Assert.assertTrue(ijSuite in activeSuites)
Assert.assertTrue(xmlSuite in activeSuites)
@@ -131,19 +125,18 @@ class CoverageSuitesTest : CoverageIntegrationBaseTest() {
closeSuite(xmlSuite)
Assert.assertSame(ijSuite, dataManager.currentSuitesBundle)
dataManager.activeSuites().also { activeSuites ->
Assert.assertSame(ijSuite, manager.currentSuitesBundle)
manager.activeSuites().also { activeSuites ->
Assert.assertEquals(1, activeSuites.count())
Assert.assertTrue(ijSuite in activeSuites)
}
closeSuite(ijSuite)
Assert.assertNull(dataManager.currentSuitesBundle)
Assert.assertEquals(0, dataManager.activeSuites().size)
Assert.assertNull(manager.currentSuitesBundle)
Assert.assertEquals(0, manager.activeSuites().size)
}
fun `test hide coverage action closes all suites`() : Unit = runBlocking {
val dataManager = CoverageDataManager.getInstance(myProject)
val ijSuite = loadIJSuite()
val xmlSuite = loadXMLSuite()
@@ -166,13 +159,12 @@ class CoverageSuitesTest : CoverageIntegrationBaseTest() {
hideAction.actionPerformed(actionEvent)
}
Assert.assertNull(dataManager.currentSuitesBundle)
Assert.assertEquals(0, dataManager.activeSuites().size)
Assert.assertNull(manager.currentSuitesBundle)
Assert.assertEquals(0, manager.activeSuites().size)
}
private fun registerSuite(suite: CoverageSuite) {
val dataManager = CoverageDataManager.getInstance(myProject) as CoverageDataManagerImpl
// Use 'presentableName' parameter to avoid report file deletion
dataManager.addCoverageSuite(suite, suite.presentableName)
manager.addCoverageSuite(suite, suite.presentableName)
}
}

View File

@@ -0,0 +1,176 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.coverage.actions
import com.intellij.coverage.CoverageIntegrationBaseTest
import com.intellij.coverage.CoverageSuite
import com.intellij.openapi.util.Disposer
import com.intellij.ui.CheckboxTree
import com.intellij.ui.CheckedTreeNode
import com.intellij.util.containers.TreeTraversal
import com.intellij.util.ui.tree.TreeUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import org.junit.Assert
class SuiteChooserTest : CoverageIntegrationBaseTest() {
fun `test chooser dialog includes registered suites`(): Unit = runBlocking {
val ijSuite = loadIJSuite().suites[0]
val jacocoSuite = loadJaCoCoSuite().suites[0]
val xmlSuite = loadXMLSuite().suites[0]
registerSuite(ijSuite)
registerSuite(jacocoSuite)
registerSuite(xmlSuite)
val dialog = openChooserDialog()
val suites = collectSuiteStates(dialog)
Assert.assertEquals(3, suites.size)
Assert.assertTrue(ijSuite in suites)
Assert.assertFalse(suites[ijSuite]!!)
Assert.assertTrue(jacocoSuite in suites)
Assert.assertFalse(suites[jacocoSuite]!!)
Assert.assertTrue(xmlSuite in suites)
Assert.assertFalse(suites[xmlSuite]!!)
closeDialog(dialog)
}
fun `test chooser dialog includes opened suites selected`(): Unit = runBlocking {
val ijBundle = loadIJSuite()
val ijSuite = ijBundle.suites[0]
registerSuite(ijSuite)
openSuiteAndWait(ijBundle)
val xmlBundle = loadXMLSuite()
val xmlSuite = xmlBundle.suites[0]
registerSuite(xmlSuite)
val dialog = openChooserDialog()
val suites = collectSuiteStates(dialog)
Assert.assertEquals(2, suites.size)
Assert.assertTrue(ijSuite in suites)
Assert.assertTrue(suites[ijSuite]!!)
Assert.assertTrue(xmlSuite in suites)
Assert.assertFalse(suites[xmlSuite]!!)
closeSuite(ijBundle)
closeDialog(dialog)
}
fun `test suite chooser opens checked suite`(): Unit = runBlocking {
val ijSuite = loadIJSuite().suites[0]
registerSuite(ijSuite)
val dialog = openChooserDialog()
collectSuiteNodes(dialog)[ijSuite]!!.isChecked = true
withContext(Dispatchers.Main) {
waitSuiteProcessing {
dialog.doOKAction()
}
}
val currentBundle = manager.currentSuitesBundle
Assert.assertEquals(1, currentBundle.suites.size)
Assert.assertTrue(ijSuite in currentBundle.suites)
closeDialog(dialog)
}
fun `test suite chooser opens all checked suites`(): Unit = runBlocking {
val ijSuite = loadIJSuite().suites[0]
registerSuite(ijSuite)
val xmlSuite = loadXMLSuite().suites[0]
registerSuite(xmlSuite)
val dialog = openChooserDialog()
val suiteNodes = collectSuiteNodes(dialog)
suiteNodes[ijSuite]!!.isChecked = true
suiteNodes[xmlSuite]!!.isChecked = true
withContext(Dispatchers.Main) {
waitSuiteProcessing {
dialog.doOKAction()
}
}
val bundles = manager.activeSuites()
Assert.assertEquals(2, bundles.size)
val allSuites = bundles.flatMap { it.suites.toList() }
Assert.assertEquals(2, allSuites.size)
Assert.assertTrue(ijSuite in allSuites)
Assert.assertTrue(xmlSuite in allSuites)
for (bundle in bundles) {
closeSuite(bundle)
}
closeDialog(dialog)
}
fun `test chooser dialog closes suites if not selected`(): Unit = runBlocking {
val ijBundle = loadIJSuite()
val ijSuite = ijBundle.suites[0]
registerSuite(ijSuite)
openSuiteAndWait(ijBundle)
val dialog = openChooserDialog()
val suiteNodes = collectSuiteNodes(dialog)
suiteNodes[ijSuite]!!.isChecked = false
withContext(Dispatchers.Main) {
dialog.doOKAction()
}
val bundles = manager.activeSuites()
Assert.assertTrue(bundles.isEmpty())
closeDialog(dialog)
}
fun `test no coverage action closes all opened suites`(): Unit = runBlocking {
val ijBundle = loadIJSuite()
val ijSuite = ijBundle.suites[0]
registerSuite(ijSuite)
openSuiteAndWait(ijBundle)
Assert.assertFalse(manager.activeSuites().isEmpty())
withContext(Dispatchers.Main) {
val dialog = CoverageSuiteChooserDialog(myProject)
dialog.NoCoverageAction().doAction(null)
closeDialog(dialog)
}
Assert.assertTrue(manager.activeSuites().isEmpty())
}
private suspend fun openChooserDialog(): CoverageSuiteChooserDialog =
withContext(Dispatchers.Main) { return@withContext CoverageSuiteChooserDialog(myProject) }
private suspend fun closeDialog(dialog: CoverageSuiteChooserDialog) {
withContext(Dispatchers.Main) {
Disposer.dispose(dialog.disposable)
}
}
private fun collectSuiteNodes(dialog: CoverageSuiteChooserDialog): Map<CoverageSuite, CheckedTreeNode> {
val tree = dialog.preferredFocusedComponent as CheckboxTree
return TreeUtil.treeTraverser(tree).traverse(TreeTraversal.PRE_ORDER_DFS).toList()
.filterIsInstance<CheckedTreeNode>()
.filter { it.userObject is CoverageSuite }
.associateBy { it.userObject as CoverageSuite }
}
private fun collectSuiteStates(dialog: CoverageSuiteChooserDialog): Map<CoverageSuite, Boolean> =
collectSuiteNodes(dialog).mapValues { it.value.isChecked }
private fun registerSuite(suite: CoverageSuite) {
// Use 'presentableName' parameter to avoid report file deletion
manager.addCoverageSuite(suite, suite.presentableName)
}
}

View File

@@ -1,7 +1,6 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.coverage.view
import com.intellij.coverage.CoverageDataManager
import com.intellij.coverage.CoverageEditorAnnotatorImpl
import com.intellij.coverage.CoverageIntegrationBaseTest
import com.intellij.openapi.application.readAction
@@ -77,7 +76,7 @@ class CoverageGutterTest : CoverageIntegrationBaseTest() {
openSuiteAndWait(suite)
waitSuiteProcessing {
CoverageDataManager.getInstance(myProject).selectSubCoverage(suite, listOf("foo.bar.BarTest,testMethod3"))
manager.selectSubCoverage(suite, listOf("foo.bar.BarTest,testMethod3"))
}
waitAnnotations()
assertGutterHighlightLines("foo.bar.BarClass", mapOf(5 to LineCoverage.FULL, 9 to LineCoverage.NONE, 13 to LineCoverage.NONE))
@@ -85,7 +84,7 @@ class CoverageGutterTest : CoverageIntegrationBaseTest() {
assertGutterHighlightLines("foo.FooClass", mapOf())
waitSuiteProcessing {
CoverageDataManager.getInstance(myProject).selectSubCoverage(suite, listOf("foo.FooTest,testMethod1"))
manager.selectSubCoverage(suite, listOf("foo.FooTest,testMethod1"))
}
waitAnnotations()
assertGutterHighlightLines("foo.bar.BarClass", mapOf())
@@ -93,7 +92,7 @@ class CoverageGutterTest : CoverageIntegrationBaseTest() {
assertGutterHighlightLines("foo.FooClass", mapOf(5 to LineCoverage.FULL, 9 to LineCoverage.NONE))
waitSuiteProcessing {
CoverageDataManager.getInstance(myProject).selectSubCoverage(suite, listOf("foo.FooTest,testMethod2"))
manager.selectSubCoverage(suite, listOf("foo.FooTest,testMethod2"))
}
waitAnnotations()
assertGutterHighlightLines("foo.bar.BarClass", mapOf())