From 5c086e23216a3f2e15f3353b72ab1d8f0681dc69 Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Thu, 6 May 2021 22:54:26 +0300 Subject: [PATCH] [FIR] Implement NEWER_VERSION_IN_SINCE_KOTLIN diagnostics, fix tests --- .../diagnostics/FirDiagnosticsList.kt | 3 +++ .../fir/analysis/diagnostics/FirErrors.kt | 1 + .../expression/FirAnnotationChecker.kt | 21 ++++++++++++++++--- .../diagnostics/FirDefaultErrorMessages.kt | 2 ++ .../illegalSinceKotlinValue.fir.kt | 2 +- .../fir/handlers/FirDiagnosticsHandler.kt | 4 ++++ .../diagnostics/KtFirDataClassConverters.kt | 7 +++++++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 5 +++++ .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 8 +++++++ 9 files changed, 49 insertions(+), 4 deletions(-) diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 0667c6258a6..1174ae41c9d 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -154,6 +154,9 @@ object DIAGNOSTICS_LIST : DiagnosticList() { val SUPERTYPES_FOR_ANNOTATION_CLASS by error(PositioningStrategy.SUPERTYPES_LIST) val ANNOTATION_USED_AS_ANNOTATION_ARGUMENT by error() val ILLEGAL_KOTLIN_VERSION_STRING_VALUE by error() + val NEWER_VERSION_IN_SINCE_KOTLIN by warning { + parameter("specifiedVersion") + } } val EXPOSED_VISIBILITY by object : DiagnosticGroup("Exposed visibility") { diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 68e3154e30d..9dfe8b773fa 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -162,6 +162,7 @@ object FirErrors { val SUPERTYPES_FOR_ANNOTATION_CLASS by error0(SourceElementPositioningStrategies.SUPERTYPES_LIST) val ANNOTATION_USED_AS_ANNOTATION_ARGUMENT by error0() val ILLEGAL_KOTLIN_VERSION_STRING_VALUE by error0() + val NEWER_VERSION_IN_SINCE_KOTLIN by warning1() // Exposed visibility val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3(SourceElementPositioningStrategies.DECLARATION_NAME) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnnotationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnnotationChecker.kt index 40f61f1b57d..131510cab96 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnnotationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnnotationChecker.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression +import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors @@ -13,6 +14,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirConstExpression import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression import org.jetbrains.kotlin.fir.expressions.unwrapArgument +import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.name.ClassId @@ -20,10 +22,11 @@ import org.jetbrains.kotlin.resolve.RequireKotlinConstants object FirAnnotationChecker : FirAnnotationCallChecker() { private val deprecatedSinceKotlinClassId = ClassId.fromString("kotlin/DeprecatedSinceKotlin") + private val sinceKotlinClassId = ClassId.fromString("kotlin/SinceKotlin") private val annotationClassIdsWithVersion = setOf( ClassId.fromString("kotlin/internal/RequireKotlin"), - ClassId.fromString("kotlin/SinceKotlin"), + sinceKotlinClassId, deprecatedSinceKotlinClassId ) @@ -40,8 +43,20 @@ object FirAnnotationChecker : FirAnnotationCallChecker() { if (argSource != null) { val constExpression = (arg as? FirConstExpression<*>) ?: ((arg as? FirNamedArgumentExpression)?.expression as? FirConstExpression<*>) - if ((constExpression?.value as? String)?.matches(RequireKotlinConstants.VERSION_REGEX) == false) { - reporter.reportOn(argSource, FirErrors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE, context) + val stringValue = constExpression?.value as? String + if (stringValue != null) { + if (!stringValue.matches(RequireKotlinConstants.VERSION_REGEX)) { + reporter.reportOn(argSource, FirErrors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE, context) + } else if (classId == sinceKotlinClassId) { + val version = ApiVersion.parse(stringValue) + val specified = context.session.languageVersionSettings.apiVersion + if (version != null && version > specified) { + reporter.report( + FirErrors.NEWER_VERSION_IN_SINCE_KOTLIN.on(argSource, specified.versionString), + context + ) + } + } } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index 8ab7cf18d40..cb6ec1a765f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -174,6 +174,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAMED_ARGUMENTS_N import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAMED_PARAMETER_NOT_FOUND import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NESTED_CLASS_NOT_ALLOWED +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NEWER_VERSION_IN_SINCE_KOTLIN import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NEXT_AMBIGUITY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY @@ -423,6 +424,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { map.put(NOT_AN_ANNOTATION_CLASS, "Illegal annotation class: {0}", NULLABLE_STRING) map.put(SUPERTYPES_FOR_ANNOTATION_CLASS, "Annotation class cannot have supertypes") map.put(ILLEGAL_KOTLIN_VERSION_STRING_VALUE, "Invalid value in version annotation (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}", NULLABLE_STRING) // Exposed visibility group // # map.put( diff --git a/compiler/testData/diagnostics/tests/annotations/illegalSinceKotlinValue.fir.kt b/compiler/testData/diagnostics/tests/annotations/illegalSinceKotlinValue.fir.kt index d24ff2702de..74ddae56b54 100644 --- a/compiler/testData/diagnostics/tests/annotations/illegalSinceKotlinValue.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/illegalSinceKotlinValue.fir.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-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt index ae39f31b772..0cd611d79c2 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.resolve.AnalyzingUtils import org.jetbrains.kotlin.test.directives.AdditionalFilesDirectives import org.jetbrains.kotlin.test.directives.DiagnosticsDirectives import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives +import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives import org.jetbrains.kotlin.test.directives.model.DirectivesContainer import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact import org.jetbrains.kotlin.test.model.TestFile @@ -76,6 +77,9 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes if (AdditionalFilesDirectives.CHECK_TYPE in module.directives) { diagnostics = diagnostics.filter { it.factory.name != FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS.name } } + if (LanguageSettingsDirectives.API_VERSION in module.directives) { + diagnostics = diagnostics.filter { it.factory.name != FirErrors.NEWER_VERSION_IN_SINCE_KOTLIN.name } + } val diagnosticsMetadataInfos = diagnostics.mapNotNull { diagnostic -> if (!diagnosticsService.shouldRenderDiagnostic(module, diagnostic.factory.name)) return@mapNotNull null // SYNTAX errors will be reported later diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt index f7f04f1e6ba..f3fb5886cc8 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -520,6 +520,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.NEWER_VERSION_IN_SINCE_KOTLIN) { firDiagnostic -> + NewerVersionInSinceKotlinImpl( + firDiagnostic.a, + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE) { firDiagnostic -> ExposedTypealiasExpandedTypeImpl( firDiagnostic.a, diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt index d0ac437af88..89da81ea6f4 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt @@ -375,6 +375,11 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = IllegalKotlinVersionStringValue::class } + abstract class NewerVersionInSinceKotlin : KtFirDiagnostic() { + override val diagnosticClass get() = NewerVersionInSinceKotlin::class + abstract val specifiedVersion: String + } + abstract class ExposedTypealiasExpandedType : KtFirDiagnostic() { override val diagnosticClass get() = ExposedTypealiasExpandedType::class abstract val elementVisibility: EffectiveVisibility diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index f336e7f54d0..55529fea4ce 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -604,6 +604,14 @@ internal class IllegalKotlinVersionStringValueImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class NewerVersionInSinceKotlinImpl( + override val specifiedVersion: String, + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.NewerVersionInSinceKotlin(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class ExposedTypealiasExpandedTypeImpl( override val elementVisibility: EffectiveVisibility, override val restrictingDeclaration: KtSymbol,