From 1b42e2fdcc1fe307777eb57e99c18d2d088c10e4 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 21 Apr 2015 12:51:04 +0300 Subject: [PATCH] Deprecate calls of annotations' methods --- .../kotlin/JavaAnnotationMethodCallChecker.kt | 39 +++++++++++++++++++ .../load/kotlin/KotlinJvmCheckerProvider.kt | 2 +- .../diagnostics/DefaultErrorMessagesJvm.java | 1 + .../resolve/jvm/diagnostics/ErrorsJvm.java | 1 + .../annotations/annotationClassMethodCall.kt | 27 +++++++++++++ .../annotations/annotationClassMethodCall.txt | 22 +++++++++++ ...JetDiagnosticsTestWithStdLibGenerated.java | 6 +++ 7 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/JavaAnnotationMethodCallChecker.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/annotations/annotationClassMethodCall.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/annotations/annotationClassMethodCall.txt diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/JavaAnnotationMethodCallChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/JavaAnnotationMethodCallChecker.kt new file mode 100644 index 00000000000..64993940525 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/JavaAnnotationMethodCallChecker.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.load.kotlin + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor +import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor +import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker +import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm + +public class JavaAnnotationMethodCallChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall, context: BasicCallResolutionContext) { + val descriptor = resolvedCall.getCandidateDescriptor().getOriginal() + val containingDeclaration = descriptor.getContainingDeclaration() + + if (containingDeclaration is JavaClassDescriptor && + containingDeclaration.getKind() == ClassKind.ANNOTATION_CLASS && + descriptor is JavaMethodDescriptor && descriptor.getKind().isReal() + ) { + context.trace.report(ErrorsJvm.DEPRECATED_ANNOTATION_METHOD_CALL.on(resolvedCall.getCall().getCallElement())) + } + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmCheckerProvider.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmCheckerProvider.kt index 9f346907026..a9d965bf4da 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmCheckerProvider.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmCheckerProvider.kt @@ -52,7 +52,7 @@ public object KotlinJvmCheckerProvider : AdditionalCheckerProvider( ReifiedTypeParameterAnnotationChecker(), NativeFunChecker(), OverloadsAnnotationChecker()), - additionalCallCheckers = listOf(NeedSyntheticChecker(), JavaAnnotationCallChecker()), + additionalCallCheckers = listOf(NeedSyntheticChecker(), JavaAnnotationCallChecker(), JavaAnnotationMethodCallChecker()), additionalTypeCheckers = listOf(JavaNullabilityWarningsChecker()) ) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java index 4d72b7482cc..e34ac3d291e 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java @@ -58,6 +58,7 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension { MAP.put(ErrorsJvm.POSITIONED_VALUE_ARGUMENT_FOR_JAVA_ANNOTATION, "Only named arguments are available for Java annotations"); MAP.put(ErrorsJvm.JAVA_LANG_CLASS_ARGUMENT_IN_ANNOTATION, "Usage of `javaClass()` in annotations is deprecated. Use T::class instead"); + MAP.put(ErrorsJvm.DEPRECATED_ANNOTATION_METHOD_CALL, "Annotation methods are deprecated. Use property instead"); MAP.put(ErrorsJvm.NO_REFLECTION_IN_CLASS_PATH, "Expression ''{0}'' uses reflection which is not found in compilation classpath. Make sure you have kotlin-reflect.jar in the classpath", Renderers.ELEMENT_TEXT); diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java index c0b5ec2f51d..733dbf8575e 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java @@ -53,6 +53,7 @@ public interface ErrorsJvm { DiagnosticFactory0 POSITIONED_VALUE_ARGUMENT_FOR_JAVA_ANNOTATION = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 JAVA_LANG_CLASS_ARGUMENT_IN_ANNOTATION = DiagnosticFactory0.create(WARNING); + DiagnosticFactory0 DEPRECATED_ANNOTATION_METHOD_CALL = DiagnosticFactory0.create(WARNING); // TODO: make this a warning DiagnosticFactory1 NO_REFLECTION_IN_CLASS_PATH = DiagnosticFactory1.create(ERROR); diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationClassMethodCall.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationClassMethodCall.kt new file mode 100644 index 00000000000..4cb16148eb5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationClassMethodCall.kt @@ -0,0 +1,27 @@ +// FILE: A.java +public @interface A { + String value(); + int arg(); +} + +// FILE: b.kt +A(value = "a", arg = 1) class MyClass + +fun foo(ann: A) { + ann.value() + ann.arg() + + ann.equals(ann) + ann.toString() + ann.hashCode() + + javaClass().getAnnotation(javaClass()).value() + javaClass().getAnnotation(javaClass()).arg() +} + +fun A.bar() { + value() + arg() + this.value() + this.arg() +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationClassMethodCall.txt b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationClassMethodCall.txt new file mode 100644 index 00000000000..d4f7f9dd305 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationClassMethodCall.txt @@ -0,0 +1,22 @@ +package + +internal fun foo(/*0*/ ann: A): kotlin.Unit +internal fun A.bar(): kotlin.Unit + +public final annotation class A : kotlin.Annotation { + public constructor A(/*0*/ value: kotlin.String, /*1*/ arg: kotlin.Int) + public final val arg: kotlin.Int + public final val value: kotlin.String + public abstract fun arg(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + public abstract fun value(): kotlin.String +} + +A(arg = IntegerValueType(1): IntegerValueType(1), value = "a": kotlin.String) internal final class MyClass { + public constructor MyClass() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestWithStdLibGenerated.java index 72ad06d7a15..db4bc6b3146 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestWithStdLibGenerated.java @@ -43,6 +43,12 @@ public class JetDiagnosticsTestWithStdLibGenerated extends AbstractJetDiagnostic JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/annotations"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("annotationClassMethodCall.kt") + public void testAnnotationClassMethodCall() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationClassMethodCall.kt"); + doTest(fileName); + } + @TestMetadata("ClassObjectAnnotatedWithItsClass.kt") public void testClassObjectAnnotatedWithItsClass() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/ClassObjectAnnotatedWithItsClass.kt");