From 4eac12e350b017f70a17531877acfcbca874b5f0 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 10 Oct 2016 14:49:48 +0300 Subject: [PATCH] Report warning when SinceKotlin value is greater than -api-version value To prevent this diagnostic be reported in each test on SinceKotlin, disable it when a diagnostic test contains the "!API_VERSION" directive --- .../jetbrains/kotlin/diagnostics/Errors.java | 1 + .../rendering/DefaultErrorMessages.java | 1 + .../SinceKotlinAnnotationValueChecker.kt | 22 +++++++++++++++---- .../jvm/apiVersionAndSinceNewerKotlin.args | 5 +++++ .../cli/jvm/apiVersionAndSinceNewerKotlin.kt | 5 +++++ .../cli/jvm/apiVersionAndSinceNewerKotlin.out | 4 ++++ compiler/testData/diagnostics/ReadMe.md | 1 + .../annotations/illegalSinceKotlinValue.kt | 2 +- .../kotlin/checkers/BaseDiagnosticsTest.java | 12 +++++++++- .../kotlin/cli/CliTestGenerated.java | 6 +++++ 10 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 compiler/testData/cli/jvm/apiVersionAndSinceNewerKotlin.args create mode 100644 compiler/testData/cli/jvm/apiVersionAndSinceNewerKotlin.kt create mode 100644 compiler/testData/cli/jvm/apiVersionAndSinceNewerKotlin.out diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 73646f21242..26243d0bab3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -182,6 +182,7 @@ public interface Errors { DiagnosticFactory0 ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 ILLEGAL_SINCE_KOTLIN_VALUE = DiagnosticFactory0.create(ERROR); + DiagnosticFactory1 NEWER_VERSION_IN_SINCE_KOTLIN = DiagnosticFactory1.create(WARNING); // Const DiagnosticFactory0 CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT = DiagnosticFactory0.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index b7ff3119e07..a41da71c064 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -162,6 +162,7 @@ public class DefaultErrorMessages { MAP.put(REDUNDANT_ANNOTATION_TARGET, "Redundant annotation target ''{0}''", STRING); MAP.put(ILLEGAL_SINCE_KOTLIN_VALUE, "Invalid @SinceKotlin annotation value (should be 'major.minor' or 'major.minor.patch')"); + MAP.put(NEWER_VERSION_IN_SINCE_KOTLIN, "The version is greater than the specified API version {0}", STRING); MAP.put(REDUNDANT_MODIFIER, "Modifier ''{0}'' is redundant because ''{1}'' is present", TO_STRING, TO_STRING); MAP.put(REDUNDANT_OPEN_IN_INTERFACE, "Modifier 'open' is redundant for abstract interface members"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/SinceKotlinAnnotationValueChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/SinceKotlinAnnotationValueChecker.kt index b7498f3e06c..f87746d1ba6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/SinceKotlinAnnotationValueChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/SinceKotlinAnnotationValueChecker.kt @@ -16,24 +16,38 @@ package org.jetbrains.kotlin.resolve.checkers +import org.jetbrains.kotlin.config.ApiVersion +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.diagnostics.DiagnosticSink -import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.diagnostics.Errors.ILLEGAL_SINCE_KOTLIN_VALUE +import org.jetbrains.kotlin.diagnostics.Errors.NEWER_VERSION_IN_SINCE_KOTLIN import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.getSinceKotlinAnnotation import org.jetbrains.kotlin.resolve.source.getPsi -object SinceKotlinAnnotationValueChecker : SimpleDeclarationChecker { +object SinceKotlinAnnotationValueChecker : DeclarationChecker { private val regex: Regex = "(0|[1-9][0-9]*)".let { number -> Regex("$number\\.$number(\\.$number)?") } override fun check( - declaration: KtDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink, bindingContext: BindingContext + declaration: KtDeclaration, + descriptor: DeclarationDescriptor, + diagnosticHolder: DiagnosticSink, + bindingContext: BindingContext, + languageVersionSettings: LanguageVersionSettings ) { val annotation = descriptor.getSinceKotlinAnnotation() ?: return val version = annotation.allValueArguments.values.singleOrNull()?.value as? String ?: return if (!version.matches(regex)) { - diagnosticHolder.report(Errors.ILLEGAL_SINCE_KOTLIN_VALUE.on(annotation.source.getPsi() ?: declaration)) + diagnosticHolder.report(ILLEGAL_SINCE_KOTLIN_VALUE.on(annotation.source.getPsi() ?: declaration)) + return + } + + val apiVersion = ApiVersion.parse(version) + val specified = languageVersionSettings.apiVersion + if (apiVersion != null && apiVersion > specified) { + diagnosticHolder.report(NEWER_VERSION_IN_SINCE_KOTLIN.on(annotation.source.getPsi() ?: declaration, specified.versionString)) } } } diff --git a/compiler/testData/cli/jvm/apiVersionAndSinceNewerKotlin.args b/compiler/testData/cli/jvm/apiVersionAndSinceNewerKotlin.args new file mode 100644 index 00000000000..6454e01784a --- /dev/null +++ b/compiler/testData/cli/jvm/apiVersionAndSinceNewerKotlin.args @@ -0,0 +1,5 @@ +$TESTDATA_DIR$/apiVersionAndSinceNewerKotlin.kt +-d +$TEMP_DIR$ +-api-version +1.0 diff --git a/compiler/testData/cli/jvm/apiVersionAndSinceNewerKotlin.kt b/compiler/testData/cli/jvm/apiVersionAndSinceNewerKotlin.kt new file mode 100644 index 00000000000..dc1db006384 --- /dev/null +++ b/compiler/testData/cli/jvm/apiVersionAndSinceNewerKotlin.kt @@ -0,0 +1,5 @@ +@SinceKotlin("1.0") +fun old() {} + +@SinceKotlin("1.1") +fun new() {} diff --git a/compiler/testData/cli/jvm/apiVersionAndSinceNewerKotlin.out b/compiler/testData/cli/jvm/apiVersionAndSinceNewerKotlin.out new file mode 100644 index 00000000000..785c4cc8b61 --- /dev/null +++ b/compiler/testData/cli/jvm/apiVersionAndSinceNewerKotlin.out @@ -0,0 +1,4 @@ +compiler/testData/cli/jvm/apiVersionAndSinceNewerKotlin.kt:4:1: warning: the version is greater than the specified API version 1.0 +@SinceKotlin("1.1") +^ +OK diff --git a/compiler/testData/diagnostics/ReadMe.md b/compiler/testData/diagnostics/ReadMe.md index 121e0a17765..d8409e542ff 100644 --- a/compiler/testData/diagnostics/ReadMe.md +++ b/compiler/testData/diagnostics/ReadMe.md @@ -87,6 +87,7 @@ This directive lets you enable or disable certain language features. Language fe ### 5. API_VERSION This directive emulates the behavior of the `-api-version` command line option, disallowing to use declarations annotated with `@SinceKotlin(X)` where X is greater than the specified API version. +Note that if this directive is present, the NEWER_VERSION_IN_SINCE_KOTLIN diagnostic is automatically disabled, _unless_ the "!DIAGNOSTICS" directive is present. #### Usage: diff --git a/compiler/testData/diagnostics/tests/annotations/illegalSinceKotlinValue.kt b/compiler/testData/diagnostics/tests/annotations/illegalSinceKotlinValue.kt index 635bb92d4e9..42a5ad6dbc1 100644 --- a/compiler/testData/diagnostics/tests/annotations/illegalSinceKotlinValue.kt +++ b/compiler/testData/diagnostics/tests/annotations/illegalSinceKotlinValue.kt @@ -70,5 +70,5 @@ fun ok2() {} @SinceKotlin("0.0.0") fun ok3() {} -@SinceKotlin("123456789012345678901234567890.123456789012345678901234567890.123456789012345678901234567890") +@SinceKotlin("123456789012345678901234567890.123456789012345678901234567890.123456789012345678901234567890") fun ok4() {} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/BaseDiagnosticsTest.java b/compiler/tests/org/jetbrains/kotlin/checkers/BaseDiagnosticsTest.java index c7711f81fd4..ac99b50a5c9 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/BaseDiagnosticsTest.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/BaseDiagnosticsTest.java @@ -205,9 +205,19 @@ public abstract class BaseDiagnosticsTest return values; } - public static Condition parseDiagnosticFilterDirective(Map directiveMap) { + private static Condition parseDiagnosticFilterDirective(Map directiveMap) { String directives = directiveMap.get(DIAGNOSTICS_DIRECTIVE); if (directives == null) { + // If "!API_VERSION" is present, disable the NEWER_VERSION_IN_SINCE_KOTLIN diagnostic. + // Otherwise it would be reported in any non-trivial test on the @SinceKotlin value. + if (directiveMap.containsKey(API_VERSION_DIRECTIVE)) { + return new Condition() { + @Override + public boolean value(Diagnostic diagnostic) { + return diagnostic.getFactory() != Errors.NEWER_VERSION_IN_SINCE_KOTLIN; + } + }; + } return Conditions.alwaysTrue(); } Condition condition = Conditions.alwaysTrue(); diff --git a/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java index c03a0fdc07e..9585e5911ff 100644 --- a/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java @@ -43,6 +43,12 @@ public class CliTestGenerated extends AbstractCliTest { doJvmTest(fileName); } + @TestMetadata("apiVersionAndSinceNewerKotlin.args") + public void testApiVersionAndSinceNewerKotlin() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/apiVersionAndSinceNewerKotlin.args"); + doJvmTest(fileName); + } + @TestMetadata("apiVersionGreaterThanLanguage.args") public void testApiVersionGreaterThanLanguage() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/apiVersionGreaterThanLanguage.args");