From 515ef7a7550485419e682cfb0f04ade444ee669a Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Mon, 9 Dec 2013 11:41:49 +0400 Subject: [PATCH] IDEA-117584 more stubs for annotations --- .../lang/parser/GroovyElementTypes.java | 25 +---- .../psi/impl/GroovyPsiElementFactoryImpl.java | 2 +- .../annotation/GrAnnotationImpl.java | 34 +++++-- .../statements/GrVariableDeclarationImpl.java | 5 +- .../lang/psi/stubs/GrAnnotationStub.java | 53 +++++++++-- .../elements/GrAnnotationElementType.java | 56 +++++++++++ .../stubs/elements/GrStubFileElementType.java | 2 +- .../lang/psi/GrStubAstSwitchTest.groovy | 94 ++++++++++++++++++- 8 files changed, 227 insertions(+), 44 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrAnnotationElementType.java diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java index bc96a546b9e1..e5291d7dc51e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java @@ -37,7 +37,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEn import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameter; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameterList; -import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.GrVariableDeclarationImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.blocks.GrBlockImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.blocks.GrClosableBlockImpl; @@ -308,29 +307,7 @@ public interface GroovyElementTypes extends GroovyTokenTypes, GroovyDocElementTy GroovyElementType ANNOTATION_ARGUMENTS = new GroovyElementType("annotation arguments"); GroovyElementType ANNOTATION_MEMBER_VALUE_PAIR = new GroovyElementType("annotation member value pair"); - GrStubElementType ANNOTATION = new GrStubElementType("annotation") { - - @Override - public GrAnnotation createPsi(@NotNull GrAnnotationStub stub) { - return new GrAnnotationImpl(stub); - } - - @Override - public GrAnnotationStub createStub(@NotNull GrAnnotation psi, StubElement parentStub) { - return new GrAnnotationStub(parentStub, psi); - } - - @Override - public void serialize(@NotNull GrAnnotationStub stub, @NotNull StubOutputStream dataStream) throws IOException { - dataStream.writeName(stub.getAnnotationName()); - } - - @NotNull - @Override - public GrAnnotationStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException { - return new GrAnnotationStub(parentStub, dataStream.readName()); - } - }; + GrStubElementType ANNOTATION = new GrAnnotationElementType("annotation"); //parameters EmptyStubElementType PARAMETERS_LIST = new EmptyStubElementType("parameters list", GroovyFileType.GROOVY_LANGUAGE) { @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java index d60892b42b32..047fe23213cc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java @@ -523,7 +523,7 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { @NotNull @Override public GrAnnotation createAnnotationFromText(@NotNull @NonNls String annotationText, @Nullable PsiElement context) throws IncorrectOperationException { - return createMethodFromText(annotationText + " void ___shdjklf_pqweirupncp_foo() {}", context).getModifierList().getAnnotations()[0]; + return createMethodFromText(annotationText + " void ___shdjklf_pqweirupncp_foo() {}", context).getModifierList().getRawAnnotations()[0]; } @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java index 674bfe6d66c1..f82b8a08cd81 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java @@ -82,20 +82,34 @@ public class GrAnnotationImpl extends GrStubElementBase implem @NotNull public GrAnnotationArgumentList getParameterList() { + final GrAnnotationStub stub = getStub(); + if (stub != null) { + return stub.getPsiElement().getParameterList(); + } return findNotNullChildByClass(GrAnnotationArgumentList.class); } @Nullable @NonNls public String getQualifiedName() { + final GrAnnotationStub stub = getStub(); + if (stub != null) { + return stub.getPsiElement().getQualifiedName(); + } + final GrCodeReferenceElement nameRef = getClassReference(); final PsiElement resolved = nameRef.resolve(); - if (resolved instanceof PsiClass) return ((PsiClass) resolved).getQualifiedName(); + if (resolved instanceof PsiClass) return ((PsiClass)resolved).getQualifiedName(); return null; } @Nullable public PsiJavaCodeReferenceElement getNameReferenceElement() { + final GrAnnotationStub stub = getStub(); + if (stub != null) { + return stub.getPsiElement().getNameReferenceElement(); + } + final GroovyResolveResult resolveResult = getClassReference().advancedResolve(); final PsiElement resolved = resolveResult.getElement(); @@ -107,6 +121,7 @@ public class GrAnnotationImpl extends GrStubElementBase implem } } + @Nullable public PsiAnnotationMemberValue findAttributeValue(@Nullable String attributeName) { return PsiImplUtil.findAttributeValue(this, attributeName); } @@ -116,7 +131,7 @@ public class GrAnnotationImpl extends GrStubElementBase implem return PsiImplUtil.findDeclaredAttributeValue(this, attributeName); } - public T setDeclaredAttributeValue(@Nullable @NonNls String attributeName, T value) { + public T setDeclaredAttributeValue(@Nullable @NonNls String attributeName, T value) { return (T)PsiImplUtil.setDeclaredAttributeValue(this, attributeName, value, ANNOTATION_CREATOR); } @@ -127,6 +142,11 @@ public class GrAnnotationImpl extends GrStubElementBase implem @NotNull public GrCodeReferenceElement getClassReference() { + final GrAnnotationStub stub = getStub(); + if (stub != null) { + return stub.getPsiElement().getClassReference(); + } + return findNotNullChildByClass(GrCodeReferenceElement.class); } @@ -134,13 +154,15 @@ public class GrAnnotationImpl extends GrStubElementBase implem public String getShortName() { final GrAnnotationStub stub = getStub(); if (stub != null) { - return stub.getAnnotationName(); - } - else { - return getClassReference().getReferenceName(); + return stub.getPsiElement().getShortName(); } + + final String referenceName = getClassReference().getReferenceName(); + assert referenceName != null; + return referenceName; } + @Nullable public PsiAnnotationOwner getOwner() { return (PsiAnnotationOwner)getParent(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java index 1ab1a1a26f81..990876dea044 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java @@ -42,6 +42,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; @@ -85,7 +86,7 @@ public class GrVariableDeclarationImpl extends GrStubElementBase impl @NotNull public GrModifierList getModifierList() { - return (GrModifierList)findNotNullChildByType(GroovyElementTypes.MODIFIERS); + return getRequiredStubOrPsiChild(GroovyElementTypes.MODIFIERS); } @Override @@ -192,7 +193,7 @@ public class GrVariableDeclarationImpl extends GrStubElementBase impl @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place) { - if (lastParent != null && lastParent == getTupleInitializer()) { + if (lastParent != null && !(getParent() instanceof GrTypeDefinitionBody) && lastParent == getTupleInitializer()) { return true; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/GrAnnotationStub.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/GrAnnotationStub.java index f78b7f34844c..c319fbd08adf 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/GrAnnotationStub.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/GrAnnotationStub.java @@ -1,28 +1,67 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.jetbrains.plugins.groovy.lang.psi.stubs; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.stubs.StubBase; import com.intellij.psi.stubs.StubElement; -import com.intellij.util.io.StringRef; +import com.intellij.reference.SoftReference; +import com.intellij.util.IncorrectOperationException; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; /** * @author peter */ public class GrAnnotationStub extends StubBase { - private final StringRef myReference; + private static final Logger LOG = Logger.getInstance(GrAnnotationStub.class); - public GrAnnotationStub(StubElement parent, StringRef reference) { + private final String myText; + private SoftReference myPsiRef; + + public GrAnnotationStub(StubElement parent, String text) { super(parent, GroovyElementTypes.ANNOTATION); - myReference = reference; + myText = text; } public GrAnnotationStub(StubElement parent, GrAnnotation from) { super(parent, GroovyElementTypes.ANNOTATION); - myReference = StringRef.fromString(from.getClassReference().getReferenceName()); + myText = from.getText(); } - public String getAnnotationName() { - return myReference.getString(); + public GrAnnotation getPsiElement() { + if (myPsiRef != null) { + final GrAnnotation annotation = myPsiRef.get(); + if (annotation != null) { + return annotation; + } + } + try { + GrAnnotation annotation = GroovyPsiElementFactory.getInstance(getProject()).createAnnotationFromText(myText, getPsi()); + myPsiRef = new SoftReference(annotation); + return annotation; + } + catch (IncorrectOperationException e) { + LOG.error("Bad annotation in repository!", e); + return null; + } + } + + public String getText() { + return myText; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrAnnotationElementType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrAnnotationElementType.java new file mode 100644 index 000000000000..9dc51c8eb3af --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrAnnotationElementType.java @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.lang.psi.stubs.elements; + +import com.intellij.psi.stubs.StubElement; +import com.intellij.psi.stubs.StubInputStream; +import com.intellij.psi.stubs.StubOutputStream; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; +import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationImpl; +import org.jetbrains.plugins.groovy.lang.psi.stubs.GrAnnotationStub; + +import java.io.IOException; + +/** + * Created by Max Medvedev on 12/6/13 + */ +public class GrAnnotationElementType extends GrStubElementType { + public GrAnnotationElementType(@NotNull String name) { + super(name); + } + + @Override + public GrAnnotation createPsi(@NotNull GrAnnotationStub stub) { + return new GrAnnotationImpl(stub); + } + + @Override + public GrAnnotationStub createStub(@NotNull GrAnnotation psi, StubElement parentStub) { + return new GrAnnotationStub(parentStub, psi); + } + + @Override + public void serialize(@NotNull GrAnnotationStub stub, @NotNull StubOutputStream dataStream) throws IOException { + dataStream.writeUTFFast(stub.getText()); + } + + @NotNull + @Override + public GrAnnotationStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException { + return new GrAnnotationStub(parentStub, dataStream.readUTFFast()); + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrStubFileElementType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrStubFileElementType.java index 10e803e33880..c54cc965ecc8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrStubFileElementType.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrStubFileElementType.java @@ -55,7 +55,7 @@ public class GrStubFileElementType extends IStubFileElementType { @Override public int getStubVersion() { - return super.getStubVersion() + 19; + return super.getStubVersion() + 20; } @NotNull diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/GrStubAstSwitchTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/GrStubAstSwitchTest.groovy index 30030f20dfdf..6a7d0f864b9f 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/GrStubAstSwitchTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/GrStubAstSwitchTest.groovy @@ -15,14 +15,19 @@ */ package org.jetbrains.plugins.groovy.lang.psi -import com.intellij.psi.PsiClass -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import com.intellij.psi.* +import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl /** * Created by Max Medvedev on 12/4/13 */ -class GrStubAstSwitchTest extends LightCodeInsightFixtureTestCase { +class GrStubAstSwitchTest extends LightGroovyTestCase { + @Override + protected String getBasePath() { + null + } + void testDontLoadContentWhenProcessingImports() { GroovyFileImpl file = (GroovyFileImpl) myFixture.addFileToProject("A.groovy", """ import java.util.concurrent.ConcurrentHashMap @@ -44,4 +49,87 @@ class B extends ConcurrentHashMap { fooMethod.findDeepestSuperMethods() assert !file.contentsLoaded } + + void testDontLoadAstForAnnotation() { + GroovyFileImpl file = myFixture.addFileToProject('a.groovy', '''\ +class A { + def foo(){} +} + +class B { + @Delegate + A a = new A() +} +''') as GroovyFileImpl + + assert !file.contentsLoaded + PsiClass clazzB = file.classes[1] + assert !file.contentsLoaded + + PsiField field = clazzB.fields[0] + assert !file.contentsLoaded + + + PsiModifierList modifierList = field.modifierList + assert !file.contentsLoaded + + PsiAnnotation[] annotations = modifierList.annotations + PsiAnnotation annotation = annotations[0] + assert !file.contentsLoaded + + assert annotation.qualifiedName == 'groovy.lang.Delegate' + assert !file.contentsLoaded + } + + void testDontLoadAstForAnnotation2() { + GroovyFileImpl file = myFixture.addFileToProject('a.groovy', '''\ +class A { + def foo(){} +} + +class B extends A { + @Override + def foo() {} +} +''') as GroovyFileImpl + + assert !file.contentsLoaded + PsiClass clazzB = file.classes[1] + assert !file.contentsLoaded + + PsiMethod method = clazzB.methods[0] + assert !file.contentsLoaded + + + PsiModifierList modifierList = method.modifierList + assert !file.contentsLoaded + + PsiAnnotation[] annotations = modifierList.annotations + PsiAnnotation annotation = annotations[0] + assert !file.contentsLoaded + + assert annotation.qualifiedName == "java.lang.Override" + assert !file.contentsLoaded + } + + + void testDelegateExists() { + GroovyFileImpl file = myFixture.addFileToProject('a.groovy', '''\ +class A { + def foo(){} +} + +class B { + @Delegate + A a = new A() +} +''') as GroovyFileImpl + + assert !file.contentsLoaded + PsiClass clazzB = file.classes[1] + assert !file.contentsLoaded + + assert clazzB.methods.find {it.name =='foo'} + assert !file.contentsLoaded + } }