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
This commit is contained in:
@@ -182,6 +182,7 @@ public interface Errors {
|
|||||||
DiagnosticFactory0<KtExpression> ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtExpression> ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT = DiagnosticFactory0.create(ERROR);
|
||||||
|
|
||||||
DiagnosticFactory0<PsiElement> ILLEGAL_SINCE_KOTLIN_VALUE = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<PsiElement> ILLEGAL_SINCE_KOTLIN_VALUE = DiagnosticFactory0.create(ERROR);
|
||||||
|
DiagnosticFactory1<PsiElement, String> NEWER_VERSION_IN_SINCE_KOTLIN = DiagnosticFactory1.create(WARNING);
|
||||||
|
|
||||||
// Const
|
// Const
|
||||||
DiagnosticFactory0<PsiElement> CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<PsiElement> CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT = DiagnosticFactory0.create(ERROR);
|
||||||
|
|||||||
+1
@@ -162,6 +162,7 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(REDUNDANT_ANNOTATION_TARGET, "Redundant annotation target ''{0}''", STRING);
|
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(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_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");
|
MAP.put(REDUNDANT_OPEN_IN_INTERFACE, "Modifier 'open' is redundant for abstract interface members");
|
||||||
|
|||||||
+18
-4
@@ -16,24 +16,38 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.checkers
|
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.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
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.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.getSinceKotlinAnnotation
|
import org.jetbrains.kotlin.resolve.getSinceKotlinAnnotation
|
||||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
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)?") }
|
private val regex: Regex = "(0|[1-9][0-9]*)".let { number -> Regex("$number\\.$number(\\.$number)?") }
|
||||||
|
|
||||||
override fun check(
|
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 annotation = descriptor.getSinceKotlinAnnotation() ?: return
|
||||||
val version = annotation.allValueArguments.values.singleOrNull()?.value as? String ?: return
|
val version = annotation.allValueArguments.values.singleOrNull()?.value as? String ?: return
|
||||||
if (!version.matches(regex)) {
|
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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
$TESTDATA_DIR$/apiVersionAndSinceNewerKotlin.kt
|
||||||
|
-d
|
||||||
|
$TEMP_DIR$
|
||||||
|
-api-version
|
||||||
|
1.0
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
@SinceKotlin("1.0")
|
||||||
|
fun old() {}
|
||||||
|
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
fun new() {}
|
||||||
@@ -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
|
||||||
+1
@@ -87,6 +87,7 @@ This directive lets you enable or disable certain language features. Language fe
|
|||||||
### 5. API_VERSION
|
### 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.
|
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:
|
#### Usage:
|
||||||
|
|
||||||
|
|||||||
@@ -70,5 +70,5 @@ fun ok2() {}
|
|||||||
@SinceKotlin("0.0.0")
|
@SinceKotlin("0.0.0")
|
||||||
fun ok3() {}
|
fun ok3() {}
|
||||||
|
|
||||||
@SinceKotlin("123456789012345678901234567890.123456789012345678901234567890.123456789012345678901234567890")
|
<!NEWER_VERSION_IN_SINCE_KOTLIN!>@SinceKotlin("123456789012345678901234567890.123456789012345678901234567890.123456789012345678901234567890")<!>
|
||||||
fun ok4() {}
|
fun ok4() {}
|
||||||
|
|||||||
@@ -205,9 +205,19 @@ public abstract class BaseDiagnosticsTest
|
|||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Condition<Diagnostic> parseDiagnosticFilterDirective(Map<String, String> directiveMap) {
|
private static Condition<Diagnostic> parseDiagnosticFilterDirective(Map<String, String> directiveMap) {
|
||||||
String directives = directiveMap.get(DIAGNOSTICS_DIRECTIVE);
|
String directives = directiveMap.get(DIAGNOSTICS_DIRECTIVE);
|
||||||
if (directives == null) {
|
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<Diagnostic>() {
|
||||||
|
@Override
|
||||||
|
public boolean value(Diagnostic diagnostic) {
|
||||||
|
return diagnostic.getFactory() != Errors.NEWER_VERSION_IN_SINCE_KOTLIN;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
return Conditions.alwaysTrue();
|
return Conditions.alwaysTrue();
|
||||||
}
|
}
|
||||||
Condition<Diagnostic> condition = Conditions.alwaysTrue();
|
Condition<Diagnostic> condition = Conditions.alwaysTrue();
|
||||||
|
|||||||
@@ -43,6 +43,12 @@ public class CliTestGenerated extends AbstractCliTest {
|
|||||||
doJvmTest(fileName);
|
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")
|
@TestMetadata("apiVersionGreaterThanLanguage.args")
|
||||||
public void testApiVersionGreaterThanLanguage() throws Exception {
|
public void testApiVersionGreaterThanLanguage() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/apiVersionGreaterThanLanguage.args");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/apiVersionGreaterThanLanguage.args");
|
||||||
|
|||||||
Reference in New Issue
Block a user