Files
openide/java/java-tests/testSrc/com/intellij/java/navigation/GotoImplementationHandlerTest.java
Nikita Kudrin cdf91bf213 [benchmarks] Renaming PerformanceTest* => Benchmark*
GitOrigin-RevId: 9963b84d51e1062acc262a8d3d3de1409a708e3b
2024-07-23 18:20:01 +00:00

411 lines
17 KiB
Java

// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.java.navigation;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.TargetElementUtil;
import com.intellij.codeInsight.navigation.GotoTargetHandler;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.IndexingTestUtil;
import com.intellij.tools.ide.metrics.benchmark.Benchmark;
import com.intellij.testFramework.fixtures.CodeInsightTestUtil;
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
import com.intellij.util.containers.ContainerUtil;
import org.intellij.lang.annotations.Language;
import java.util.Arrays;
import java.util.List;
public class GotoImplementationHandlerTest extends JavaCodeInsightFixtureTestCase {
public void testMultipleImplsFromAbstractCall() {
@Language("JAVA") @SuppressWarnings("ALL")
String fileText = "public abstract class Hello {\n" +
" abstract void foo();\n" +
"\n" +
" class A {\n" +
" {\n" +
" fo<caret>o();\n" +
" }\n" +
" }\n" +
" class Hello1 extends Hello {\n" +
" void foo() {}\n" +
" }\n" +
" class Hello2 extends Hello {\n" +
" void foo() {}\n" +
" }\n" +
"}";
PsiFile file = myFixture.addFileToProject("Foo.java", fileText);
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
final PsiElement[] impls = getTargets(file);
assertEquals(2, impls.length);
}
public void testFromIncompleteCode() {
@Language("JAVA") @SuppressWarnings("ALL")
String fileText = "public abstract class Hello {\n" +
" abstract void foo();\n" +
"\n" +
" class A {\n" +
" {\n" +
" Hello<caret>\n" +
" }\n" +
" }\n" +
" class Hello1 extends Hello {\n" +
" void foo() {}\n" +
" }\n" +
"}" +
"class Hello2 extends Hello {\n" +
" void foo() {}\n" +
"}\n";
PsiFile file = myFixture.addFileToProject("Foo.java", fileText);
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
final PsiElement[] impls = getTargets(file);
assertEquals(2, impls.length);
}
public void testToStringOnUnqualifiedPerformance() {
@Language("JAVA") @SuppressWarnings("ALL")
String fileText = "public class Fix {\n" +
" {\n" +
" <caret>toString();\n" +
" }\n" +
"}\n" +
"class FixImpl1 extends Fix {\n" +
" @Override\n" +
" public String toString() {\n" +
" return \"Impl1\";\n" +
" }\n" +
"}\n" +
"class FixImpl2 extends Fix {\n" +
" @Override\n" +
" public String toString() {\n" +
" return \"Impl2\";\n" +
" }\n" +
"}";
final PsiFile file = myFixture.addFileToProject("Foo.java", fileText);
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
Benchmark.newBenchmark(getTestName(false), () -> {
PsiElement[] impls = getTargets(file);
assertEquals(3, impls.length);
}).start();
}
public void testToStringOnQualifiedPerformance() {
@SuppressWarnings("ALL") @Language("JAVA")
String fileText = "public class Fix {\n" +
" {\n" +
" Fix ff = getFix();\n" +
" ff.<caret>toString();\n" +
" }\n" +
" \n" +
" Fix getFix() {return new FixImpl1();}\n" +
"}\n" +
"class FixImpl1 extends Fix {\n" +
" @Override\n" +
" public String toString() {\n" +
" return \"Impl1\";\n" +
" }\n" +
"}\n" +
"class FixImpl2 extends Fix {\n" +
" @Override\n" +
" public String toString() {\n" +
" return \"Impl2\";\n" +
" }\n" +
"}";
final PsiFile file = myFixture.addFileToProject("Foo.java", fileText);
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
Benchmark.newBenchmark(getTestName(false), () -> {
PsiElement[] impls = getTargets(file);
assertEquals(3, impls.length);
}).start();
}
public void testShowSelfNonAbstract() {
//fails if groovy plugin is enabled: org.jetbrains.plugins.groovy.codeInsight.JavaClsMethodElementEvaluator
@Language("JAVA") @SuppressWarnings("ALL")
String fileText = "public class Hello {\n" +
" void foo(){}\n" +
"\n" +
" class A {\n" +
" {\n" +
" fo<caret>o();\n" +
" }\n" +
" }\n" +
" class Hello1 extends Hello {\n" +
" void foo() {}\n" +
" }\n" +
" class Hello2 extends Hello {\n" +
" void foo() {}\n" +
" }\n" +
"}";
PsiFile file = myFixture.addFileToProject("Foo.java", fileText);
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
final PsiElement[] impls = getTargets(file);
assertEquals(3, impls.length);
}
public void testMultipleImplsFromStaticCall() {
@Language("JAVA") @SuppressWarnings("ALL")
String fileText = "public abstract class Hello {\n" +
" static void bar (){}\n" +
" class Hello1 extends Hello {\n" +
" }\n" +
" class Hello2 extends Hello {\n" +
" }\n" +
"class D {\n" +
" {\n" +
" He<caret>llo.bar();\n" +
" }\n" +
"}}";
PsiFile file = myFixture.addFileToProject("Foo.java", fileText);
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
final PsiElement[] impls = getTargets(file);
assertEquals(2, impls.length);
}
public void testFilterOutImpossibleVariants() {
@Language("JAVA") @SuppressWarnings("ALL")
String fileText = "interface A {\n" +
" void save();\n" +
"}\n" +
"interface B extends A {\n" +
" void foo();\n" +
"}\n" +
"class X implements B {\n" +
" public void foo() { }\n" +
" public void save(){}\n" +
"}\n" +
"class Y implements A {\n" +
" public void save(){}\n" +
"}\n" +
"class App {\n" +
" private B b;\n" +
" private void some() {\n" +
" b.sa<caret>ve();\n" +
" }\n" +
"}";
PsiFile file = myFixture.addFileToProject("Foo.java", fileText);
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
final PsiElement[] impls = getTargets(file);
assertEquals(1, impls.length);
final PsiElement method = impls[0];
assertTrue(method instanceof PsiMethod);
final PsiClass aClass = ((PsiMethod)method).getContainingClass();
assertNotNull(aClass);
assertEquals("X", aClass.getName());
}
public void testImplicitInheritance() {
@Language("JAVA") @SuppressWarnings("ALL")
String fileText = "interface PackContainer {\n" +
" void foo();\n" +
"}\n" +
"interface PsiPackage extends PackContainer {}\n" +
"class PsiPackageBase implements PackContainer {\n" +
" public void foo() {}\n" +
"}\n" +
"class PsiPackageImpl extends PsiPackageBase implements PsiPackage {}\n" +
"\n" +
"class Foo {\n" +
" class Bar {\n" +
" void bar(PsiPackage i) {\n" +
" i.fo<caret>o();\n" +
" }\n" +
" }\n" +
"}";
PsiFile file = myFixture.addFileToProject("Foo.java", fileText);
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
final PsiElement[] impls = getTargets(file);
assertEquals(1, impls.length);
final PsiElement method = impls[0];
assertTrue(method instanceof PsiMethod);
final PsiClass aClass = ((PsiMethod)method).getContainingClass();
assertNotNull(aClass);
assertEquals("PsiPackageBase", aClass.getName());
}
public void testMethodReferences() {
@Language("JAVA") @SuppressWarnings("ALL")
String fileText = "interface I {void f();}\n" +
"class A implements I { public void f(){}}\n" +
"class B implements I { public void f(){}}\n" +
"class C {\n" +
" void foo(java.util.List<I> l) {l.stream().forEach(I::<caret>f);}" +
"}";
PsiFile file = myFixture.addFileToProject("Foo.java", fileText);
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
final PsiElement[] impls = getTargets(file);
assertEquals(2, impls.length);
// target are non-deterministic now
Arrays.sort(impls, (o1, o2) -> {
String name1 = ((PsiMethod)o1).getContainingClass().getName();
String name2 = ((PsiMethod)o2).getContainingClass().getName();
return StringUtil.compare(name1, name2, false);
});
final PsiElement method = impls[0];
assertTrue(method instanceof PsiMethod);
final PsiClass aClass = ((PsiMethod)method).getContainingClass();
assertNotNull(aClass);
assertEquals("A", aClass.getName());
}
public void testMethodImplementationsOnTypeVariable() {
@Language("JAVA") @SuppressWarnings("ALL")
String fileText = "interface I {}\n" +
"interface Im {\n" +
" void m();\n" +
"}\n" +
"class Im1 implements Im {\n" +
" public void m() {}\n" +
"}\n" +
"class Im2 implements Im {\n" +
" public void m() {}\n" +
"}\n" +
"class JavaClass<T extends K, K extends I & Im> {\n" +
" void a(T t){\n" +
" t.<caret>m();\n" +
" }\n" +
"}";
PsiFile file = myFixture.addFileToProject("Foo.java", fileText);
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
PsiElement[] targets = getTargets(file);
assertSize(2, targets);
}
public void testStaticMethodReference() {
@Language("JAVA") @SuppressWarnings("ALL")
String fileText = "class C {\n" +
" static void a(){}\n" +
" {a<caret>();}" +
"}";
PsiFile file = myFixture.addFileToProject("Foo.java",
fileText);
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
final PsiElement[] impls = getTargets(file);
assertEquals(1, impls.length);
}
public void testPrivateClassInheritors() {
@Language("JAVA")
String fileText = """
class C {
private static class Pr<caret>ivate {}
public static class Public extends Private {}}""";
PsiFile file = myFixture.addFileToProject("Foo.java",
fileText);
myFixture.addClass("class Inheritor extends C.Public {}");
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
assertSize(2, getTargets(file));
}
public void testPrivateClassInheritorsInJdkDecompiled() {
Sdk sdk = IdeaTestUtil.getMockJdk18();
WriteAction.run(() -> ProjectJdkTable.getInstance().addJdk(sdk, getTestRootDisposable()));
ModuleRootModificationUtil.setModuleSdk(getModule(), sdk);
IndexingTestUtil.waitUntilIndexesAreReady(getProject());
PsiClass aClass = myFixture.getJavaFacade().findClass("java.util.ResourceBundle.CacheKeyReference");
PsiFile file = aClass.getContainingFile();
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
myFixture.getEditor().getCaretModel().moveToOffset(aClass.getTextOffset());
assertSize(2, getTargets(file));
}
public void testScopeForPrivateMethod() {
@Language("JAVA") @SuppressWarnings("ALL")
String text = "class Foo {" +
" {f<caret>oo();}" +
" private void foo() {}" +
"}";
PsiFile file = myFixture.configureByText(JavaFileType.INSTANCE, text);
PsiClass inheritor = myFixture.addClass("class FooImpl extends Foo {}");
SearchScope scope = TargetElementUtil.getInstance().getSearchScope(myFixture.getEditor(), ((PsiJavaFile)file).getClasses()[0].getMethods()[0]);
assertFalse(scope.contains(PsiUtilCore.getVirtualFile(inheritor)));
}
public void testAnonymousAndLocalClassesInLibrary() {
ModuleRootModificationUtil.addModuleLibrary(
getModule(),
"jar://" + JavaTestUtil.getJavaTestDataPath() + "/codeInsight/navigation/MyInterfaceLibrary.jar!/"
);
@Language("JAVA")
String fileText = """
import com.company.MyInterface;
public class MyInterfaceImplementation implements My<caret>Interface {
@Override
public void doIt() {}
}
""";
PsiFile psiFile = myFixture.addFileToProject("MyInterfaceImplementation.java",
fileText);
myFixture.configureFromExistingVirtualFile(psiFile.getVirtualFile());
PsiClass implementation = myFixture.findClass("MyInterfaceImplementation");
assertNotNull(implementation);
PsiClass[] supers = implementation.getSupers();
assertTrue(supers.length == 2 && "com.company.MyInterface".equalsIgnoreCase(supers[1].getQualifiedName()));
PsiElement[] targets = getTargets(psiFile);
assertSize(5, targets);
List<String> names = ContainerUtil.map(targets, element -> ((PsiClass)element).getName());
for(PsiElement element:targets) {
PsiClass psiClass = (PsiClass)element;
String name = psiClass.getName();
if ("1".equals(name) || "2".equals(name)) {
assertNull(psiClass.getModifierList());
assertTrue(psiClass.hasModifierProperty(PsiModifier.FINAL));
assertInstanceOf(psiClass, PsiAnonymousClass.class);
}
else if (!"MyInterfaceImplementation".equals(name)) {
assertNotNull(psiClass.getModifierList());
}
}
assertContainsElements(names, "1");
assertContainsElements(names, "2");
assertContainsElements(names, "MyLocalClassImplementation");
assertContainsElements(names, "MyLocalClassImplementationInInner");
assertContainsElements(names, "MyInterfaceImplementation");
implementation = myFixture.getJavaFacade().findClass("MyLocalClassImplementation");
assertNull(implementation);
implementation = myFixture.getJavaFacade().findClass("MyLocalClassImplementationInInner");
assertNull(implementation);
implementation = myFixture.getJavaFacade().findClass("1");
assertNull(implementation);
implementation = myFixture.getJavaFacade().findClass("2");
assertNull(implementation);
}
private PsiElement[] getTargets(PsiFile file) {
GotoTargetHandler.GotoData gotoData = CodeInsightTestUtil.gotoImplementation(myFixture.getEditor(), file);
assertNotNull(gotoData);
return gotoData.targets;
}
}