blob: 6ee91ef2581f1ef3200487756f3c5ad9e1e77162 [file] [log] [blame]
/*
* Copyright 2000-2013 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 org.jetbrains.plugins.groovy.lang.findUsages
import com.intellij.codeInsight.TargetElementUtilBase
import com.intellij.find.FindManager
import com.intellij.find.findUsages.FindUsagesHandler
import com.intellij.find.findUsages.FindUsagesManager
import com.intellij.find.findUsages.FindUsagesOptions
import com.intellij.find.impl.FindManagerImpl
import com.intellij.psi.*
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.searches.DirectClassInheritorsSearch
import com.intellij.psi.search.searches.MethodReferencesSearch
import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.psi.search.searches.SuperMethodsSearch
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.usageView.UsageInfo
import com.intellij.util.CommonProcessors
import com.intellij.util.Query
import org.jetbrains.plugins.groovy.LightGroovyTestCase
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod
import org.jetbrains.plugins.groovy.util.TestUtils
/**
* @author ven
*/
public class FindUsagesTest extends LightGroovyTestCase {
@Override
protected String getBasePath() {
return "${TestUtils.testDataPath}findUsages/${getTestName(true)}/";
}
private void doConstructorTest(String filePath, int expectedCount) throws Throwable {
myFixture.configureByFile(filePath);
final PsiElement elementAt = myFixture.file.findElementAt(myFixture.editor.caretModel.offset);
final PsiMethod method = PsiTreeUtil.getParentOfType(elementAt, PsiMethod.class);
assertNotNull(method);
assertTrue(method.constructor);
final Query<PsiReference> query = ReferencesSearch.search(method);
assertEquals(expectedCount, query.findAll().size());
}
public void testDerivedClass() throws Throwable {
myFixture.configureByFiles("p/B.java", "A.groovy");
final PsiElement elementAt = myFixture.file.findElementAt(myFixture.editor.caretModel.offset);
final PsiClass clazz = PsiTreeUtil.getParentOfType(elementAt, PsiClass.class);
assertNotNull(clazz);
final GlobalSearchScope projectScope = GlobalSearchScope.projectScope(myFixture.project);
final Query<PsiClass> query = DirectClassInheritorsSearch.search(clazz, projectScope);
assertEquals(1, query.findAll().size());
}
public void testConstructor1() throws Throwable {
doConstructorTest("A.groovy", 2);
}
public void testConstructorUsageInNewExpression() throws Throwable {
myFixture.configureByFile("ConstructorUsageInNewExpression.groovy");
final PsiElement resolved = TargetElementUtilBase.findTargetElement(myFixture.editor, TargetElementUtilBase.instance.referenceSearchFlags);
assertNotNull("Could not resolve reference", resolved);
final GlobalSearchScope projectScope = GlobalSearchScope.projectScope(myFixture.project);
assertEquals(2, MethodReferencesSearch.search((PsiMethod)resolved, projectScope, true).findAll().size());
assertEquals(4, MethodReferencesSearch.search((PsiMethod)resolved, projectScope, false).findAll().size());
}
public void testGotoConstructor() throws Throwable {
myFixture.configureByFile("GotoConstructor.groovy");
final PsiElement target = TargetElementUtilBase.findTargetElement(myFixture.editor, TargetElementUtilBase.instance.referenceSearchFlags);
assertNotNull(target);
assertInstanceOf(target, PsiMethod.class);
assertTrue(((PsiMethod)target).constructor);
assertTrue(((PsiMethod)target).parameterList.parametersCount == 0);
}
public void testSetter1() throws Throwable {
doTestImpl("A.groovy", 2);
}
public void testGetter1() throws Throwable {
doTestImpl("A.groovy", 1);
}
public void testProperty1() throws Throwable {
doTestImpl("A.groovy", 2);
}
public void testProperty2() throws Throwable {
doTestImpl("A.groovy", 1);
}
public void testEscapedReference() throws Throwable {
doTestImpl("A.groovy", 1);
}
public void testKeywordPropertyName() throws Throwable {
doTestImpl("A.groovy", 1);
}
public void testTypeAlias() throws Throwable {
doTestImpl("A.groovy", 2);
}
public void testMethodAlias() throws Throwable {
doTestImpl("A.groovy", 2);
}
public void testAliasImportedProperty() throws Throwable {
myFixture.addFileToProject("Abc.groovy", "class Abc {static def foo}");
doTestImpl("A.groovy", 5);
}
public void testGetterWhenAliasedImportedProperty() throws Throwable {
myFixture.addFileToProject("Abc.groovy", "class Abc {static def foo}");
doTestImpl("A.groovy", 5);
}
public void testForInParameter() throws Throwable {
doTestImpl("A.groovy", 1);
}
public void testSyntheticParameter() throws Throwable {
doTestImpl("A.groovy", 1);
}
public void testOverridingMethodUsage() throws Throwable {
doTestImpl("OverridingMethodUsage.groovy", 2);
}
public void testDynamicUsages() {
doTestImpl("DynamicUsages.groovy", 2);
}
public void testAnnotatedMemberSearch() throws Throwable {
final PsiReference ref = myFixture.getReferenceAtCaretPosition("A.groovy");
assertNotNull("Did not find reference", ref);
final PsiElement resolved = ref.resolve();
assertNotNull("Could not resolve reference", resolved);
final Query<PsiReference> query;
final GlobalSearchScope projectScope = GlobalSearchScope.projectScope(myFixture.getProject());
if (resolved instanceof PsiMethod) {
query = MethodReferencesSearch.search((PsiMethod)resolved, projectScope, true);
}
else {
query = ReferencesSearch.search(resolved, projectScope);
}
assertEquals(1, query.findAll().size());
}
private void doTestImpl(String filePath, int expectedUsagesCount) {
myFixture.configureByFile(filePath);
assertUsageCount(expectedUsagesCount);
}
private void assertUsageCount(int expectedUsagesCount) {
final PsiElement resolved = TargetElementUtilBase.findTargetElement(myFixture.getEditor(),
TargetElementUtilBase.getInstance().getReferenceSearchFlags());
assertNotNull("Could not resolve reference", resolved);
doFind(expectedUsagesCount, resolved);
}
private void doFind(int expectedUsagesCount, PsiElement resolved) {
FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(getProject())).getFindUsagesManager();
FindUsagesHandler handler = findUsagesManager.getFindUsagesHandler(resolved, false);
assertNotNull(handler);
final FindUsagesOptions options = handler.getFindUsagesOptions();
final CommonProcessors.CollectProcessor<UsageInfo> processor = new CommonProcessors.CollectProcessor<UsageInfo>();
for (PsiElement element : handler.getPrimaryElements()) {
handler.processElementUsages(element, processor, options);
}
for (PsiElement element : handler.getSecondaryElements()) {
handler.processElementUsages(element, processor, options);
}
assertEquals(expectedUsagesCount, processor.getResults().size());
}
public void testGdkMethod() throws Exception {
myFixture.configureByText("a.groovy", "[''].ea<caret>ch {}");
assertUsageCount(1);
}
public void testGDKSuperMethodSearch() throws Exception {
doSuperMethodTest("T");
}
public void testGDKSuperMethodForMapSearch() throws Exception {
doSuperMethodTest("Map");
}
public void testLabels() throws Exception {
myFixture.configureByFile(getTestName(false) + ".groovy");
final GroovyFile file = (GroovyFile)myFixture.getFile();
assertEquals(2, ReferencesSearch.search(file.getTopStatements()[0]).findAll().size());
}
public void testConstructorUsageInAnonymousClass() {
doTestImpl("A.groovy", 1);
}
void testCapitalizedProperty1() {
doTest(1, '''\
class A {
def Pro<caret>p
}
new A().Prop''')
}
void testCapitalizedProperty2() {
doTest(1, '''\
class A {
def Pro<caret>p
}
new A().prop''')
}
void testCapitalizedProperty3() {
doTest(0, '''\
class A {
def pro<caret>p
}
new A().Prop''')
}
void testCapitalizedProperty4() {
doTest(1, '''\
class A {
def p<caret>rop
}
new A().prop''')
}
void testCategoryProperty() {
doTest(1, '''\
class Cat {
static def ge<caret>tFoo(Number s) {'num'}
}
use(Cat) {
2.foo
}
''')
}
void "test do not report dynamic usages when argument count differs"() {
doTest(0, '''\
class A {
static void start<caret>sWith(String s, String s1, boolean b) {}
def c = { it.startsWith("aaa") }
}
''')
}
void 'test literal names'() {
doTest(1, '''\
def 'f<caret>oo'() {}
'foo'()
''')
}
void 'test literal name with escaping'() {
doTest(1, '''\
def 'f<caret>oo \\''() {}
'foo \\''()
''')
}
void 'test literal name with escaping and other quotes'() {
doTest(1, '''\
def 'f<caret>oo \\''() {}
"foo '"()
''')
}
//todo
void '_test literal name with escaping and other quotes 2'() {
doTest(1, '''\
def '<caret>\\''() {}
"'"()
''')
}
void testResolveBinding1() {
doTest(2, '''\
abc = 4
print ab<caret>c
''')
}
void testResolveBinding2() {
doTest(2, '''\
print ab<caret>c
abc = 4
''', )
}
void testResolveBinding3() {
doTest(2, '''\
a<caret>bc = 4
print abc
''', )
}
void testResolveBinding4() {
doTest(2, '''\
print abc
a<caret>bc = 4
''', )
}
void testResolveBinding5() {
doTest(2, '''\
def foo() {
abc = 4
}
def bar() {
print ab<caret>c
}
''', )
}
void testResolveBinding6() {
doTest(2, '''\
def foo() {
print ab<caret>c
}
def bar() {
abc = 4
}
''', )
}
void testResolveBinding7() {
doTest(2, '''\
def foo() {
a<caret>bc = 4
}
def bar() {
print abc
}
''', )
}
void testResolveBinding8() {
doTest(2, '''\
def foo() {
print abc
}
def bar() {
a<caret>bc = 4
}
''', )
}
void testBinding9() {
doTest(4, '''\
a<caret>a = 5
print aa
aa = 6
print aa
''', )
}
void testBinding10() {
doTest(4, '''\
aa = 5
print a<caret>a
aa = 6
print aa
''', )
}
void testBinding11() {
doTest(4, '''\
aa = 5
print aa
a<caret>a = 6
print aa
''', )
}
void testBinding12() {
doTest(4, '''\
aa = 5
print aa
aa = 6
print a<caret>a
''', )
}
void testTraitField() {
doTest(4, '''
trait T {
public int fi<caret>eld = 4
def bar() {
print field
print T__field
}
}
class C implements T {
def abc() {
print field //unresolved
print T__field
}
}
new C().T__field
new C().field //unresolved
''')
}
private void doSuperMethodTest(String... firstParameterTypes) {
myFixture.configureByFile(getTestName(false) + ".groovy");
final GroovyFile file = (GroovyFile)myFixture.getFile();
final GrTypeDefinition psiClass = (GrTypeDefinition)file.getClasses()[0];
final GrMethod method = (GrMethod)psiClass.getMethods()[0];
final Collection<MethodSignatureBackedByPsiMethod> superMethods = SuperMethodsSearch.search(method, null, true, true).findAll();
assertEquals(firstParameterTypes.length, superMethods.size());
final Iterator<MethodSignatureBackedByPsiMethod> iterator = superMethods.iterator();
for (String firstParameterType : firstParameterTypes) {
final MethodSignatureBackedByPsiMethod methodSignature = iterator.next();
final PsiMethod superMethod = methodSignature.getMethod();
final String className = superMethod.getContainingClass().getName();
assertEquals("DefaultGroovyMethods", className);
final String actualParameterType = ((PsiClassType)methodSignature.getParameterTypes()[0]).resolve().getName();
assertEquals(firstParameterType, actualParameterType);
}
}
private void doTest(int usageCount, String text) {
myFixture.configureByText('_.groovy', text)
assertUsageCount(usageCount);
}
}