[java-tests] Convert Groovy to Java; restore copyrights

GitOrigin-RevId: 2c1ab0479b2f26bc51926f0a78663436b9bf5852
This commit is contained in:
Tagir Valeev
2024-02-21 17:28:38 +01:00
committed by intellij-monorepo-bot
parent 4942586999
commit b4d12c1883
8 changed files with 735 additions and 736 deletions

View File

@@ -1,148 +1,135 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.java.psi
// 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.psi;
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.psi.*
import com.intellij.psi.impl.source.PsiClassReferenceType
import com.intellij.psi.impl.source.PsiFileImpl
import com.intellij.psi.impl.source.tree.java.JavaFileElement
import com.intellij.psi.impl.source.tree.java.MethodElement
import com.intellij.psi.impl.source.tree.java.ParameterElement
import com.intellij.testFramework.LeakHunter
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase
import com.intellij.util.ref.GCWatcher
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.psi.impl.source.tree.java.JavaFileElement;
import com.intellij.psi.impl.source.tree.java.MethodElement;
import com.intellij.psi.impl.source.tree.java.ParameterElement;
import com.intellij.testFramework.LeakHunter;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import com.intellij.util.ref.GCWatcher;
import java.util.function.Predicate
public class AstLeaksTest extends LightJavaCodeInsightFixtureTestCase {
public void test_AST_should_be_on_a_soft_reference__for_changed_files_as_well() {
final PsiFile file = myFixture.addClass("class Foo {}").getContainingFile();
assertTrue(file.findElementAt(0) instanceof PsiKeyword);
LeakHunter.checkLeak(file, JavaFileElement.class, e -> e.getPsi().equals(file));
class AstLeaksTest extends LightJavaCodeInsightFixtureTestCase {
void "test AST should be on a soft reference, for changed files as well"() {
def file = myFixture.addClass('class Foo {}').containingFile
assert file.findElementAt(0) instanceof PsiKeyword
LeakHunter.checkLeak(file, JavaFileElement) { e -> e.psi == file }
WriteCommandAction.runWriteCommandAction project, {
file.viewProvider.document.insertString(0, ' ')
PsiDocumentManager.getInstance(project).commitAllDocuments()
}
assert file.findElementAt(0) instanceof PsiWhiteSpace
LeakHunter.checkLeak(file, JavaFileElement) { e -> e.psi == file }
WriteCommandAction.runWriteCommandAction(getProject(), () -> {
file.getViewProvider().getDocument().insertString(0, " ");
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
});
assertTrue(file.findElementAt(0) instanceof PsiWhiteSpace);
LeakHunter.checkLeak(file, JavaFileElement.class, e -> e.getPsi().equals(file));
}
void "test super methods held via their signatures in class user data"() {
def superClass = myFixture.addClass('class Super { void foo() {} }')
superClass.text // load AST
public void test_super_methods_held_via_their_signatures_in_class_user_data() {
final PsiClass superClass = myFixture.addClass("class Super { void foo() {} }");
assertNotNull(superClass.getText()); // load AST
def file = myFixture.addFileToProject('Main.java', 'class Main extends Super { void foo() { System.out.println("hello"); } }')
myFixture.configureFromExistingVirtualFile(file.virtualFile)
myFixture.doHighlighting()
PsiFile file = myFixture.addFileToProject("Main.java", "class Main extends Super { void foo() { System.out.println(\"hello\"); } }");
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
myFixture.doHighlighting();
def mainClass = ((PsiJavaFile)file).classes[0]
LeakHunter.checkLeak(mainClass, MethodElement) { MethodElement node ->
superClass == node.psi.parent
}
PsiClass mainClass = ((PsiJavaFile)file).getClasses()[0];
LeakHunter.checkLeak(mainClass, MethodElement.class, node -> superClass.equals(node.getPsi().getParent()));
}
void "test no hard refs to AST after highlighting"() {
def sup = myFixture.addFileToProject('sup.java', 'class Super { Super() {} }')
assert sup.findElementAt(0) // load AST
assert !((PsiFileImpl)sup).stub
public void test_no_hard_refs_to_AST_after_highlighting() {
final PsiFile sup = myFixture.addFileToProject("sup.java", "class Super { Super() {} }");
assertNotNull(sup.findElementAt(0));// load AST
assertNull(((PsiFileImpl)sup).getStub());
LeakHunter.checkLeak(sup, MethodElement, { it.psi.containingFile == sup })
LeakHunter.checkLeak(sup, MethodElement.class, it -> it.getPsi().getContainingFile().equals(sup));
def foo = myFixture.addFileToProject('a.java', 'class Foo extends Super { void bar() { bar(); } }')
myFixture.configureFromExistingVirtualFile(foo.virtualFile)
myFixture.doHighlighting()
final PsiFile foo = myFixture.addFileToProject("a.java", "class Foo extends Super { void bar() { bar(); } }");
myFixture.configureFromExistingVirtualFile(foo.getVirtualFile());
myFixture.doHighlighting();
assert !((PsiFileImpl)foo).stub
assert ((PsiFileImpl)foo).treeElement
assertNull(((PsiFileImpl)foo).getStub());
assertNotNull(((PsiFileImpl)foo).getTreeElement());
LeakHunter.checkLeak(foo, MethodElement, { it.psi.containingFile == foo })
LeakHunter.checkLeak(sup, MethodElement, { it.psi.containingFile == sup })
LeakHunter.checkLeak(foo, MethodElement.class, it -> it.getPsi().getContainingFile().equals(foo));
LeakHunter.checkLeak(sup, MethodElement.class, it -> it.getPsi().getContainingFile().equals(sup));
}
void "test no hard refs to AST via class reference type"() {
def cls = myFixture.addClass("class Foo { Object bar() {} }")
def file = cls.containingFile as PsiFileImpl
cls.node
def type = cls.methods[0].returnType
assert type instanceof PsiClassReferenceType
public void test_no_hard_refs_to_AST_via_class_reference_type() {
final PsiClass cls = myFixture.addClass("class Foo { Object bar() {} }");
PsiFileImpl file = (PsiFileImpl)cls.getContainingFile();
assertNotNull(cls.getNode());
PsiType type = cls.getMethods()[0].getReturnType();
assertTrue(type instanceof PsiClassReferenceType);
LeakHunter.checkLeak(type, MethodElement, { MethodElement node ->
node.psi == cls.methods[0]
})
LeakHunter.checkLeak(type, MethodElement.class, node -> node.getPsi().equals(cls.getMethods()[0]));
GCWatcher.tracking(cls.node).ensureCollected()
assert !file.contentsLoaded
GCWatcher.tracking(cls.getNode()).ensureCollected();
assertFalse(file.isContentsLoaded());
assert type.equalsToText(Object.name)
assert !file.contentsLoaded
assertTrue(type.equalsToText(Object.class.getName()));
assertFalse(file.isContentsLoaded());
}
@SuppressWarnings('CStyleArrayDeclaration')
void "test no hard refs to AST via class reference type of c-style array"() {
def cls = myFixture.addClass("class Foo { static void main(String args[]) {} }")
def file = cls.containingFile as PsiFileImpl
cls.node
def type = cls.methods[0].parameterList.parameters[0].typeElement.type
assert type instanceof PsiClassReferenceType
@SuppressWarnings("CStyleArrayDeclaration")
public void test_no_hard_refs_to_AST_via_class_reference_type_of_c_style_array() {
final PsiClass cls = myFixture.addClass("class Foo { static void main(String args[]) {} }");
PsiFileImpl file = (PsiFileImpl)cls.getContainingFile();
assertNotNull(cls.getNode());
PsiType type = cls.getMethods()[0].getParameterList().getParameters()[0].getTypeElement().getType();
assertTrue(type instanceof PsiClassReferenceType);
LeakHunter.checkLeak(type, ParameterElement, { ParameterElement node ->
node.psi == cls.methods[0].parameterList.parameters[0]
})
LeakHunter.checkLeak(type, ParameterElement.class,
node -> node.getPsi().equals(cls.getMethods()[0].getParameterList().getParameters()[0]));
GCWatcher.tracking(cls.node).ensureCollected()
assert !file.contentsLoaded
GCWatcher.tracking(cls.getNode()).ensureCollected();
assertFalse(file.isContentsLoaded());
assert type.equalsToText(String.name)
assert !file.contentsLoaded
assertTrue(type.equalsToText(String.class.getName()));
assertFalse(file.isContentsLoaded());
}
void "test no hard refs to AST via array component type"() {
def cls = myFixture.addClass("class Foo { Object[] bar() {} }")
def file = cls.containingFile as PsiFileImpl
cls.node
def type = cls.methods[0].returnType
assert type instanceof PsiArrayType
def componentType = type.getComponentType()
assert componentType instanceof PsiClassReferenceType
public void test_no_hard_refs_to_AST_via_array_component_type() {
final PsiClass cls = myFixture.addClass("class Foo { Object[] bar() {} }");
PsiFileImpl file = (PsiFileImpl)cls.getContainingFile();
assertNotNull(cls.getNode());
PsiType type = cls.getMethods()[0].getReturnType();
assertTrue(type instanceof PsiArrayType);
PsiType componentType = ((PsiArrayType)type).getComponentType();
assertTrue(componentType instanceof PsiClassReferenceType);
LeakHunter.checkLeak(type, MethodElement, { MethodElement node ->
node.psi == cls.methods[0]
})
LeakHunter.checkLeak(type, MethodElement.class, node -> node.getPsi().equals(cls.getMethods()[0]));
GCWatcher.tracking(cls.node).ensureCollected()
assert !file.contentsLoaded
GCWatcher.tracking(cls.getNode()).ensureCollected();
assertFalse(file.isContentsLoaded());
assert componentType.equalsToText(Object.name)
assert !file.contentsLoaded
assertTrue(componentType.equalsToText(Object.class.getName()));
assertFalse(file.isContentsLoaded());
}
void "test no hard refs to AST via generic component type"() {
def cls = myFixture.addClass("class Foo { java.util.Map<String[], ? extends CharSequence> bar() {} }")
def file = cls.containingFile as PsiFileImpl
cls.node
def type = cls.methods[0].returnType
assert type instanceof PsiClassReferenceType
def parameters = (type as PsiClassReferenceType).getParameters()
assert parameters.length == 2
assert parameters[0] instanceof PsiArrayType
def componentType = parameters[0].getDeepComponentType()
assert componentType instanceof PsiClassReferenceType
assert parameters[1] instanceof PsiWildcardType
def bound = (parameters[1] as PsiWildcardType).getExtendsBound()
assert bound instanceof PsiClassReferenceType
public void test_no_hard_refs_to_AST_via_generic_component_type() {
final PsiClass cls = myFixture.addClass("class Foo { java.util.Map<String[], ? extends CharSequence> bar() {} }");
PsiFileImpl file = (PsiFileImpl)cls.getContainingFile();
assertNotNull(cls.getNode());
PsiType type = cls.getMethods()[0].getReturnType();
assertTrue(type instanceof PsiClassReferenceType);
PsiType[] parameters = ((PsiClassReferenceType)type).getParameters();
assertEquals(2, parameters.length);
assertTrue(parameters[0] instanceof PsiArrayType);
PsiType componentType = parameters[0].getDeepComponentType();
assertTrue(componentType instanceof PsiClassReferenceType);
assertTrue(parameters[1] instanceof PsiWildcardType);
PsiType bound = ((PsiWildcardType)parameters[1]).getExtendsBound();
assertTrue(bound instanceof PsiClassReferenceType);
LeakHunter.checkLeak(type, MethodElement, { MethodElement node ->
node.psi == cls.methods[0]
})
LeakHunter.checkLeak(type, MethodElement.class, node -> node.getPsi().equals(cls.getMethods()[0]));
GCWatcher.tracking(cls.node).ensureCollected()
assert !file.contentsLoaded
GCWatcher.tracking(cls.getNode()).ensureCollected();
assertFalse(file.isContentsLoaded());
assert componentType.equalsToText(String.name)
assert bound.equalsToText(CharSequence.name)
assert !file.contentsLoaded
assertTrue(componentType.equalsToText(String.class.getName()));
assertTrue(bound.equalsToText(CharSequence.class.getName()));
assertFalse(file.isContentsLoaded());
}
}

View File

@@ -1,518 +1,505 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.java.psi
// 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.psi;
import com.intellij.codeInsight.AnnotationTargetUtil
import com.intellij.codeInspection.dataFlow.JavaMethodContractUtil
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ReadAction
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.editor.Document
import com.intellij.psi.*
import com.intellij.psi.impl.source.PsiClassImpl
import com.intellij.psi.impl.source.PsiFieldImpl
import com.intellij.psi.impl.source.PsiFileImpl
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.PsiShortNamesCache
import com.intellij.psi.search.searches.AnnotatedElementsSearch
import com.intellij.psi.search.searches.ClassInheritorsSearch
import com.intellij.psi.search.searches.DirectClassInheritorsSearch
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.util.PsiUtil
import com.intellij.testFramework.PsiTestUtil
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase
import groovy.transform.CompileStatic
import com.intellij.codeInsight.AnnotationTargetUtil;
import com.intellij.codeInspection.dataFlow.JavaMethodContractUtil;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiClassImpl;
import com.intellij.psi.impl.source.PsiFieldImpl;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.psi.search.searches.AnnotatedElementsSearch;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import java.util.concurrent.Callable
import java.util.concurrent.ExecutionException;
@CompileStatic
class JavaStubsTest extends LightJavaCodeInsightFixtureTestCase {
public class JavaStubsTest extends LightJavaCodeInsightFixtureTestCase {
public void test_resolve_from_annotation_method_default() {
PsiClass cls = myFixture.addClass("""
public @interface BrokenAnnotation {
enum Foo {DEFAULT, OTHER}
Foo value() default Foo.DEFAULT;
}""");
void "test resolve from annotation method default"() {
def cls = myFixture.addClass("""\
public @interface BrokenAnnotation {
enum Foo {DEFAULT, OTHER}
Foo value() default Foo.DEFAULT;
}
""".stripIndent())
PsiFileImpl file = (PsiFileImpl)cls.getContainingFile();
assertNotNull(file.getStub());
def file = cls.containingFile as PsiFileImpl
assert file.stub
PsiAnnotationMemberValue ref = (((PsiAnnotationMethod)cls.getMethods()[0])).getDefaultValue();
assertNotNull(file.getStub());
def ref = (cls.methods[0] as PsiAnnotationMethod).defaultValue
assert file.stub
assert ref instanceof PsiReferenceExpression
assert ref.resolve() == cls.innerClasses[0].fields[0]
assert file.stub
assertTrue(ref instanceof PsiReferenceExpression);
assertEquals(((PsiReferenceExpression)ref).resolve(), cls.getInnerClasses()[0].getFields()[0]);
assertNotNull(file.getStub());
}
void "test literal annotation value"() {
def cls = myFixture.addClass("""\
class Foo {
@org.jetbrains.annotations.Contract(pure=true)
native int foo();
}
""".stripIndent())
public void test_literal_annotation_value() {
PsiClass cls = myFixture.addClass("""
class Foo {
@org.jetbrains.annotations.Contract(pure=true)
native int foo();
}""");
def file = cls.containingFile as PsiFileImpl
assert JavaMethodContractUtil.isPure(cls.methods[0])
assert file.stub
assert !file.contentsLoaded
PsiFileImpl file = (PsiFileImpl)cls.getContainingFile();
assertTrue(JavaMethodContractUtil.isPure(cls.getMethods()[0]));
assertNotNull(file.getStub());
assertFalse(file.isContentsLoaded());
}
void "test local variable annotation doesn't cause stub-ast switch"() {
def cls = myFixture.addClass("""
public void test_local_variable_annotation_doesn_t_cause_stub_ast_switch() {
PsiClass cls = myFixture.addClass("""
class Foo {
@Anno int foo() {
@Anno int var = 2;
}
}
@interface Anno {}
""")
@interface Anno {}""");
def file = cls.containingFile as PsiFileImpl
assert AnnotatedElementsSearch.searchPsiMethods(myFixture.findClass("Anno"), GlobalSearchScope.allScope(project)).size() == 1
assert file.stub
assert !file.contentsLoaded
PsiFileImpl file = (PsiFileImpl)cls.getContainingFile();
assertEquals(1, AnnotatedElementsSearch.searchPsiMethods(myFixture.findClass("Anno"), GlobalSearchScope.allScope(getProject()))
.findAll().size());
assertNotNull(file.getStub());
assertFalse(file.isContentsLoaded());
}
void "test applying type annotations"() {
def cls = myFixture.addClass("""\
import java.lang.annotation.*;
class Foo {
@Target(ElementType.TYPE_USE)
@interface TA { String value(); }
public void test_applying_type_annotations() {
PsiClass cls = myFixture.addClass("""
import java.lang.annotation.*;
class Foo {
@Target(ElementType.TYPE_USE)
@interface TA { String value(); }
private @TA String f1;
private @TA String f1;
private static @TA int m1(@TA int p1) { return 0; }
}
""".stripIndent())
private static @TA int m1(@TA int p1) { return 0; }
}""");
def f1 = cls.fields[0].type
def m1 = cls.methods[0].returnType
def p1 = cls.methods[0].parameterList.parameters[0].type
assert (cls as PsiClassImpl).stub
PsiType f1 = cls.getFields()[0].getType();
PsiType m1 = cls.getMethods()[0].getReturnType();
PsiType p1 = cls.getMethods()[0].getParameterList().getParameters()[0].getType();
assertNotNull(((PsiClassImpl)cls).getStub());
assert f1.getCanonicalText(true) == "java.lang.@Foo.TA String"
assert m1.getCanonicalText(true) == "@Foo.TA int"
assert p1.getCanonicalText(true) == "@Foo.TA int"
assertEquals("java.lang.@Foo.TA String", f1.getCanonicalText(true));
assertEquals("@Foo.TA int", m1.getCanonicalText(true));
assertEquals("@Foo.TA int", p1.getCanonicalText(true));
}
void "test containing class of a local class is null"() {
def foo = myFixture.addClass("""\
class Foo {
static { class Bar extends Foo { } }
}""".stripIndent())
def bar = ClassInheritorsSearch.search(foo).findFirst()
public void test_containing_class_of_a_local_class_is_null() {
PsiClass foo = myFixture.addClass("""
class Foo {
static { class Bar extends Foo { } }
}""");
PsiClass bar = ClassInheritorsSearch.search(foo).findFirst();
def file = (PsiFileImpl)foo.containingFile
assert !file.contentsLoaded
PsiFileImpl file = (PsiFileImpl)foo.getContainingFile();
assertFalse(file.isContentsLoaded());
assert bar.containingClass == null
assert !file.contentsLoaded
assertNull(bar.getContainingClass());
assertFalse(file.isContentsLoaded());
bar.node
assert bar.containingClass == null
assert file.contentsLoaded
assertNotNull(bar.getNode());
assertNull(bar.getContainingClass());
assertTrue(file.isContentsLoaded());
}
void "test stub-based super class type parameter resolve"() {
public void test_stub_based_super_class_type_parameter_resolve() throws ExecutionException, InterruptedException {
for (int i = 0; i < 100; i++) {
def foo = myFixture.addClass("class Foo$i<T> {}")
def bar = myFixture.addClass("class Bar$i<T> extends Foo$i<T> {}")
PsiClass foo = myFixture.addClass("class Foo" + i + "<T> {}");
final PsiClass bar = myFixture.addClass("class Bar" + i + "<T> extends Foo" + i + "<T> {}");
def app = ApplicationManager.application
app.executeOnPooledThread({ ReadAction.compute { bar.node } })
def superType = app.executeOnPooledThread({ ReadAction.compute { bar.superTypes[0] }} as Callable<PsiClassType>).get()
assert foo == superType.resolve()
assert bar.typeParameters[0] == PsiUtil.resolveClassInClassTypeOnly(superType.parameters[0])
Application app = ApplicationManager.getApplication();
app.executeOnPooledThread(() -> ReadAction.compute(() -> bar.getNode()));
PsiClassType superType = app.executeOnPooledThread(() -> ReadAction.compute(() -> bar.getSuperTypes()[0])).get();
assertEquals(foo, superType.resolve());
assertEquals(bar.getTypeParameters()[0], PsiUtil.resolveClassInClassTypeOnly(superType.getParameters()[0]));
}
}
void "test default annotation attribute name"() {
def cls = myFixture.addClass('@Anno("foo") class Foo {}')
def file = (PsiFileImpl)cls.containingFile
assert !file.contentsLoaded
public void test_default_annotation_attribute_name() {
PsiClass cls = myFixture.addClass("@Anno(\"foo\") class Foo {}");
PsiFileImpl file = (PsiFileImpl)cls.getContainingFile();
assertFalse(file.isContentsLoaded());
def attr = cls.modifierList.annotations[0].parameterList.attributes[0]
assert attr.name == null
assert !file.contentsLoaded
PsiNameValuePair attr = cls.getModifierList().getAnnotations()[0].getParameterList().getAttributes()[0];
assertNull(attr.getName());
assertFalse(file.isContentsLoaded());
attr.node
assert attr.name == null
assertNotNull(attr.getNode());
assertNull(attr.getName());
}
void "test determine annotation target without AST"() {
def cls = myFixture.addClass("""\
import java.lang.annotation.*;
@Anno class Some {}
@Target(ElementType.METHOD) @interface Anno {}""".stripIndent())
assert "Some" == cls.name
assert !AnnotationTargetUtil.isTypeAnnotation(cls.modifierList.annotations[0])
assert !((PsiFileImpl) cls.containingFile).contentsLoaded
public void test_determine_annotation_target_without_AST() {
PsiClass cls = myFixture.addClass("""
import java.lang.annotation.*;
@Anno class Some {}
@Target(ElementType.METHOD) @interface Anno {}""");
assertEquals("Some", cls.getName());
assertFalse(AnnotationTargetUtil.isTypeAnnotation(cls.getModifierList().getAnnotations()[0]));
assertFalse(((PsiFileImpl)cls.getContainingFile()).isContentsLoaded());
}
void "test parameter list count"() {
myFixture.addFileToProject("a.java", "class Cls { void foo(a) {} }")
def list = myFixture.findClass("Cls").methods[0].parameterList
assert list.parametersCount == list.parameters.size()
public void test_parameter_list_count() {
myFixture.addFileToProject("a.java", "class Cls { void foo(a) {} }");
PsiParameterList list = myFixture.findClass("Cls").getMethods()[0].getParameterList();
assertEquals(list.getParametersCount(), list.getParameters().length);
}
void "test deprecated enum constant"() {
def cls = myFixture.addClass("enum Foo { c1, @Deprecated c2, /** @deprecated */ c3 }")
assert !((PsiFileImpl) cls.containingFile).contentsLoaded
public void test_deprecated_enum_constant() {
PsiClass cls = myFixture.addClass("enum Foo { c1, @Deprecated c2, /** @deprecated */ c3 }");
assertFalse(((PsiFileImpl)cls.getContainingFile()).isContentsLoaded());
assert !cls.fields[0].deprecated
assert cls.fields[1].deprecated
assert cls.fields[2].deprecated
assertFalse(cls.getFields()[0].isDeprecated());
assertTrue(cls.getFields()[1].isDeprecated());
assertTrue(cls.getFields()[2].isDeprecated());
assert !((PsiFileImpl) cls.containingFile).contentsLoaded
assertFalse(((PsiFileImpl)cls.getContainingFile()).isContentsLoaded());
}
void "test breaking and adding import does not cause stub AST mismatch"() {
def file = myFixture.addFileToProject("a.java", "import foo.*; import bar.*; class Foo {}") as PsiJavaFile
def another = myFixture.addClass("package zoo; public class Another {}")
WriteCommandAction.runWriteCommandAction(project) {
file.viewProvider.document.insertString(file.text.indexOf("import"), "x")
PsiDocumentManager.getInstance(project).commitAllDocuments()
file.importClass(another)
}
PsiTestUtil.checkStubsMatchText(file)
public void test_breaking_and_adding_import_does_not_cause_stub_AST_mismatch() {
PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("a.java", "import foo.*; import bar.*; class Foo {}");
PsiClass another = myFixture.addClass("package zoo; public class Another {}");
WriteCommandAction.runWriteCommandAction(getProject(), (Computable<Boolean>)() -> {
file.getViewProvider().getDocument().insertString(file.getText().indexOf("import"), "x");
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
return file.importClass(another);
});
PsiTestUtil.checkStubsMatchText(file);
}
void "test removing import in broken code does not cause stub AST mismatch"() {
def file = myFixture.addFileToProject("a.java", "import foo..module.SomeClass; class Foo {}") as PsiJavaFile
WriteCommandAction.runWriteCommandAction(project) {
file.importList.importStatements[0].delete()
}
PsiTestUtil.checkStubsMatchText(file)
public void test_removing_import_in_broken_code_does_not_cause_stub_AST_mismatch() {
PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("a.java", "import foo..module.SomeClass; class Foo {}");
WriteCommandAction.runWriteCommandAction(getProject(), () -> file.getImportList().getImportStatements()[0].delete());
PsiTestUtil.checkStubsMatchText(file);
}
void "test adding type before method call does not cause stub AST mismatch"() {
def file = myFixture.addFileToProject("a.java", """\
public void test_adding_type_before_method_call_does_not_cause_stub_AST_mismatch() {
final PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("a.java", """
class Foo {
void foo() {
something();
call();
}
}""".stripIndent()) as PsiJavaFile
WriteCommandAction.runWriteCommandAction(project) {
file.viewProvider.document.insertString(file.text.indexOf("call"), "char ")
PsiDocumentManager.getInstance(project).commitAllDocuments()
PsiTestUtil.checkStubsMatchText(file)
}
}""");
WriteCommandAction.runWriteCommandAction(getProject(), () -> {
file.getViewProvider().getDocument().insertString(file.getText().indexOf("call"), "char ");
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
PsiTestUtil.checkStubsMatchText(file);
});
}
void "test inserting class keyword"() {
String text = "class Foo { void foo() { return; } }"
PsiFile psiFile = myFixture.addFileToProject("a.java", text)
Document document = psiFile.getViewProvider().getDocument()
public void test_inserting_class_keyword() {
final String text = "class Foo { void foo() { return; } }";
PsiFile psiFile = myFixture.addFileToProject("a.java", text);
final Document document = psiFile.getViewProvider().getDocument();
WriteCommandAction.runWriteCommandAction(project) {
document.insertString(text.indexOf("return"), "class ")
}
PsiDocumentManager.getInstance(getProject()).commitAllDocuments()
PsiTestUtil.checkStubsMatchText(psiFile)
WriteCommandAction.runWriteCommandAction(
getProject(), () -> document.insertString(text.indexOf("return"), "class "));
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
PsiTestUtil.checkStubsMatchText(psiFile);
}
void "test inserting enum keyword"() {
String text = "class Foo { void foo() { return; } }"
PsiFile psiFile = myFixture.addFileToProject("a.java", text)
Document document = psiFile.getViewProvider().getDocument()
public void test_inserting_enum_keyword() {
final String text = "class Foo { void foo() { return; } }";
PsiFile psiFile = myFixture.addFileToProject("a.java", text);
final Document document = psiFile.getViewProvider().getDocument();
WriteCommandAction.runWriteCommandAction(project) {
document.insertString(text.indexOf("return"), "enum Foo")
}
PsiDocumentManager.getInstance(getProject()).commitAllDocuments()
PsiTestUtil.checkStubsMatchText(psiFile)
WriteCommandAction.runWriteCommandAction(
getProject(), () -> document.insertString(text.indexOf("return"), "enum Foo"));
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
PsiTestUtil.checkStubsMatchText(psiFile);
}
void "test type arguments without type in a method"() {
String text = "class Foo { { final Collection<String> contexts; f instanceof -> } }"
PsiFile psiFile = myFixture.addFileToProject("a.java", text)
public void test_type_arguments_without_type_in_a_method() {
String text = "class Foo { { final Collection<String> contexts; f instanceof -> } }";
final PsiFile psiFile = myFixture.addFileToProject("a.java", text);
WriteCommandAction.runWriteCommandAction(project) { deleteString(psiFile, "Collection") }
PsiDocumentManager.getInstance(getProject()).commitAllDocuments()
PsiTestUtil.checkStubsMatchText(psiFile)
WriteCommandAction.runWriteCommandAction(getProject(), () -> deleteString(psiFile, "Collection"));
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
PsiTestUtil.checkStubsMatchText(psiFile);
}
private static void deleteString(PsiFile file, String fragment) {
def document = file.viewProvider.document
def index = document.text.indexOf(fragment)
document.deleteString(index, index + fragment.size())
Document document = file.getViewProvider().getDocument();
int index = document.getText().indexOf(fragment);
document.deleteString(index, index + fragment.length());
}
void "test remove class literal qualifier"() {
String text = "class Foo { { foo(String.class); } }"
PsiFile psiFile = myFixture.addFileToProject("a.java", text)
WriteCommandAction.runWriteCommandAction(project) {
psiFile.viewProvider.document.insertString(text.indexOf(");"), " x")
WriteCommandAction.runWriteCommandAction(project) { deleteString(psiFile, "String") }
}
PsiDocumentManager.getInstance(getProject()).commitAllDocuments()
PsiTestUtil.checkStubsMatchText(psiFile)
public void test_remove_class_literal_qualifier() {
final String text = "class Foo { { foo(String.class); } }";
final PsiFile psiFile = myFixture.addFileToProject("a.java", text);
WriteCommandAction.runWriteCommandAction(
getProject(), () -> {
psiFile.getViewProvider().getDocument().insertString(text.indexOf(");"), " x");
WriteCommandAction.runWriteCommandAction(getProject(), () -> deleteString(psiFile, "String"));
});
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
PsiTestUtil.checkStubsMatchText(psiFile);
}
void "test annotation stub without reference"() {
PsiFile psiFile = myFixture.addFileToProject("a.java", "@() class Foo { } }")
assert ((PsiJavaFile) psiFile).classes[0].modifierList.annotations[0].nameReferenceElement == null
assert !((PsiFileImpl) psiFile).contentsLoaded
public void test_annotation_stub_without_reference() {
PsiFile psiFile = myFixture.addFileToProject("a.java", "@() class Foo { } }");
assertNull(((PsiJavaFile)psiFile).getClasses()[0].getModifierList().getAnnotations()[0].getNameReferenceElement());
assertFalse(((PsiFileImpl)psiFile).isContentsLoaded());
}
void "test anonymous class stubs see method type parameters"() {
PsiFileImpl file = (PsiFileImpl) myFixture.addFileToProject("A.java", """\
public void test_anonymous_class_stubs_see_method_type_parameters() {
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("A.java", """
class A {
<V> Object foo() {
return new I<V>(){};
}
}
interface I<T> {}
""".stripIndent())
interface I<T> {}""");
PsiClass a = ((PsiJavaFile) file).classes[0]
PsiClass i = ((PsiJavaFile) file).classes[1]
PsiAnonymousClass anon = assertOneElement(DirectClassInheritorsSearch.search(i).findAll()) as PsiAnonymousClass
PsiClass a = ((PsiJavaFile)file).getClasses()[0];
PsiClass i = ((PsiJavaFile)file).getClasses()[1];
PsiAnonymousClass anon = (PsiAnonymousClass)UsefulTestCase.assertOneElement(DirectClassInheritorsSearch.search(i).findAll());
assert i == anon.baseClassType.resolve()
assert a.methods[0].typeParameters[0] == PsiUtil.resolveClassInClassTypeOnly(anon.baseClassType.parameters[0])
assertEquals(i, anon.getBaseClassType().resolve());
assertEquals(a.getMethods()[0].getTypeParameters()[0], PsiUtil.resolveClassInClassTypeOnly(anon.getBaseClassType().getParameters()[0]));
assert !file.contentsLoaded
assertFalse(file.isContentsLoaded());
}
void "test anonymous class stubs see local classes"() {
PsiFileImpl file = (PsiFileImpl) myFixture.addFileToProject("A.java", """\
public void test_anonymous_class_stubs_see_local_classes() {
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("A.java", """
class A {
void foo() {
class Local {}
new I<Local>(){};
}
}
interface I<T> {}
""".stripIndent())
interface I<T> {}""");
PsiClass i = ((PsiJavaFile) file).classes[1]
PsiAnonymousClass anon = assertOneElement(DirectClassInheritorsSearch.search(i).findAll()) as PsiAnonymousClass
PsiClass i = ((PsiJavaFile)file).getClasses()[1];
PsiAnonymousClass anon = (PsiAnonymousClass)UsefulTestCase.assertOneElement(DirectClassInheritorsSearch.search(i).findAll());
assert !file.contentsLoaded
assertFalse(file.isContentsLoaded());
assert i == anon.baseClassType.resolve()
assert PsiUtil.resolveClassInClassTypeOnly(anon.baseClassType.parameters[0])?.name == "Local"
assertEquals(i, anon.getBaseClassType().resolve());
final PsiClass only = PsiUtil.resolveClassInClassTypeOnly(anon.getBaseClassType().getParameters()[0]);
assertEquals("Local", (only == null ? null : only.getName()));
}
void "test local class stubs see other local classes"() {
PsiFileImpl file = (PsiFileImpl) myFixture.addFileToProject("A.java", """\
public void test_local_class_stubs_see_other_local_classes() {
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("A.java", """
class A {
void foo() {
class Local1 {}
class Local2 extends Local1 {}
}
}
""".stripIndent())
}""");
def cache = PsiShortNamesCache.getInstance(project)
def local1 = cache.getClassesByName("Local1", GlobalSearchScope.allScope(project))[0]
def local2 = cache.getClassesByName("Local2", GlobalSearchScope.allScope(project))[0]
PsiShortNamesCache cache = PsiShortNamesCache.getInstance(getProject());
PsiClass local1 = cache.getClassesByName("Local1", GlobalSearchScope.allScope(getProject()))[0];
PsiClass local2 = cache.getClassesByName("Local2", GlobalSearchScope.allScope(getProject()))[0];
assert !file.contentsLoaded
assertFalse(file.isContentsLoaded());
assert local1 == local2.superClass
assertEquals(local1, local2.getSuperClass());
}
void "test local class stubs do not load AST for inheritance checking when possible"() {
PsiFileImpl file = (PsiFileImpl) myFixture.addFileToProject("A.java", """\
class A {
void foo() {
class UnrelatedLocal {}
class Local extends A {}
}
}
""".stripIndent())
public void test_local_class_stubs_do_not_load_AST_for_inheritance_checking_when_possible() {
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("A.java", """
class A {
void foo() {
class UnrelatedLocal {}
class Local extends A {}
}
}""");
def local = PsiShortNamesCache.getInstance(project).getClassesByName("Local", GlobalSearchScope.allScope(project))[0]
assert "A" == local.superClass.name
assert !file.contentsLoaded
PsiClass local = PsiShortNamesCache.getInstance(getProject()).getClassesByName("Local", GlobalSearchScope.allScope(getProject()))[0];
assertEquals("A", local.getSuperClass().getName());
assertFalse(file.isContentsLoaded());
}
void "test broken anonymous"() {
String text = """\
public void test_broken_anonymous() {
final String text = """
class A {
public GroupDescriptor[] getGroupDescriptors() {
return new ThreadGroup(Descriptor[]{
new GroupDescriptor(groupId, "test")
};
}
}""".stripIndent()
PsiFile psiFile = myFixture.addFileToProject("a.java", text)
WriteCommandAction.runWriteCommandAction(project) {
psiFile.viewProvider.document.insertString(text.indexOf("]{"), "x")
}
PsiDocumentManager.getInstance(getProject()).commitAllDocuments()
PsiTestUtil.checkStubsMatchText(psiFile)
}""";
final PsiFile psiFile = myFixture.addFileToProject("a.java", text);
WriteCommandAction.runWriteCommandAction(
getProject(), () -> psiFile.getViewProvider().getDocument().insertString(text.indexOf("]{"), "x"));
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
PsiTestUtil.checkStubsMatchText(psiFile);
}
void "test broken nested anonymous"() {
PsiTestUtil.checkStubsMatchText(myFixture.addFileToProject("a.java", "class A { { new A(new B[a]{b}); } }"))
public void test_broken_nested_anonymous() {
PsiTestUtil.checkStubsMatchText(myFixture.addFileToProject("a.java", "class A { { new A(new B[a]{b}); } }"));
}
void "test lone angle brackets"() {
String text = """\
public void test_lone_angle_brackets() {
String text = """
class A {
{
PsiLanguageInjectionHost host = PsiTreeUtil.getParentOfType(element, .class);
final <PsiElement, TextRange> pair;
}
}""".stripIndent()
PsiTestUtil.checkStubsMatchText(myFixture.addFileToProject("a.java", text))
}
void "test incomplete static import does not cause CCE"() {
def file = myFixture.addFileToProject("a.java", "import static foo.bar.") as PsiJavaFile
assert ((PsiFileImpl)file).stub
assert file.node
def staticImport = ((PsiJavaFile)file).importList.importStaticStatements[0]
assert staticImport.referenceName == null
assert !staticImport.resolveTargetClass()
}
void "test adding import to broken file with type parameters"() {
def file = myFixture.addFileToProject("a.java", "A<B>") as PsiJavaFile
WriteCommandAction.runWriteCommandAction(project) {
file.importClass(myFixture.findClass(CommonClassNames.JAVA_UTIL_LIST))
}
PsiTestUtil.checkStubsMatchText(file)
}
void "test remove extends reference before dot"() {
def file = myFixture.addFileToProject("a.java", "class A extends B. { int a; }")
WriteCommandAction.runWriteCommandAction(project) {
def javaFile = file as PsiJavaFile
def clazz = (javaFile.classes[0] as PsiImplicitClass).innerClasses[0]
clazz.extendsList.referenceElements[0].delete()
}
PsiTestUtil.checkStubsMatchText(file)
}
void "test remove type argument list after space"() {
def file = myFixture.addFileToProject("a.java", "class A { A <B>a; }")
WriteCommandAction.runWriteCommandAction(project) {
myFixture.findClass("A").fields[0].typeElement.innermostComponentReferenceElement.parameterList.delete()
}
PsiTestUtil.checkStubsMatchText(file)
PsiTestUtil.checkFileStructure(file)
}
void "test remove modifier making a comment a class javadoc"() {
def file = myFixture.addFileToProject("a.java", "import foo; final /** @deprecated */ public class A { }")
WriteCommandAction.runWriteCommandAction(project) {
def clazz = myFixture.findClass("A")
def children = clazz.modifierList.children
assert children.length != 0 : clazz.containingFile.text + ";" + clazz.containingFile.virtualFile.path
children[0].delete()
}
PsiTestUtil.checkFileStructure(file)
PsiTestUtil.checkStubsMatchText(file)
}
void "test add reference into broken extends list"() {
def file = myFixture.addFileToProject("a.java", "class A extends.ends Foo { int a; }")
WriteCommandAction.runWriteCommandAction(project) {
def javaFile = file as PsiJavaFile
def clazz = (javaFile.classes[0] as PsiImplicitClass).innerClasses[0]
clazz.extendsList.add(JavaPsiFacade.getElementFactory(project).createReferenceElementByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, file.resolveScope))
}
PsiTestUtil.checkStubsMatchText(file)
}
void "test identifier dot before class"() {
def file = myFixture.addFileToProject("a.java", "class A {{ public id.class B {}}}")
PsiTestUtil.checkStubsMatchText(file)
}
void "test removing orphan annotation"() {
String text = """\
public class Foo {
public Foo() {
}
@Override
public void initSteps {
}
}""".stripIndent()
PsiFile psiFile = myFixture.addFileToProject("a.java", text)
WriteCommandAction.runWriteCommandAction(project) {
PsiTreeUtil.findChildOfType(psiFile, PsiAnnotation).delete()
}
PsiTestUtil.checkStubsMatchText(psiFile)
}""";
PsiTestUtil.checkStubsMatchText(myFixture.addFileToProject("a.java", text));
}
void "test local record"() {
PsiTestUtil.checkStubsMatchText(myFixture.addFileToProject("a.java", """\
class A {
void test() {
record A(String s) { }
}
}
""".stripIndent()))
public void test_incomplete_static_import_does_not_cause_CCE() {
PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("a.java", "import static foo.bar.");
assertNotNull(((PsiFileImpl)file).getStub());
assertNotNull(file.getNode());
PsiImportStaticStatement staticImport = file.getImportList().getImportStaticStatements()[0];
assertNull(staticImport.getReferenceName());
assertNull(staticImport.resolveTargetClass());
}
void "test field with missing initializer"() {
def file = myFixture.addFileToProject("a.java", "class A { int a = ; } ")
def clazz = myFixture.findClass("A")
assert PsiFieldImpl.getDetachedInitializer(clazz.fields[0]) == null
assert !(file as PsiFileImpl).contentsLoaded
public void test_adding_import_to_broken_file_with_type_parameters() {
final PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("a.java", "A<B>");
WriteCommandAction.runWriteCommandAction(
getProject(), (Computable<Boolean>)() -> file.importClass(myFixture.findClass(CommonClassNames.JAVA_UTIL_LIST)));
PsiTestUtil.checkStubsMatchText(file);
}
void "test implicit class"() {
public void test_remove_extends_reference_before_dot() {
final PsiFile file = myFixture.addFileToProject("a.java", "class A extends B. { int a; }");
WriteCommandAction.runWriteCommandAction(getProject(), () -> {
PsiJavaFile javaFile = (PsiJavaFile)file;
PsiClass clazz = javaFile.getClasses()[0].getInnerClasses()[0];
clazz.getExtendsList().getReferenceElements()[0].delete();
});
PsiTestUtil.checkStubsMatchText(file);
}
def psiFile = myFixture.addFileToProject("a.java", """\
public void test_remove_type_argument_list_after_space() {
PsiFile file = myFixture.addFileToProject("a.java", "class A { A <B>a; }");
WriteCommandAction.runWriteCommandAction(
getProject(),
() -> myFixture.findClass("A").getFields()[0].getTypeElement().getInnermostComponentReferenceElement().getParameterList().delete());
PsiTestUtil.checkStubsMatchText(file);
PsiTestUtil.checkFileStructure(file);
}
public void test_remove_modifier_making_a_comment_a_class_javadoc() {
PsiFile file = myFixture.addFileToProject("a.java", "import foo; final /** @deprecated */ public class A { }");
WriteCommandAction.runWriteCommandAction(getProject(), () -> {
PsiClass clazz = myFixture.findClass("A");
PsiElement[] children = clazz.getModifierList().getChildren();
assertTrue(clazz.getContainingFile().getText() + ";" + clazz.getContainingFile().getVirtualFile().getPath(),
children.length != 0);
children[0].delete();
});
PsiTestUtil.checkFileStructure(file);
PsiTestUtil.checkStubsMatchText(file);
}
public void test_add_reference_into_broken_extends_list() {
final PsiFile file = myFixture.addFileToProject("a.java", "class A extends.ends Foo { int a; }");
WriteCommandAction.runWriteCommandAction(getProject(), (Computable<PsiElement>)() -> {
PsiJavaFile javaFile = (PsiJavaFile)file;
PsiClass clazz = javaFile.getClasses()[0].getInnerClasses()[0];
return clazz.getExtendsList().add(JavaPsiFacade.getElementFactory(getProject())
.createReferenceElementByFQClassName(CommonClassNames.JAVA_LANG_OBJECT,
file.getResolveScope()));
});
PsiTestUtil.checkStubsMatchText(file);
}
public void test_identifier_dot_before_class() {
PsiFile file = myFixture.addFileToProject("a.java", "class A {{ public id.class B {}}}");
PsiTestUtil.checkStubsMatchText(file);
}
public void test_removing_orphan_annotation() {
String text = """
public class Foo {
public Foo() {
}
@Override
public void initSteps {
}
}""";
final PsiFile psiFile = myFixture.addFileToProject("a.java", text);
WriteCommandAction.runWriteCommandAction(getProject(), () -> PsiTreeUtil.findChildOfType(psiFile, PsiAnnotation.class).delete());
PsiTestUtil.checkStubsMatchText(psiFile);
}
public void test_local_record() {
PsiTestUtil.checkStubsMatchText(myFixture.addFileToProject("a.java", """
class A {
void test() {
record A(String s) { }
}
}"""));
}
public void test_field_with_missing_initializer() {
PsiFile file = myFixture.addFileToProject("a.java", "class A { int a = ; } ");
PsiClass clazz = myFixture.findClass("A");
assertNull(PsiFieldImpl.getDetachedInitializer(clazz.getFields()[0]));
assertFalse(((PsiFileImpl)file).isContentsLoaded());
}
public void test_implicit_class() {
PsiFile psiFile = myFixture.addFileToProject("a.java", """
void test() {
}
String s = "foo";
int i = 10;
static {} // not allowed by spec, but we parse
""".stripIndent())
PsiTestUtil.checkStubsMatchText(psiFile)
static {} // not allowed by spec, but we parse""");
PsiTestUtil.checkStubsMatchText(psiFile);
}
void "test array type use annotation stubbing"() {
myFixture.addClass("""\
import java.lang.annotation.*;
@Target(ElementType.TYPE_USE)
@interface Anno { int value(); }""".stripIndent())
public void test_array_type_use_annotation_stubbing() {
myFixture.addClass("""
import java.lang.annotation.*;
@Target(ElementType.TYPE_USE)
@interface Anno { int value(); }""");
PsiClass clazz = myFixture.addClass("""\
class Foo {
<T> @Anno(0) String @Anno(1) [] @Anno(2) [] foo(@Anno(3) byte @Anno(4) [] data) {}
List<String> @Anno(5) [] field;
}""".stripIndent())
PsiClass clazz = myFixture.addClass("""
class Foo {
<T> @Anno(0) String @Anno(1) [] @Anno(2) [] foo(@Anno(3) byte @Anno(4) [] data) {}
List<String> @Anno(5) [] field;
}""");
def method = clazz.methods[0]
def field = clazz.fields[0]
def parameter = method.parameterList.parameters[0]
def parameterAnnotations = parameter.type.annotations
def parameterComponentAnnotations = (parameter.type as PsiArrayType).componentType.annotations
def methodAnnotations = method.returnType.annotations
def methodComponentAnnotations = (method.returnType as PsiArrayType).componentType.annotations
def methodDeepComponentAnnotations = method.returnType.deepComponentType.annotations
def fieldAnnotations = field.type.annotations
PsiMethod method = clazz.getMethods()[0];
PsiField field = clazz.getFields()[0];
PsiParameter parameter = method.getParameterList().getParameters()[0];
PsiAnnotation[] parameterAnnotations = parameter.getType().getAnnotations();
PsiAnnotation[] parameterComponentAnnotations = ((PsiArrayType)parameter.getType()).getComponentType().getAnnotations();
PsiAnnotation[] methodAnnotations = method.getReturnType().getAnnotations();
PsiAnnotation[] methodComponentAnnotations = ((PsiArrayType)method.getReturnType()).getComponentType().getAnnotations();
PsiAnnotation[] methodDeepComponentAnnotations = method.getReturnType().getDeepComponentType().getAnnotations();
PsiAnnotation[] fieldAnnotations = field.getType().getAnnotations();
assert !(clazz.containingFile as PsiFileImpl).contentsLoaded
assertAnnotationValueText methodDeepComponentAnnotations, "0"
assertAnnotationValueText methodAnnotations, "1"
assertAnnotationValueText methodComponentAnnotations, "2"
assertAnnotationValueText parameterComponentAnnotations, "3"
assertAnnotationValueText parameterAnnotations, "4"
assertAnnotationValueText fieldAnnotations, "5"
assert !(clazz.containingFile as PsiFileImpl).contentsLoaded
assertFalse(((PsiFileImpl)clazz.getContainingFile()).isContentsLoaded());
assertAnnotationValueText(methodDeepComponentAnnotations, "0");
assertAnnotationValueText(methodAnnotations, "1");
assertAnnotationValueText(methodComponentAnnotations, "2");
assertAnnotationValueText(parameterComponentAnnotations, "3");
assertAnnotationValueText(parameterAnnotations, "4");
assertAnnotationValueText(fieldAnnotations, "5");
assertFalse(((PsiFileImpl)clazz.getContainingFile()).isContentsLoaded());
assert clazz.node // load AST
assert parameter.type.annotations.size() == 1
assertNotNull(clazz.getNode());// load AST
assertEquals(1, parameter.getType().getAnnotations().length);
}
private static void assertAnnotationValueText(PsiAnnotation[] annotations, String text) {
assert annotations.size() == 1
assert annotations[0].findAttributeValue("value").text == text
assertEquals(1, annotations.length);
assertEquals(annotations[0].findAttributeValue("value").getText(), text);
}
}

View File

@@ -1,334 +1,354 @@
// 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.psi
package com.intellij.java.psi;
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ReadAction
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.psi.*
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes
import com.intellij.psi.impl.source.DummyHolder
import com.intellij.psi.impl.source.PsiClassImpl
import com.intellij.psi.impl.source.PsiFileImpl
import com.intellij.psi.impl.source.PsiJavaFileImpl
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.searches.DirectClassInheritorsSearch
import com.intellij.psi.search.searches.OverridingMethodsSearch
import com.intellij.psi.stubs.StubElement
import com.intellij.psi.stubs.StubTree
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.testFramework.LeakHunter
import com.intellij.testFramework.SkipSlowTestLocally
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase
import com.intellij.util.ref.GCUtil
import com.intellij.util.ref.GCWatcher
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.source.DummyHolder;
import com.intellij.psi.impl.source.PsiClassImpl;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.psi.impl.source.PsiJavaFileImpl;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
import com.intellij.psi.search.searches.OverridingMethodsSearch;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubTree;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.LeakHunter;
import com.intellij.testFramework.SkipSlowTestLocally;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ref.GCUtil;
import com.intellij.util.ref.GCWatcher;
import junit.framework.TestCase;
import one.util.streamex.IntStreamEx;
import java.lang.ref.SoftReference
import java.util.concurrent.Callable
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Future
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.stream.IntStream;
import static org.junit.Assert.assertNotEquals;
@SuppressWarnings("CallToSystemGC")
@SkipSlowTestLocally
class StubAstSwitchTest extends LightJavaCodeInsightFixtureTestCase {
public class StubAstSwitchTest extends LightJavaCodeInsightFixtureTestCase {
public void test_modifying_file_with_stubs_via_VFS() throws IOException {
final PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("Foo.java", "class Foo {}");
assertNotNull(file.getStub());
PsiClass cls = ((PsiJavaFile)file).getClasses()[0];
assertNotNull(file.getStub());
void "test modifying file with stubs via VFS"() {
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject('Foo.java', 'class Foo {}')
assert file.stub
def cls = ((PsiJavaFile)file).classes[0]
assert file.stub
long oldCount = getPsiManager().getModificationTracker().getModificationCount();
def oldCount = psiManager.modificationTracker.modificationCount
WriteAction.run(() -> file.getVirtualFile().setBinaryContent(file.getVirtualFile().contentsToByteArray()));
ApplicationManager.application.runWriteAction { file.virtualFile.setBinaryContent(file.virtualFile.contentsToByteArray()) }
assertTrue(getPsiManager().getModificationTracker().getModificationCount() != oldCount);
assert psiManager.modificationTracker.modificationCount != oldCount
assert !cls.valid
assert file.stub
assert cls != PsiTreeUtil.findElementOfClassAtOffset(file, 1, PsiClass, false)
assert !file.stub
assertFalse(cls.isValid());
assertNotNull(file.getStub());
assertNotEquals(cls, PsiTreeUtil.findElementOfClassAtOffset(file, 1, PsiClass.class, false));
assertNull(file.getStub());
}
void "test reachable psi classes remain valid when nothing changes"() {
int count = 1000
List<SoftReference<PsiClass>> classList = (0..<count).collect { new SoftReference<PsiClass>(myFixture.addClass("class Foo$it {}")) }
System.gc()
System.gc()
System.gc()
assert classList.every {
def cls = it.get()
if (!cls || cls.valid) return true
cls.text //load AST
return cls.valid
}
public void test_reachable_psi_classes_remain_valid_when_nothing_changes() {
int count = 1000;
List<SoftReference<PsiClass>> classList = IntStream.range(0, count)
.mapToObj(n -> new SoftReference<>(myFixture.addClass("class Foo" + n + " {}"))).toList();
System.gc();
System.gc();
System.gc();
assertTrue(ContainerUtil.all(classList, ref -> {
PsiClass cls = ref.get();
if (cls == null || cls.isValid()) return true;
assertNotNull(cls.getText());//load AST
//noinspection ConstantValue
return cls.isValid();
}));
}
void "test traversing PSI and switching concurrently"() {
int count = 100
List<PsiClass> classList = (0..<count).collect {
myFixture.addClass("class Foo$it { " +
"void foo$it(" +
(0..250).collect { "int i$it"}.join(", ") +
") {}" +
" }")
}
CountDownLatch latch = new CountDownLatch(count)
for (c in classList) {
ApplicationManager.application.executeOnPooledThread {
Thread.yield()
ApplicationManager.application.runReadAction {
c.text
}
latch.countDown()
}
for (m in c.methods) {
def parameters = m.parameterList.parameters
for (i in 0..<parameters.size()) {
assert i == m.parameterList.getParameterIndex(parameters[i])
public void test_traversing_PSI_and_switching_concurrently() throws InterruptedException {
int count = 100;
List<PsiClass> classList = IntStream.range(0, count)
.mapToObj(num -> myFixture.addClass(
"class Foo" + num + " {\n" +
"void foo" + num + "(" + IntStreamEx.range(0, 250).mapToObj(parNum -> "int i" + parNum).joining(", ") + ") {}\n" +
"}")).toList();
final CountDownLatch latch = new CountDownLatch(count);
for (PsiClass c : classList) {
ApplicationManager.getApplication().executeOnPooledThread(() -> {
Thread.yield();
ReadAction.compute(() -> c.getText());
latch.countDown();
});
for (PsiMethod m : c.getMethods()) {
PsiParameter[] parameters = m.getParameterList().getParameters();
for (int i = 0; i < parameters.length; i++) {
assertEquals(i, m.getParameterList().getParameterIndex(parameters[i]));
}
}
}
latch.await()
latch.await();
}
void "test smart pointer survives an external modification of a stubbed file"() {
PsiFile file = myFixture.addFileToProject("A.java", "class A {}")
def oldClass = JavaPsiFacade.getInstance(project).findClass("A", GlobalSearchScope.allScope(project))
def pointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(oldClass)
public void test_smart_pointer_survives_an_external_modification_of_a_stubbed_file() throws IOException {
final PsiFile file = myFixture.addFileToProject("A.java", "class A {}");
PsiClass oldClass = JavaPsiFacade.getInstance(getProject()).findClass("A", GlobalSearchScope.allScope(getProject()));
SmartPsiElementPointer<PsiClass> pointer = SmartPointerManager.getInstance(getProject()).createSmartPsiElementPointer(oldClass);
def document = FileDocumentManager.instance.getDocument(file.virtualFile)
assert document
assert file == PsiDocumentManager.getInstance(project).getCachedPsiFile(document)
assert document == PsiDocumentManager.getInstance(project).getCachedDocument(file)
Document document = FileDocumentManager.getInstance().getDocument(file.getVirtualFile());
assertNotNull(document);
assertEquals(file, PsiDocumentManager.getInstance(getProject()).getCachedPsiFile(document));
assertEquals(document, PsiDocumentManager.getInstance(getProject()).getCachedDocument(file));
assert ((PsiFileImpl)file).stub
assertNotNull(((PsiFileImpl)file).getStub());
ApplicationManager.application.runWriteAction { VfsUtil.saveText(file.virtualFile, "import java.util.*; class A {}; class B {}") }
assert pointer.element == oldClass
WriteAction.run(() -> VfsUtil.saveText(file.getVirtualFile(), "import java.util.*; class A {}; class B {}"));
assertEquals(pointer.getElement(), oldClass);
}
void "test do not parse when resolving references inside an anonymous class"() {
PsiFileImpl file = (PsiFileImpl) myFixture.addFileToProject("A.java", """
class A {
Object field = new B() {
void foo(Object o) {
public void test_do_not_parse_when_resolving_references_inside_an_anonymous_class() {
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("A.java", """
class A {
Object field = new B() {
void foo(Object o) {
}
class MyInner extends Inner {}
};
Runnable r = () -> { new B() {}; };
Runnable r2 = (new B(){})::hashCode();
}
class MyInner extends Inner {}
};
Runnable r = () -> { new B() {}; };
Runnable r2 = (new B(){})::hashCode();
}
class B {
void foo(Object o) {}
static class Inner {}
}
""");
assertFalse(file.isContentsLoaded());
PsiClass bClass = ((PsiJavaFile)file).getClasses()[1];
assertEquals(3, DirectClassInheritorsSearch.search(bClass).findAll().size());
assertFalse(file.isContentsLoaded());
class B {
void foo(Object o) {}
static class Inner {}
}
""")
assert !file.contentsLoaded
PsiClass bClass = ((PsiJavaFile) file).classes[1]
assert DirectClassInheritorsSearch.search(bClass).findAll().size() == 3
assert !file.contentsLoaded
PsiMethod fooMethod = bClass.getMethods()[0];
assertFalse(file.isContentsLoaded());
def fooMethod = bClass.methods[0]
assert !file.contentsLoaded
PsiMethod override = OverridingMethodsSearch.search(fooMethod).findFirst();
assertNotNull(override);
assertFalse(file.isContentsLoaded());
def override = OverridingMethodsSearch.search(fooMethod).findAll().first()
assert override
assert !file.contentsLoaded
assertTrue(override.getContainingClass() instanceof PsiAnonymousClass);
assertFalse(file.isContentsLoaded());
assert override.containingClass instanceof PsiAnonymousClass
assert !file.contentsLoaded
assert bClass == override.containingClass.superClass
assert bClass.innerClasses[0] == override.containingClass.innerClasses[0].superClass
assert !file.contentsLoaded
assertEquals(bClass, override.getContainingClass().getSuperClass());
assertEquals(bClass.getInnerClasses()[0], override.getContainingClass().getInnerClasses()[0].getSuperClass());
assertFalse(file.isContentsLoaded());
}
void "test AST can be gc-ed and recreated"() {
def psiClass = myFixture.addClass("class Foo {}")
def file = psiClass.containingFile as PsiFileImpl
assert file.stub
public void test_AST_can_be_gc_ed_and_recreated() {
PsiClass psiClass = myFixture.addClass("class Foo {}");
PsiFileImpl file = (PsiFileImpl)psiClass.getContainingFile();
assertNotNull(file.getStub());
assert psiClass.nameIdentifier
assert !file.stub
assert file.treeElement
assertNotNull(psiClass.getNameIdentifier());
assertNull(file.getStub());
assertNotNull(file.getTreeElement());
GCUtil.tryGcSoftlyReachableObjects()
assert !file.treeElement
assert file.stub
GCUtil.tryGcSoftlyReachableObjects();
assertNull(file.getTreeElement());
assertNotNull(file.getStub());
assert psiClass.nameIdentifier
assert !file.stub
assert file.treeElement
assertNotNull(psiClass.getNameIdentifier());
assertNull(file.getStub());
assertNotNull(file.getTreeElement());
}
void "test no AST loading on file rename"() {
PsiJavaFile file = (PsiJavaFile) myFixture.addFileToProject('a.java', 'class Foo {}')
assert file.classes.length == 1
assert ((PsiFileImpl)file).stub
public void test_no_AST_loading_on_file_rename() {
final PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("a.java", "class Foo {}");
assertEquals(1, file.getClasses().length);
assertNotNull(((PsiFileImpl)file).getStub());
WriteCommandAction.runWriteCommandAction project, { file.setName('b.java') }
assert file.classes.length == 1
assert ((PsiFileImpl)file).stub
WriteCommandAction.runWriteCommandAction(getProject(), (Computable<PsiElement>)() -> file.setName("b.java"));
assertEquals(1, file.getClasses().length);
assertNotNull(((PsiFileImpl)file).getStub());
assert file.classes[0].nameIdentifier.text == 'Foo'
assert ((PsiFileImpl)file).contentsLoaded
assertEquals("Foo", file.getClasses()[0].getNameIdentifier().getText());
assertTrue(((PsiFileImpl)file).isContentsLoaded());
}
void "test use green stub after AST loaded and gc-ed"() {
PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("a.java", "class A{public static void foo() { }}")
//noinspection GroovyUnusedAssignment
StubTree stubHardRef = ((PsiFileImpl)file).stubTree
public void test_use_green_stub_after_AST_loaded_and_gc_ed() {
PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("a.java", "class A{public static void foo() { }}");
assertNotNull(((PsiFileImpl)file).getStubTree());
assert file.classes[0].nameIdentifier
loadAndGcAst(file)
assertNoStubLoaded(file)
assertNotNull(file.getClasses()[0].getNameIdentifier());
loadAndGcAst(file);
assertNoStubLoaded(file);
assert file.classes[0].methods[0].modifierList.hasExplicitModifier(PsiModifier.STATIC)
assert !((PsiFileImpl)file).getTreeElement()
assertTrue(file.getClasses()[0].getMethods()[0].getModifierList().hasExplicitModifier(PsiModifier.STATIC));
assertNull(((PsiFileImpl)file).getTreeElement());
}
void "test use green stub after building it from AST"() {
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("a.java", "class A<T>{}")
PsiClass psiClass = ((PsiJavaFile)file).classes[0]
assert psiClass.nameIdentifier
public void test_use_green_stub_after_building_it_from_AST() {
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("a.java", "class A<T>{}");
PsiClass psiClass = ((PsiJavaFile)file).getClasses()[0];
assertNotNull(psiClass.getNameIdentifier());
loadAndGcAst(file)
loadAndGcAst(file);
assertNoStubLoaded(file)
StubElement hardRefToStub = file.greenStub
assert hardRefToStub
assert hardRefToStub == file.stub
assertNoStubLoaded(file);
StubElement<?> hardRefToStub = file.getGreenStub();
assertNotNull(hardRefToStub);
assertEquals(hardRefToStub, file.getStub());
loadAndGcAst(file)
assert hardRefToStub.is(file.greenStub)
loadAndGcAst(file);
assertSame(hardRefToStub, file.getGreenStub());
assert psiClass.typeParameters.length == 1
assert !file.treeElement
assertEquals(1, psiClass.getTypeParameters().length);
assertNull(file.getTreeElement());
}
private static void loadAndGcAst(PsiFile file) {
GCWatcher.tracking(file.node).ensureCollected()
assert !((PsiFileImpl)file).treeElement
GCWatcher.tracking(file.getNode()).ensureCollected();
assertNull(((PsiFileImpl)file).getTreeElement());
}
private static assertNoStubLoaded(PsiFile file) {
LeakHunter.checkLeak(file, StubTree) { candidate -> candidate.root.psi == file }
private static void assertNoStubLoaded(final PsiFile file) {
LeakHunter.checkLeak(file, StubTree.class, candidate -> candidate.getRoot().getPsi().equals(file));
}
void "test node has same PSI when loaded in green stub presence"() {
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("a.java", "class A<T>{}")
def stubTree = file.stubTree
PsiClass psiClass = ((PsiJavaFile)file).classes[0]
assert psiClass.nameIdentifier
GCUtil.tryGcSoftlyReachableObjects()
public void test_node_has_same_PSI_when_loaded_in_green_stub_presence() {
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("a.java", "class A<T>{}");
StubTree stubTree = file.getStubTree();
PsiClass psiClass = ((PsiJavaFile)file).getClasses()[0];
assertNotNull(psiClass.getNameIdentifier());
GCUtil.tryGcSoftlyReachableObjects();
assert stubTree.is(file.greenStubTree)
assert file.node.lastChildNode.psi.is(psiClass)
assertSame(stubTree, file.getGreenStubTree());
assertSame(file.getNode().getLastChildNode().getPsi(), psiClass);
}
void "test load stub from non-file PSI after AST is unloaded"() {
PsiJavaFileImpl file = (PsiJavaFileImpl)myFixture.addFileToProject("a.java", "class A<T>{}")
def cls = file.classes[0]
assert cls.nameIdentifier
public void test_load_stub_from_non_file_PSI_after_AST_is_unloaded() {
PsiJavaFileImpl file = (PsiJavaFileImpl)myFixture.addFileToProject("a.java", "class A<T>{}");
PsiClass cls = file.getClasses()[0];
assertNotNull(cls.getNameIdentifier());
loadAndGcAst(file)
loadAndGcAst(file);
assert ((PsiClassImpl) cls).stub
assertNotNull(((PsiClassImpl)cls).getStub());
}
void "test load PSI via stub when AST is gc-ed but PSI exists that was loaded via AST but knows its stub index"() {
PsiJavaFileImpl file = (PsiJavaFileImpl)myFixture.addFileToProject("a.java", "class A{}")
def cls = file.lastChild
assert cls instanceof PsiClass
public void test_load_PSI_via_stub_when_AST_is_gc_ed_but_PSI_exists_that_was_loaded_via_AST_but_knows_its_stub_index() {
PsiJavaFileImpl file = (PsiJavaFileImpl)myFixture.addFileToProject("a.java", "class A{}");
PsiElement cls = file.getLastChild();
assertTrue(cls instanceof PsiClass);
GCUtil.tryGcSoftlyReachableObjects()
assert file.treeElement // we still hold a strong reference to AST
GCUtil.tryGcSoftlyReachableObjects();
assertNotNull(file.getTreeElement());// we still hold a strong reference to AST
assertEquals(cls, myFixture.findClass("A"));
assert cls == myFixture.findClass('A')
// now we know stub index and can GC AST
GCUtil.tryGcSoftlyReachableObjects()
assert !file.treeElement
assert cls == myFixture.findClass('A')
assert !file.treeElement
GCUtil.tryGcSoftlyReachableObjects();
assertNull(file.getTreeElement());
assertEquals(cls, myFixture.findClass("A"));
assertNull(file.getTreeElement());
}
void "test bind stubs to AST after AST has been loaded and gc-ed"() {
PsiJavaFileImpl file = (PsiJavaFileImpl)myFixture.addFileToProject("a.java", "class A{}")
loadAndGcAst(file)
public void test_bind_stubs_to_AST_after_AST_has_been_loaded_and_gc_ed() {
PsiJavaFileImpl file = (PsiJavaFileImpl)myFixture.addFileToProject("a.java", "class A{}");
loadAndGcAst(file);
def cls1 = file.classes[0]
def cls2 = file.lastChild
assert cls1 == cls2
PsiClass cls1 = file.getClasses()[0];
PsiElement cls2 = file.getLastChild();
assertEquals(cls1, cls2);
}
void "test concurrent stub and AST reloading"() {
def fileNumbers = 0..<3
List<PsiJavaFileImpl> files = fileNumbers.collect {
(PsiJavaFileImpl)myFixture.addFileToProject("a${it}.java", "import foo.bar; class A{}")
}
for (iteration in 0..<3) {
GCWatcher.tracking(files.collect { it.node }).ensureCollected()
files.each { assert !it.treeElement }
List<Future<PsiImportList>> stubFutures = []
List<Future<PsiImportList>> astFutures = []
for (i in fileNumbers) {
def file = files[i]
stubFutures << ApplicationManager.application.executeOnPooledThread({ ReadAction.compute {
file.importList
} } as Callable)
astFutures << ApplicationManager.application.executeOnPooledThread({ ReadAction.compute {
PsiTreeUtil.findElementOfClassAtOffset(file, 0, PsiImportList, false)
} } as Callable)
public void test_concurrent_stub_and_AST_reloading() throws ExecutionException, InterruptedException {
int maxFile = 3;
final List<PsiJavaFileImpl> files = IntStream.range(0, maxFile).mapToObj(
num -> (PsiJavaFileImpl)myFixture.addFileToProject("a" + num + ".java", "import foo.bar; class A{}"))
.toList();
for (int iteration = 0; iteration <= 3; iteration++) {
GCWatcher.tracking(ContainerUtil.map(files, PsiFileImpl::getNode)).ensureCollected();
for (PsiJavaFileImpl file : files) {
assertNull(file.getTreeElement());
}
GCUtil.tryGcSoftlyReachableObjects()
for (i in fileNumbers) {
def stubImport = stubFutures[i].get()
def astImport = astFutures[i].get()
if (stubImport != astImport) {
fail("Different import psi in ${files[i].name}: stub=$stubImport, ast=$astImport")
List<Future<PsiImportList>> stubFutures = new ArrayList<>();
List<Future<PsiImportList>> astFutures = new ArrayList<>();
for (int i = 0; i < 3; i++) {
final PsiJavaFileImpl file = files.get(i);
stubFutures.add(ApplicationManager.getApplication()
.executeOnPooledThread(() -> ReadAction.compute(() -> file.getImportList())));
astFutures.add(ApplicationManager.getApplication()
.executeOnPooledThread(
() -> ReadAction.compute(() -> PsiTreeUtil.findElementOfClassAtOffset(file, 0, PsiImportList.class, false))));
}
GCUtil.tryGcSoftlyReachableObjects();
for (int i = 0; i < maxFile; i++) {
PsiImportList stubImport = stubFutures.get(i).get();
PsiImportList astImport = astFutures.get(i).get();
if (!stubImport.equals(astImport)) {
TestCase.fail("Different import psi in " +
files.get(i).getName() +
": stub=" +
stubImport +
", ast=" +
astImport);
}
}
}
}
void "test DummyHolder calcStubTree does not fail"() {
def text = "{ new Runnable() { public void run() {} }; }"
def file = JavaPsiFacade.getElementFactory(project).createCodeBlockFromText(text, null).containingFile
public void test_DummyHolder_calcStubTree_does_not_fail() {
String text = "{ new Runnable() { public void run() {} }; }";
PsiFile file = JavaPsiFacade.getElementFactory(getProject()).createCodeBlockFromText(text, null).getContainingFile();
// main thing is it doesn't fail; DummyHolder.calcStubTree can be changed to null in future if we decide we don't need it
def stubTree = assertInstanceOf(file, DummyHolder).calcStubTree()
// The main thing is it doesn't fail; DummyHolder.calcStubTree can be changed to null in future if we decide we don't need it
StubTree stubTree = UsefulTestCase.assertInstanceOf(file, DummyHolder.class).calcStubTree();
assert stubTree.plainList.find { it.stubType == JavaStubElementTypes.ANONYMOUS_CLASS }
assertTrue(ContainerUtil.exists(stubTree.getPlainList(),
it -> JavaStubElementTypes.ANONYMOUS_CLASS.equals(it.getStubType())));
}
void "test stub index is cleared on AST change"() {
def clazz = myFixture.addClass("class Foo { int a; }")
def field = clazz.fields[0]
def file = clazz.containingFile as PsiFileImpl
WriteCommandAction.runWriteCommandAction(project, {
file.viewProvider.document.insertString(0, ' ')
PsiDocumentManager.getInstance(project).commitAllDocuments()
})
assert file.calcStubTree()
public void test_stub_index_is_cleared_on_AST_change() {
PsiClass clazz = myFixture.addClass("class Foo { int a; }");
PsiField field = clazz.getFields()[0];
final PsiFileImpl file = (PsiFileImpl)clazz.getContainingFile();
WriteCommandAction.runWriteCommandAction(getProject(), () -> {
file.getViewProvider().getDocument().insertString(0, " ");
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
});
WriteCommandAction.runWriteCommandAction(project, {
file.viewProvider.document.insertString(file.text.indexOf('int'), 'void foo();')
PsiDocumentManager.getInstance(project).commitAllDocuments()
})
GCUtil.tryGcSoftlyReachableObjects()
assertNotNull(file.calcStubTree());
assert file.calcStubTree()
assert field.valid
assert field.name == 'a'
WriteCommandAction.runWriteCommandAction(getProject(), () -> {
file.getViewProvider().getDocument().insertString(file.getText().indexOf("int"), "void foo();");
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
});
GCUtil.tryGcSoftlyReachableObjects();
assertNotNull(file.calcStubTree());
assertTrue(field.isValid());
assertEquals("a", field.getName());
}
}

View File

@@ -1,3 +1,4 @@
// 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.refactoring;
import com.intellij.codeInsight.TargetElementUtil;

View File

@@ -1,3 +1,4 @@
// 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.run;
import com.intellij.application.options.PathMacrosCollector;

View File

@@ -1,3 +1,4 @@
// 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.psi.impl.source.tree.java;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;

View File

@@ -1,3 +1,4 @@
// 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.unscramble;
import junit.framework.TestCase;

View File

@@ -1,3 +1,4 @@
// 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.unscramble;
import com.intellij.testFramework.PlatformTestUtil;