Resolve annotation arguments only once

This commit is contained in:
Andrey Breslav
2014-03-26 15:16:00 +04:00
parent 298ddcf0ad
commit 708694a09d
6 changed files with 34 additions and 7 deletions
@@ -223,11 +223,17 @@ public class AnnotationResolver {
return; return;
} }
AnnotationDescriptorImpl annotationDescriptorImpl = (AnnotationDescriptorImpl) annotationDescriptor;
if (annotationDescriptorImpl.areValueArgumentsResolved()) return;
OverloadResolutionResults<FunctionDescriptor> results = resolveAnnotationCall(annotationEntry, scope, trace); OverloadResolutionResults<FunctionDescriptor> results = resolveAnnotationCall(annotationEntry, scope, trace);
if (results.isSingleResult()) { if (results.isSingleResult()) {
checkAnnotationType(annotationEntry, trace, results); checkAnnotationType(annotationEntry, trace, results);
resolveAnnotationArguments(annotationDescriptor, results.getResultingCall(), trace); resolveAnnotationArguments(annotationDescriptor, results.getResultingCall(), trace);
} }
else {
annotationDescriptorImpl.markValueArgumentsResolved();
}
} }
public static void resolveAnnotationArguments( public static void resolveAnnotationArguments(
@@ -240,15 +246,19 @@ public class AnnotationResolver {
return; return;
} }
AnnotationDescriptorImpl annotationDescriptorImpl = (AnnotationDescriptorImpl) annotationDescriptor;
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> descriptorToArgument : resolvedCall.getValueArguments().entrySet()) { for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> descriptorToArgument : resolvedCall.getValueArguments().entrySet()) {
ValueParameterDescriptor parameterDescriptor = descriptorToArgument.getKey(); ValueParameterDescriptor parameterDescriptor = descriptorToArgument.getKey();
ResolvedValueArgument resolvedArgument = descriptorToArgument.getValue(); ResolvedValueArgument resolvedArgument = descriptorToArgument.getValue();
CompileTimeConstant<?> value = getAnnotationArgumentValue(trace, parameterDescriptor, resolvedArgument); CompileTimeConstant<?> value = getAnnotationArgumentValue(trace, parameterDescriptor, resolvedArgument);
if (value != null) { if (value != null) {
((AnnotationDescriptorImpl) annotationDescriptor).setValueArgument(parameterDescriptor, value); annotationDescriptorImpl.setValueArgument(parameterDescriptor, value);
} }
} }
annotationDescriptorImpl.markValueArgumentsResolved();
} }
@Nullable @Nullable
@@ -157,6 +157,7 @@ public class AnnotationDescriptorDeserializer extends BaseDescriptorDeserializer
@Override @Override
public void visitEnd() { public void visitEnd() {
annotation.markValueArgumentsResolved();
result.add(annotation); result.add(annotation);
} }
@@ -30,6 +30,7 @@ import java.util.Map;
public class AnnotationDescriptorImpl implements AnnotationDescriptor { public class AnnotationDescriptorImpl implements AnnotationDescriptor {
private JetType annotationType; private JetType annotationType;
private final Map<ValueParameterDescriptor, CompileTimeConstant<?>> valueArguments = Maps.newHashMap(); private final Map<ValueParameterDescriptor, CompileTimeConstant<?>> valueArguments = Maps.newHashMap();
private boolean valueArgumentsResolved = false;
@Override @Override
@NotNull @NotNull
@@ -40,12 +41,14 @@ public class AnnotationDescriptorImpl implements AnnotationDescriptor {
@Override @Override
@Nullable @Nullable
public CompileTimeConstant<?> getValueArgument(@NotNull ValueParameterDescriptor valueParameterDescriptor) { public CompileTimeConstant<?> getValueArgument(@NotNull ValueParameterDescriptor valueParameterDescriptor) {
return valueArguments.get(valueParameterDescriptor); return getAllValueArguments().get(valueParameterDescriptor);
} }
@Override @Override
@NotNull @NotNull
public Map<ValueParameterDescriptor, CompileTimeConstant<?>> getAllValueArguments() { public Map<ValueParameterDescriptor, CompileTimeConstant<?>> 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); return Collections.unmodifiableMap(valueArguments);
} }
@@ -54,9 +57,18 @@ public class AnnotationDescriptorImpl implements AnnotationDescriptor {
} }
public void setValueArgument(@NotNull ValueParameterDescriptor name, @NotNull CompileTimeConstant<?> value) { public void setValueArgument(@NotNull ValueParameterDescriptor name, @NotNull CompileTimeConstant<?> value) {
assert !valueArgumentsResolved : "Value arguments are already resolved for " + this;
valueArguments.put(name, value); valueArguments.put(name, value);
} }
public void markValueArgumentsResolved() {
this.valueArgumentsResolved = true;
}
public boolean areValueArgumentsResolved() {
return valueArgumentsResolved;
}
@Override @Override
public String toString() { public String toString() {
return DescriptorRenderer.TEXT.renderAnnotation(this); return DescriptorRenderer.TEXT.renderAnnotation(this);
@@ -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); JetDeclaration declaration = PsiTreeUtil.getParentOfType(jetAnnotationEntry, JetDeclaration.class);
if (declaration != null) { 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()); ForceResolveUtil.forceResolveAllContents(descriptor.getAnnotations());
} }
@@ -1,6 +1,5 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true" // "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
// ERROR: An integer literal does not conform to the expected type kotlin.String
[suppress(1, "REDUNDANT_NULLABLE")] [suppress(1, "REDUNDANT_NULLABLE")]
fun foo(): String?<caret>? = null fun foo(): String?<caret>? = null
@@ -1,6 +1,5 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true" // "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
// ERROR: An integer literal does not conform to the expected type kotlin.String
[suppress(1)] [suppress(1)]
fun foo(): String?<caret>? = null fun foo(): String?<caret>? = null