From 984e37c7f17fd2e599023830549f811ba13b7ffd Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 27 Jun 2018 12:28:20 +0200 Subject: [PATCH] Prohibit explicit usage of kotlin.Metadata as annotation --- .../jvm/checkers/ExplicitMetadataChecker.kt | 27 +++++++++++++++++++ .../diagnostics/DefaultErrorMessagesJvm.java | 1 + .../resolve/jvm/diagnostics/ErrorsJvm.java | 2 ++ .../jvm/platform/JvmPlatformConfigurator.kt | 3 ++- .../annotations/explicitMetadata.kt | 11 ++++++++ .../annotations/explicitMetadata.txt | 18 +++++++++++++ .../DiagnosticsTestWithStdLibGenerated.java | 5 ++++ ...ticsTestWithStdLibUsingJavacGenerated.java | 5 ++++ 8 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ExplicitMetadataChecker.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/annotations/explicitMetadata.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/annotations/explicitMetadata.txt diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ExplicitMetadataChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ExplicitMetadataChecker.kt new file mode 100644 index 00000000000..8e95d6c47ab --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ExplicitMetadataChecker.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.resolve.jvm.checkers + +import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.KtAnnotationEntry +import org.jetbrains.kotlin.resolve.AdditionalAnnotationChecker +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm + +object ExplicitMetadataChecker : AdditionalAnnotationChecker { + private val METADATA_FQ_NAME = FqName("kotlin.Metadata") + + override fun checkEntries(entries: List, actualTargets: List, trace: BindingTrace) { + for (entry in entries) { + val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue + if (descriptor.fqName == METADATA_FQ_NAME) { + trace.report(ErrorsJvm.EXPLICIT_METADATA_IS_DISALLOWED.on(entry)) + } + } + } +} 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 a3c5df9bd07..ec1167a4557 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 @@ -141,6 +141,7 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension { MAP.put(JVM_DEFAULT_THROUGH_INHERITANCE, "Inheritance from an interface with '@JvmDefault' members is only allowed with -Xjvm-default option"); MAP.put(USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL, "Super calls of '@JvmDefault' members are only allowed with -Xjvm-default option"); MAP.put(NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT, "Non-@JvmDefault interface method cannot override default Java method. Please annotate this method with @JvmDefault"); + MAP.put(EXPLICIT_METADATA_IS_DISALLOWED, "Explicit @Metadata is disallowed"); } @NotNull 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 d09cef0d3f0..3d742611ea6 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 @@ -123,6 +123,8 @@ public interface ErrorsJvm { DiagnosticFactory0 NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE); + DiagnosticFactory0 EXPLICIT_METADATA_IS_DISALLOWED = DiagnosticFactory0.create(ERROR); + enum NullabilityInformationSource { KOTLIN { @NotNull diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt index b3b7bc26922..fedc33f7067 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt @@ -71,7 +71,8 @@ object JvmPlatformConfigurator : PlatformConfigurator( additionalAnnotationCheckers = listOf( RepeatableAnnotationChecker, - FileClassAnnotationsChecker + FileClassAnnotationsChecker, + ExplicitMetadataChecker ), identifierChecker = JvmSimpleNameBacktickChecker, diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/explicitMetadata.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/explicitMetadata.kt new file mode 100644 index 00000000000..883c807f42b --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/explicitMetadata.kt @@ -0,0 +1,11 @@ +// !DIAGNOSTICS: -INVISIBLE_MEMBER -INVISIBLE_REFERENCE -EXPOSED_PARAMETER_TYPE + +@Metadata +class A + +@Metadata(xs = "_") +annotation class B(val m: Metadata) + +@Metadata(xi = 0) +@B(Metadata()) +fun f() {} diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/explicitMetadata.txt b/compiler/testData/diagnostics/testsWithStdLib/annotations/explicitMetadata.txt new file mode 100644 index 00000000000..140b65c65a0 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/explicitMetadata.txt @@ -0,0 +1,18 @@ +package + +@kotlin.Metadata(xi = 0) @B(m = kotlin.Metadata) public fun f(): kotlin.Unit + +@kotlin.Metadata public final class A { + public constructor A() + 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 +} + +@kotlin.Metadata(xs = "_") public final annotation class B : kotlin.Annotation { + public constructor B(/*0*/ m: kotlin.Metadata) + public final val m: kotlin.Metadata + 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/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index af6abe2ef17..31b731aab0a 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -171,6 +171,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/defaultValueMustBeConstant.kt"); } + @TestMetadata("explicitMetadata.kt") + public void testExplicitMetadata() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/explicitMetadata.kt"); + } + @TestMetadata("JvmSyntheticOnDelegate.kt") public void testJvmSyntheticOnDelegate() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/JvmSyntheticOnDelegate.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java index 2d7351444ff..77c9541633b 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java @@ -171,6 +171,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/defaultValueMustBeConstant.kt"); } + @TestMetadata("explicitMetadata.kt") + public void testExplicitMetadata() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/explicitMetadata.kt"); + } + @TestMetadata("JvmSyntheticOnDelegate.kt") public void testJvmSyntheticOnDelegate() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/JvmSyntheticOnDelegate.kt");