From df00ec8bf364204bbcb06a24d0e9781900f57a54 Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Fri, 14 Oct 2016 21:10:48 +0300 Subject: [PATCH] [groovy] do not process non code members when resolving reference expression within annotation value --- .../expressions/GrReferenceResolveRunner.kt | 27 ++++++++++--------- .../lang/psi/GrStubAstSwitchTest.groovy | 14 ++++++++++ 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceResolveRunner.kt b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceResolveRunner.kt index 31cd4006b960..60ef6f7a4e1e 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceResolveRunner.kt +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceResolveRunner.kt @@ -18,8 +18,10 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions import com.intellij.psi.* import com.intellij.psi.scope.PsiScopeProcessor import com.intellij.psi.util.InheritanceUtil +import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes import org.jetbrains.plugins.groovy.lang.psi.api.SpreadState +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationNameValuePair import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression @@ -27,38 +29,39 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GrTraitType import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureParameterEnhancer import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil -import org.jetbrains.plugins.groovy.lang.resolve.ClosureMissingMethodContributor -import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil -import org.jetbrains.plugins.groovy.lang.resolve.processNonCodeMembers +import org.jetbrains.plugins.groovy.lang.resolve.* import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassHint class GrReferenceResolveRunner(val place: GrReferenceExpression, val processor: PsiScopeProcessor) { fun resolveReferenceExpression(): Boolean { + val processNonCode = PsiTreeUtil.skipParentsOfType(place, GrReferenceExpression::class.java) !is GrAnnotationNameValuePair + val initialState = initialState(processNonCode) val qualifier = place.qualifier if (qualifier == null) { - if (!ResolveUtil.treeWalkUp(place, processor, true)) return false - return place.context !is GrMethodCall || ClosureMissingMethodContributor.processMethodsFromClosures(place, processor) + if (!treeWalkUp(place, processor, initialState)) return false + if (!processNonCode) return true + if (place.context is GrMethodCall && !ClosureMissingMethodContributor.processMethodsFromClosures(place, processor)) return false } else { if (place.dotTokenType === GroovyTokenTypes.mSPREAD_DOT) { val qType = qualifier.type val componentType = ClosureParameterEnhancer.findTypeForIteration(qType, place) if (componentType != null) { - val state = ResolveState.initial().put(ClassHint.RESOLVE_CONTEXT, qualifier).put(SpreadState.SPREAD_STATE, SpreadState.create(qType, null)) + val state = initialState.put(ClassHint.RESOLVE_CONTEXT, qualifier).put(SpreadState.SPREAD_STATE, SpreadState.create(qType, null)) return processQualifierType(componentType, state) } } else { if (ResolveUtil.isClassReference(place)) return false - if (!processJavaLangClass(qualifier)) return false - return processQualifier(qualifier) + if (!processJavaLangClass(qualifier, initialState)) return false + if (!processQualifier(qualifier, initialState)) return false } } return true } - private fun processJavaLangClass(qualifier: GrExpression): Boolean { + private fun processJavaLangClass(qualifier: GrExpression, initialState: ResolveState): Boolean { if (qualifier !is GrReferenceExpression) return true //optimization: only 'class' or 'this' in static context can be an alias of java.lang.Class @@ -66,14 +69,14 @@ class GrReferenceResolveRunner(val place: GrReferenceExpression, val processor: val classType = ResolveUtil.unwrapClassType(qualifier.getType()) return classType?.let { - val state = ResolveState.initial().put(ClassHint.RESOLVE_CONTEXT, qualifier) + val state = initialState.put(ClassHint.RESOLVE_CONTEXT, qualifier) processQualifierType(classType, state) } ?: true } - private fun processQualifier(qualifier: GrExpression): Boolean { + private fun processQualifier(qualifier: GrExpression, initialState: ResolveState): Boolean { val qualifierType = qualifier.type - val state = ResolveState.initial().put(ClassHint.RESOLVE_CONTEXT, qualifier) + val state = initialState.put(ClassHint.RESOLVE_CONTEXT, qualifier) if (qualifierType == null || PsiType.VOID == qualifierType) { if (qualifier is GrReferenceExpression) { val resolved = qualifier.resolve() 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 422f6e04ef6b..c119541f416e 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 @@ -225,6 +225,20 @@ class X { assert file.contentsLoaded } + void 'test do not load ast for annotation reference value'() { + def file = myFixture.addFileToProject('Pogo.groovy', '''\ +@groovy.transform.AutoClone(style=groovy.transform.AutoCloneStyle.SIMPLE) +class Pogo {} +''') as GroovyFileImpl + assert !file.contentsLoaded + def clazz = file.classes[0] + assert !file.contentsLoaded + def method = clazz.methods.find { it.name == 'cloneOrCopyMembers' } + assert !file.contentsLoaded + assert method?.hasModifierProperty(PsiModifier.PROTECTED) + assert !file.contentsLoaded + } + void "test do not load content for findMethodsByName"() { GroovyFileImpl file = myFixture.addFileToProject('usage.groovy', '''\ class X {