[FIR] Implement NEWER_VERSION_IN_SINCE_KOTLIN diagnostics, fix tests
This commit is contained in:
committed by
TeamCityServer
parent
1be02e3ac4
commit
5c086e2321
+3
@@ -154,6 +154,9 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
|||||||
val SUPERTYPES_FOR_ANNOTATION_CLASS by error<KtClass>(PositioningStrategy.SUPERTYPES_LIST)
|
val SUPERTYPES_FOR_ANNOTATION_CLASS by error<KtClass>(PositioningStrategy.SUPERTYPES_LIST)
|
||||||
val ANNOTATION_USED_AS_ANNOTATION_ARGUMENT by error<KtAnnotation>()
|
val ANNOTATION_USED_AS_ANNOTATION_ARGUMENT by error<KtAnnotation>()
|
||||||
val ILLEGAL_KOTLIN_VERSION_STRING_VALUE by error<KtExpression>()
|
val ILLEGAL_KOTLIN_VERSION_STRING_VALUE by error<KtExpression>()
|
||||||
|
val NEWER_VERSION_IN_SINCE_KOTLIN by warning<KtExpression> {
|
||||||
|
parameter<String>("specifiedVersion")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val EXPOSED_VISIBILITY by object : DiagnosticGroup("Exposed visibility") {
|
val EXPOSED_VISIBILITY by object : DiagnosticGroup("Exposed visibility") {
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ object FirErrors {
|
|||||||
val SUPERTYPES_FOR_ANNOTATION_CLASS by error0<KtClass>(SourceElementPositioningStrategies.SUPERTYPES_LIST)
|
val SUPERTYPES_FOR_ANNOTATION_CLASS by error0<KtClass>(SourceElementPositioningStrategies.SUPERTYPES_LIST)
|
||||||
val ANNOTATION_USED_AS_ANNOTATION_ARGUMENT by error0<KtAnnotation>()
|
val ANNOTATION_USED_AS_ANNOTATION_ARGUMENT by error0<KtAnnotation>()
|
||||||
val ILLEGAL_KOTLIN_VERSION_STRING_VALUE by error0<KtExpression>()
|
val ILLEGAL_KOTLIN_VERSION_STRING_VALUE by error0<KtExpression>()
|
||||||
|
val NEWER_VERSION_IN_SINCE_KOTLIN by warning1<KtExpression, String>()
|
||||||
|
|
||||||
// Exposed visibility
|
// Exposed visibility
|
||||||
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<KtNamedDeclaration, EffectiveVisibility, FirMemberDeclaration, EffectiveVisibility>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<KtNamedDeclaration, EffectiveVisibility, FirMemberDeclaration, EffectiveVisibility>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||||
|
|||||||
+18
-3
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
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.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
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.FirConstExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
|
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.unwrapArgument
|
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.ConeClassLikeType
|
||||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
@@ -20,10 +22,11 @@ import org.jetbrains.kotlin.resolve.RequireKotlinConstants
|
|||||||
|
|
||||||
object FirAnnotationChecker : FirAnnotationCallChecker() {
|
object FirAnnotationChecker : FirAnnotationCallChecker() {
|
||||||
private val deprecatedSinceKotlinClassId = ClassId.fromString("kotlin/DeprecatedSinceKotlin")
|
private val deprecatedSinceKotlinClassId = ClassId.fromString("kotlin/DeprecatedSinceKotlin")
|
||||||
|
private val sinceKotlinClassId = ClassId.fromString("kotlin/SinceKotlin")
|
||||||
|
|
||||||
private val annotationClassIdsWithVersion = setOf(
|
private val annotationClassIdsWithVersion = setOf(
|
||||||
ClassId.fromString("kotlin/internal/RequireKotlin"),
|
ClassId.fromString("kotlin/internal/RequireKotlin"),
|
||||||
ClassId.fromString("kotlin/SinceKotlin"),
|
sinceKotlinClassId,
|
||||||
deprecatedSinceKotlinClassId
|
deprecatedSinceKotlinClassId
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -40,8 +43,20 @@ object FirAnnotationChecker : FirAnnotationCallChecker() {
|
|||||||
if (argSource != null) {
|
if (argSource != null) {
|
||||||
val constExpression = (arg as? FirConstExpression<*>)
|
val constExpression = (arg as? FirConstExpression<*>)
|
||||||
?: ((arg as? FirNamedArgumentExpression)?.expression as? FirConstExpression<*>)
|
?: ((arg as? FirNamedArgumentExpression)?.expression as? FirConstExpression<*>)
|
||||||
if ((constExpression?.value as? String)?.matches(RequireKotlinConstants.VERSION_REGEX) == false) {
|
val stringValue = constExpression?.value as? String
|
||||||
reporter.reportOn(argSource, FirErrors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE, context)
|
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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -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.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.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.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.NEXT_AMBIGUITY
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY
|
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(NOT_AN_ANNOTATION_CLASS, "Illegal annotation class: {0}", NULLABLE_STRING)
|
||||||
map.put(SUPERTYPES_FOR_ANNOTATION_CLASS, "Annotation class cannot have supertypes")
|
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(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 // #
|
// Exposed visibility group // #
|
||||||
map.put(
|
map.put(
|
||||||
|
|||||||
+1
-1
@@ -70,5 +70,5 @@ fun ok2() {}
|
|||||||
@SinceKotlin("0.0.0")
|
@SinceKotlin("0.0.0")
|
||||||
fun ok3() {}
|
fun ok3() {}
|
||||||
|
|
||||||
@SinceKotlin("123456789012345678901234567890.123456789012345678901234567890.123456789012345678901234567890")
|
@SinceKotlin(<!NEWER_VERSION_IN_SINCE_KOTLIN!>"123456789012345678901234567890.123456789012345678901234567890.123456789012345678901234567890"<!>)
|
||||||
fun ok4() {}
|
fun ok4() {}
|
||||||
|
|||||||
+4
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.resolve.AnalyzingUtils
|
|||||||
import org.jetbrains.kotlin.test.directives.AdditionalFilesDirectives
|
import org.jetbrains.kotlin.test.directives.AdditionalFilesDirectives
|
||||||
import org.jetbrains.kotlin.test.directives.DiagnosticsDirectives
|
import org.jetbrains.kotlin.test.directives.DiagnosticsDirectives
|
||||||
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
|
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.directives.model.DirectivesContainer
|
||||||
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
|
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
|
||||||
import org.jetbrains.kotlin.test.model.TestFile
|
import org.jetbrains.kotlin.test.model.TestFile
|
||||||
@@ -76,6 +77,9 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes
|
|||||||
if (AdditionalFilesDirectives.CHECK_TYPE in module.directives) {
|
if (AdditionalFilesDirectives.CHECK_TYPE in module.directives) {
|
||||||
diagnostics = diagnostics.filter { it.factory.name != FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS.name }
|
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 ->
|
val diagnosticsMetadataInfos = diagnostics.mapNotNull { diagnostic ->
|
||||||
if (!diagnosticsService.shouldRenderDiagnostic(module, diagnostic.factory.name)) return@mapNotNull null
|
if (!diagnosticsService.shouldRenderDiagnostic(module, diagnostic.factory.name)) return@mapNotNull null
|
||||||
// SYNTAX errors will be reported later
|
// SYNTAX errors will be reported later
|
||||||
|
|||||||
+7
@@ -520,6 +520,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.NEWER_VERSION_IN_SINCE_KOTLIN) { firDiagnostic ->
|
||||||
|
NewerVersionInSinceKotlinImpl(
|
||||||
|
firDiagnostic.a,
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE) { firDiagnostic ->
|
add(FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE) { firDiagnostic ->
|
||||||
ExposedTypealiasExpandedTypeImpl(
|
ExposedTypealiasExpandedTypeImpl(
|
||||||
firDiagnostic.a,
|
firDiagnostic.a,
|
||||||
|
|||||||
+5
@@ -375,6 +375,11 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = IllegalKotlinVersionStringValue::class
|
override val diagnosticClass get() = IllegalKotlinVersionStringValue::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class NewerVersionInSinceKotlin : KtFirDiagnostic<KtExpression>() {
|
||||||
|
override val diagnosticClass get() = NewerVersionInSinceKotlin::class
|
||||||
|
abstract val specifiedVersion: String
|
||||||
|
}
|
||||||
|
|
||||||
abstract class ExposedTypealiasExpandedType : KtFirDiagnostic<KtNamedDeclaration>() {
|
abstract class ExposedTypealiasExpandedType : KtFirDiagnostic<KtNamedDeclaration>() {
|
||||||
override val diagnosticClass get() = ExposedTypealiasExpandedType::class
|
override val diagnosticClass get() = ExposedTypealiasExpandedType::class
|
||||||
abstract val elementVisibility: EffectiveVisibility
|
abstract val elementVisibility: EffectiveVisibility
|
||||||
|
|||||||
+8
@@ -604,6 +604,14 @@ internal class IllegalKotlinVersionStringValueImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class NewerVersionInSinceKotlinImpl(
|
||||||
|
override val specifiedVersion: String,
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.NewerVersionInSinceKotlin(), KtAbstractFirDiagnostic<KtExpression> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
internal class ExposedTypealiasExpandedTypeImpl(
|
internal class ExposedTypealiasExpandedTypeImpl(
|
||||||
override val elementVisibility: EffectiveVisibility,
|
override val elementVisibility: EffectiveVisibility,
|
||||||
override val restrictingDeclaration: KtSymbol,
|
override val restrictingDeclaration: KtSymbol,
|
||||||
|
|||||||
Reference in New Issue
Block a user