From 708694a09d4ed4d98498fd0e0e37f91524d2ee8f Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 26 Mar 2014 15:16:00 +0400 Subject: [PATCH] Resolve annotation arguments only once --- .../jet/lang/resolve/AnnotationResolver.java | 12 +++++++++++- .../kotlin/AnnotationDescriptorDeserializer.java | 1 + .../annotations/AnnotationDescriptorImpl.java | 16 ++++++++++++++-- .../jet/plugin/project/ResolveElementCache.java | 10 ++++++++-- .../errorRecovery/afterNonStringInSuppress.kt | 1 - .../errorRecovery/beforeNonStringInSuppress.kt | 1 - 6 files changed, 34 insertions(+), 7 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java index 6a8b123574a..0d31430dc0c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java @@ -223,11 +223,17 @@ public class AnnotationResolver { return; } + AnnotationDescriptorImpl annotationDescriptorImpl = (AnnotationDescriptorImpl) annotationDescriptor; + if (annotationDescriptorImpl.areValueArgumentsResolved()) return; + OverloadResolutionResults results = resolveAnnotationCall(annotationEntry, scope, trace); if (results.isSingleResult()) { checkAnnotationType(annotationEntry, trace, results); resolveAnnotationArguments(annotationDescriptor, results.getResultingCall(), trace); } + else { + annotationDescriptorImpl.markValueArgumentsResolved(); + } } public static void resolveAnnotationArguments( @@ -240,15 +246,19 @@ public class AnnotationResolver { return; } + AnnotationDescriptorImpl annotationDescriptorImpl = (AnnotationDescriptorImpl) annotationDescriptor; + for (Map.Entry descriptorToArgument : resolvedCall.getValueArguments().entrySet()) { ValueParameterDescriptor parameterDescriptor = descriptorToArgument.getKey(); ResolvedValueArgument resolvedArgument = descriptorToArgument.getValue(); CompileTimeConstant value = getAnnotationArgumentValue(trace, parameterDescriptor, resolvedArgument); if (value != null) { - ((AnnotationDescriptorImpl) annotationDescriptor).setValueArgument(parameterDescriptor, value); + annotationDescriptorImpl.setValueArgument(parameterDescriptor, value); } } + + annotationDescriptorImpl.markValueArgumentsResolved(); } @Nullable diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java index ea68c5b6dd1..1dbb21646d0 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java @@ -157,6 +157,7 @@ public class AnnotationDescriptorDeserializer extends BaseDescriptorDeserializer @Override public void visitEnd() { + annotation.markValueArgumentsResolved(); result.add(annotation); } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationDescriptorImpl.java b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationDescriptorImpl.java index fb584349022..e3428c409e1 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationDescriptorImpl.java @@ -30,6 +30,7 @@ import java.util.Map; public class AnnotationDescriptorImpl implements AnnotationDescriptor { private JetType annotationType; private final Map> valueArguments = Maps.newHashMap(); + private boolean valueArgumentsResolved = false; @Override @NotNull @@ -40,12 +41,14 @@ public class AnnotationDescriptorImpl implements AnnotationDescriptor { @Override @Nullable public CompileTimeConstant getValueArgument(@NotNull ValueParameterDescriptor valueParameterDescriptor) { - return valueArguments.get(valueParameterDescriptor); + return getAllValueArguments().get(valueParameterDescriptor); } - + @Override @NotNull public Map> getAllValueArguments() { + // TODO: this assertion does not hold now, but this whole class will be gone before long, so I'm not fixing it + //assert valueArgumentsResolved : "Value arguments are not resolved yet for [" + getType() + "]"; return Collections.unmodifiableMap(valueArguments); } @@ -54,9 +57,18 @@ public class AnnotationDescriptorImpl implements AnnotationDescriptor { } public void setValueArgument(@NotNull ValueParameterDescriptor name, @NotNull CompileTimeConstant value) { + assert !valueArgumentsResolved : "Value arguments are already resolved for " + this; valueArguments.put(name, value); } + public void markValueArgumentsResolved() { + this.valueArgumentsResolved = true; + } + + public boolean areValueArgumentsResolved() { + return valueArgumentsResolved; + } + @Override public String toString() { return DescriptorRenderer.TEXT.renderAnnotation(this); diff --git a/idea/src/org/jetbrains/jet/plugin/project/ResolveElementCache.java b/idea/src/org/jetbrains/jet/plugin/project/ResolveElementCache.java index 147ef26d0ce..ca1c7b494e7 100644 --- a/idea/src/org/jetbrains/jet/plugin/project/ResolveElementCache.java +++ b/idea/src/org/jetbrains/jet/plugin/project/ResolveElementCache.java @@ -207,10 +207,16 @@ public class ResolveElementCache { } } - private static void annotationAdditionalResolve(KotlinCodeAnalyzer analyzer, JetAnnotationEntry jetAnnotationEntry) { + private static void annotationAdditionalResolve(ResolveSession resolveSession, JetAnnotationEntry jetAnnotationEntry) { JetDeclaration declaration = PsiTreeUtil.getParentOfType(jetAnnotationEntry, JetDeclaration.class); if (declaration != null) { - Annotated descriptor = analyzer.resolveToDescriptor(declaration); + Annotated descriptor = resolveSession.resolveToDescriptor(declaration); + + resolveSession.getAnnotationResolver().resolveAnnotationsArguments( + descriptor, + resolveSession.getTrace(), + resolveSession.getScopeProvider().getResolutionScopeForDeclaration(declaration) + ); ForceResolveUtil.forceResolveAllContents(descriptor.getAnnotations()); } diff --git a/idea/testData/quickfix/suppress/errorRecovery/afterNonStringInSuppress.kt b/idea/testData/quickfix/suppress/errorRecovery/afterNonStringInSuppress.kt index 033c0c8b681..67732730a50 100644 --- a/idea/testData/quickfix/suppress/errorRecovery/afterNonStringInSuppress.kt +++ b/idea/testData/quickfix/suppress/errorRecovery/afterNonStringInSuppress.kt @@ -1,6 +1,5 @@ // "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true" // ERROR: An integer literal does not conform to the expected type kotlin.String -// ERROR: An integer literal does not conform to the expected type kotlin.String [suppress(1, "REDUNDANT_NULLABLE")] fun foo(): String?? = null \ No newline at end of file diff --git a/idea/testData/quickfix/suppress/errorRecovery/beforeNonStringInSuppress.kt b/idea/testData/quickfix/suppress/errorRecovery/beforeNonStringInSuppress.kt index 060b3e0b8d4..bfb91b60c43 100644 --- a/idea/testData/quickfix/suppress/errorRecovery/beforeNonStringInSuppress.kt +++ b/idea/testData/quickfix/suppress/errorRecovery/beforeNonStringInSuppress.kt @@ -1,6 +1,5 @@ // "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true" // ERROR: An integer literal does not conform to the expected type kotlin.String -// ERROR: An integer literal does not conform to the expected type kotlin.String [suppress(1)] fun foo(): String?? = null \ No newline at end of file