From 197218a512b5bd99544458eaa643441b4869063f Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Tue, 20 Oct 2015 17:43:44 +0300 Subject: [PATCH] KT-9389 Code completion inserts annotation FQN into annotation list #KT-9389 Fixed --- .../idea/project/ResolveElementCache.kt | 40 +++++++++++++------ .../handlers/basic/AnnotationInBrackets.kt | 10 +++++ .../basic/AnnotationInBrackets.kt.after | 10 +++++ .../BasicCompletionHandlerTestGenerated.java | 6 +++ 4 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 idea/idea-completion/testData/handlers/basic/AnnotationInBrackets.kt create mode 100644 idea/idea-completion/testData/handlers/basic/AnnotationInBrackets.kt.after diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt index e089a7a3891..0337bec7a27 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt @@ -144,7 +144,6 @@ public class ResolveElementCache( partialResolveMap[statementToResolve ?: resolveElement] ?.check { it.isUpToDate(file) } ?.let { return it.bindingContext } // partial resolve is already cached for this statement - val (bindingContext, statementFilter) = performElementAdditionalResolve(resolveElement, contextElement, BodyResolveMode.PARTIAL) if (statementFilter == StatementFilter.NONE) { // partial resolve is not supported for the given declaration - full resolve performed instead @@ -412,33 +411,37 @@ public class ResolveElementCache( return trace } - private fun propertyAdditionalResolve(resolveSession: ResolveSession, jetProperty: KtProperty, file: KtFile, statementFilter: StatementFilter): BindingTrace { - val trace = createDelegatingTrace(jetProperty) - val propertyResolutionScope = resolveSession.getDeclarationScopeProvider().getResolutionScopeForDeclaration(jetProperty) + private fun propertyAdditionalResolve(resolveSession: ResolveSession, property: KtProperty, file: KtFile, statementFilter: StatementFilter): BindingTrace { + val trace = createDelegatingTrace(property) + val propertyResolutionScope = resolveSession.getDeclarationScopeProvider().getResolutionScopeForDeclaration(property) val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter) - val descriptor = resolveSession.resolveToDescriptor(jetProperty) as PropertyDescriptor + val descriptor = resolveSession.resolveToDescriptor(property) as PropertyDescriptor ForceResolveUtil.forceResolveAllContents(descriptor) - val propertyInitializer = jetProperty.getInitializer() + val propertyInitializer = property.getInitializer() if (propertyInitializer != null) { - bodyResolver.resolvePropertyInitializer(DataFlowInfo.EMPTY, jetProperty, descriptor, propertyInitializer, propertyResolutionScope) + bodyResolver.resolvePropertyInitializer(DataFlowInfo.EMPTY, property, descriptor, propertyInitializer, propertyResolutionScope) } - val propertyDelegate = jetProperty.getDelegateExpression() + val propertyDelegate = property.getDelegateExpression() if (propertyDelegate != null) { - bodyResolver.resolvePropertyDelegate(DataFlowInfo.EMPTY, jetProperty, descriptor, propertyDelegate, propertyResolutionScope, propertyResolutionScope) + bodyResolver.resolvePropertyDelegate(DataFlowInfo.EMPTY, property, descriptor, propertyDelegate, propertyResolutionScope, propertyResolutionScope) } val bodyResolveContext = BodyResolveContextForLazy(TopDownAnalysisMode.LocalDeclarations, { declaration -> - assert(declaration.getParent() == jetProperty) { "Must be called only for property accessors, but called for $declaration" } + assert(declaration.getParent() == property) { "Must be called only for property accessors, but called for $declaration" } resolveSession.getDeclarationScopeProvider().getResolutionScopeForDeclaration(declaration) }) - bodyResolver.resolvePropertyAccessors(bodyResolveContext, jetProperty, descriptor) + bodyResolver.resolvePropertyAccessors(bodyResolveContext, property, descriptor) - for (accessor in jetProperty.getAccessors()) { + forceResolveAnnotations(property) + + for (accessor in property.getAccessors()) { JetFlowInformationProvider(accessor, trace).checkDeclaration() + + forceResolveAnnotations(accessor) } return trace @@ -454,6 +457,8 @@ public class ResolveElementCache( val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter) bodyResolver.resolveFunctionBody(DataFlowInfo.EMPTY, trace, namedFunction, functionDescriptor, scope) + forceResolveAnnotations(namedFunction) + return trace } @@ -467,6 +472,8 @@ public class ResolveElementCache( val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter) bodyResolver.resolveSecondaryConstructorBody(DataFlowInfo.EMPTY, trace, constructor, constructorDescriptor, scope) + forceResolveAnnotations(constructor) + return trace } @@ -493,9 +500,18 @@ public class ResolveElementCache( val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter) bodyResolver.resolveAnonymousInitializer(DataFlowInfo.EMPTY, classInitializer, classOrObjectDescriptor) + forceResolveAnnotations(classInitializer) + return trace } + private fun forceResolveAnnotations(declaration: KtModifierListOwner) { + for (annotationEntry in declaration.annotationEntries) { + val annotationDescriptor = resolveSession.bindingContext[BindingContext.ANNOTATION, annotationEntry] ?: continue + ForceResolveUtil.forceResolveAllContents(annotationDescriptor) + } + } + private fun createBodyResolver( resolveSession: ResolveSession, trace: BindingTrace, diff --git a/idea/idea-completion/testData/handlers/basic/AnnotationInBrackets.kt b/idea/idea-completion/testData/handlers/basic/AnnotationInBrackets.kt new file mode 100644 index 00000000000..1b1c9a5a14b --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/AnnotationInBrackets.kt @@ -0,0 +1,10 @@ +package some + +annotation class AnnComplete + +class Multiplier { + @get:[A] + var property = 0 +} + +// ELEMENT: AnnComplete \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/basic/AnnotationInBrackets.kt.after b/idea/idea-completion/testData/handlers/basic/AnnotationInBrackets.kt.after new file mode 100644 index 00000000000..4795add066a --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/AnnotationInBrackets.kt.after @@ -0,0 +1,10 @@ +package some + +annotation class AnnComplete + +class Multiplier { + @get:[AnnComplete] + var property = 0 +} + +// ELEMENT: AnnComplete \ No newline at end of file diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java index 2aeaf03eb29..4a7ffce6896 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java @@ -35,6 +35,12 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/handlers/basic"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("AnnotationInBrackets.kt") + public void testAnnotationInBrackets() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/AnnotationInBrackets.kt"); + doTest(fileName); + } + @TestMetadata("AnnotationInClassAddImport.kt") public void testAnnotationInClassAddImport() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/AnnotationInClassAddImport.kt");