From 0a42abc7c91607b00d902b506fde725d07b89e91 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 28 Mar 2012 19:40:45 +0400 Subject: [PATCH] KT-1152 Only allow annotation classes to be instantiated as annotations #KT-1152 Fixed --- .../jet/lang/diagnostics/Errors.java | 2 + .../jet/lang/resolve/AnnotationResolver.java | 47 ++++++++++++------- .../jet/lang/resolve/calls/CallResolver.java | 4 +- .../calls/OverloadResolutionResults.java | 2 +- .../calls/OverloadResolutionResultsImpl.java | 4 +- .../BasicExpressionTypingVisitor.java | 2 +- .../expressions/ExpressionTypingContext.java | 2 +- .../AmbigiousAnnotationConstructor.jet | 5 ++ .../tests/annotations/NonAnnotationClass.jet | 3 ++ 9 files changed, 47 insertions(+), 24 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/annotations/AmbigiousAnnotationConstructor.jet create mode 100644 compiler/testData/diagnostics/tests/annotations/NonAnnotationClass.jet diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 52ebcbd8be8..c683d8948e6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -448,6 +448,8 @@ public interface Errors { DiagnosticFactory DANGLING_FUNCTION_LITERAL_ARGUMENT_SUSPECTED = DiagnosticFactory.create(WARNING, "This expression is treated as an argument to the function call on the previous line. " + "Separate it with a semicolon (;) if it is not intended to be an argument."); + DiagnosticFactory1 NOT_AN_ANNOTATION_CLASS = DiagnosticFactory1.create(ERROR, "{0} is not an annotation class"); + // This field is needed to make the Initializer class load (interfaces cannot have static initializers) @SuppressWarnings("UnusedDeclaration") 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 34e3d93b576..93233c8c36c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java @@ -19,9 +19,9 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; -import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.calls.CallMaker; import org.jetbrains.jet.lang.resolve.calls.CallResolver; @@ -82,23 +82,36 @@ public class AnnotationResolver { } public void resolveAnnotationStub(@NotNull JetScope scope, @NotNull JetAnnotationEntry entryElement, - @NotNull AnnotationDescriptor descriptor, BindingTrace trace) { - OverloadResolutionResults results = resolveType(scope, entryElement, descriptor, trace); - resolveArguments(results, descriptor, trace); - } - - @NotNull - private OverloadResolutionResults resolveType(@NotNull JetScope scope, - @NotNull JetAnnotationEntry entryElement, - @NotNull AnnotationDescriptor descriptor, BindingTrace trace) { - OverloadResolutionResults results = callResolver.resolveFunctionCall(trace, scope, CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, entryElement), NO_EXPECTED_TYPE, DataFlowInfo.EMPTY); - JetType annotationType = results.getResultingDescriptor().getReturnType(); + @NotNull AnnotationDescriptor annotationDescriptor, BindingTrace trace) { + OverloadResolutionResults results = callResolver.resolveFunctionCall( + trace, + scope, + CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, entryElement), + NO_EXPECTED_TYPE, + DataFlowInfo.EMPTY); if (results.isSuccess()) { - descriptor.setAnnotationType(annotationType); - } else { - descriptor.setAnnotationType(ErrorUtils.createErrorType("Unresolved annotation type")); + FunctionDescriptor descriptor = results.getResultingDescriptor(); + if (!ErrorUtils.isError(descriptor)) { + if (descriptor instanceof ConstructorDescriptor) { + ConstructorDescriptor constructor = (ConstructorDescriptor)descriptor; + ClassDescriptor classDescriptor = constructor.getContainingDeclaration(); + if (classDescriptor.getKind() != ClassKind.ANNOTATION_CLASS) { + trace.report(Errors.NOT_AN_ANNOTATION_CLASS.on(entryElement, classDescriptor.getName())); + } + } + else { + trace.report(Errors.NOT_AN_ANNOTATION_CLASS.on(entryElement, descriptor.getName())); + } + } + } + if (results.isSuccess()) { + JetType annotationType = results.getResultingDescriptor().getReturnType(); + annotationDescriptor.setAnnotationType(annotationType); + resolveArguments(results, annotationDescriptor, trace); + } + else { + annotationDescriptor.setAnnotationType(ErrorUtils.createErrorType("Unresolved annotation type")); } - return results; } private void resolveArguments(@NotNull OverloadResolutionResults results, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 2a7fe8aced5..64174476b73 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -276,7 +276,7 @@ public class CallResolver { } if (traceForFirstNonemptyCandidateSet != null) { traceForFirstNonemptyCandidateSet.commit(); - if (resultsForFirstNonemptyCandidateSet.singleResult()) { + if (resultsForFirstNonemptyCandidateSet.isSingleResult()) { debugInfo.set(ResolutionDebugInfo.RESULT, resultsForFirstNonemptyCandidateSet.getResultingCall()); } @@ -436,7 +436,7 @@ public class CallResolver { } OverloadResolutionResultsImpl results = computeResultAndReportErrors(task.trace, task.tracing, successfulCandidates, failedCandidates); - if (!results.singleResult()) { + if (!results.isSingleResult()) { checkTypesWithNoCallee(task.toBasic()); } return results; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadResolutionResults.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadResolutionResults.java index 73a4382bc11..e9db7837c0c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadResolutionResults.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadResolutionResults.java @@ -57,7 +57,7 @@ public interface OverloadResolutionResults { boolean isSuccess(); - boolean singleResult(); + boolean isSingleResult(); boolean isNothing(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadResolutionResultsImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadResolutionResultsImpl.java index 351faf428e6..5e90d79d572 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadResolutionResultsImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadResolutionResultsImpl.java @@ -63,7 +63,7 @@ import java.util.Collections; @Override @NotNull public ResolvedCallImpl getResultingCall() { - assert singleResult(); + assert isSingleResult(); return results.iterator().next(); } @@ -85,7 +85,7 @@ import java.util.Collections; } @Override - public boolean singleResult() { + public boolean isSingleResult() { return isSuccess() || resultCode == Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index d49ec8fc56d..ba5495af49b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -609,7 +609,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { checkSuper(receiver, resultingDescriptor, context.trace, selectorExpression); return resultingDescriptor.getType(); } - if (resolutionResult.isAmbiguity() || resolutionResult.singleResult()) { + if (resolutionResult.isAmbiguity() || resolutionResult.isSingleResult()) { temporaryTrace.commit(); return null; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java index dac045d3042..6db02920ecc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java @@ -172,7 +172,7 @@ public class ExpressionTypingContext { @Nullable public FunctionDescriptor resolveCall(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetCallExpression callExpression) { OverloadResolutionResults results = expressionTypingServices.getCallResolver().resolveFunctionCall(trace, scope, CallMaker.makeCall(receiver, callOperationNode, callExpression), expectedType, dataFlowInfo); - return results.singleResult() ? results.getResultingDescriptor() : null; + return results.isSingleResult() ? results.getResultingDescriptor() : null; } @NotNull diff --git a/compiler/testData/diagnostics/tests/annotations/AmbigiousAnnotationConstructor.jet b/compiler/testData/diagnostics/tests/annotations/AmbigiousAnnotationConstructor.jet new file mode 100644 index 00000000000..e8f8363234b --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/AmbigiousAnnotationConstructor.jet @@ -0,0 +1,5 @@ +import java.util.ArrayList + +ArrayList(1, 1) fun b() {} +Xoo(x) fun c() {} +Deprecated(x) fun a() {} diff --git a/compiler/testData/diagnostics/tests/annotations/NonAnnotationClass.jet b/compiler/testData/diagnostics/tests/annotations/NonAnnotationClass.jet new file mode 100644 index 00000000000..d71367298d0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/NonAnnotationClass.jet @@ -0,0 +1,3 @@ +class Foo + +Foo class Bar \ No newline at end of file