mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 14:23:28 +07:00
[java-tests] Convert Groovy to Java; restore copyrights
GitOrigin-RevId: 2c1ab0479b2f26bc51926f0a78663436b9bf5852
This commit is contained in:
committed by
intellij-monorepo-bot
parent
4942586999
commit
b4d12c1883
@@ -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.
|
// 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.command.WriteCommandAction
|
import com.intellij.openapi.command.WriteCommandAction;
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*;
|
||||||
import com.intellij.psi.impl.source.PsiClassReferenceType
|
import com.intellij.psi.impl.source.PsiClassReferenceType;
|
||||||
import com.intellij.psi.impl.source.PsiFileImpl
|
import com.intellij.psi.impl.source.PsiFileImpl;
|
||||||
import com.intellij.psi.impl.source.tree.java.JavaFileElement
|
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.MethodElement;
|
||||||
import com.intellij.psi.impl.source.tree.java.ParameterElement
|
import com.intellij.psi.impl.source.tree.java.ParameterElement;
|
||||||
import com.intellij.testFramework.LeakHunter
|
import com.intellij.testFramework.LeakHunter;
|
||||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase
|
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
|
||||||
import com.intellij.util.ref.GCWatcher
|
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 {
|
WriteCommandAction.runWriteCommandAction(getProject(), () -> {
|
||||||
|
file.getViewProvider().getDocument().insertString(0, " ");
|
||||||
void "test AST should be on a soft reference, for changed files as well"() {
|
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||||
def file = myFixture.addClass('class Foo {}').containingFile
|
});
|
||||||
assert file.findElementAt(0) instanceof PsiKeyword
|
assertTrue(file.findElementAt(0) instanceof PsiWhiteSpace);
|
||||||
LeakHunter.checkLeak(file, JavaFileElement) { e -> e.psi == file }
|
LeakHunter.checkLeak(file, JavaFileElement.class, e -> e.getPsi().equals(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 }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test super methods held via their signatures in class user data"() {
|
public void test_super_methods_held_via_their_signatures_in_class_user_data() {
|
||||||
def superClass = myFixture.addClass('class Super { void foo() {} }')
|
final PsiClass superClass = myFixture.addClass("class Super { void foo() {} }");
|
||||||
superClass.text // load AST
|
assertNotNull(superClass.getText()); // load AST
|
||||||
|
|
||||||
def file = myFixture.addFileToProject('Main.java', 'class Main extends Super { void foo() { System.out.println("hello"); } }')
|
PsiFile file = myFixture.addFileToProject("Main.java", "class Main extends Super { void foo() { System.out.println(\"hello\"); } }");
|
||||||
myFixture.configureFromExistingVirtualFile(file.virtualFile)
|
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
|
||||||
myFixture.doHighlighting()
|
myFixture.doHighlighting();
|
||||||
|
|
||||||
def mainClass = ((PsiJavaFile)file).classes[0]
|
PsiClass mainClass = ((PsiJavaFile)file).getClasses()[0];
|
||||||
LeakHunter.checkLeak(mainClass, MethodElement) { MethodElement node ->
|
LeakHunter.checkLeak(mainClass, MethodElement.class, node -> superClass.equals(node.getPsi().getParent()));
|
||||||
superClass == node.psi.parent
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test no hard refs to AST after highlighting"() {
|
public void test_no_hard_refs_to_AST_after_highlighting() {
|
||||||
def sup = myFixture.addFileToProject('sup.java', 'class Super { Super() {} }')
|
final PsiFile sup = myFixture.addFileToProject("sup.java", "class Super { Super() {} }");
|
||||||
assert sup.findElementAt(0) // load AST
|
assertNotNull(sup.findElementAt(0));// load AST
|
||||||
assert !((PsiFileImpl)sup).stub
|
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(); } }')
|
final PsiFile foo = myFixture.addFileToProject("a.java", "class Foo extends Super { void bar() { bar(); } }");
|
||||||
myFixture.configureFromExistingVirtualFile(foo.virtualFile)
|
myFixture.configureFromExistingVirtualFile(foo.getVirtualFile());
|
||||||
myFixture.doHighlighting()
|
myFixture.doHighlighting();
|
||||||
|
|
||||||
assert !((PsiFileImpl)foo).stub
|
assertNull(((PsiFileImpl)foo).getStub());
|
||||||
assert ((PsiFileImpl)foo).treeElement
|
assertNotNull(((PsiFileImpl)foo).getTreeElement());
|
||||||
|
|
||||||
LeakHunter.checkLeak(foo, MethodElement, { it.psi.containingFile == foo })
|
LeakHunter.checkLeak(foo, MethodElement.class, it -> it.getPsi().getContainingFile().equals(foo));
|
||||||
LeakHunter.checkLeak(sup, MethodElement, { it.psi.containingFile == sup })
|
LeakHunter.checkLeak(sup, MethodElement.class, it -> it.getPsi().getContainingFile().equals(sup));
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test no hard refs to AST via class reference type"() {
|
public void test_no_hard_refs_to_AST_via_class_reference_type() {
|
||||||
def cls = myFixture.addClass("class Foo { Object bar() {} }")
|
final PsiClass cls = myFixture.addClass("class Foo { Object bar() {} }");
|
||||||
def file = cls.containingFile as PsiFileImpl
|
PsiFileImpl file = (PsiFileImpl)cls.getContainingFile();
|
||||||
cls.node
|
assertNotNull(cls.getNode());
|
||||||
def type = cls.methods[0].returnType
|
PsiType type = cls.getMethods()[0].getReturnType();
|
||||||
assert type instanceof PsiClassReferenceType
|
assertTrue(type instanceof PsiClassReferenceType);
|
||||||
|
|
||||||
LeakHunter.checkLeak(type, MethodElement, { MethodElement node ->
|
LeakHunter.checkLeak(type, MethodElement.class, node -> node.getPsi().equals(cls.getMethods()[0]));
|
||||||
node.psi == cls.methods[0]
|
|
||||||
})
|
|
||||||
|
|
||||||
GCWatcher.tracking(cls.node).ensureCollected()
|
GCWatcher.tracking(cls.getNode()).ensureCollected();
|
||||||
assert !file.contentsLoaded
|
assertFalse(file.isContentsLoaded());
|
||||||
|
|
||||||
assert type.equalsToText(Object.name)
|
assertTrue(type.equalsToText(Object.class.getName()));
|
||||||
assert !file.contentsLoaded
|
assertFalse(file.isContentsLoaded());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings('CStyleArrayDeclaration')
|
@SuppressWarnings("CStyleArrayDeclaration")
|
||||||
void "test no hard refs to AST via class reference type of c-style array"() {
|
public 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[]) {} }")
|
final PsiClass cls = myFixture.addClass("class Foo { static void main(String args[]) {} }");
|
||||||
def file = cls.containingFile as PsiFileImpl
|
PsiFileImpl file = (PsiFileImpl)cls.getContainingFile();
|
||||||
cls.node
|
assertNotNull(cls.getNode());
|
||||||
def type = cls.methods[0].parameterList.parameters[0].typeElement.type
|
PsiType type = cls.getMethods()[0].getParameterList().getParameters()[0].getTypeElement().getType();
|
||||||
assert type instanceof PsiClassReferenceType
|
assertTrue(type instanceof PsiClassReferenceType);
|
||||||
|
|
||||||
LeakHunter.checkLeak(type, ParameterElement, { ParameterElement node ->
|
LeakHunter.checkLeak(type, ParameterElement.class,
|
||||||
node.psi == cls.methods[0].parameterList.parameters[0]
|
node -> node.getPsi().equals(cls.getMethods()[0].getParameterList().getParameters()[0]));
|
||||||
})
|
|
||||||
|
|
||||||
GCWatcher.tracking(cls.node).ensureCollected()
|
GCWatcher.tracking(cls.getNode()).ensureCollected();
|
||||||
assert !file.contentsLoaded
|
assertFalse(file.isContentsLoaded());
|
||||||
|
|
||||||
assert type.equalsToText(String.name)
|
assertTrue(type.equalsToText(String.class.getName()));
|
||||||
assert !file.contentsLoaded
|
assertFalse(file.isContentsLoaded());
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test no hard refs to AST via array component type"() {
|
public void test_no_hard_refs_to_AST_via_array_component_type() {
|
||||||
def cls = myFixture.addClass("class Foo { Object[] bar() {} }")
|
final PsiClass cls = myFixture.addClass("class Foo { Object[] bar() {} }");
|
||||||
def file = cls.containingFile as PsiFileImpl
|
PsiFileImpl file = (PsiFileImpl)cls.getContainingFile();
|
||||||
cls.node
|
assertNotNull(cls.getNode());
|
||||||
def type = cls.methods[0].returnType
|
PsiType type = cls.getMethods()[0].getReturnType();
|
||||||
assert type instanceof PsiArrayType
|
assertTrue(type instanceof PsiArrayType);
|
||||||
def componentType = type.getComponentType()
|
PsiType componentType = ((PsiArrayType)type).getComponentType();
|
||||||
assert componentType instanceof PsiClassReferenceType
|
assertTrue(componentType instanceof PsiClassReferenceType);
|
||||||
|
|
||||||
LeakHunter.checkLeak(type, MethodElement, { MethodElement node ->
|
LeakHunter.checkLeak(type, MethodElement.class, node -> node.getPsi().equals(cls.getMethods()[0]));
|
||||||
node.psi == cls.methods[0]
|
|
||||||
})
|
|
||||||
|
|
||||||
GCWatcher.tracking(cls.node).ensureCollected()
|
GCWatcher.tracking(cls.getNode()).ensureCollected();
|
||||||
assert !file.contentsLoaded
|
assertFalse(file.isContentsLoaded());
|
||||||
|
|
||||||
assert componentType.equalsToText(Object.name)
|
assertTrue(componentType.equalsToText(Object.class.getName()));
|
||||||
assert !file.contentsLoaded
|
assertFalse(file.isContentsLoaded());
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test no hard refs to AST via generic component type"() {
|
public void test_no_hard_refs_to_AST_via_generic_component_type() {
|
||||||
def cls = myFixture.addClass("class Foo { java.util.Map<String[], ? extends CharSequence> bar() {} }")
|
final PsiClass cls = myFixture.addClass("class Foo { java.util.Map<String[], ? extends CharSequence> bar() {} }");
|
||||||
def file = cls.containingFile as PsiFileImpl
|
PsiFileImpl file = (PsiFileImpl)cls.getContainingFile();
|
||||||
cls.node
|
assertNotNull(cls.getNode());
|
||||||
def type = cls.methods[0].returnType
|
PsiType type = cls.getMethods()[0].getReturnType();
|
||||||
assert type instanceof PsiClassReferenceType
|
assertTrue(type instanceof PsiClassReferenceType);
|
||||||
def parameters = (type as PsiClassReferenceType).getParameters()
|
PsiType[] parameters = ((PsiClassReferenceType)type).getParameters();
|
||||||
assert parameters.length == 2
|
assertEquals(2, parameters.length);
|
||||||
assert parameters[0] instanceof PsiArrayType
|
assertTrue(parameters[0] instanceof PsiArrayType);
|
||||||
def componentType = parameters[0].getDeepComponentType()
|
PsiType componentType = parameters[0].getDeepComponentType();
|
||||||
assert componentType instanceof PsiClassReferenceType
|
assertTrue(componentType instanceof PsiClassReferenceType);
|
||||||
assert parameters[1] instanceof PsiWildcardType
|
assertTrue(parameters[1] instanceof PsiWildcardType);
|
||||||
def bound = (parameters[1] as PsiWildcardType).getExtendsBound()
|
PsiType bound = ((PsiWildcardType)parameters[1]).getExtendsBound();
|
||||||
assert bound instanceof PsiClassReferenceType
|
assertTrue(bound instanceof PsiClassReferenceType);
|
||||||
|
|
||||||
LeakHunter.checkLeak(type, MethodElement, { MethodElement node ->
|
LeakHunter.checkLeak(type, MethodElement.class, node -> node.getPsi().equals(cls.getMethods()[0]));
|
||||||
node.psi == cls.methods[0]
|
|
||||||
})
|
|
||||||
|
|
||||||
GCWatcher.tracking(cls.node).ensureCollected()
|
GCWatcher.tracking(cls.getNode()).ensureCollected();
|
||||||
assert !file.contentsLoaded
|
assertFalse(file.isContentsLoaded());
|
||||||
|
|
||||||
assert componentType.equalsToText(String.name)
|
assertTrue(componentType.equalsToText(String.class.getName()));
|
||||||
assert bound.equalsToText(CharSequence.name)
|
assertTrue(bound.equalsToText(CharSequence.class.getName()));
|
||||||
assert !file.contentsLoaded
|
assertFalse(file.isContentsLoaded());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
// 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.codeInsight.AnnotationTargetUtil
|
import com.intellij.codeInsight.AnnotationTargetUtil;
|
||||||
import com.intellij.codeInspection.dataFlow.JavaMethodContractUtil
|
import com.intellij.codeInspection.dataFlow.JavaMethodContractUtil;
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.application.Application;
|
||||||
import com.intellij.openapi.application.ReadAction
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
import com.intellij.openapi.command.WriteCommandAction
|
import com.intellij.openapi.application.ReadAction;
|
||||||
import com.intellij.openapi.editor.Document
|
import com.intellij.openapi.command.WriteCommandAction;
|
||||||
import com.intellij.psi.*
|
import com.intellij.openapi.editor.Document;
|
||||||
import com.intellij.psi.impl.source.PsiClassImpl
|
import com.intellij.openapi.util.Computable;
|
||||||
import com.intellij.psi.impl.source.PsiFieldImpl
|
import com.intellij.psi.*;
|
||||||
import com.intellij.psi.impl.source.PsiFileImpl
|
import com.intellij.psi.impl.source.PsiClassImpl;
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.impl.source.PsiFieldImpl;
|
||||||
import com.intellij.psi.search.PsiShortNamesCache
|
import com.intellij.psi.impl.source.PsiFileImpl;
|
||||||
import com.intellij.psi.search.searches.AnnotatedElementsSearch
|
import com.intellij.psi.search.GlobalSearchScope;
|
||||||
import com.intellij.psi.search.searches.ClassInheritorsSearch
|
import com.intellij.psi.search.PsiShortNamesCache;
|
||||||
import com.intellij.psi.search.searches.DirectClassInheritorsSearch
|
import com.intellij.psi.search.searches.AnnotatedElementsSearch;
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||||
import com.intellij.psi.util.PsiUtil
|
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
|
||||||
import com.intellij.testFramework.PsiTestUtil
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase
|
import com.intellij.psi.util.PsiUtil;
|
||||||
import groovy.transform.CompileStatic
|
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
|
public class JavaStubsTest extends LightJavaCodeInsightFixtureTestCase {
|
||||||
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"() {
|
PsiFileImpl file = (PsiFileImpl)cls.getContainingFile();
|
||||||
def cls = myFixture.addClass("""\
|
assertNotNull(file.getStub());
|
||||||
public @interface BrokenAnnotation {
|
|
||||||
enum Foo {DEFAULT, OTHER}
|
|
||||||
Foo value() default Foo.DEFAULT;
|
|
||||||
}
|
|
||||||
""".stripIndent())
|
|
||||||
|
|
||||||
def file = cls.containingFile as PsiFileImpl
|
PsiAnnotationMemberValue ref = (((PsiAnnotationMethod)cls.getMethods()[0])).getDefaultValue();
|
||||||
assert file.stub
|
assertNotNull(file.getStub());
|
||||||
|
|
||||||
def ref = (cls.methods[0] as PsiAnnotationMethod).defaultValue
|
assertTrue(ref instanceof PsiReferenceExpression);
|
||||||
assert file.stub
|
assertEquals(((PsiReferenceExpression)ref).resolve(), cls.getInnerClasses()[0].getFields()[0]);
|
||||||
|
assertNotNull(file.getStub());
|
||||||
assert ref instanceof PsiReferenceExpression
|
|
||||||
assert ref.resolve() == cls.innerClasses[0].fields[0]
|
|
||||||
assert file.stub
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test literal annotation value"() {
|
public void test_literal_annotation_value() {
|
||||||
def cls = myFixture.addClass("""\
|
PsiClass cls = myFixture.addClass("""
|
||||||
class Foo {
|
class Foo {
|
||||||
@org.jetbrains.annotations.Contract(pure=true)
|
@org.jetbrains.annotations.Contract(pure=true)
|
||||||
native int foo();
|
native int foo();
|
||||||
}
|
}""");
|
||||||
""".stripIndent())
|
|
||||||
|
|
||||||
def file = cls.containingFile as PsiFileImpl
|
PsiFileImpl file = (PsiFileImpl)cls.getContainingFile();
|
||||||
assert JavaMethodContractUtil.isPure(cls.methods[0])
|
assertTrue(JavaMethodContractUtil.isPure(cls.getMethods()[0]));
|
||||||
assert file.stub
|
assertNotNull(file.getStub());
|
||||||
assert !file.contentsLoaded
|
assertFalse(file.isContentsLoaded());
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test local variable annotation doesn't cause stub-ast switch"() {
|
public void test_local_variable_annotation_doesn_t_cause_stub_ast_switch() {
|
||||||
def cls = myFixture.addClass("""
|
PsiClass cls = myFixture.addClass("""
|
||||||
class Foo {
|
class Foo {
|
||||||
@Anno int foo() {
|
@Anno int foo() {
|
||||||
@Anno int var = 2;
|
@Anno int var = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@interface Anno {}
|
@interface Anno {}""");
|
||||||
""")
|
|
||||||
|
|
||||||
def file = cls.containingFile as PsiFileImpl
|
PsiFileImpl file = (PsiFileImpl)cls.getContainingFile();
|
||||||
assert AnnotatedElementsSearch.searchPsiMethods(myFixture.findClass("Anno"), GlobalSearchScope.allScope(project)).size() == 1
|
assertEquals(1, AnnotatedElementsSearch.searchPsiMethods(myFixture.findClass("Anno"), GlobalSearchScope.allScope(getProject()))
|
||||||
assert file.stub
|
.findAll().size());
|
||||||
assert !file.contentsLoaded
|
assertNotNull(file.getStub());
|
||||||
|
assertFalse(file.isContentsLoaded());
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test applying type annotations"() {
|
public void test_applying_type_annotations() {
|
||||||
def cls = myFixture.addClass("""\
|
PsiClass cls = myFixture.addClass("""
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
class Foo {
|
class Foo {
|
||||||
@Target(ElementType.TYPE_USE)
|
@Target(ElementType.TYPE_USE)
|
||||||
@interface TA { String value(); }
|
@interface TA { String value(); }
|
||||||
|
|
||||||
private @TA String f1;
|
private @TA String f1;
|
||||||
|
|
||||||
private static @TA int m1(@TA int p1) { return 0; }
|
private static @TA int m1(@TA int p1) { return 0; }
|
||||||
}
|
}""");
|
||||||
""".stripIndent())
|
|
||||||
|
|
||||||
def f1 = cls.fields[0].type
|
PsiType f1 = cls.getFields()[0].getType();
|
||||||
def m1 = cls.methods[0].returnType
|
PsiType m1 = cls.getMethods()[0].getReturnType();
|
||||||
def p1 = cls.methods[0].parameterList.parameters[0].type
|
PsiType p1 = cls.getMethods()[0].getParameterList().getParameters()[0].getType();
|
||||||
assert (cls as PsiClassImpl).stub
|
assertNotNull(((PsiClassImpl)cls).getStub());
|
||||||
|
|
||||||
assert f1.getCanonicalText(true) == "java.lang.@Foo.TA String"
|
assertEquals("java.lang.@Foo.TA String", f1.getCanonicalText(true));
|
||||||
assert m1.getCanonicalText(true) == "@Foo.TA int"
|
assertEquals("@Foo.TA int", m1.getCanonicalText(true));
|
||||||
assert p1.getCanonicalText(true) == "@Foo.TA int"
|
assertEquals("@Foo.TA int", p1.getCanonicalText(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test containing class of a local class is null"() {
|
public void test_containing_class_of_a_local_class_is_null() {
|
||||||
def foo = myFixture.addClass("""\
|
PsiClass foo = myFixture.addClass("""
|
||||||
class Foo {
|
class Foo {
|
||||||
static { class Bar extends Foo { } }
|
static { class Bar extends Foo { } }
|
||||||
}""".stripIndent())
|
}""");
|
||||||
def bar = ClassInheritorsSearch.search(foo).findFirst()
|
PsiClass bar = ClassInheritorsSearch.search(foo).findFirst();
|
||||||
|
|
||||||
def file = (PsiFileImpl)foo.containingFile
|
PsiFileImpl file = (PsiFileImpl)foo.getContainingFile();
|
||||||
assert !file.contentsLoaded
|
assertFalse(file.isContentsLoaded());
|
||||||
|
|
||||||
assert bar.containingClass == null
|
assertNull(bar.getContainingClass());
|
||||||
assert !file.contentsLoaded
|
assertFalse(file.isContentsLoaded());
|
||||||
|
|
||||||
bar.node
|
assertNotNull(bar.getNode());
|
||||||
assert bar.containingClass == null
|
assertNull(bar.getContainingClass());
|
||||||
assert file.contentsLoaded
|
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++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
def foo = myFixture.addClass("class Foo$i<T> {}")
|
PsiClass foo = myFixture.addClass("class Foo" + i + "<T> {}");
|
||||||
def bar = myFixture.addClass("class Bar$i<T> extends Foo$i<T> {}")
|
final PsiClass bar = myFixture.addClass("class Bar" + i + "<T> extends Foo" + i + "<T> {}");
|
||||||
|
|
||||||
def app = ApplicationManager.application
|
Application app = ApplicationManager.getApplication();
|
||||||
app.executeOnPooledThread({ ReadAction.compute { bar.node } })
|
app.executeOnPooledThread(() -> ReadAction.compute(() -> bar.getNode()));
|
||||||
def superType = app.executeOnPooledThread({ ReadAction.compute { bar.superTypes[0] }} as Callable<PsiClassType>).get()
|
PsiClassType superType = app.executeOnPooledThread(() -> ReadAction.compute(() -> bar.getSuperTypes()[0])).get();
|
||||||
assert foo == superType.resolve()
|
assertEquals(foo, superType.resolve());
|
||||||
assert bar.typeParameters[0] == PsiUtil.resolveClassInClassTypeOnly(superType.parameters[0])
|
assertEquals(bar.getTypeParameters()[0], PsiUtil.resolveClassInClassTypeOnly(superType.getParameters()[0]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test default annotation attribute name"() {
|
public void test_default_annotation_attribute_name() {
|
||||||
def cls = myFixture.addClass('@Anno("foo") class Foo {}')
|
PsiClass cls = myFixture.addClass("@Anno(\"foo\") class Foo {}");
|
||||||
def file = (PsiFileImpl)cls.containingFile
|
PsiFileImpl file = (PsiFileImpl)cls.getContainingFile();
|
||||||
assert !file.contentsLoaded
|
assertFalse(file.isContentsLoaded());
|
||||||
|
|
||||||
def attr = cls.modifierList.annotations[0].parameterList.attributes[0]
|
PsiNameValuePair attr = cls.getModifierList().getAnnotations()[0].getParameterList().getAttributes()[0];
|
||||||
assert attr.name == null
|
assertNull(attr.getName());
|
||||||
assert !file.contentsLoaded
|
assertFalse(file.isContentsLoaded());
|
||||||
|
|
||||||
attr.node
|
assertNotNull(attr.getNode());
|
||||||
assert attr.name == null
|
assertNull(attr.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test determine annotation target without AST"() {
|
public void test_determine_annotation_target_without_AST() {
|
||||||
def cls = myFixture.addClass("""\
|
PsiClass cls = myFixture.addClass("""
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
@Anno class Some {}
|
@Anno class Some {}
|
||||||
@Target(ElementType.METHOD) @interface Anno {}""".stripIndent())
|
@Target(ElementType.METHOD) @interface Anno {}""");
|
||||||
assert "Some" == cls.name
|
assertEquals("Some", cls.getName());
|
||||||
assert !AnnotationTargetUtil.isTypeAnnotation(cls.modifierList.annotations[0])
|
assertFalse(AnnotationTargetUtil.isTypeAnnotation(cls.getModifierList().getAnnotations()[0]));
|
||||||
assert !((PsiFileImpl) cls.containingFile).contentsLoaded
|
assertFalse(((PsiFileImpl)cls.getContainingFile()).isContentsLoaded());
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test parameter list count"() {
|
public void test_parameter_list_count() {
|
||||||
myFixture.addFileToProject("a.java", "class Cls { void foo(a) {} }")
|
myFixture.addFileToProject("a.java", "class Cls { void foo(a) {} }");
|
||||||
def list = myFixture.findClass("Cls").methods[0].parameterList
|
PsiParameterList list = myFixture.findClass("Cls").getMethods()[0].getParameterList();
|
||||||
assert list.parametersCount == list.parameters.size()
|
assertEquals(list.getParametersCount(), list.getParameters().length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test deprecated enum constant"() {
|
public void test_deprecated_enum_constant() {
|
||||||
def cls = myFixture.addClass("enum Foo { c1, @Deprecated c2, /** @deprecated */ c3 }")
|
PsiClass cls = myFixture.addClass("enum Foo { c1, @Deprecated c2, /** @deprecated */ c3 }");
|
||||||
assert !((PsiFileImpl) cls.containingFile).contentsLoaded
|
assertFalse(((PsiFileImpl)cls.getContainingFile()).isContentsLoaded());
|
||||||
|
|
||||||
assert !cls.fields[0].deprecated
|
assertFalse(cls.getFields()[0].isDeprecated());
|
||||||
assert cls.fields[1].deprecated
|
assertTrue(cls.getFields()[1].isDeprecated());
|
||||||
assert cls.fields[2].deprecated
|
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"() {
|
public 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
|
PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("a.java", "import foo.*; import bar.*; class Foo {}");
|
||||||
def another = myFixture.addClass("package zoo; public class Another {}")
|
PsiClass another = myFixture.addClass("package zoo; public class Another {}");
|
||||||
WriteCommandAction.runWriteCommandAction(project) {
|
WriteCommandAction.runWriteCommandAction(getProject(), (Computable<Boolean>)() -> {
|
||||||
file.viewProvider.document.insertString(file.text.indexOf("import"), "x")
|
file.getViewProvider().getDocument().insertString(file.getText().indexOf("import"), "x");
|
||||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||||
file.importClass(another)
|
return file.importClass(another);
|
||||||
}
|
});
|
||||||
PsiTestUtil.checkStubsMatchText(file)
|
PsiTestUtil.checkStubsMatchText(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test removing import in broken code does not cause stub AST mismatch"() {
|
public 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
|
PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("a.java", "import foo..module.SomeClass; class Foo {}");
|
||||||
WriteCommandAction.runWriteCommandAction(project) {
|
WriteCommandAction.runWriteCommandAction(getProject(), () -> file.getImportList().getImportStatements()[0].delete());
|
||||||
file.importList.importStatements[0].delete()
|
PsiTestUtil.checkStubsMatchText(file);
|
||||||
}
|
|
||||||
PsiTestUtil.checkStubsMatchText(file)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test adding type before method call does not cause stub AST mismatch"() {
|
public void test_adding_type_before_method_call_does_not_cause_stub_AST_mismatch() {
|
||||||
def file = myFixture.addFileToProject("a.java", """\
|
final PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("a.java", """
|
||||||
class Foo {
|
class Foo {
|
||||||
void foo() {
|
void foo() {
|
||||||
something();
|
something();
|
||||||
call();
|
call();
|
||||||
}
|
}
|
||||||
}""".stripIndent()) as PsiJavaFile
|
}""");
|
||||||
WriteCommandAction.runWriteCommandAction(project) {
|
WriteCommandAction.runWriteCommandAction(getProject(), () -> {
|
||||||
file.viewProvider.document.insertString(file.text.indexOf("call"), "char ")
|
file.getViewProvider().getDocument().insertString(file.getText().indexOf("call"), "char ");
|
||||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||||
PsiTestUtil.checkStubsMatchText(file)
|
PsiTestUtil.checkStubsMatchText(file);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test inserting class keyword"() {
|
public void test_inserting_class_keyword() {
|
||||||
String text = "class Foo { void foo() { return; } }"
|
final String text = "class Foo { void foo() { return; } }";
|
||||||
PsiFile psiFile = myFixture.addFileToProject("a.java", text)
|
PsiFile psiFile = myFixture.addFileToProject("a.java", text);
|
||||||
Document document = psiFile.getViewProvider().getDocument()
|
final Document document = psiFile.getViewProvider().getDocument();
|
||||||
|
|
||||||
WriteCommandAction.runWriteCommandAction(project) {
|
WriteCommandAction.runWriteCommandAction(
|
||||||
document.insertString(text.indexOf("return"), "class ")
|
getProject(), () -> document.insertString(text.indexOf("return"), "class "));
|
||||||
}
|
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||||
PsiDocumentManager.getInstance(getProject()).commitAllDocuments()
|
PsiTestUtil.checkStubsMatchText(psiFile);
|
||||||
PsiTestUtil.checkStubsMatchText(psiFile)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test inserting enum keyword"() {
|
public void test_inserting_enum_keyword() {
|
||||||
String text = "class Foo { void foo() { return; } }"
|
final String text = "class Foo { void foo() { return; } }";
|
||||||
PsiFile psiFile = myFixture.addFileToProject("a.java", text)
|
PsiFile psiFile = myFixture.addFileToProject("a.java", text);
|
||||||
Document document = psiFile.getViewProvider().getDocument()
|
final Document document = psiFile.getViewProvider().getDocument();
|
||||||
|
|
||||||
WriteCommandAction.runWriteCommandAction(project) {
|
WriteCommandAction.runWriteCommandAction(
|
||||||
document.insertString(text.indexOf("return"), "enum Foo")
|
getProject(), () -> document.insertString(text.indexOf("return"), "enum Foo"));
|
||||||
}
|
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||||
PsiDocumentManager.getInstance(getProject()).commitAllDocuments()
|
PsiTestUtil.checkStubsMatchText(psiFile);
|
||||||
PsiTestUtil.checkStubsMatchText(psiFile)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test type arguments without type in a method"() {
|
public void test_type_arguments_without_type_in_a_method() {
|
||||||
String text = "class Foo { { final Collection<String> contexts; f instanceof -> } }"
|
String text = "class Foo { { final Collection<String> contexts; f instanceof -> } }";
|
||||||
PsiFile psiFile = myFixture.addFileToProject("a.java", text)
|
final PsiFile psiFile = myFixture.addFileToProject("a.java", text);
|
||||||
|
|
||||||
WriteCommandAction.runWriteCommandAction(project) { deleteString(psiFile, "Collection") }
|
WriteCommandAction.runWriteCommandAction(getProject(), () -> deleteString(psiFile, "Collection"));
|
||||||
PsiDocumentManager.getInstance(getProject()).commitAllDocuments()
|
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||||
PsiTestUtil.checkStubsMatchText(psiFile)
|
PsiTestUtil.checkStubsMatchText(psiFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void deleteString(PsiFile file, String fragment) {
|
private static void deleteString(PsiFile file, String fragment) {
|
||||||
def document = file.viewProvider.document
|
Document document = file.getViewProvider().getDocument();
|
||||||
def index = document.text.indexOf(fragment)
|
int index = document.getText().indexOf(fragment);
|
||||||
document.deleteString(index, index + fragment.size())
|
document.deleteString(index, index + fragment.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test remove class literal qualifier"() {
|
public void test_remove_class_literal_qualifier() {
|
||||||
String text = "class Foo { { foo(String.class); } }"
|
final String text = "class Foo { { foo(String.class); } }";
|
||||||
PsiFile psiFile = myFixture.addFileToProject("a.java", text)
|
final PsiFile psiFile = myFixture.addFileToProject("a.java", text);
|
||||||
WriteCommandAction.runWriteCommandAction(project) {
|
WriteCommandAction.runWriteCommandAction(
|
||||||
psiFile.viewProvider.document.insertString(text.indexOf(");"), " x")
|
getProject(), () -> {
|
||||||
WriteCommandAction.runWriteCommandAction(project) { deleteString(psiFile, "String") }
|
psiFile.getViewProvider().getDocument().insertString(text.indexOf(");"), " x");
|
||||||
}
|
WriteCommandAction.runWriteCommandAction(getProject(), () -> deleteString(psiFile, "String"));
|
||||||
PsiDocumentManager.getInstance(getProject()).commitAllDocuments()
|
});
|
||||||
PsiTestUtil.checkStubsMatchText(psiFile)
|
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||||
|
PsiTestUtil.checkStubsMatchText(psiFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test annotation stub without reference"() {
|
public void test_annotation_stub_without_reference() {
|
||||||
PsiFile psiFile = myFixture.addFileToProject("a.java", "@() class Foo { } }")
|
PsiFile psiFile = myFixture.addFileToProject("a.java", "@() class Foo { } }");
|
||||||
assert ((PsiJavaFile) psiFile).classes[0].modifierList.annotations[0].nameReferenceElement == null
|
assertNull(((PsiJavaFile)psiFile).getClasses()[0].getModifierList().getAnnotations()[0].getNameReferenceElement());
|
||||||
assert !((PsiFileImpl) psiFile).contentsLoaded
|
assertFalse(((PsiFileImpl)psiFile).isContentsLoaded());
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test anonymous class stubs see method type parameters"() {
|
public void test_anonymous_class_stubs_see_method_type_parameters() {
|
||||||
PsiFileImpl file = (PsiFileImpl) myFixture.addFileToProject("A.java", """\
|
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("A.java", """
|
||||||
class A {
|
class A {
|
||||||
<V> Object foo() {
|
<V> Object foo() {
|
||||||
return new I<V>(){};
|
return new I<V>(){};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
interface I<T> {}
|
interface I<T> {}""");
|
||||||
""".stripIndent())
|
|
||||||
|
|
||||||
PsiClass a = ((PsiJavaFile) file).classes[0]
|
PsiClass a = ((PsiJavaFile)file).getClasses()[0];
|
||||||
PsiClass i = ((PsiJavaFile) file).classes[1]
|
PsiClass i = ((PsiJavaFile)file).getClasses()[1];
|
||||||
PsiAnonymousClass anon = assertOneElement(DirectClassInheritorsSearch.search(i).findAll()) as PsiAnonymousClass
|
PsiAnonymousClass anon = (PsiAnonymousClass)UsefulTestCase.assertOneElement(DirectClassInheritorsSearch.search(i).findAll());
|
||||||
|
|
||||||
assert i == anon.baseClassType.resolve()
|
assertEquals(i, anon.getBaseClassType().resolve());
|
||||||
assert a.methods[0].typeParameters[0] == PsiUtil.resolveClassInClassTypeOnly(anon.baseClassType.parameters[0])
|
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"() {
|
public void test_anonymous_class_stubs_see_local_classes() {
|
||||||
PsiFileImpl file = (PsiFileImpl) myFixture.addFileToProject("A.java", """\
|
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("A.java", """
|
||||||
class A {
|
class A {
|
||||||
void foo() {
|
void foo() {
|
||||||
class Local {}
|
class Local {}
|
||||||
new I<Local>(){};
|
new I<Local>(){};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
interface I<T> {}
|
interface I<T> {}""");
|
||||||
""".stripIndent())
|
|
||||||
|
|
||||||
PsiClass i = ((PsiJavaFile) file).classes[1]
|
PsiClass i = ((PsiJavaFile)file).getClasses()[1];
|
||||||
PsiAnonymousClass anon = assertOneElement(DirectClassInheritorsSearch.search(i).findAll()) as PsiAnonymousClass
|
PsiAnonymousClass anon = (PsiAnonymousClass)UsefulTestCase.assertOneElement(DirectClassInheritorsSearch.search(i).findAll());
|
||||||
|
|
||||||
assert !file.contentsLoaded
|
assertFalse(file.isContentsLoaded());
|
||||||
|
|
||||||
assert i == anon.baseClassType.resolve()
|
assertEquals(i, anon.getBaseClassType().resolve());
|
||||||
assert PsiUtil.resolveClassInClassTypeOnly(anon.baseClassType.parameters[0])?.name == "Local"
|
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"() {
|
public void test_local_class_stubs_see_other_local_classes() {
|
||||||
PsiFileImpl file = (PsiFileImpl) myFixture.addFileToProject("A.java", """\
|
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("A.java", """
|
||||||
class A {
|
class A {
|
||||||
void foo() {
|
void foo() {
|
||||||
class Local1 {}
|
class Local1 {}
|
||||||
class Local2 extends Local1 {}
|
class Local2 extends Local1 {}
|
||||||
}
|
}
|
||||||
}
|
}""");
|
||||||
""".stripIndent())
|
|
||||||
|
|
||||||
def cache = PsiShortNamesCache.getInstance(project)
|
PsiShortNamesCache cache = PsiShortNamesCache.getInstance(getProject());
|
||||||
def local1 = cache.getClassesByName("Local1", GlobalSearchScope.allScope(project))[0]
|
PsiClass local1 = cache.getClassesByName("Local1", GlobalSearchScope.allScope(getProject()))[0];
|
||||||
def local2 = cache.getClassesByName("Local2", GlobalSearchScope.allScope(project))[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"() {
|
public void test_local_class_stubs_do_not_load_AST_for_inheritance_checking_when_possible() {
|
||||||
PsiFileImpl file = (PsiFileImpl) myFixture.addFileToProject("A.java", """\
|
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("A.java", """
|
||||||
class A {
|
class A {
|
||||||
void foo() {
|
void foo() {
|
||||||
class UnrelatedLocal {}
|
class UnrelatedLocal {}
|
||||||
class Local extends A {}
|
class Local extends A {}
|
||||||
}
|
}
|
||||||
}
|
}""");
|
||||||
""".stripIndent())
|
|
||||||
|
|
||||||
def local = PsiShortNamesCache.getInstance(project).getClassesByName("Local", GlobalSearchScope.allScope(project))[0]
|
PsiClass local = PsiShortNamesCache.getInstance(getProject()).getClassesByName("Local", GlobalSearchScope.allScope(getProject()))[0];
|
||||||
assert "A" == local.superClass.name
|
assertEquals("A", local.getSuperClass().getName());
|
||||||
assert !file.contentsLoaded
|
assertFalse(file.isContentsLoaded());
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test broken anonymous"() {
|
public void test_broken_anonymous() {
|
||||||
String text = """\
|
final String text = """
|
||||||
class A {
|
class A {
|
||||||
public GroupDescriptor[] getGroupDescriptors() {
|
public GroupDescriptor[] getGroupDescriptors() {
|
||||||
return new ThreadGroup(Descriptor[]{
|
return new ThreadGroup(Descriptor[]{
|
||||||
new GroupDescriptor(groupId, "test")
|
new GroupDescriptor(groupId, "test")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}""".stripIndent()
|
}""";
|
||||||
PsiFile psiFile = myFixture.addFileToProject("a.java", text)
|
final PsiFile psiFile = myFixture.addFileToProject("a.java", text);
|
||||||
WriteCommandAction.runWriteCommandAction(project) {
|
WriteCommandAction.runWriteCommandAction(
|
||||||
psiFile.viewProvider.document.insertString(text.indexOf("]{"), "x")
|
getProject(), () -> psiFile.getViewProvider().getDocument().insertString(text.indexOf("]{"), "x"));
|
||||||
}
|
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||||
PsiDocumentManager.getInstance(getProject()).commitAllDocuments()
|
PsiTestUtil.checkStubsMatchText(psiFile);
|
||||||
PsiTestUtil.checkStubsMatchText(psiFile)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test broken nested anonymous"() {
|
public void test_broken_nested_anonymous() {
|
||||||
PsiTestUtil.checkStubsMatchText(myFixture.addFileToProject("a.java", "class A { { new A(new B[a]{b}); } }"))
|
PsiTestUtil.checkStubsMatchText(myFixture.addFileToProject("a.java", "class A { { new A(new B[a]{b}); } }"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test lone angle brackets"() {
|
public void test_lone_angle_brackets() {
|
||||||
String text = """\
|
String text = """
|
||||||
class A {
|
class A {
|
||||||
{
|
{
|
||||||
PsiLanguageInjectionHost host = PsiTreeUtil.getParentOfType(element, .class);
|
PsiLanguageInjectionHost host = PsiTreeUtil.getParentOfType(element, .class);
|
||||||
final <PsiElement, TextRange> pair;
|
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)
|
PsiTestUtil.checkStubsMatchText(myFixture.addFileToProject("a.java", text));
|
||||||
WriteCommandAction.runWriteCommandAction(project) {
|
|
||||||
PsiTreeUtil.findChildOfType(psiFile, PsiAnnotation).delete()
|
|
||||||
}
|
|
||||||
PsiTestUtil.checkStubsMatchText(psiFile)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test local record"() {
|
public void test_incomplete_static_import_does_not_cause_CCE() {
|
||||||
PsiTestUtil.checkStubsMatchText(myFixture.addFileToProject("a.java", """\
|
PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("a.java", "import static foo.bar.");
|
||||||
class A {
|
assertNotNull(((PsiFileImpl)file).getStub());
|
||||||
void test() {
|
assertNotNull(file.getNode());
|
||||||
record A(String s) { }
|
PsiImportStaticStatement staticImport = file.getImportList().getImportStaticStatements()[0];
|
||||||
}
|
assertNull(staticImport.getReferenceName());
|
||||||
}
|
assertNull(staticImport.resolveTargetClass());
|
||||||
""".stripIndent()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test field with missing initializer"() {
|
public void test_adding_import_to_broken_file_with_type_parameters() {
|
||||||
def file = myFixture.addFileToProject("a.java", "class A { int a = ; } ")
|
final PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("a.java", "A<B>");
|
||||||
def clazz = myFixture.findClass("A")
|
WriteCommandAction.runWriteCommandAction(
|
||||||
assert PsiFieldImpl.getDetachedInitializer(clazz.fields[0]) == null
|
getProject(), (Computable<Boolean>)() -> file.importClass(myFixture.findClass(CommonClassNames.JAVA_UTIL_LIST)));
|
||||||
assert !(file as PsiFileImpl).contentsLoaded
|
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() {
|
void test() {
|
||||||
}
|
}
|
||||||
|
|
||||||
String s = "foo";
|
String s = "foo";
|
||||||
int i = 10;
|
int i = 10;
|
||||||
static {} // not allowed by spec, but we parse
|
static {} // not allowed by spec, but we parse""");
|
||||||
""".stripIndent())
|
PsiTestUtil.checkStubsMatchText(psiFile);
|
||||||
PsiTestUtil.checkStubsMatchText(psiFile)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test array type use annotation stubbing"() {
|
public void test_array_type_use_annotation_stubbing() {
|
||||||
myFixture.addClass("""\
|
myFixture.addClass("""
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
@Target(ElementType.TYPE_USE)
|
@Target(ElementType.TYPE_USE)
|
||||||
@interface Anno { int value(); }""".stripIndent())
|
@interface Anno { int value(); }""");
|
||||||
|
|
||||||
PsiClass clazz = myFixture.addClass("""\
|
PsiClass clazz = myFixture.addClass("""
|
||||||
class Foo {
|
class Foo {
|
||||||
<T> @Anno(0) String @Anno(1) [] @Anno(2) [] foo(@Anno(3) byte @Anno(4) [] data) {}
|
<T> @Anno(0) String @Anno(1) [] @Anno(2) [] foo(@Anno(3) byte @Anno(4) [] data) {}
|
||||||
List<String> @Anno(5) [] field;
|
List<String> @Anno(5) [] field;
|
||||||
}""".stripIndent())
|
}""");
|
||||||
|
|
||||||
def method = clazz.methods[0]
|
PsiMethod method = clazz.getMethods()[0];
|
||||||
def field = clazz.fields[0]
|
PsiField field = clazz.getFields()[0];
|
||||||
def parameter = method.parameterList.parameters[0]
|
PsiParameter parameter = method.getParameterList().getParameters()[0];
|
||||||
def parameterAnnotations = parameter.type.annotations
|
PsiAnnotation[] parameterAnnotations = parameter.getType().getAnnotations();
|
||||||
def parameterComponentAnnotations = (parameter.type as PsiArrayType).componentType.annotations
|
PsiAnnotation[] parameterComponentAnnotations = ((PsiArrayType)parameter.getType()).getComponentType().getAnnotations();
|
||||||
def methodAnnotations = method.returnType.annotations
|
PsiAnnotation[] methodAnnotations = method.getReturnType().getAnnotations();
|
||||||
def methodComponentAnnotations = (method.returnType as PsiArrayType).componentType.annotations
|
PsiAnnotation[] methodComponentAnnotations = ((PsiArrayType)method.getReturnType()).getComponentType().getAnnotations();
|
||||||
def methodDeepComponentAnnotations = method.returnType.deepComponentType.annotations
|
PsiAnnotation[] methodDeepComponentAnnotations = method.getReturnType().getDeepComponentType().getAnnotations();
|
||||||
def fieldAnnotations = field.type.annotations
|
PsiAnnotation[] fieldAnnotations = field.getType().getAnnotations();
|
||||||
|
|
||||||
assert !(clazz.containingFile as PsiFileImpl).contentsLoaded
|
assertFalse(((PsiFileImpl)clazz.getContainingFile()).isContentsLoaded());
|
||||||
assertAnnotationValueText methodDeepComponentAnnotations, "0"
|
assertAnnotationValueText(methodDeepComponentAnnotations, "0");
|
||||||
assertAnnotationValueText methodAnnotations, "1"
|
assertAnnotationValueText(methodAnnotations, "1");
|
||||||
assertAnnotationValueText methodComponentAnnotations, "2"
|
assertAnnotationValueText(methodComponentAnnotations, "2");
|
||||||
assertAnnotationValueText parameterComponentAnnotations, "3"
|
assertAnnotationValueText(parameterComponentAnnotations, "3");
|
||||||
assertAnnotationValueText parameterAnnotations, "4"
|
assertAnnotationValueText(parameterAnnotations, "4");
|
||||||
assertAnnotationValueText fieldAnnotations, "5"
|
assertAnnotationValueText(fieldAnnotations, "5");
|
||||||
assert !(clazz.containingFile as PsiFileImpl).contentsLoaded
|
assertFalse(((PsiFileImpl)clazz.getContainingFile()).isContentsLoaded());
|
||||||
|
|
||||||
assert clazz.node // load AST
|
assertNotNull(clazz.getNode());// load AST
|
||||||
assert parameter.type.annotations.size() == 1
|
assertEquals(1, parameter.getType().getAnnotations().length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void assertAnnotationValueText(PsiAnnotation[] annotations, String text) {
|
private static void assertAnnotationValueText(PsiAnnotation[] annotations, String text) {
|
||||||
assert annotations.size() == 1
|
assertEquals(1, annotations.length);
|
||||||
assert annotations[0].findAttributeValue("value").text == text
|
assertEquals(annotations[0].findAttributeValue("value").getText(), text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
// 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.ApplicationManager;
|
||||||
import com.intellij.openapi.application.ReadAction
|
import com.intellij.openapi.application.ReadAction;
|
||||||
import com.intellij.openapi.command.WriteCommandAction
|
import com.intellij.openapi.application.WriteAction;
|
||||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
import com.intellij.openapi.command.WriteCommandAction;
|
||||||
import com.intellij.openapi.vfs.VfsUtil
|
import com.intellij.openapi.editor.Document;
|
||||||
import com.intellij.psi.*
|
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||||
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes
|
import com.intellij.openapi.util.Computable;
|
||||||
import com.intellij.psi.impl.source.DummyHolder
|
import com.intellij.openapi.vfs.VfsUtil;
|
||||||
import com.intellij.psi.impl.source.PsiClassImpl
|
import com.intellij.psi.*;
|
||||||
import com.intellij.psi.impl.source.PsiFileImpl
|
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
|
||||||
import com.intellij.psi.impl.source.PsiJavaFileImpl
|
import com.intellij.psi.impl.source.DummyHolder;
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.impl.source.PsiClassImpl;
|
||||||
import com.intellij.psi.search.searches.DirectClassInheritorsSearch
|
import com.intellij.psi.impl.source.PsiFileImpl;
|
||||||
import com.intellij.psi.search.searches.OverridingMethodsSearch
|
import com.intellij.psi.impl.source.PsiJavaFileImpl;
|
||||||
import com.intellij.psi.stubs.StubElement
|
import com.intellij.psi.search.GlobalSearchScope;
|
||||||
import com.intellij.psi.stubs.StubTree
|
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||||
import com.intellij.testFramework.LeakHunter
|
import com.intellij.psi.stubs.StubElement;
|
||||||
import com.intellij.testFramework.SkipSlowTestLocally
|
import com.intellij.psi.stubs.StubTree;
|
||||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import com.intellij.util.ref.GCUtil
|
import com.intellij.testFramework.LeakHunter;
|
||||||
import com.intellij.util.ref.GCWatcher
|
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.io.IOException;
|
||||||
import java.util.concurrent.Callable
|
import java.lang.ref.SoftReference;
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.ArrayList;
|
||||||
import java.util.concurrent.Future
|
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
|
@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"() {
|
long oldCount = getPsiManager().getModificationTracker().getModificationCount();
|
||||||
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject('Foo.java', 'class Foo {}')
|
|
||||||
assert file.stub
|
|
||||||
def cls = ((PsiJavaFile)file).classes[0]
|
|
||||||
assert file.stub
|
|
||||||
|
|
||||||
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
|
assertFalse(cls.isValid());
|
||||||
|
assertNotNull(file.getStub());
|
||||||
assert !cls.valid
|
assertNotEquals(cls, PsiTreeUtil.findElementOfClassAtOffset(file, 1, PsiClass.class, false));
|
||||||
assert file.stub
|
assertNull(file.getStub());
|
||||||
assert cls != PsiTreeUtil.findElementOfClassAtOffset(file, 1, PsiClass, false)
|
|
||||||
assert !file.stub
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test reachable psi classes remain valid when nothing changes"() {
|
public void test_reachable_psi_classes_remain_valid_when_nothing_changes() {
|
||||||
int count = 1000
|
int count = 1000;
|
||||||
List<SoftReference<PsiClass>> classList = (0..<count).collect { new SoftReference<PsiClass>(myFixture.addClass("class Foo$it {}")) }
|
List<SoftReference<PsiClass>> classList = IntStream.range(0, count)
|
||||||
System.gc()
|
.mapToObj(n -> new SoftReference<>(myFixture.addClass("class Foo" + n + " {}"))).toList();
|
||||||
System.gc()
|
System.gc();
|
||||||
System.gc()
|
System.gc();
|
||||||
assert classList.every {
|
System.gc();
|
||||||
def cls = it.get()
|
assertTrue(ContainerUtil.all(classList, ref -> {
|
||||||
if (!cls || cls.valid) return true
|
PsiClass cls = ref.get();
|
||||||
cls.text //load AST
|
if (cls == null || cls.isValid()) return true;
|
||||||
return cls.valid
|
assertNotNull(cls.getText());//load AST
|
||||||
}
|
//noinspection ConstantValue
|
||||||
|
return cls.isValid();
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test traversing PSI and switching concurrently"() {
|
public void test_traversing_PSI_and_switching_concurrently() throws InterruptedException {
|
||||||
int count = 100
|
int count = 100;
|
||||||
List<PsiClass> classList = (0..<count).collect {
|
List<PsiClass> classList = IntStream.range(0, count)
|
||||||
myFixture.addClass("class Foo$it { " +
|
.mapToObj(num -> myFixture.addClass(
|
||||||
"void foo$it(" +
|
"class Foo" + num + " {\n" +
|
||||||
(0..250).collect { "int i$it"}.join(", ") +
|
"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) {
|
||||||
CountDownLatch latch = new CountDownLatch(count)
|
ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||||
for (c in classList) {
|
Thread.yield();
|
||||||
ApplicationManager.application.executeOnPooledThread {
|
ReadAction.compute(() -> c.getText());
|
||||||
Thread.yield()
|
latch.countDown();
|
||||||
ApplicationManager.application.runReadAction {
|
});
|
||||||
c.text
|
for (PsiMethod m : c.getMethods()) {
|
||||||
}
|
PsiParameter[] parameters = m.getParameterList().getParameters();
|
||||||
latch.countDown()
|
for (int i = 0; i < parameters.length; i++) {
|
||||||
}
|
assertEquals(i, m.getParameterList().getParameterIndex(parameters[i]));
|
||||||
for (m in c.methods) {
|
|
||||||
def parameters = m.parameterList.parameters
|
|
||||||
for (i in 0..<parameters.size()) {
|
|
||||||
assert i == m.parameterList.getParameterIndex(parameters[i])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
latch.await()
|
|
||||||
|
latch.await();
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test smart pointer survives an external modification of a stubbed file"() {
|
public void test_smart_pointer_survives_an_external_modification_of_a_stubbed_file() throws IOException {
|
||||||
PsiFile file = myFixture.addFileToProject("A.java", "class A {}")
|
final PsiFile file = myFixture.addFileToProject("A.java", "class A {}");
|
||||||
def oldClass = JavaPsiFacade.getInstance(project).findClass("A", GlobalSearchScope.allScope(project))
|
PsiClass oldClass = JavaPsiFacade.getInstance(getProject()).findClass("A", GlobalSearchScope.allScope(getProject()));
|
||||||
def pointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(oldClass)
|
SmartPsiElementPointer<PsiClass> pointer = SmartPointerManager.getInstance(getProject()).createSmartPsiElementPointer(oldClass);
|
||||||
|
|
||||||
def document = FileDocumentManager.instance.getDocument(file.virtualFile)
|
Document document = FileDocumentManager.getInstance().getDocument(file.getVirtualFile());
|
||||||
assert document
|
assertNotNull(document);
|
||||||
assert file == PsiDocumentManager.getInstance(project).getCachedPsiFile(document)
|
assertEquals(file, PsiDocumentManager.getInstance(getProject()).getCachedPsiFile(document));
|
||||||
assert document == PsiDocumentManager.getInstance(project).getCachedDocument(file)
|
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 {}") }
|
WriteAction.run(() -> VfsUtil.saveText(file.getVirtualFile(), "import java.util.*; class A {}; class B {}"));
|
||||||
assert pointer.element == oldClass
|
assertEquals(pointer.getElement(), oldClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test do not parse when resolving references inside an anonymous class"() {
|
public void test_do_not_parse_when_resolving_references_inside_an_anonymous_class() {
|
||||||
PsiFileImpl file = (PsiFileImpl) myFixture.addFileToProject("A.java", """
|
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("A.java", """
|
||||||
class A {
|
|
||||||
Object field = new B() {
|
class A {
|
||||||
void foo(Object o) {
|
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 {}
|
class B {
|
||||||
};
|
void foo(Object o) {}
|
||||||
Runnable r = () -> { new B() {}; };
|
static class Inner {}
|
||||||
Runnable r2 = (new B(){})::hashCode();
|
}
|
||||||
}
|
""");
|
||||||
|
assertFalse(file.isContentsLoaded());
|
||||||
|
PsiClass bClass = ((PsiJavaFile)file).getClasses()[1];
|
||||||
|
assertEquals(3, DirectClassInheritorsSearch.search(bClass).findAll().size());
|
||||||
|
assertFalse(file.isContentsLoaded());
|
||||||
|
|
||||||
class B {
|
PsiMethod fooMethod = bClass.getMethods()[0];
|
||||||
void foo(Object o) {}
|
assertFalse(file.isContentsLoaded());
|
||||||
static class Inner {}
|
|
||||||
}
|
|
||||||
""")
|
|
||||||
assert !file.contentsLoaded
|
|
||||||
PsiClass bClass = ((PsiJavaFile) file).classes[1]
|
|
||||||
assert DirectClassInheritorsSearch.search(bClass).findAll().size() == 3
|
|
||||||
assert !file.contentsLoaded
|
|
||||||
|
|
||||||
def fooMethod = bClass.methods[0]
|
PsiMethod override = OverridingMethodsSearch.search(fooMethod).findFirst();
|
||||||
assert !file.contentsLoaded
|
assertNotNull(override);
|
||||||
|
assertFalse(file.isContentsLoaded());
|
||||||
|
|
||||||
def override = OverridingMethodsSearch.search(fooMethod).findAll().first()
|
assertTrue(override.getContainingClass() instanceof PsiAnonymousClass);
|
||||||
assert override
|
assertFalse(file.isContentsLoaded());
|
||||||
assert !file.contentsLoaded
|
|
||||||
|
|
||||||
assert override.containingClass instanceof PsiAnonymousClass
|
assertEquals(bClass, override.getContainingClass().getSuperClass());
|
||||||
assert !file.contentsLoaded
|
assertEquals(bClass.getInnerClasses()[0], override.getContainingClass().getInnerClasses()[0].getSuperClass());
|
||||||
|
assertFalse(file.isContentsLoaded());
|
||||||
assert bClass == override.containingClass.superClass
|
|
||||||
assert bClass.innerClasses[0] == override.containingClass.innerClasses[0].superClass
|
|
||||||
assert !file.contentsLoaded
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test AST can be gc-ed and recreated"() {
|
public void test_AST_can_be_gc_ed_and_recreated() {
|
||||||
def psiClass = myFixture.addClass("class Foo {}")
|
PsiClass psiClass = myFixture.addClass("class Foo {}");
|
||||||
def file = psiClass.containingFile as PsiFileImpl
|
PsiFileImpl file = (PsiFileImpl)psiClass.getContainingFile();
|
||||||
assert file.stub
|
assertNotNull(file.getStub());
|
||||||
|
|
||||||
assert psiClass.nameIdentifier
|
assertNotNull(psiClass.getNameIdentifier());
|
||||||
assert !file.stub
|
assertNull(file.getStub());
|
||||||
assert file.treeElement
|
assertNotNull(file.getTreeElement());
|
||||||
|
|
||||||
GCUtil.tryGcSoftlyReachableObjects()
|
GCUtil.tryGcSoftlyReachableObjects();
|
||||||
assert !file.treeElement
|
assertNull(file.getTreeElement());
|
||||||
assert file.stub
|
assertNotNull(file.getStub());
|
||||||
|
|
||||||
assert psiClass.nameIdentifier
|
assertNotNull(psiClass.getNameIdentifier());
|
||||||
assert !file.stub
|
assertNull(file.getStub());
|
||||||
assert file.treeElement
|
assertNotNull(file.getTreeElement());
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test no AST loading on file rename"() {
|
public void test_no_AST_loading_on_file_rename() {
|
||||||
PsiJavaFile file = (PsiJavaFile) myFixture.addFileToProject('a.java', 'class Foo {}')
|
final PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("a.java", "class Foo {}");
|
||||||
assert file.classes.length == 1
|
assertEquals(1, file.getClasses().length);
|
||||||
assert ((PsiFileImpl)file).stub
|
assertNotNull(((PsiFileImpl)file).getStub());
|
||||||
|
|
||||||
WriteCommandAction.runWriteCommandAction project, { file.setName('b.java') }
|
WriteCommandAction.runWriteCommandAction(getProject(), (Computable<PsiElement>)() -> file.setName("b.java"));
|
||||||
assert file.classes.length == 1
|
assertEquals(1, file.getClasses().length);
|
||||||
assert ((PsiFileImpl)file).stub
|
assertNotNull(((PsiFileImpl)file).getStub());
|
||||||
|
|
||||||
assert file.classes[0].nameIdentifier.text == 'Foo'
|
assertEquals("Foo", file.getClasses()[0].getNameIdentifier().getText());
|
||||||
assert ((PsiFileImpl)file).contentsLoaded
|
assertTrue(((PsiFileImpl)file).isContentsLoaded());
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test use green stub after AST loaded and gc-ed"() {
|
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() { }}")
|
PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("a.java", "class A{public static void foo() { }}");
|
||||||
//noinspection GroovyUnusedAssignment
|
assertNotNull(((PsiFileImpl)file).getStubTree());
|
||||||
StubTree stubHardRef = ((PsiFileImpl)file).stubTree
|
|
||||||
|
|
||||||
assert file.classes[0].nameIdentifier
|
assertNotNull(file.getClasses()[0].getNameIdentifier());
|
||||||
loadAndGcAst(file)
|
loadAndGcAst(file);
|
||||||
assertNoStubLoaded(file)
|
assertNoStubLoaded(file);
|
||||||
|
|
||||||
assert file.classes[0].methods[0].modifierList.hasExplicitModifier(PsiModifier.STATIC)
|
assertTrue(file.getClasses()[0].getMethods()[0].getModifierList().hasExplicitModifier(PsiModifier.STATIC));
|
||||||
assert !((PsiFileImpl)file).getTreeElement()
|
assertNull(((PsiFileImpl)file).getTreeElement());
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test use green stub after building it from AST"() {
|
public void test_use_green_stub_after_building_it_from_AST() {
|
||||||
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("a.java", "class A<T>{}")
|
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("a.java", "class A<T>{}");
|
||||||
PsiClass psiClass = ((PsiJavaFile)file).classes[0]
|
PsiClass psiClass = ((PsiJavaFile)file).getClasses()[0];
|
||||||
assert psiClass.nameIdentifier
|
assertNotNull(psiClass.getNameIdentifier());
|
||||||
|
|
||||||
loadAndGcAst(file)
|
loadAndGcAst(file);
|
||||||
|
|
||||||
assertNoStubLoaded(file)
|
assertNoStubLoaded(file);
|
||||||
StubElement hardRefToStub = file.greenStub
|
StubElement<?> hardRefToStub = file.getGreenStub();
|
||||||
assert hardRefToStub
|
assertNotNull(hardRefToStub);
|
||||||
assert hardRefToStub == file.stub
|
assertEquals(hardRefToStub, file.getStub());
|
||||||
|
|
||||||
loadAndGcAst(file)
|
loadAndGcAst(file);
|
||||||
assert hardRefToStub.is(file.greenStub)
|
assertSame(hardRefToStub, file.getGreenStub());
|
||||||
|
|
||||||
assert psiClass.typeParameters.length == 1
|
assertEquals(1, psiClass.getTypeParameters().length);
|
||||||
assert !file.treeElement
|
assertNull(file.getTreeElement());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadAndGcAst(PsiFile file) {
|
private static void loadAndGcAst(PsiFile file) {
|
||||||
GCWatcher.tracking(file.node).ensureCollected()
|
GCWatcher.tracking(file.getNode()).ensureCollected();
|
||||||
assert !((PsiFileImpl)file).treeElement
|
assertNull(((PsiFileImpl)file).getTreeElement());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static assertNoStubLoaded(PsiFile file) {
|
private static void assertNoStubLoaded(final PsiFile file) {
|
||||||
LeakHunter.checkLeak(file, StubTree) { candidate -> candidate.root.psi == file }
|
LeakHunter.checkLeak(file, StubTree.class, candidate -> candidate.getRoot().getPsi().equals(file));
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test node has same PSI when loaded in green stub presence"() {
|
public void test_node_has_same_PSI_when_loaded_in_green_stub_presence() {
|
||||||
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("a.java", "class A<T>{}")
|
PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("a.java", "class A<T>{}");
|
||||||
def stubTree = file.stubTree
|
StubTree stubTree = file.getStubTree();
|
||||||
PsiClass psiClass = ((PsiJavaFile)file).classes[0]
|
PsiClass psiClass = ((PsiJavaFile)file).getClasses()[0];
|
||||||
assert psiClass.nameIdentifier
|
assertNotNull(psiClass.getNameIdentifier());
|
||||||
GCUtil.tryGcSoftlyReachableObjects()
|
GCUtil.tryGcSoftlyReachableObjects();
|
||||||
|
|
||||||
assert stubTree.is(file.greenStubTree)
|
assertSame(stubTree, file.getGreenStubTree());
|
||||||
assert file.node.lastChildNode.psi.is(psiClass)
|
assertSame(file.getNode().getLastChildNode().getPsi(), psiClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test load stub from non-file PSI after AST is unloaded"() {
|
public void test_load_stub_from_non_file_PSI_after_AST_is_unloaded() {
|
||||||
PsiJavaFileImpl file = (PsiJavaFileImpl)myFixture.addFileToProject("a.java", "class A<T>{}")
|
PsiJavaFileImpl file = (PsiJavaFileImpl)myFixture.addFileToProject("a.java", "class A<T>{}");
|
||||||
def cls = file.classes[0]
|
PsiClass cls = file.getClasses()[0];
|
||||||
assert cls.nameIdentifier
|
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"() {
|
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{}")
|
PsiJavaFileImpl file = (PsiJavaFileImpl)myFixture.addFileToProject("a.java", "class A{}");
|
||||||
def cls = file.lastChild
|
PsiElement cls = file.getLastChild();
|
||||||
assert cls instanceof PsiClass
|
assertTrue(cls instanceof PsiClass);
|
||||||
|
|
||||||
GCUtil.tryGcSoftlyReachableObjects()
|
GCUtil.tryGcSoftlyReachableObjects();
|
||||||
assert file.treeElement // we still hold a strong reference to AST
|
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
|
// now we know stub index and can GC AST
|
||||||
GCUtil.tryGcSoftlyReachableObjects()
|
GCUtil.tryGcSoftlyReachableObjects();
|
||||||
assert !file.treeElement
|
assertNull(file.getTreeElement());
|
||||||
|
assertEquals(cls, myFixture.findClass("A"));
|
||||||
assert cls == myFixture.findClass('A')
|
assertNull(file.getTreeElement());
|
||||||
assert !file.treeElement
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test bind stubs to AST after AST has been loaded and gc-ed"() {
|
public void test_bind_stubs_to_AST_after_AST_has_been_loaded_and_gc_ed() {
|
||||||
PsiJavaFileImpl file = (PsiJavaFileImpl)myFixture.addFileToProject("a.java", "class A{}")
|
PsiJavaFileImpl file = (PsiJavaFileImpl)myFixture.addFileToProject("a.java", "class A{}");
|
||||||
loadAndGcAst(file)
|
loadAndGcAst(file);
|
||||||
|
|
||||||
def cls1 = file.classes[0]
|
PsiClass cls1 = file.getClasses()[0];
|
||||||
def cls2 = file.lastChild
|
PsiElement cls2 = file.getLastChild();
|
||||||
assert cls1 == cls2
|
assertEquals(cls1, cls2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void "test concurrent stub and AST reloading"() {
|
public void test_concurrent_stub_and_AST_reloading() throws ExecutionException, InterruptedException {
|
||||||
def fileNumbers = 0..<3
|
int maxFile = 3;
|
||||||
List<PsiJavaFileImpl> files = fileNumbers.collect {
|
final List<PsiJavaFileImpl> files = IntStream.range(0, maxFile).mapToObj(
|
||||||
(PsiJavaFileImpl)myFixture.addFileToProject("a${it}.java", "import foo.bar; class A{}")
|
num -> (PsiJavaFileImpl)myFixture.addFileToProject("a" + num + ".java", "import foo.bar; class A{}"))
|
||||||
}
|
.toList();
|
||||||
for (iteration in 0..<3) {
|
for (int iteration = 0; iteration <= 3; iteration++) {
|
||||||
GCWatcher.tracking(files.collect { it.node }).ensureCollected()
|
GCWatcher.tracking(ContainerUtil.map(files, PsiFileImpl::getNode)).ensureCollected();
|
||||||
files.each { assert !it.treeElement }
|
for (PsiJavaFileImpl file : files) {
|
||||||
|
assertNull(file.getTreeElement());
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
GCUtil.tryGcSoftlyReachableObjects()
|
|
||||||
|
|
||||||
for (i in fileNumbers) {
|
List<Future<PsiImportList>> stubFutures = new ArrayList<>();
|
||||||
def stubImport = stubFutures[i].get()
|
List<Future<PsiImportList>> astFutures = new ArrayList<>();
|
||||||
def astImport = astFutures[i].get()
|
|
||||||
if (stubImport != astImport) {
|
for (int i = 0; i < 3; i++) {
|
||||||
fail("Different import psi in ${files[i].name}: stub=$stubImport, ast=$astImport")
|
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"() {
|
public void test_DummyHolder_calcStubTree_does_not_fail() {
|
||||||
def text = "{ new Runnable() { public void run() {} }; }"
|
String text = "{ new Runnable() { public void run() {} }; }";
|
||||||
def file = JavaPsiFacade.getElementFactory(project).createCodeBlockFromText(text, null).containingFile
|
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
|
// 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
|
||||||
def stubTree = assertInstanceOf(file, DummyHolder).calcStubTree()
|
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"() {
|
public void test_stub_index_is_cleared_on_AST_change() {
|
||||||
def clazz = myFixture.addClass("class Foo { int a; }")
|
PsiClass clazz = myFixture.addClass("class Foo { int a; }");
|
||||||
def field = clazz.fields[0]
|
PsiField field = clazz.getFields()[0];
|
||||||
def file = clazz.containingFile as PsiFileImpl
|
final PsiFileImpl file = (PsiFileImpl)clazz.getContainingFile();
|
||||||
WriteCommandAction.runWriteCommandAction(project, {
|
WriteCommandAction.runWriteCommandAction(getProject(), () -> {
|
||||||
file.viewProvider.document.insertString(0, ' ')
|
file.getViewProvider().getDocument().insertString(0, " ");
|
||||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||||
})
|
});
|
||||||
|
|
||||||
assert file.calcStubTree()
|
|
||||||
|
|
||||||
WriteCommandAction.runWriteCommandAction(project, {
|
assertNotNull(file.calcStubTree());
|
||||||
file.viewProvider.document.insertString(file.text.indexOf('int'), 'void foo();')
|
|
||||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
|
||||||
})
|
|
||||||
|
|
||||||
GCUtil.tryGcSoftlyReachableObjects()
|
|
||||||
|
|
||||||
assert file.calcStubTree()
|
WriteCommandAction.runWriteCommandAction(getProject(), () -> {
|
||||||
|
file.getViewProvider().getDocument().insertString(file.getText().indexOf("int"), "void foo();");
|
||||||
assert field.valid
|
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||||
assert field.name == 'a'
|
});
|
||||||
|
|
||||||
|
GCUtil.tryGcSoftlyReachableObjects();
|
||||||
|
|
||||||
|
assertNotNull(file.calcStubTree());
|
||||||
|
|
||||||
|
assertTrue(field.isValid());
|
||||||
|
assertEquals("a", field.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
package com.intellij.java.refactoring;
|
||||||
|
|
||||||
import com.intellij.codeInsight.TargetElementUtil;
|
import com.intellij.codeInsight.TargetElementUtil;
|
||||||
|
|||||||
@@ -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;
|
package com.intellij.java.run;
|
||||||
|
|
||||||
import com.intellij.application.options.PathMacrosCollector;
|
import com.intellij.application.options.PathMacrosCollector;
|
||||||
|
|||||||
@@ -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;
|
package com.intellij.psi.impl.source.tree.java;
|
||||||
|
|
||||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
|
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
|
||||||
|
|||||||
@@ -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;
|
package com.intellij.unscramble;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|||||||
@@ -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;
|
package com.intellij.unscramble;
|
||||||
|
|
||||||
import com.intellij.testFramework.PlatformTestUtil;
|
import com.intellij.testFramework.PlatformTestUtil;
|
||||||
|
|||||||
Reference in New Issue
Block a user