blob: d6e5e9d8fd8a3a44abd38ead60a12d76bc16976c [file] [log] [blame]
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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.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.IdeaTestUtil;
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, IdeaTestUtil.getMockJdk17());
PsiTestUtil.createTestProjectStructure(myProject, myModule, root, myFilesToDelete);
}
public void testOverloadConstructors() throws Exception {
PsiClass aClass = myJavaFacade.findClass("B", GlobalSearchScope.allScope(myProject));
PsiMethod constructor = aClass.findMethodsByName("B", false)[0];
PsiMethodCallExpression superCall = (PsiMethodCallExpression) constructor.getBody().getStatements()[0].getFirstChild();
PsiReferenceExpression superExpr = superCall.getMethodExpression();
String[] fileNames = {"B.java", "A.java", "A.java", "B.java"};
int[] starts = {};
int[] ends = {};
final ArrayList<PsiFile> filesList = new ArrayList<PsiFile>();
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<PsiMethod> 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 testLibraryClassUsageFromDecompiledSource() {
PsiElement decompiled =
((PsiCompiledElement)myJavaFacade.findClass("javax.swing.JLabel", GlobalSearchScope.allScope(myProject))).getMirror();
assertEquals(2, ReferencesSearch.search(decompiled, GlobalSearchScope.projectScope(myProject)).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<PsiFile> 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, "<root action='com.Foo'/>", 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.getId());
moduleModel.commit();
tdf.createFile("plugin.xml", "<document>\n" +
" <action class=\"com.Foo\" />\n" +
" <action class=\"com.Foo.Bar\" />\n" +
" <action class=\"com.Foo$Bar\" />\n" +
"</document>");
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<UsageInfo> processor = new Processor<UsageInfo>() {
@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<PsiFile> filesList = new ArrayList<PsiFile>();
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<SearchResult> {
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<PsiFile> filesList, int[] starts, final IntArrayList startsList, int[] ends, final IntArrayList endsList) {
List<SearchResult> expected = new ArrayList<SearchResult>();
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<SearchResult> actual = new ArrayList<SearchResult>();
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);
}
}