diff --git a/java/execution/impl/src/com/intellij/execution/testDiscovery/FindTestsInTestDiscoveryServerAction.java b/java/execution/impl/src/com/intellij/execution/testDiscovery/FindTestsInTestDiscoveryServerAction.java index 058b2ed52c40..c049c96891c4 100644 --- a/java/execution/impl/src/com/intellij/execution/testDiscovery/FindTestsInTestDiscoveryServerAction.java +++ b/java/execution/impl/src/com/intellij/execution/testDiscovery/FindTestsInTestDiscoveryServerAction.java @@ -1,10 +1,6 @@ // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.execution.testDiscovery; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.gson.annotations.SerializedName; import com.intellij.codeInsight.navigation.ListBackgroundUpdaterTask; import com.intellij.execution.Executor; import com.intellij.execution.actions.ConfigurationContext; @@ -20,14 +16,12 @@ import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ReadAction; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.IconButton; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.PopupChooserBuilder; import com.intellij.openapi.util.Ref; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; @@ -38,27 +32,15 @@ import com.intellij.ui.popup.AbstractPopup; import com.intellij.ui.popup.HintUpdateSupply; import com.intellij.util.ArrayUtil; import com.intellij.util.PsiNavigateUtil; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.io.HttpRequests; -import com.intellij.util.io.RequestBuilder; import com.intellij.util.ui.EdtInvocationManager; import com.intellij.util.ui.JBDimension; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; import static com.intellij.openapi.actionSystem.CommonDataKeys.EDITOR; import static com.intellij.openapi.actionSystem.CommonDataKeys.PSI_FILE; public class FindTestsInTestDiscoveryServerAction extends AnAction { - private static final Logger LOG = Logger.getInstance(FindTestsInTestDiscoveryServerAction.class); - @Override public void update(AnActionEvent e) { Editor editor = e.getData(EDITOR); @@ -157,10 +139,9 @@ public class FindTestsInTestDiscoveryServerAction extends AnAction { loadTestsTask.init((AbstractPopup)popup, list, new Ref<>()); ApplicationManager.getApplication().executeOnPooledThread(() -> { - Map map = fetchDataFromDiscoveryServer(fqn, methodName); - map.forEach((classFqn, testMethodName) -> { + TestDiscoveryProducer.consumeTestClassesAndMethods(project, fqn, methodName, "j", (testClassFqn, testMethodName) -> { PsiMethod psiMethod = ReadAction.compute(() -> { - PsiClass cc = classFqn == null ? null : javaFacade.findClass(classFqn, scope); + PsiClass cc = testClassFqn == null ? null : javaFacade.findClass(testClassFqn, scope); return cc == null ? null : ArrayUtil.getFirstElement(cc.findMethodsByName(testMethodName, false)); }); if (psiMethod != null) { @@ -174,100 +155,4 @@ public class FindTestsInTestDiscoveryServerAction extends AnAction { }); }); } - - private static final String INTELLIJ_TEST_DISCOVERY_HOST = "http://intellij-test-discovery"; - - private static Map fetchDataFromDiscoveryServer(@NotNull String classFQName, @NotNull String methodName) { - String methodFqn = classFQName + "." + methodName; - RequestBuilder r = HttpRequests.request(INTELLIJ_TEST_DISCOVERY_HOST + "/search/tests/by-method/" + methodFqn); - - try { - return r.connect(request -> { - Map map = ContainerUtil.newLinkedHashMap(); - ObjectMapper mapper = new ObjectMapper(); - TestsSearchResult result = mapper.readValue(request.getInputStream(), TestsSearchResult.class); - - result.getTests().forEach(s -> { - - s = s.length() > 1 && s.charAt(0) == 'j' ? s.substring(1) : s; - String classFqn = StringUtil.substringBefore(s, "-"); - String testMethodName = StringUtil.substringAfter(s, "-"); - - map.put(classFqn, testMethodName); - }); - return map; - }); - } - catch (HttpRequests.HttpStatusException http) { - LOG.debug("No tests found for " + methodFqn); - } - catch (IOException e) { - LOG.debug(e); - } - return Collections.emptyMap(); - } - - @JsonInclude(JsonInclude.Include.NON_EMPTY) - public static class TestsSearchResult { - @Nullable - private String method; - - @SerializedName("class") - @JsonProperty("class") - @Nullable - private String className; - - private int found; - - @NotNull - private List tests = new ArrayList<>(); - - @Nullable - private String message; - - @Nullable - public String getMethod() { - return method; - } - - public TestsSearchResult setMethod(String method) { - this.method = method; - return this; - } - - @Nullable - public String getClassName() { - return className; - } - - public TestsSearchResult setClassName(String name) { - this.className = name; - return this; - } - - public int getFound() { - return found; - } - - @NotNull - public List getTests() { - return tests; - } - - public TestsSearchResult setTests(List tests) { - this.tests = tests; - this.found = tests.size(); - return this; - } - - @Nullable - public String getMessage() { - return message; - } - - public TestsSearchResult setMessage(String message) { - this.message = message; - return this; - } - } } diff --git a/java/execution/impl/src/com/intellij/execution/testDiscovery/IntellijTestDiscoveryProducer.java b/java/execution/impl/src/com/intellij/execution/testDiscovery/IntellijTestDiscoveryProducer.java new file mode 100644 index 000000000000..40482ae9685e --- /dev/null +++ b/java/execution/impl/src/com/intellij/execution/testDiscovery/IntellijTestDiscoveryProducer.java @@ -0,0 +1,118 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.execution.testDiscovery; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.annotations.SerializedName; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.io.HttpRequests; +import com.intellij.util.io.RequestBuilder; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class IntellijTestDiscoveryProducer implements TestDiscoveryProducer { + private static final String INTELLIJ_TEST_DISCOVERY_HOST = "http://intellij-test-discovery"; + + @NotNull + @Override + public Map getTestClassesAndMethodNames(Project project, String classFQName, String methodName, String frameworkId) { + String methodFqn = classFQName + "." + methodName; + RequestBuilder r = HttpRequests.request(INTELLIJ_TEST_DISCOVERY_HOST + "/search/tests/by-method/" + methodFqn); + + try { + return r.connect(request -> { + Map map = ContainerUtil.newLinkedHashMap(); + ObjectMapper mapper = new ObjectMapper(); + TestsSearchResult result = mapper.readValue(request.getInputStream(), TestsSearchResult.class); + + result.getTests().forEach(s -> { + s = s.length() > 1 && s.charAt(0) == 'j' ? s.substring(1) : s; + String classFqn = StringUtil.substringBefore(s, "-"); + String testMethodName = StringUtil.substringAfter(s, "-"); + map.put(classFqn, testMethodName); + }); + return map; + }); + } + catch (HttpRequests.HttpStatusException http) { + LOG.debug("No tests found for " + methodFqn); + } + catch (IOException e) { + LOG.debug(e); + } + return Collections.emptyMap(); + } + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public static class TestsSearchResult { + @Nullable + private String method; + + @SerializedName("class") + @JsonProperty("class") + @Nullable + private String className; + + private int found; + + @NotNull + private List tests = new ArrayList<>(); + + @Nullable + private String message; + + @Nullable + public String getMethod() { + return method; + } + + public TestsSearchResult setMethod(String method) { + this.method = method; + return this; + } + + @Nullable + public String getClassName() { + return className; + } + + public TestsSearchResult setClassName(String name) { + this.className = name; + return this; + } + + public int getFound() { + return found; + } + + @NotNull + public List getTests() { + return tests; + } + + public TestsSearchResult setTests(List tests) { + this.tests = tests; + this.found = tests.size(); + return this; + } + + @Nullable + public String getMessage() { + return message; + } + + public TestsSearchResult setMessage(String message) { + this.message = message; + return this; + } + } +} diff --git a/java/execution/impl/src/com/intellij/execution/testDiscovery/LocalTestDiscoveryProducer.java b/java/execution/impl/src/com/intellij/execution/testDiscovery/LocalTestDiscoveryProducer.java new file mode 100644 index 000000000000..10ae52777fc5 --- /dev/null +++ b/java/execution/impl/src/com/intellij/execution/testDiscovery/LocalTestDiscoveryProducer.java @@ -0,0 +1,41 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.execution.testDiscovery; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class LocalTestDiscoveryProducer implements TestDiscoveryProducer { + @Override + @NotNull + public Map getTestClassesAndMethodNames(@NotNull Project project, + @NotNull String classFQName, + @NotNull String methodName, + @NotNull String frameworkId) { + try { + Map map = ContainerUtil.newLinkedHashMap(); + TestDiscoveryIndex discoveryIndex = TestDiscoveryIndex.getInstance(project); + Collection testsByMethodName = discoveryIndex.getTestsByMethodName(classFQName, methodName, frameworkId); + if (testsByMethodName != null) { + for (String pattern : testsByMethodName) { // todo[batkovich]: filter by framework id + List split = StringUtil.split(pattern, "-"); + if (split.size() == 2) { + map.put(split.get(0), split.get(1)); + } + } + } + return map; + } + catch (IOException io) { + TestDiscoveryProducer.LOG.warn(io); + } + return Collections.emptyMap(); + } +} diff --git a/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryProducer.java b/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryProducer.java new file mode 100644 index 000000000000..55ccced4fcff --- /dev/null +++ b/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryProducer.java @@ -0,0 +1,35 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.execution.testDiscovery; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.util.Map; +import java.util.function.BiConsumer; + +@ApiStatus.Experimental +public interface TestDiscoveryProducer { + Logger LOG = Logger.getInstance(LocalTestDiscoveryProducer.class); + + @NotNull + Map getTestClassesAndMethodNames(Project project, + String classFQName, + String methodName, + String frameworkId); + + ExtensionPointName EP = ExtensionPointName.create("com.intellij.testDiscoveryProducer"); + + static void consumeTestClassesAndMethods(@NotNull Project project, + @NotNull String classFQName, + @NotNull String methodName, + @NotNull String frameworkId, + @NotNull BiConsumer consumer) { + for (TestDiscoveryProducer producer : EP.getExtensions()) { + producer.getTestClassesAndMethodNames(project, classFQName, methodName, frameworkId).forEach(consumer); + } + } +} diff --git a/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoverySearchHelper.java b/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoverySearchHelper.java index 6f487f01c2a8..4c0b9b3de3e2 100644 --- a/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoverySearchHelper.java +++ b/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoverySearchHelper.java @@ -20,7 +20,6 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.diff.FilesTooBigForDiffException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.util.*; @@ -32,11 +31,7 @@ public class TestDiscoverySearchHelper { final String frameworkPrefix) { final Set patterns = new LinkedHashSet<>(); if (position != null) { - try { - collectPatterns(project, patterns, position.first, position.second, frameworkPrefix); - } - catch (IOException ignore) { - } + collectPatterns(project, patterns, position.first, position.second, frameworkPrefix); } final List files = getAffectedFiles(changeList, project); final PsiManager psiManager = PsiManager.getInstance(project); @@ -92,18 +87,12 @@ public class TestDiscoverySearchHelper { return new HashSet<>(ContainerUtil.filter(patterns, fqn -> ReadAction.compute(() -> psiFacade.findClass(StringUtil.getPackageName(fqn, ','), searchScope) != null))); } - private static void collectPatterns(final Project project, - final Set patterns, - final String classFQName, - final String methodName, - final String frameworkId) throws IOException { - final TestDiscoveryIndex discoveryIndex = TestDiscoveryIndex.getInstance(project); - final Collection testsByMethodName = discoveryIndex.getTestsByMethodName(classFQName, methodName, frameworkId); - if (testsByMethodName != null) { - for (String pattern : testsByMethodName) { - patterns.add(pattern.replace('-', ',')); - } - } + private static void collectPatterns(@NotNull Project project, + @NotNull Set patterns, + @NotNull String classFQName, + @NotNull String methodName, + @NotNull String frameworkId) { + TestDiscoveryProducer.consumeTestClassesAndMethods(project, classFQName, methodName, frameworkId, (c, m) -> patterns.add(c + "," + m)); } @NotNull @@ -130,19 +119,14 @@ public class TestDiscoverySearchHelper { return Collections.emptyList(); } - @Nullable + @NotNull private static LinkedHashSet collectPatterns(PsiMethod psiMethod, String frameworkId) { LinkedHashSet patterns = new LinkedHashSet<>(); final PsiClass containingClass = psiMethod.getContainingClass(); if (containingClass != null) { final String qualifiedName = containingClass.getQualifiedName(); if (qualifiedName != null) { - try { - collectPatterns(psiMethod.getProject(), patterns, qualifiedName, psiMethod.getName(), frameworkId); - } - catch (IOException e) { - return null; - } + collectPatterns(psiMethod.getProject(), patterns, qualifiedName, psiMethod.getName(), frameworkId); } } return patterns; diff --git a/plugins/junit/src/META-INF/plugin.xml b/plugins/junit/src/META-INF/plugin.xml index 05696d524a5e..115c3b43cdb7 100644 --- a/plugins/junit/src/META-INF/plugin.xml +++ b/plugins/junit/src/META-INF/plugin.xml @@ -77,6 +77,8 @@ + + @@ -95,6 +97,7 @@ +