diff --git a/java/java-tests/testData/junit/configurations/module1/test1/nested/TestA.java b/java/java-tests/testData/junit/configurations/module1/test1/nested/TestA.java new file mode 100644 index 000000000000..3021ed1de316 --- /dev/null +++ b/java/java-tests/testData/junit/configurations/module1/test1/nested/TestA.java @@ -0,0 +1,6 @@ +package test1.nested; + +import junit.framework.TestCase; + +public class TestA extends TestCase { +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/execution/ConfigurationsTest.java b/java/java-tests/testSrc/com/intellij/java/execution/ConfigurationsTest.java index f1bd4a7a0db7..3b5464eb3be7 100644 --- a/java/java-tests/testSrc/com/intellij/java/execution/ConfigurationsTest.java +++ b/java/java-tests/testSrc/com/intellij/java/execution/ConfigurationsTest.java @@ -174,8 +174,9 @@ public class ConfigurationsTest extends BaseConfigurationTestCase { Assertion.compareUnordered( //category, filters, classNames... new Object[]{"", "", psiClass.getQualifiedName(), - psiClass.getQualifiedName(), - derivedTest.getQualifiedName(), //RT_INNER_TEST_NAME, + psiClass2.getQualifiedName(), + derivedTest.getQualifiedName(), RT_INNER_TEST_NAME, + "test1.nested.TestA", testB.getQualifiedName()}, lines); } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 5734a3ea4775..209a660d46a4 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -1433,4 +1433,7 @@ vue.extract.component.intention.description=Allows "Vue Extract Component" inten folding.signature.validation=false folding.signature.validation.description=Validate that signature for a PSI element, for which a folding region is generated, can be used to\ - find exactly the same PSI element \ No newline at end of file + find exactly the same PSI element + +junit4.accept.inner.classes=true +junit4.accept.inner.classes.description=If false, inner classes won't be included in search for tests in package \ No newline at end of file diff --git a/plugins/junit/src/com/intellij/execution/junit/TestPackage.java b/plugins/junit/src/com/intellij/execution/junit/TestPackage.java index ae0267d5b405..ae8cb7878552 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestPackage.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestPackage.java @@ -37,6 +37,7 @@ import com.intellij.psi.search.PackageScope; import com.intellij.psi.util.ClassUtil; import com.intellij.refactoring.listeners.RefactoringElementListener; import com.intellij.rt.execution.junit.JUnitStarter; +import com.intellij.util.containers.JBTreeTraverser; import gnu.trove.THashSet; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; @@ -47,7 +48,9 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.function.Predicate; public class TestPackage extends TestObject { @@ -84,14 +87,21 @@ public class TestPackage extends TestObject { if (Registry.is("junit4.search.4.tests.all.in.scope", true)) { String packageName = getPackageName(data); PsiPackage aPackage = JavaPsiFacade.getInstance(myProject).findPackage(packageName); - PsiClass[] classes = aPackage == null - ? PsiClass.EMPTY_ARRAY - : ReadAction.compute(() -> - aPackage.getClasses(GlobalSearchScope.projectScope(myProject) - .intersectWith(classFilter.getScope()))); - Arrays.stream(classes) - .filter(aClass -> ReadAction.compute(() -> classFilter.isAccepted(aClass))) - .forEach(myClasses::add); + List classes = new ArrayList<>(); + if (aPackage != null) { + ReadAction.run(() -> + { + PsiDirectory[] directories = + aPackage.getDirectories(GlobalSearchScope.projectScope(myProject).intersectWith(classFilter.getScope())); + for (PsiDirectory directory : directories) { + collectClassesRecursively(directory, classes); + } + }); + } + classes + .stream() + .filter(aClass -> ReadAction.compute(() -> classFilter.isAccepted(aClass))) + .forEach(myClasses::add); } else if (Registry.is("junit4.search.4.tests.in.classpath", false)) { String packageName = getPackageName(data); @@ -115,6 +125,23 @@ public class TestPackage extends TestObject { } } + private void collectClassesRecursively(PsiElement root, List classes) { + PsiElement[] children = root.getChildren(); + for (PsiElement child : children) { + if (child instanceof PsiClassOwner) { + for (PsiClass aClass : ((PsiClassOwner)child).getClasses()) { + classes.add(aClass); + if (Registry.is("junit4.accept.inner.classes", true)) { + classes.addAll(JBTreeTraverser.of(PsiClass::getInnerClasses).withRoot(aClass).toList()); + } + } + } + else { + collectClassesRecursively(child, classes); + } + } + } + @Override protected void onFound() {