diff --git a/java/java-tests/testData/psi/search/findUsages/fieldInJavadoc/A.java b/java/java-tests/testData/psi/search/findUsages/fieldInJavadoc/A.java new file mode 100644 index 000000000000..2587d2204998 --- /dev/null +++ b/java/java-tests/testData/psi/search/findUsages/fieldInJavadoc/A.java @@ -0,0 +1,8 @@ +class A{ + static int FIELD; + + /** + * @see #FIELD + */ + void foo(){} +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/search/findUsages/implicitConstructorUsage/A.java b/java/java-tests/testData/psi/search/findUsages/implicitConstructorUsage/A.java new file mode 100644 index 000000000000..7d9db808e4f2 --- /dev/null +++ b/java/java-tests/testData/psi/search/findUsages/implicitConstructorUsage/A.java @@ -0,0 +1,13 @@ +class Foo { + public Foo() { + } + + public Foo(String text) { + } +} +class Bar extends Foo { + + public Bar() { + super("hello"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/search/findUsages/protectedMethodInPackageLocalClass/bar/Bar.java b/java/java-tests/testData/psi/search/findUsages/protectedMethodInPackageLocalClass/bar/Bar.java new file mode 100644 index 000000000000..d37d2962f140 --- /dev/null +++ b/java/java-tests/testData/psi/search/findUsages/protectedMethodInPackageLocalClass/bar/Bar.java @@ -0,0 +1,11 @@ +import foo.*; + +class Bar extends Foo { + protected void foo(); +} + +class Goo extends Foo { + { + foo(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/search/findUsages/protectedMethodInPackageLocalClass/foo/Foo.java b/java/java-tests/testData/psi/search/findUsages/protectedMethodInPackageLocalClass/foo/Foo.java new file mode 100644 index 000000000000..72ee6e5d691d --- /dev/null +++ b/java/java-tests/testData/psi/search/findUsages/protectedMethodInPackageLocalClass/foo/Foo.java @@ -0,0 +1,7 @@ +package foo; + +class PackageLocal { + protected void foo() {} +} + +public class Foo extends PackageLocal {} \ No newline at end of file diff --git a/java/java-tests/testData/psi/search/findUsages/xml/Test.xml b/java/java-tests/testData/psi/search/findUsages/xml/Test.xml new file mode 100644 index 000000000000..136aa9f5762a --- /dev/null +++ b/java/java-tests/testData/psi/search/findUsages/xml/Test.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/java/java-tests/testData/psi/search/findUsages/xml/com/Foo.java b/java/java-tests/testData/psi/search/findUsages/xml/com/Foo.java new file mode 100644 index 000000000000..968907726fdb --- /dev/null +++ b/java/java-tests/testData/psi/search/findUsages/xml/com/Foo.java @@ -0,0 +1,2 @@ +package com; +public class Foo {} \ No newline at end of file diff --git a/java/java-tests/testData/psi/search/findUsages15/enumConstructor/pack/OurEnum.java b/java/java-tests/testData/psi/search/findUsages15/enumConstructor/pack/OurEnum.java new file mode 100644 index 000000000000..bbd25e7cb393 --- /dev/null +++ b/java/java-tests/testData/psi/search/findUsages15/enumConstructor/pack/OurEnum.java @@ -0,0 +1,7 @@ +package pack; +enum OurEnum { + A(10), B, C(27); + + OurEnum(int i) {} + OurEnum() {} +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/search/findUsages15/findRawOverriddenUsages/pack/RawOverridden.java b/java/java-tests/testData/psi/search/findUsages15/findRawOverriddenUsages/pack/RawOverridden.java new file mode 100644 index 000000000000..ca6fc7e88a64 --- /dev/null +++ b/java/java-tests/testData/psi/search/findUsages15/findRawOverriddenUsages/pack/RawOverridden.java @@ -0,0 +1,10 @@ +package pack; + +class Base { + void foo(List l) {} +} + +class Derived extends Base { + void foo(List l) { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/search/findUsages15/genericMethodOverriderUsages/pack/GenericClass.java b/java/java-tests/testData/psi/search/findUsages15/genericMethodOverriderUsages/pack/GenericClass.java new file mode 100644 index 000000000000..0d5e1988bc1a --- /dev/null +++ b/java/java-tests/testData/psi/search/findUsages15/genericMethodOverriderUsages/pack/GenericClass.java @@ -0,0 +1,13 @@ +package pack; + +class GenericClass { + void foo (T t) {} +} + +class GenericClassDerived extends GenericClass { + void foo (String s) {} + + void bar () { + foo (""); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/search/findUsages15/genericOverride/pack/Gen.java b/java/java-tests/testData/psi/search/findUsages15/genericOverride/pack/Gen.java new file mode 100644 index 000000000000..b93c64ea999e --- /dev/null +++ b/java/java-tests/testData/psi/search/findUsages15/genericOverride/pack/Gen.java @@ -0,0 +1,18 @@ +package pack; +import java.util.Map; + +class BeforeRunTask {} +class RunConfiguration{} +class Key {} +public abstract class Gen { + public abstract Map, BeforeRunTask> getBeforeRunTasks(RunConfiguration settings); +} + +class X2 extends Gen { + Object o = getBeforeRunTasks(null); + + public Map, BeforeRunTask> getBeforeRunTasks(RunConfiguration settings) { + + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/search/inheritors/noScanJdk/empty.txt b/java/java-tests/testData/psi/search/inheritors/noScanJdk/empty.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/java/java-tests/testData/psi/search/inheritors/sameNamedClasses/x/Test.java b/java/java-tests/testData/psi/search/inheritors/sameNamedClasses/x/Test.java new file mode 100644 index 000000000000..2c4691fc37ae --- /dev/null +++ b/java/java-tests/testData/psi/search/inheritors/sameNamedClasses/x/Test.java @@ -0,0 +1,18 @@ +package x; + +public class Test { + public void foo(T t) { + //Tracked f; + } +} + +class Goo extends Test { + public void foo(T t) {} +} +class Goo { + +} + +class Zoo extends Goo { + public void foo(Object t) {} +} diff --git a/java/java-tests/testData/psi/search/inheritors/scope/Derived2.java b/java/java-tests/testData/psi/search/inheritors/scope/Derived2.java new file mode 100644 index 000000000000..443181b7946a --- /dev/null +++ b/java/java-tests/testData/psi/search/inheritors/scope/Derived2.java @@ -0,0 +1,6 @@ + +import pack1.Derived1; +import pack1.Base; + +public class Derived2 extends Base{ +} diff --git a/java/java-tests/testData/psi/search/inheritors/scope/pack1/Base.java b/java/java-tests/testData/psi/search/inheritors/scope/pack1/Base.java new file mode 100644 index 000000000000..10104fc8bfe3 --- /dev/null +++ b/java/java-tests/testData/psi/search/inheritors/scope/pack1/Base.java @@ -0,0 +1,4 @@ +package pack1; + +public class Base { +} diff --git a/java/java-tests/testData/psi/search/inheritors/scope/pack1/Derived1.java b/java/java-tests/testData/psi/search/inheritors/scope/pack1/Derived1.java new file mode 100644 index 000000000000..205a3d9e7697 --- /dev/null +++ b/java/java-tests/testData/psi/search/inheritors/scope/pack1/Derived1.java @@ -0,0 +1,4 @@ +package pack1; + +public class Derived1 extends Base{ +} diff --git a/java/java-tests/testData/psi/search/inheritors/scope/pack1/Derived3.java b/java/java-tests/testData/psi/search/inheritors/scope/pack1/Derived3.java new file mode 100644 index 000000000000..51c217046906 --- /dev/null +++ b/java/java-tests/testData/psi/search/inheritors/scope/pack1/Derived3.java @@ -0,0 +1,6 @@ +package pack1; + +import Derived2; + +public class Derived3 extends Derived2{ +} diff --git a/java/java-tests/testData/psi/search/plainTextUsages/simple/Test.txt b/java/java-tests/testData/psi/search/plainTextUsages/simple/Test.txt new file mode 100644 index 000000000000..0b33aa04f891 --- /dev/null +++ b/java/java-tests/testData/psi/search/plainTextUsages/simple/Test.txt @@ -0,0 +1,3 @@ +aaa com.Foo bbb +aaacom.Foo +aaa com.Foobbb diff --git a/java/java-tests/testData/psi/search/plainTextUsages/xmlOutOfScope/com/Foo.java b/java/java-tests/testData/psi/search/plainTextUsages/xmlOutOfScope/com/Foo.java new file mode 100644 index 000000000000..ad0c3f4105f8 --- /dev/null +++ b/java/java-tests/testData/psi/search/plainTextUsages/xmlOutOfScope/com/Foo.java @@ -0,0 +1,3 @@ +package com; + +public class Foo {} \ No newline at end of file diff --git a/java/java-tests/testData/psi/search/plainTextUsages/xmlOutOfScope/resources/Test.xml b/java/java-tests/testData/psi/search/plainTextUsages/xmlOutOfScope/resources/Test.xml new file mode 100644 index 000000000000..136aa9f5762a --- /dev/null +++ b/java/java-tests/testData/psi/search/plainTextUsages/xmlOutOfScope/resources/Test.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/java/java-tests/testData/psi/search/searchInLibs/lib/classes/LibraryClass1.class b/java/java-tests/testData/psi/search/searchInLibs/lib/classes/LibraryClass1.class new file mode 100644 index 000000000000..c1148b00e362 Binary files /dev/null and b/java/java-tests/testData/psi/search/searchInLibs/lib/classes/LibraryClass1.class differ diff --git a/java/java-tests/testData/psi/search/searchInLibs/lib/classes/LibraryClass2.class b/java/java-tests/testData/psi/search/searchInLibs/lib/classes/LibraryClass2.class new file mode 100644 index 000000000000..6bf93d0165ae Binary files /dev/null and b/java/java-tests/testData/psi/search/searchInLibs/lib/classes/LibraryClass2.class differ diff --git a/java/java-tests/testData/psi/search/searchInLibs/lib/src/LibraryClass1.java b/java/java-tests/testData/psi/search/searchInLibs/lib/src/LibraryClass1.java new file mode 100644 index 000000000000..b2bb5f3da55b --- /dev/null +++ b/java/java-tests/testData/psi/search/searchInLibs/lib/src/LibraryClass1.java @@ -0,0 +1,4 @@ +class LibraryClass1{ + LibraryClass2 libClass2; + ProjectClass projectClass; // should not find this! +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/search/searchInLibs/lib/src/LibraryClass2.java b/java/java-tests/testData/psi/search/searchInLibs/lib/src/LibraryClass2.java new file mode 100644 index 000000000000..2136ef2563fd --- /dev/null +++ b/java/java-tests/testData/psi/search/searchInLibs/lib/src/LibraryClass2.java @@ -0,0 +1,3 @@ +class LibraryClass2{ + LibraryClass1 libClass1; +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/search/searchInLibs/project/ProjectClass.java b/java/java-tests/testData/psi/search/searchInLibs/project/ProjectClass.java new file mode 100644 index 000000000000..4e8e07e3cf91 --- /dev/null +++ b/java/java-tests/testData/psi/search/searchInLibs/project/ProjectClass.java @@ -0,0 +1,4 @@ +class ProjectClass{ + ProjectClass aClass; + LibraryClass1 libClass1; +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/search/searchInLibs/project/src2/ProjectClass2.java b/java/java-tests/testData/psi/search/searchInLibs/project/src2/ProjectClass2.java new file mode 100644 index 000000000000..b7a92854639b --- /dev/null +++ b/java/java-tests/testData/psi/search/searchInLibs/project/src2/ProjectClass2.java @@ -0,0 +1,3 @@ +class ProjectClass2{ + ProjectClass2 aClass; +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/search/updateCache/1.java b/java/java-tests/testData/psi/search/updateCache/1.java new file mode 100644 index 000000000000..6ea20619f69f --- /dev/null +++ b/java/java-tests/testData/psi/search/updateCache/1.java @@ -0,0 +1,4 @@ +class Class1{ + Exception e; + String s; //newtodo +} diff --git a/java/java-tests/testData/psi/search/updateCache/aDir/2.java b/java/java-tests/testData/psi/search/updateCache/aDir/2.java new file mode 100644 index 000000000000..df23af2e90e1 --- /dev/null +++ b/java/java-tests/testData/psi/search/updateCache/aDir/2.java @@ -0,0 +1,4 @@ +class B{ + Exception e; + Thread thread; //todo +} diff --git a/java/java-tests/testSrc/com/intellij/psi/search/FindUsages15Test.java b/java/java-tests/testSrc/com/intellij/psi/search/FindUsages15Test.java new file mode 100644 index 000000000000..818b044c32d5 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/search/FindUsages15Test.java @@ -0,0 +1,76 @@ +package com.intellij.psi.search; + +import com.intellij.JavaTestUtil; +import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; +import com.intellij.openapi.roots.LanguageLevelProjectExtension; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.*; +import com.intellij.psi.search.searches.MethodReferencesSearch; +import com.intellij.psi.search.searches.OverridingMethodsSearch; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.testFramework.PsiTestCase; +import com.intellij.testFramework.PsiTestUtil; + +public class FindUsages15Test extends PsiTestCase{ + + @Override + protected void setUp() throws Exception { + super.setUp(); + + LanguageLevelProjectExtension.getInstance(myJavaFacade.getProject()).setLanguageLevel(LanguageLevel.JDK_1_5); + String root = JavaTestUtil.getJavaTestDataPath() + "/psi/search/findUsages15/" + getTestName(true); + PsiTestUtil.removeAllRoots(myModule, JavaSdkImpl.getMockJdk17("java 1.5")); + PsiTestUtil.createTestProjectStructure(myProject, myModule, root, myFilesToDelete); + } + + public void testEnumConstructor() throws Exception { + PsiClass enumClass = myJavaFacade.findClass("pack.OurEnum", GlobalSearchScope.moduleScope(myModule)); + assertNotNull(enumClass); + assertTrue(enumClass.isEnum()); + PsiMethod[] constructors = enumClass.getConstructors(); + assertEquals(2, constructors.length); + PsiReference[] references0 = + ReferencesSearch.search(constructors[0], GlobalSearchScope.moduleScope(myModule), false).toArray(new PsiReference[0]); + assertEquals(2, references0.length); + assertTrue(references0[0].getElement() instanceof PsiEnumConstant); + assertTrue(references0[1].getElement() instanceof PsiEnumConstant); + PsiReference[] references1 = + ReferencesSearch.search(constructors[1], GlobalSearchScope.moduleScope(myModule), false).toArray(new PsiReference[0]); + assertEquals(1, references1.length); + assertTrue(references1[0].getElement() instanceof PsiEnumConstant); + } + + public void testGenericMethodOverriderUsages () throws Exception { + final PsiClass baseClass = myJavaFacade.findClass("pack.GenericClass", GlobalSearchScope.moduleScope(myModule)); + assertNotNull(baseClass); + final PsiMethod method = baseClass.getMethods()[0]; + PsiReference[] references = + MethodReferencesSearch.search(method, GlobalSearchScope.moduleScope(myModule), false).toArray(PsiReference.EMPTY_ARRAY); + assertEquals(1, references.length); + final PsiElement element = references[0].getElement(); + final PsiClass refClass = PsiTreeUtil.getParentOfType(element, PsiClass.class); + assertEquals(refClass.getName(), "GenericClassDerived"); + } + + public void testFindRawOverriddenUsages () throws Exception { + final PsiClass baseClass = myJavaFacade.findClass("pack.Base", GlobalSearchScope.moduleScope(myModule)); + assertNotNull(baseClass); + final PsiMethod method = baseClass.getMethods()[0]; + PsiMethod[] overriders = + OverridingMethodsSearch.search(method, GlobalSearchScope.moduleScope(myModule), true).toArray(PsiMethod.EMPTY_ARRAY); + assertEquals(1, overriders.length); + } + public void testGenericOverride() throws Exception { + final PsiClass baseClass = myJavaFacade.findClass("pack.Gen", GlobalSearchScope.moduleScope(myModule)); + assertNotNull(baseClass); + final PsiMethod method = baseClass.getMethods()[0]; + PsiReference[] references = + MethodReferencesSearch.search(method, GlobalSearchScope.projectScope(getProject()), true).toArray(PsiReference.EMPTY_ARRAY); + + assertEquals(1, references.length); + + PsiClass refClass = PsiTreeUtil.getParentOfType(references[0].getElement(), PsiClass.class); + assertEquals("X2", refClass.getName()); + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/search/FindUsagesTest.java b/java/java-tests/testSrc/com/intellij/psi/search/FindUsagesTest.java new file mode 100644 index 000000000000..4be491c3f5d2 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/search/FindUsagesTest.java @@ -0,0 +1,241 @@ +package com.intellij.psi.search; + +import com.intellij.JavaTestUtil; +import com.intellij.find.findUsages.JavaFindUsagesHandler; +import com.intellij.find.findUsages.JavaFindUsagesHandlerFactory; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.openapi.module.ModifiableModuleModel; +import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.module.StdModuleTypes; +import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.psi.search.searches.MethodReferencesSearch; +import com.intellij.psi.search.searches.OverridingMethodsSearch; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.testFramework.PsiTestCase; +import com.intellij.testFramework.PsiTestUtil; +import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory; +import com.intellij.testFramework.fixtures.TempDirTestFixture; +import com.intellij.usageView.UsageInfo; +import com.intellij.util.Processor; +import com.intellij.util.containers.IntArrayList; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class FindUsagesTest extends PsiTestCase{ + + @Override + protected void setUp() throws Exception { + super.setUp(); + + String root = JavaTestUtil.getJavaTestDataPath() + "/psi/search/findUsages/" + getTestName(true); + PsiTestUtil.removeAllRoots(myModule, JavaSdkImpl.getMockJdk17()); + PsiTestUtil.createTestProjectStructure(myProject, myModule, root, myFilesToDelete); + } + + public void testOverloadConstructors() throws Exception { + PsiClass aClass = myJavaFacade.findClass("B", GlobalSearchScope.allScope(myProject)); + PsiMethod constructor; +// constructor = myJavaFacade.getElementFactory().createConstructor(); +// constructor = aClass.findMethodBySignature(constructor, false); + constructor = aClass.findMethodsByName("B", false)[0]; + PsiMethodCallExpression superCall = (PsiMethodCallExpression) constructor.getBody().getStatements()[0].getFirstChild(); + PsiReferenceExpression superExpr = superCall.getMethodExpression(); + String[] fileNames = new String[]{"B.java", "A.java", "A.java", "B.java"}; + int[] starts = new int[]{}; + int[] ends = new int[]{}; + final ArrayList filesList = new ArrayList(); + final IntArrayList startsList = new IntArrayList(); + final IntArrayList endsList = new IntArrayList(); + PsiReference[] refs = + MethodReferencesSearch.search((PsiMethod)superExpr.resolve(), GlobalSearchScope.projectScope(myProject), false).toArray(PsiReference.EMPTY_ARRAY); + for (PsiReference ref : refs) { + addReference(ref, filesList, startsList, endsList); + } + checkResult(fileNames, filesList, starts, startsList, ends, endsList); + } + + public void testSiblingImplement() throws Exception { + PsiClass anInterface = myJavaFacade.findClass("A.I", GlobalSearchScope.allScope(myProject)); + PsiMethod method = anInterface.getMethods()[0]; + final Collection overriders = OverridingMethodsSearch.search(method).findAll(); + assertEquals(1, overriders.size()); + } + + public void testProtectedMethodInPackageLocalClass() throws Throwable { + PsiMethod method = myJavaFacade.findClass("foo.PackageLocal", GlobalSearchScope.allScope(myProject)).getMethods()[0]; + assertEquals(1, OverridingMethodsSearch.search(method).findAll().size()); + assertEquals(1, ReferencesSearch.search(method).findAll().size()); + } + + public void testImplicitConstructorUsage() throws Throwable { + PsiMethod[] ctrs = myJavaFacade.findClass("Foo", GlobalSearchScope.allScope(myProject)).getConstructors(); + PsiMethod method = ctrs[0]; + assertEquals(0, method.getParameterList().getParametersCount()); + assertEquals(0, ReferencesSearch.search(method).findAll().size()); + + PsiMethod usedMethod = ctrs[1]; + assertEquals(1, usedMethod.getParameterList().getParametersCount()); + assertEquals(1, ReferencesSearch.search(usedMethod).findAll().size()); + } + + private static void addReference(PsiReference ref, ArrayList filesList, IntArrayList startsList, IntArrayList endsList) { + PsiElement element = ref.getElement(); + filesList.add(element.getContainingFile()); + TextRange range = element.getTextRange(); + TextRange rangeInElement = ref.getRangeInElement(); + startsList.add(range.getStartOffset() + rangeInElement.getStartOffset()); + endsList.add(range.getStartOffset() + rangeInElement.getEndOffset()); + } + + public void testFieldInJavadoc() throws Exception{ + PsiClass aClass = myJavaFacade.findClass("A", GlobalSearchScope.allScope(myProject)); + PsiField field = aClass.findFieldByName("FIELD", false); + doTest(field, new String[]{"A.java"}, new int[]{}, new int[]{}); + } + + public void testXml() throws Exception{ + PsiClass aClass = myJavaFacade.findClass("com.Foo", GlobalSearchScope.allScope(myProject)); + doTest(aClass, new String[]{"Test.xml"}, new int[]{32}, new int[]{35}); + + final PsiFile nonCodeUsage = PsiFileFactory.getInstance(myProject).createFileFromText("a.xml", StdFileTypes.XML, "", 0, true); + assertTrue(new UsageInfo(nonCodeUsage, 14, 21, true).getNavigationOffset() > 0); + } + + public void testNonCodeClassUsages() throws Exception { + final TempDirTestFixture tdf = IdeaTestFixtureFactory.getFixtureFactory().createTempDirTestFixture(); + tdf.setUp(); + + try { + new WriteCommandAction(getProject()) { + @Override + protected void run(Result result) throws Throwable { + final ModifiableModuleModel moduleModel = ModuleManager.getInstance(getProject()).getModifiableModel(); + moduleModel.newModule("independent/independent.iml", StdModuleTypes.JAVA); + moduleModel.commit(); + + tdf.createFile("plugin.xml", "\n" + + " \n" + + " \n" + + " \n" + + ""); + + PsiTestUtil.addContentRoot(ModuleManager.getInstance(getProject()).findModuleByName("independent"), tdf.getFile("")); + } + }.execute(); + + GlobalSearchScope scope = GlobalSearchScope.allScope(getProject()); + PsiClass foo = myJavaFacade.findClass("com.Foo", scope); + PsiClass bar = myJavaFacade.findClass("com.Foo.Bar", scope); + + final int[] count = {0}; + Processor processor = new Processor() { + @Override + public boolean process(UsageInfo usageInfo) { + int navigationOffset = usageInfo.getNavigationOffset(); + assertTrue(navigationOffset > 0); + String textAfter = usageInfo.getFile().getText().substring(navigationOffset); + assertTrue(textAfter, textAfter.startsWith("Foo") || textAfter.startsWith("Bar") || + textAfter.startsWith("com.Foo.Bar") // sorry, can't get references with dollar-dot mismatch to work now + ); + count[0]++; + return true; + } + }; + JavaFindUsagesHandler handler = new JavaFindUsagesHandler(bar, JavaFindUsagesHandlerFactory.getInstance(getProject())); + + count[0] = 0; + handler.processUsagesInText(foo, processor, scope); + assertEquals(3, count[0]); + + count[0] = 0; + handler.processUsagesInText(bar, processor, scope); + assertEquals(2, count[0]); + } + finally { + tdf.tearDown(); + } + } + + public static void doTest(PsiElement element, String[] fileNames, int[] starts, int[] ends) throws Exception { + final ArrayList filesList = new ArrayList(); + final IntArrayList startsList = new IntArrayList(); + final IntArrayList endsList = new IntArrayList(); + ReferencesSearch.search(element, GlobalSearchScope.projectScope(element.getProject()), false).forEach(new PsiReferenceProcessorAdapter(new PsiReferenceProcessor() { + @Override + public boolean execute(PsiReference ref) { + addReference(ref, filesList, startsList, endsList); + return true; + } + })); + + checkResult(fileNames, filesList, starts, startsList, ends, endsList); + + } + + private static class SearchResult implements Comparable { + String fileName; + int startOffset; + int endOffset; + + private SearchResult(final String fileName, final int startOffset, final int endOffset) { + this.fileName = fileName; + this.startOffset = startOffset; + this.endOffset = endOffset; + } + + @Override + public int compareTo(final SearchResult o) { + int rc = fileName.compareTo(o.fileName); + if (rc != 0) return rc; + + rc = startOffset - o.startOffset; + if (rc != 0) return rc; + + return endOffset - o.endOffset; + } + + public String toString() { + return fileName + "[" + startOffset + ":" + endOffset + "]"; + } + + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + final SearchResult that = (SearchResult)o; + + if (endOffset != that.endOffset) return false; + if (startOffset != that.startOffset) return false; + if (fileName != null ? !fileName.equals(that.fileName) : that.fileName != null) return false; + + return true; + } + } + + private static void checkResult(String[] fileNames, final ArrayList filesList, int[] starts, final IntArrayList startsList, int[] ends, final IntArrayList endsList) { + List expected = new ArrayList(); + for (int i = 0; i < fileNames.length; i++) { + String fileName = fileNames[i]; + expected.add(new SearchResult(fileName, i < starts.length ? starts[i] : -1, i < ends.length ? ends[i] : -1)); + } + + List actual = new ArrayList(); + for (int i = 0; i < filesList.size(); i++) { + PsiFile psiFile = filesList.get(i); + actual.add( + new SearchResult(psiFile.getName(), i < starts.length ? startsList.get(i) : -1, i < ends.length ? endsList.get(i) : -1)); + } + + Collections.sort(expected); + Collections.sort(actual); + + assertEquals("Usages don't match", expected, actual); + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/search/InheritorsTest.java b/java/java-tests/testSrc/com/intellij/psi/search/InheritorsTest.java new file mode 100644 index 000000000000..2c8548a361c0 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/search/InheritorsTest.java @@ -0,0 +1,73 @@ +package com.intellij.psi.search; + +import com.intellij.JavaTestUtil; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiPackage; +import com.intellij.psi.search.searches.ClassInheritorsSearch; +import com.intellij.testFramework.PsiTestCase; +import com.intellij.testFramework.PsiTestUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; + +public class InheritorsTest extends PsiTestCase{ + private static final Logger LOG = Logger.getInstance("#com.intellij.psi.search.InheritorsTest"); + + @Override + protected void setUp() throws Exception { + super.setUp(); + + String root = JavaTestUtil.getJavaTestDataPath() + "/psi/search/inheritors/" + getTestName(true); + PsiTestUtil.removeAllRoots(myModule, JavaSdkImpl.getMockJdk17()); + PsiTestUtil.createTestProjectStructure(myProject, myModule, root, myFilesToDelete); + } + + public void testScope() throws Exception { + doTest("pack1.Base", "pack1", true, "pack1.Derived1", "pack1.Derived3"); + } + + public void testNoScanJdk() throws Exception { + doTest("javax.swing.JPanel", "", false); + } + + public void testSameNamedClasses() throws Exception { + doTest("x.Test", "", true, "x.Goo", "x.Zoo"); + } + + private void doTest(String className, String packageScopeName, final boolean deep, String... inheritorNames) throws Exception { + final PsiClass aClass = myJavaFacade.findClass(className); + assertNotNull(aClass); + + final SearchScope scope; + if (packageScopeName != null){ + PsiPackage aPackage = JavaPsiFacade.getInstance(myPsiManager.getProject()).findPackage(packageScopeName); + scope = PackageScope.packageScope(aPackage, true).intersectWith(GlobalSearchScope.projectScope(myProject)); + } + else{ + scope = GlobalSearchScope.projectScope(myProject); + } + + final ArrayList inheritorsList = new ArrayList(); + ProgressManager.getInstance().runProcess( + new Runnable() { + @Override + public void run() { + ClassInheritorsSearch.search(aClass, scope, deep).forEach(new PsiElementProcessorAdapter(new PsiElementProcessor() { + @Override + public boolean execute(@NotNull PsiClass element) { + inheritorsList.add(element.getQualifiedName()); + return true; + } + })); + } + }, + null + ); + + assertSameElements(inheritorsList, inheritorNames); + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/search/PlainTextUsagesTest.java b/java/java-tests/testSrc/com/intellij/psi/search/PlainTextUsagesTest.java new file mode 100644 index 000000000000..6aa4ba710f5c --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/search/PlainTextUsagesTest.java @@ -0,0 +1,91 @@ +package com.intellij.psi.search; + +import com.intellij.JavaTestUtil; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.testFramework.PsiTestCase; +import com.intellij.testFramework.PsiTestUtil; +import com.intellij.util.containers.IntArrayList; + +import java.util.ArrayList; +import java.util.List; + +public class PlainTextUsagesTest extends PsiTestCase { + @Override + protected void setUp() throws Exception { + super.setUp(); + + String root = JavaTestUtil.getJavaTestDataPath() + "/psi/search/plainTextUsages/" + getTestName(true); + PsiTestUtil.removeAllRoots(myModule, JavaSdkImpl.getMockJdk17()); + PsiTestUtil.createTestProjectStructure(myProject, myModule, root, myFilesToDelete); + } + + public void testSimple() throws Exception { + doTest("com.Foo", null, new String[]{"Test.txt"}, new int[]{4}, new int[]{11}); + } + + public void testXmlOutOfScope() throws Exception { + final VirtualFile resourcesDir = ModuleRootManager.getInstance(myModule).getSourceRoots()[0].findChild("resources"); + assertNotNull(resourcesDir); + new WriteAction() { + @Override + protected void run(final Result result) { + final Module module = createModule("res"); + PsiTestUtil.addContentRoot(module, resourcesDir); + final VirtualFile child = resourcesDir.findChild("Test.xml"); + assert child != null; + assertSame(module, ModuleUtil.findModuleForFile(child, getProject())); + } + }.execute(); + + PsiClass aClass = myJavaFacade.findClass("com.Foo", GlobalSearchScope.allScope(myProject)); + assertNotNull(aClass); + doTest("com.Foo", aClass, new String[]{"Test.xml"}, new int[]{28}, new int[]{35}); + } + + private void doTest(String qNameToSearch, + final PsiElement originalElement, + String[] fileNames, + int[] starts, + int[] ends) throws Exception { + PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(myProject); + final List filesList = new ArrayList(); + final IntArrayList startsList = new IntArrayList(); + final IntArrayList endsList = new IntArrayList(); + helper.processUsagesInNonJavaFiles(originalElement, + qNameToSearch, + new PsiNonJavaFileReferenceProcessor() { + @Override + public boolean process(PsiFile file, int startOffset, int endOffset) { + filesList.add(file); + startsList.add(startOffset); + endsList.add(endOffset); + return true; + } + }, + GlobalSearchScope.projectScope(myProject) + ); + + assertEquals("usages count", fileNames.length, filesList.size()); + + for (int i = 0; i < fileNames.length; i++) { + assertEquals("files[" + i + "]", fileNames[i], filesList.get(i).getName()); + } + + for (int i = 0; i < starts.length; i++) { + assertEquals("starts[" + i + "]", starts[i], startsList.get(i)); + } + + for (int i = 0; i < ends.length; i++) { + assertEquals("ends[" + i + "]", ends[i], endsList.get(i)); + } + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/search/SearchInLibsTest.java b/java/java-tests/testSrc/com/intellij/psi/search/SearchInLibsTest.java new file mode 100644 index 000000000000..8755e4e29bcb --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/search/SearchInLibsTest.java @@ -0,0 +1,106 @@ +package com.intellij.psi.search; + +import com.intellij.JavaTestUtil; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.roots.ContentEntry; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiReference; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.testFramework.PsiTestCase; +import com.intellij.testFramework.PsiTestUtil; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; + +public class SearchInLibsTest extends PsiTestCase { + public void testSearchInProject() throws Exception { + doTest("ProjectClass", new String[]{"ProjectClass.java"}, GlobalSearchScope.projectScope(myProject)); + doTest("LibraryClass1", new String[]{"ProjectClass.java"}, GlobalSearchScope.projectScope(myProject)); + doTest("LibraryClass2", new String[]{}, GlobalSearchScope.projectScope(myProject)); + } + + public void testSearchInLibs() throws Exception { + doTest("ProjectClass", new String[]{"ProjectClass.java"}, GlobalSearchScope.allScope(myProject)); + doTest("LibraryClass1", new String[]{"LibraryClass2.java", "ProjectClass.java"}, GlobalSearchScope.allScope(myProject)); + doTest("LibraryClass2", new String[]{"LibraryClass1.java"}, GlobalSearchScope.allScope(myProject)); + } + + public void testInnerSourceRoot() throws Exception { + doTest("ProjectClass2", new String[]{"ProjectClass2.java"}, GlobalSearchScope.projectScope(myProject)); + } + + private void doTest(String classNameToSearch, String[] expectedFileNames, SearchScope scope) throws Exception { + + String root = JavaTestUtil.getJavaTestDataPath() + "/psi/search/searchInLibs"; + VirtualFile rootFile = PsiTestUtil.createTestProjectStructure(myProject, myModule, root, myFilesToDelete, false); + + final VirtualFile projectRoot = rootFile.findChild("project"); + assertNotNull(projectRoot); + + final VirtualFile innerSourceRoot = projectRoot.findChild("src2"); + assertNotNull(innerSourceRoot); + + VirtualFile libRoot = rootFile.findChild("lib"); + final VirtualFile libClassesRoot = libRoot.findChild("classes"); + final VirtualFile libSrcRoot = libRoot.findChild("src"); + assertNotNull(libRoot); + final ModuleRootManager rootManager = ModuleRootManager.getInstance(myModule); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + final ModifiableRootModel rootModel = rootManager.getModifiableModel(); + rootModel.clear(); + rootModel.setSdk(null); + final ContentEntry contentEntry = rootModel.addContentEntry(projectRoot); + contentEntry.addSourceFolder(projectRoot, false); + contentEntry.addSourceFolder(innerSourceRoot, false); + final Library.ModifiableModel libraryModel = rootModel.getModuleLibraryTable().createLibrary().getModifiableModel(); + libraryModel.addRoot(libSrcRoot, OrderRootType.SOURCES); + libraryModel.addRoot(libClassesRoot, OrderRootType.CLASSES); + libraryModel.commit(); + rootModel.commit(); + } + }); + + + final PsiClass aClass = myJavaFacade.findClass(classNameToSearch); + assertNotNull(aClass); + + PsiReference[] refs = ReferencesSearch.search(aClass, scope, false).toArray(new PsiReference[0]); + + ArrayList files = new ArrayList(); + for (int i = 0; i < refs.length; i++) { + PsiReference ref = refs[i]; + PsiFile file = ref.getElement().getContainingFile(); + if (!files.contains(file)) { + files.add(file); + } + } + + assertEquals("files count", expectedFileNames.length, files.size()); + + Collections.sort(files, new Comparator() { + @Override + public int compare(Object o1, Object o2) { + PsiFile file1 = (PsiFile) o1; + PsiFile file2 = (PsiFile) o2; + return file1.getName().compareTo(file2.getName()); + } + }); + Arrays.sort(expectedFileNames); + + for (int i = 0; i < expectedFileNames.length; i++) { + String name = expectedFileNames[i]; + PsiFile file = (PsiFile) files.get(i); + assertEquals(name, file.getName()); + } + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java b/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java new file mode 100644 index 000000000000..d1877bd01d70 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java @@ -0,0 +1,537 @@ +package com.intellij.psi.search; + +import com.intellij.JavaTestUtil; +import com.intellij.ide.impl.ProjectUtil; +import com.intellij.ide.todo.TodoConfiguration; +import com.intellij.lang.injection.InjectedLanguageManager; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.project.ex.ProjectManagerEx; +import com.intellij.openapi.projectRoots.impl.ProjectRootUtil; +import com.intellij.openapi.roots.*; +import com.intellij.openapi.roots.ex.ProjectRootManagerEx; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.*; +import com.intellij.psi.impl.JavaPsiFacadeImpl; +import com.intellij.psi.impl.PsiManagerImpl; +import com.intellij.psi.impl.cache.impl.id.IdIndex; +import com.intellij.psi.impl.cache.impl.todo.TodoIndex; +import com.intellij.psi.impl.cache.impl.todo.TodoIndexEntry; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.testFramework.PlatformTestCase; +import com.intellij.testFramework.PsiTestCase; +import com.intellij.testFramework.PsiTestUtil; +import com.intellij.util.ArrayUtil; +import com.intellij.util.Processor; +import com.intellij.util.indexing.FileBasedIndex; +import org.jetbrains.annotations.NonNls; + +import java.io.File; +import java.util.*; + +@PlatformTestCase.WrapInCommand +public class UpdateCacheTest extends PsiTestCase{ + @Override + protected void setUp() throws Exception { + super.setUp(); + + FileBasedIndex.requestRebuild(IdIndex.NAME); + FileBasedIndex.requestRebuild(TodoIndex.NAME); + } + + @Override + protected void setUpProject() throws Exception { + myProjectManager = ProjectManagerEx.getInstanceEx(); + LOG.assertTrue(myProjectManager != null, "Cannot instantiate ProjectManager component"); + + File projectFile = getIprFile(); + loadAndSetupProject(projectFile.getPath()); + } + + private void loadAndSetupProject(String path) throws Exception { + LocalFileSystem.getInstance().refreshIoFiles(myFilesToDelete); + + myProject = ProjectManager.getInstance().loadAndOpenProject(path); + + setUpModule(); + + final String root = JavaTestUtil.getJavaTestDataPath() + "/psi/search/updateCache"; + PsiTestUtil.createTestProjectStructure(myProject, myModule, root, myFilesToDelete); + + setUpJdk(); + + myProjectManager.setCurrentTestProject(myProject); + runStartupActivities(); + } + + @Override + protected void tearDown() throws Exception { + ProjectManager.getInstance().closeProject(myProject); + super.tearDown(); + } + + public void testFileCreation() throws Exception { + PsiDirectory root = ProjectRootUtil.getAllContentRoots(myProject) [0]; + + PsiFile file = PsiFileFactory.getInstance(myProject).createFileFromText("New.java", "class A{ Object o;}"); + file = (PsiFile)root.add(file); + assertNotNull(file); + + PsiClass objectClass = myJavaFacade.findClass("java.lang.Object", GlobalSearchScope.allScope(getProject())); + assertNotNull(objectClass); + checkUsages(objectClass, new String[]{"New.java"}); + } + + public void testExternalFileCreation() throws Exception { + VirtualFile root = ProjectRootManager.getInstance(myProject).getContentRoots()[0]; + + String newFilePath = root.getPresentableUrl() + File.separatorChar + "New.java"; + FileUtil.writeToFile(new File(newFilePath), "class A{ Object o;}".getBytes()); + VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(newFilePath.replace(File.separatorChar, '/')); + assertNotNull(file); + PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + + PsiClass objectClass = myJavaFacade.findClass("java.lang.Object", GlobalSearchScope.allScope(getProject())); + assertNotNull(objectClass); + checkUsages(objectClass, new String[]{"New.java"}); + } + + public void testExternalFileDeletion() throws Exception { + VirtualFile root = ProjectRootManager.getInstance(myProject).getContentRoots()[0]; + + VirtualFile file = root.findChild("1.java"); + assertNotNull(file); + file.delete(null); + + PsiClass stringClass = myJavaFacade.findClass("java.lang.String", GlobalSearchScope.allScope(getProject())); + assertNotNull(stringClass); + checkUsages(stringClass, ArrayUtil.EMPTY_STRING_ARRAY); + } + + public void testExternalFileModification() throws Exception { + VirtualFile root = ProjectRootManager.getInstance(myProject).getContentRoots()[0]; + + VirtualFile file = root.findChild("1.java"); + assertNotNull(file); + VfsUtil.saveText(file, "class A{ Object o;}"); + PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + + PsiClass objectClass = myJavaFacade.findClass("java.lang.Object", GlobalSearchScope.allScope(getProject())); + assertNotNull(objectClass); + checkUsages(objectClass, new String[]{"1.java"}); + } + + @Override + protected boolean isRunInWriteAction() { + return !getTestName(false).equals("ExternalFileModificationWhileProjectClosed"); + } + + public void testExternalFileModificationWhileProjectClosed() throws Exception { + VirtualFile root = ProjectRootManager.getInstance(myProject).getContentRoots()[0]; + + PsiClass objectClass = myJavaFacade.findClass("java.lang.Object", GlobalSearchScope.allScope(getProject())); + assertNotNull(objectClass); + checkUsages(objectClass, new String[]{}); + FileBasedIndex.getInstance().getContainingFiles(TodoIndex.NAME, new TodoIndexEntry("todo", true), GlobalSearchScope.allScope(getProject())); + + final String projectLocation = myProject.getLocation(); + myProject.save(); + final VirtualFile content = ModuleRootManager.getInstance(getModule()).getContentRoots()[0]; + ProjectUtil.closeAndDispose(myProject); + ((InjectedLanguageManagerImpl)InjectedLanguageManager.getInstance(getProject())).checkInjectorsAreDisposed(); + assertTrue("Project was not disposed", myProject.isDisposed()); + myModule = null; + + final File file = new File(root.getPath(), "1.java"); + assertTrue(file.exists()); + + FileUtil.writeToFile(file, "class A{ Object o;}".getBytes()); + root.refresh(false, true); + + LocalFileSystem.getInstance().refresh(false); + + myProject = ProjectManager.getInstance().loadAndOpenProject(projectLocation); + ((InjectedLanguageManagerImpl)InjectedLanguageManager.getInstance(getProject())).pushInjectors(); + setUpModule(); + setUpJdk(); + ProjectManagerEx.getInstanceEx().setCurrentTestProject(myProject); + runStartupActivities(); + PsiTestUtil.addSourceContentToRoots(getModule(), content); + + assertNotNull(myProject); + myPsiManager = (PsiManagerImpl) PsiManager.getInstance(myProject); + myJavaFacade = (JavaPsiFacadeImpl) JavaPsiFacade.getInstance(myProject); + + objectClass = myJavaFacade.findClass("java.lang.Object", GlobalSearchScope.allScope(getProject())); + assertNotNull(objectClass); + checkUsages(objectClass, new String[]{"1.java"}); + } + + public void testExternalDirCreation() throws Exception { + VirtualFile root = ProjectRootManager.getInstance(myProject).getContentRoots()[0]; + + String newFilePath = root.getPresentableUrl() + File.separatorChar + "dir" + File.separatorChar + "New.java"; + LOG.assertTrue(new File(newFilePath).getParentFile().mkdir()); + FileUtil.writeToFile(new File(newFilePath), "class A{ Object o;}".getBytes()); + VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(newFilePath.replace(File.separatorChar, '/')); + assertNotNull(file); + PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + + PsiClass objectClass = myJavaFacade.findClass("java.lang.Object", GlobalSearchScope.allScope(getProject())); + assertNotNull(objectClass); + checkUsages(objectClass, new String[]{"New.java"}); + } + + public void testExternalDirDeletion() throws Exception { + VirtualFile root = ProjectRootManager.getInstance(myProject).getContentRoots()[0]; + + VirtualFile file = root.findChild("aDir"); + assertNotNull(file); + file.delete(null); + + PsiClass threadClass = myJavaFacade.findClass("java.lang.Thread", GlobalSearchScope.allScope(getProject())); + assertNotNull(threadClass); + checkUsages(threadClass, ArrayUtil.EMPTY_STRING_ARRAY); + } + + public void testTodoConfigurationChange() throws Exception{ + TodoPattern pattern = new TodoPattern("newtodo", TodoAttributes.createDefault(), true); + TodoPattern[] oldPatterns = TodoConfiguration.getInstance().getTodoPatterns(); + + checkTodos(new String[]{"2.java"}); + + TodoConfiguration.getInstance().setTodoPatterns(new TodoPattern[]{pattern}); + + try{ + checkTodos(new String[]{"1.java"}); + } + finally{ + TodoConfiguration.getInstance().setTodoPatterns(oldPatterns); + checkTodos(new String[]{"2.java"}); + } + } + + public void testAddExcludeRoot() throws Exception{ + PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithTodoItems(); // to initialize caches + + ProjectRootManagerEx rootManager = (ProjectRootManagerEx)ProjectRootManager.getInstance(myProject); + final VirtualFile root = rootManager.getContentRoots()[0]; + + final VirtualFile dir = root.findChild("aDir"); + + new WriteCommandAction.Simple(getProject()) { + @Override + protected void run() throws Throwable { + VirtualFile newFile = dir.createChildData(null, "New.java"); + VfsUtil.saveText(newFile, "class A{ Exception e;} //todo"); + } + }.execute().throwException(); + + PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel(); + final ContentEntry[] content = rootModel.getContentEntries(); + for (ContentEntry contentEntry : content) { + if (root.equals(contentEntry.getFile())) { + contentEntry.addExcludeFolder(dir); + break; + } + } + rootModel.commit(); + } + }); + + + PsiClass exceptionClass = myJavaFacade.findClass("java.lang.Exception",GlobalSearchScope.allScope(getProject())); + assertNotNull(exceptionClass); + checkUsages(exceptionClass, new String[]{"1.java"}); + checkTodos(new String[]{}); + } + + public void testRemoveExcludeRoot() throws Exception{ + ProjectRootManagerEx rootManager = (ProjectRootManagerEx)ProjectRootManager.getInstance(myProject); + final VirtualFile root = rootManager.getContentRoots()[0]; + + final VirtualFile dir = root.findChild("aDir"); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel(); + final ContentEntry[] content = rootModel.getContentEntries(); + for (ContentEntry contentEntry : content) { + if (root.equals(contentEntry.getFile())) { + contentEntry.addExcludeFolder(dir); + break; + } + } + rootModel.commit(); + } + }); + + + PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithTodoItems(); // to initialize caches + + new WriteCommandAction.Simple(getProject()) { + @Override + protected void run() throws Throwable { + VirtualFile newFile = dir.createChildData(null, "New.java"); + VfsUtil.saveText(newFile, "class A{ Exception e;} //todo"); + } + }.execute().throwException(); + + PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + + PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithTodoItems(); // to update caches + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + final ModifiableRootModel rootModel1 = ModuleRootManager.getInstance(myModule).getModifiableModel(); + final ContentEntry[] content1 = rootModel1.getContentEntries(); + contentLoop: + for (ContentEntry contentEntry : content1) { + if (root.equals(contentEntry.getFile())) { + final ExcludeFolder[] excludeFolders = contentEntry.getExcludeFolders(); + for (ExcludeFolder excludeFolder : excludeFolders) { + if (dir.equals(excludeFolder.getFile())) { + contentEntry.removeExcludeFolder(excludeFolder); + break contentLoop; + } + } + } + } + rootModel1.commit(); + } + }); + + + PsiClass exceptionClass = myJavaFacade.findClass("java.lang.Exception", GlobalSearchScope.allScope(getProject())); + assertNotNull(exceptionClass); + checkUsages(exceptionClass, new String[]{"1.java", "2.java", "New.java"}); + checkTodos(new String[]{"2.java", "New.java"}); + } + + public void testAddSourceRoot() throws Exception{ + File dir = createTempDirectory(); + + final VirtualFile root = LocalFileSystem.getInstance().refreshAndFindFileByPath(dir.getCanonicalPath().replace(File.separatorChar, '/')); + + new WriteCommandAction.Simple(getProject()) { + @Override + protected void run() throws Throwable { + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel(); + rootModel.addContentEntry(root); + rootModel.commit(); + + VirtualFile newFile = root.createChildData(null, "New.java"); + VfsUtil.saveText(newFile, "class A{ Exception e;} //todo"); + } + }.execute().throwException(); + + PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + + PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithTodoItems(); // to initialize caches + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + final ModifiableRootModel rootModel1 = ModuleRootManager.getInstance(myModule).getModifiableModel(); + final ContentEntry[] content = rootModel1.getContentEntries(); + for (ContentEntry contentEntry : content) { + if (root.equals(contentEntry.getFile())) { + contentEntry.addSourceFolder(root, false); + break; + } + } + rootModel1.commit(); + } + }); + + + PsiClass exceptionClass = myJavaFacade.findClass("java.lang.Exception", GlobalSearchScope.allScope(getProject())); + assertNotNull(exceptionClass); + checkUsages(exceptionClass, new String[]{"1.java", "2.java", "New.java"}); + checkTodos(new String[]{"2.java", "New.java"}); + } + + public void testRemoveSourceRoot() throws Exception{ + final ModuleRootManager rootManager = ModuleRootManager.getInstance(myModule); + final VirtualFile root = rootManager.getContentRoots()[0]; + + PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithTodoItems(); // to initialize caches + + new WriteCommandAction.Simple(getProject()) { + @Override + protected void run() throws Throwable { + VirtualFile newFile = root.createChildData(null, "New.java"); + VfsUtil.saveText(newFile, "class A{ Exception e;} //todo"); + } + }.execute().throwException(); + + PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + + PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithTodoItems(); // to update caches + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + VirtualFile[] sourceRoots = rootManager.getSourceRoots(); + LOG.assertTrue(sourceRoots.length == 1); + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel(); + final ContentEntry[] content1 = rootModel.getContentEntries(); + contentLoop: + for (ContentEntry contentEntry : content1) { + if (root.equals(contentEntry.getFile())) { + final SourceFolder[] sourceFolders = contentEntry.getSourceFolders(); + for (SourceFolder sourceFolder : sourceFolders) { + if (sourceRoots[0].equals(sourceFolder.getFile())) { + contentEntry.removeSourceFolder(sourceFolder); + break contentLoop; + } + } + } + } + rootModel.commit(); + } + }); + + + PsiClass exceptionClass = myJavaFacade.findClass("java.lang.Exception", GlobalSearchScope.allScope(getProject())); + assertNotNull(exceptionClass); + // currently it actually finds usages by FQN due to Java PSI enabled for out-of-source java files + // so the following check is disabled + //checkUsages(exceptionClass, new String[]{}); + checkTodos(new String[]{"2.java", "New.java"}); + } + + public void testAddProjectRoot() throws Exception{ + File dir = createTempDirectory(); + + final VirtualFile root = LocalFileSystem.getInstance().refreshAndFindFileByPath(dir.getCanonicalPath().replace(File.separatorChar, '/')); + + new WriteCommandAction.Simple(getProject()) { + @Override + protected void run() throws Throwable { + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel(); + rootModel.addContentEntry(root).addSourceFolder(root, false); + rootModel.commit(); + + VirtualFile newFile = root.createChildData(null, "New.java"); + VfsUtil.saveText(newFile, "class A{ Exception e;} //todo"); + } + }.execute().throwException(); + + PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + + PsiSearchHelper.SERVICE.getInstance(myProject).processAllFilesWithWord("aaa", GlobalSearchScope.allScope(myProject), new Processor() { + @Override + public boolean process(final PsiFile psiFile) { + return true; + } + }, true); // to initialize caches + +/* + rootManager.startChange(); + rootManager.addRoot(root, ProjectRootType.PROJECT); + rootManager.finishChange(); +*/ + + PsiClass exceptionClass = myJavaFacade.findClass("java.lang.Exception", GlobalSearchScope.allScope(getProject())); + assertNotNull(exceptionClass); + checkUsages(exceptionClass, new String[]{"1.java", "2.java", "New.java"}); + checkTodos(new String[]{"2.java", "New.java"}); + } + + public void testSCR6066() throws Exception{ + ProjectRootManagerEx rootManager = (ProjectRootManagerEx)ProjectRootManager.getInstance(myProject); + final VirtualFile root = rootManager.getContentRoots()[0]; + + PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithTodoItems(); // to initialize caches + + new WriteCommandAction.Simple(getProject()) { + @Override + protected void run() throws Throwable { + VirtualFile newFile = root.createChildData(null, "New.java"); + VfsUtil.saveText(newFile, "class A{ Exception e;} //todo"); + } + }.execute().throwException(); + + PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + + PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithTodoItems(); // to update caches + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel(); + final ContentEntry[] content = rootModel.getContentEntries(); + for (ContentEntry contentEntry : content) { + if (root.equals(contentEntry.getFile())) { + contentEntry.addExcludeFolder(root); + break; + } + } + rootModel.commit(); + } + }); + + + PsiClass exceptionClass = myJavaFacade.findClass("java.lang.Exception", GlobalSearchScope.allScope(getProject())); + assertNotNull(exceptionClass); + checkUsages(exceptionClass, new String[]{}); + checkTodos(new String[]{}); + } + + private void checkUsages(PsiElement element, @NonNls String[] expectedFiles){ + PsiReference[] refs = ReferencesSearch.search(element, GlobalSearchScope.projectScope(myProject), false).toArray(new PsiReference[0]); + + List files = new ArrayList(); + for (PsiReference ref : refs) { + PsiFile file = ref.getElement().getContainingFile(); + if (!files.contains(file)) { + files.add(file); + } + } + + assertEquals(expectedFiles.length, files.size()); + + Collections.sort(files, new Comparator() { + @Override + public int compare(PsiFile file1, PsiFile file2) { + return file1.getName().compareTo(file2.getName()); + } + }); + Arrays.sort(expectedFiles); + + for(int i = 0; i < expectedFiles.length; i++){ + String name = expectedFiles[i]; + PsiFile file = files.get(i); + assertEquals(name, file.getName()); + } + } + + private void checkTodos(@NonNls String[] expectedFiles){ + PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(myProject); + + PsiFile[] files = helper.findFilesWithTodoItems(); + + assertEquals(expectedFiles.length, files.length); + + Arrays.sort(files, new Comparator() { + @Override + public int compare(PsiFile file1, PsiFile file2) { + return file1.getName().compareTo(file2.getName()); + } + }); + Arrays.sort(expectedFiles); + + for(int i = 0; i < expectedFiles.length; i++){ + String name = expectedFiles[i]; + PsiFile file = files[i]; + assertEquals(name, file.getName()); + } + } +}