[FIR] Add DEPRECATED_SINCE_KOTLIN_WITHOUT_DEPRECATED diagnostics, fix tests

This commit is contained in:
Ivan Kochurkin
2021-05-11 16:38:07 +03:00
committed by TeamCityServer
parent 3191e0b925
commit 77c137df22
14 changed files with 107 additions and 29 deletions
@@ -54,6 +54,7 @@ fun main(args: Array<String>) {
alias<FirConstructor>("ConstructorChecker")
alias<FirFile>("FileChecker")
alias<FirTypeParameter>("FirTypeParameterChecker")
alias<FirAnnotatedDeclaration>("FirAnnotatedDeclarationChecker")
additional(
fieldName = "controlFlowAnalyserCheckers",
@@ -159,6 +159,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
}
val DEPRECATED_SINCE_KOTLIN_WITH_UNORDERED_VERSIONS by error<PsiElement>()
val DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS by error<PsiElement>()
val DEPRECATED_SINCE_KOTLIN_WITHOUT_DEPRECATED by error<PsiElement>()
}
val EXPOSED_VISIBILITY by object : DiagnosticGroup("Exposed visibility") {
@@ -35,6 +35,8 @@ class ComposedDeclarationCheckers : DeclarationCheckers() {
get() = _fileCheckers
override val typeParameterCheckers: Set<FirTypeParameterChecker>
get() = _typeParameterCheckers
override val annotatedDeclarationCheckers: Set<FirAnnotatedDeclarationChecker>
get() = _annotatedDeclarationCheckers
override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker>
get() = _controlFlowAnalyserCheckers
override val variableAssignmentCfaBasedCheckers: Set<AbstractFirPropertyInitializationChecker>
@@ -50,6 +52,7 @@ class ComposedDeclarationCheckers : DeclarationCheckers() {
private val _constructorCheckers: MutableSet<FirConstructorChecker> = mutableSetOf()
private val _fileCheckers: MutableSet<FirFileChecker> = mutableSetOf()
private val _typeParameterCheckers: MutableSet<FirTypeParameterChecker> = mutableSetOf()
private val _annotatedDeclarationCheckers: MutableSet<FirAnnotatedDeclarationChecker> = mutableSetOf()
private val _controlFlowAnalyserCheckers: MutableSet<FirControlFlowChecker> = mutableSetOf()
private val _variableAssignmentCfaBasedCheckers: MutableSet<AbstractFirPropertyInitializationChecker> = mutableSetOf()
@@ -65,6 +68,7 @@ class ComposedDeclarationCheckers : DeclarationCheckers() {
_constructorCheckers += checkers.constructorCheckers
_fileCheckers += checkers.fileCheckers
_typeParameterCheckers += checkers.typeParameterCheckers
_annotatedDeclarationCheckers += checkers.annotatedDeclarationCheckers
_controlFlowAnalyserCheckers += checkers.controlFlowAnalyserCheckers
_variableAssignmentCfaBasedCheckers += checkers.variableAssignmentCfaBasedCheckers
}
@@ -29,18 +29,20 @@ abstract class DeclarationCheckers {
open val constructorCheckers: Set<FirConstructorChecker> = emptySet()
open val fileCheckers: Set<FirFileChecker> = emptySet()
open val typeParameterCheckers: Set<FirTypeParameterChecker> = emptySet()
open val annotatedDeclarationCheckers: Set<FirAnnotatedDeclarationChecker> = emptySet()
open val controlFlowAnalyserCheckers: Set<FirControlFlowChecker> = emptySet()
open val variableAssignmentCfaBasedCheckers: Set<AbstractFirPropertyInitializationChecker> = emptySet()
@CheckersComponentInternal internal val allBasicDeclarationCheckers: Set<FirBasicDeclarationChecker> get() = basicDeclarationCheckers
@CheckersComponentInternal internal val allMemberDeclarationCheckers: Set<FirMemberDeclarationChecker> get() = memberDeclarationCheckers + basicDeclarationCheckers
@CheckersComponentInternal internal val allFunctionCheckers: Set<FirFunctionChecker> get() = functionCheckers + basicDeclarationCheckers
@CheckersComponentInternal internal val allSimpleFunctionCheckers: Set<FirSimpleFunctionChecker> get() = simpleFunctionCheckers + functionCheckers + basicDeclarationCheckers + memberDeclarationCheckers
@CheckersComponentInternal internal val allPropertyCheckers: Set<FirPropertyChecker> get() = propertyCheckers + basicDeclarationCheckers + memberDeclarationCheckers
@CheckersComponentInternal internal val allClassCheckers: Set<FirClassChecker> get() = classCheckers + basicDeclarationCheckers
@CheckersComponentInternal internal val allRegularClassCheckers: Set<FirRegularClassChecker> get() = regularClassCheckers + memberDeclarationCheckers + basicDeclarationCheckers + classCheckers
@CheckersComponentInternal internal val allConstructorCheckers: Set<FirConstructorChecker> get() = constructorCheckers + functionCheckers + basicDeclarationCheckers + memberDeclarationCheckers
@CheckersComponentInternal internal val allFileCheckers: Set<FirFileChecker> get() = fileCheckers + basicDeclarationCheckers
@CheckersComponentInternal internal val allTypeParameterCheckers: Set<FirTypeParameterChecker> get() = typeParameterCheckers + basicDeclarationCheckers
@CheckersComponentInternal internal val allMemberDeclarationCheckers: Set<FirMemberDeclarationChecker> get() = memberDeclarationCheckers + annotatedDeclarationCheckers + basicDeclarationCheckers
@CheckersComponentInternal internal val allFunctionCheckers: Set<FirFunctionChecker> get() = functionCheckers + annotatedDeclarationCheckers + basicDeclarationCheckers
@CheckersComponentInternal internal val allSimpleFunctionCheckers: Set<FirSimpleFunctionChecker> get() = simpleFunctionCheckers + functionCheckers + annotatedDeclarationCheckers + basicDeclarationCheckers + memberDeclarationCheckers
@CheckersComponentInternal internal val allPropertyCheckers: Set<FirPropertyChecker> get() = propertyCheckers + annotatedDeclarationCheckers + basicDeclarationCheckers + memberDeclarationCheckers
@CheckersComponentInternal internal val allClassCheckers: Set<FirClassChecker> get() = classCheckers + annotatedDeclarationCheckers + basicDeclarationCheckers
@CheckersComponentInternal internal val allRegularClassCheckers: Set<FirRegularClassChecker> get() = regularClassCheckers + memberDeclarationCheckers + annotatedDeclarationCheckers + basicDeclarationCheckers + classCheckers
@CheckersComponentInternal internal val allConstructorCheckers: Set<FirConstructorChecker> get() = constructorCheckers + functionCheckers + annotatedDeclarationCheckers + basicDeclarationCheckers + memberDeclarationCheckers
@CheckersComponentInternal internal val allFileCheckers: Set<FirFileChecker> get() = fileCheckers + annotatedDeclarationCheckers + basicDeclarationCheckers
@CheckersComponentInternal internal val allTypeParameterCheckers: Set<FirTypeParameterChecker> get() = typeParameterCheckers + annotatedDeclarationCheckers + basicDeclarationCheckers
@CheckersComponentInternal internal val allAnnotatedDeclarationCheckers: Set<FirAnnotatedDeclarationChecker> get() = annotatedDeclarationCheckers + basicDeclarationCheckers
}
@@ -10,6 +10,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
* DO NOT MODIFY IT MANUALLY
*/
import org.jetbrains.kotlin.fir.declarations.FirAnnotatedDeclaration
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
@@ -31,3 +32,4 @@ typealias FirRegularClassChecker = FirDeclarationChecker<FirRegularClass>
typealias FirConstructorChecker = FirDeclarationChecker<FirConstructor>
typealias FirFileChecker = FirDeclarationChecker<FirFile>
typealias FirTypeParameterChecker = FirDeclarationChecker<FirTypeParameter>
typealias FirAnnotatedDeclarationChecker = FirDeclarationChecker<FirAnnotatedDeclaration>
@@ -165,6 +165,7 @@ object FirErrors {
val NEWER_VERSION_IN_SINCE_KOTLIN by warning1<KtExpression, String>()
val DEPRECATED_SINCE_KOTLIN_WITH_UNORDERED_VERSIONS by error0<PsiElement>()
val DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS by error0<PsiElement>()
val DEPRECATED_SINCE_KOTLIN_WITHOUT_DEPRECATED by error0<PsiElement>()
// Exposed visibility
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<KtNamedDeclaration, EffectiveVisibility, FirMemberDeclaration, EffectiveVisibility>(SourceElementPositioningStrategies.DECLARATION_NAME)
@@ -0,0 +1,41 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.fir.analysis.checkers.declaration
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
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirAnnotatedDeclaration
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.resolve.fqName
import org.jetbrains.kotlin.name.FqName
object FirAnnotationChecker : FirAnnotatedDeclarationChecker() {
private val deprecatedClassId = FqName("kotlin.Deprecated")
private val deprecatedSinceKotlinClassId = FqName("kotlin.DeprecatedSinceKotlin")
override fun check(
declaration: FirAnnotatedDeclaration,
context: CheckerContext,
reporter: DiagnosticReporter
) {
var deprecatedCall: FirAnnotationCall? = null
var deprecatedSinceKotlinCall: FirAnnotationCall? = null
for (annotation in declaration.annotations) {
val fqName = annotation.fqName(context.session)
if (fqName == deprecatedClassId) {
deprecatedCall = annotation
} else if (fqName == deprecatedSinceKotlinClassId) {
deprecatedSinceKotlinCall = annotation
}
}
if (deprecatedSinceKotlinCall != null && deprecatedCall == null) {
reporter.reportOn(deprecatedSinceKotlinCall.source, FirErrors.DEPRECATED_SINCE_KOTLIN_WITHOUT_DEPRECATED, context)
}
}
}
@@ -18,32 +18,31 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.*
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
import org.jetbrains.kotlin.fir.resolve.fqName
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.RequireKotlinConstants
object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
private val deprecatedSinceKotlinClassId = ClassId.fromString("kotlin/DeprecatedSinceKotlin")
private val sinceKotlinClassId = ClassId.fromString("kotlin/SinceKotlin")
private val deprecatedSinceKotlinFqName = FqName("kotlin.DeprecatedSinceKotlin")
private val sinceKotlinFqName = FqName("kotlin.SinceKotlin")
private val annotationClassIdsWithVersion = setOf(
ClassId.fromString("kotlin/internal/RequireKotlin"),
sinceKotlinClassId,
deprecatedSinceKotlinClassId
private val annotationFqNamesWithVersion = setOf(
FqName("kotlin.internal.RequireKotlin"),
sinceKotlinFqName,
deprecatedSinceKotlinFqName
)
override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
val argumentMapping = expression.argumentMapping ?: return
val classId = ((expression.annotationTypeRef as? FirResolvedTypeRef)?.type as? ConeClassLikeType)?.lookupTag?.classId
val fqName = expression.fqName(context.session)
for ((arg, _) in argumentMapping) {
val argExpression = (arg as? FirNamedArgumentExpression)?.expression ?: arg
checkAnnotationArgumentWithSubElements(argExpression, classId, context.session, reporter, context)
checkAnnotationArgumentWithSubElements(argExpression, fqName, context.session, reporter, context)
?.let { reporter.reportOn(argExpression.source, it, context) }
}
checkDeprecatedSinceKotlin(expression.source, classId, argumentMapping, context, reporter)
checkDeprecatedSinceKotlin(expression.source, fqName, argumentMapping, context, reporter)
val args = expression.argumentList.arguments
for (arg in args) {
@@ -55,7 +54,7 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
private fun checkAnnotationArgumentWithSubElements(
expression: FirExpression,
classId: ClassId?,
fqName: FqName?,
session: FirSession,
reporter: DiagnosticReporter,
context: CheckerContext
@@ -67,7 +66,7 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
for (arg in expression.argumentList.arguments) {
val sourceForReport = arg.source
when (val err = checkAnnotationArgumentWithSubElements(arg, classId, session, reporter, context)) {
when (val err = checkAnnotationArgumentWithSubElements(arg, fqName, session, reporter, context)) {
null -> {
//DO NOTHING
}
@@ -82,7 +81,7 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
}
is FirVarargArgumentsExpression -> {
for (arg in expression.arguments)
checkAnnotationArgumentWithSubElements(arg, classId, session, reporter, context)
checkAnnotationArgumentWithSubElements(arg, fqName, session, reporter, context)
?.let { reporter.reportOn(arg.source, it, context) }
}
else -> {
@@ -96,14 +95,14 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
}
if (error != null) {
return error
} else if (classId != null && annotationClassIdsWithVersion.contains(classId)) {
} else if (annotationFqNamesWithVersion.contains(fqName)) {
val argSource = expression.source
if (argSource != null) {
val stringValue = (expression as? FirConstExpression<*>)?.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) {
} else if (fqName == sinceKotlinFqName) {
val version = ApiVersion.parse(stringValue)
val specified = context.session.languageVersionSettings.apiVersion
if (version != null && version > specified) {
@@ -123,12 +122,12 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
private fun checkDeprecatedSinceKotlin(
source: FirSourceElement?,
classId: ClassId?,
fqName: FqName?,
argumentMapping: LinkedHashMap<FirExpression, FirValueParameter>,
context: CheckerContext,
reporter: DiagnosticReporter
) {
if (classId != deprecatedSinceKotlinClassId)
if (fqName != deprecatedSinceKotlinFqName)
return
if (argumentMapping.size == 0) {
@@ -87,6 +87,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATION_IN_INT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_MODIFIER_PAIR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_SINCE_KOTLIN_WITHOUT_DEPRECATED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_SINCE_KOTLIN_WITH_UNORDERED_VERSIONS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_TYPE_PARAMETER_SYNTAX
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DESERIALIZATION_ERROR
@@ -438,6 +439,10 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS,
"DeprecatedSinceKotlin annotation should have at least one argument"
)
map.put(
DEPRECATED_SINCE_KOTLIN_WITHOUT_DEPRECATED,
" DeprecatedSinceKotlin annotation can be used only together with Deprecated annotation"
)
// Exposed visibility group // #
map.put(
@@ -120,4 +120,9 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirReifiedTypeParameterChecker,
FirTypeParameterSyntaxChecker,
)
override val annotatedDeclarationCheckers: Set<FirAnnotatedDeclarationChecker>
get() = setOf(
FirAnnotationChecker,
)
}
@@ -5,7 +5,7 @@ package kotlin.sub
@DeprecatedSinceKotlin(warningSince = "1.0", errorSince = "1.1", hiddenSince = "1.2")
fun good() {}
<!DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS!>@DeprecatedSinceKotlin()<!>
<!DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS, DEPRECATED_SINCE_KOTLIN_WITHOUT_DEPRECATED!>@DeprecatedSinceKotlin()<!>
class Clazz
@Deprecated("", level = DeprecationLevel.WARNING)
@@ -539,6 +539,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.DEPRECATED_SINCE_KOTLIN_WITHOUT_DEPRECATED) { firDiagnostic ->
DeprecatedSinceKotlinWithoutDeprecatedImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE) { firDiagnostic ->
ExposedTypealiasExpandedTypeImpl(
firDiagnostic.a,
@@ -388,6 +388,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = DeprecatedSinceKotlinWithoutArguments::class
}
abstract class DeprecatedSinceKotlinWithoutDeprecated : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = DeprecatedSinceKotlinWithoutDeprecated::class
}
abstract class ExposedTypealiasExpandedType : KtFirDiagnostic<KtNamedDeclaration>() {
override val diagnosticClass get() = ExposedTypealiasExpandedType::class
abstract val elementVisibility: EffectiveVisibility
@@ -626,6 +626,13 @@ internal class DeprecatedSinceKotlinWithoutArgumentsImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class DeprecatedSinceKotlinWithoutDeprecatedImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.DeprecatedSinceKotlinWithoutDeprecated(), KtAbstractFirDiagnostic<PsiElement> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ExposedTypealiasExpandedTypeImpl(
override val elementVisibility: EffectiveVisibility,
override val restrictingDeclaration: KtSymbol,