[FIR] Implement DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS diagnostics, fix tests, merge and refactor annotation checkers
This commit is contained in:
committed by
TeamCityServer
parent
dc99a673a5
commit
3191e0b925
+1
@@ -158,6 +158,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
|||||||
parameter<String>("specifiedVersion")
|
parameter<String>("specifiedVersion")
|
||||||
}
|
}
|
||||||
val DEPRECATED_SINCE_KOTLIN_WITH_UNORDERED_VERSIONS by error<PsiElement>()
|
val DEPRECATED_SINCE_KOTLIN_WITH_UNORDERED_VERSIONS by error<PsiElement>()
|
||||||
|
val DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS by error<PsiElement>()
|
||||||
}
|
}
|
||||||
|
|
||||||
val EXPOSED_VISIBILITY by object : DiagnosticGroup("Exposed visibility") {
|
val EXPOSED_VISIBILITY by object : DiagnosticGroup("Exposed visibility") {
|
||||||
|
|||||||
@@ -164,6 +164,7 @@ object FirErrors {
|
|||||||
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>()
|
val NEWER_VERSION_IN_SINCE_KOTLIN by warning1<KtExpression, String>()
|
||||||
val DEPRECATED_SINCE_KOTLIN_WITH_UNORDERED_VERSIONS by error0<PsiElement>()
|
val DEPRECATED_SINCE_KOTLIN_WITH_UNORDERED_VERSIONS by error0<PsiElement>()
|
||||||
|
val DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS by error0<PsiElement>()
|
||||||
|
|
||||||
// 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)
|
||||||
|
|||||||
+111
-6
@@ -5,7 +5,9 @@
|
|||||||
|
|
||||||
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.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.ConstantArgumentKind
|
import org.jetbrains.kotlin.fir.analysis.checkers.ConstantArgumentKind
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.checkConstantArguments
|
import org.jetbrains.kotlin.fir.analysis.checkers.checkConstantArguments
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
@@ -13,22 +15,47 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
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.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.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
import org.jetbrains.kotlin.resolve.RequireKotlinConstants
|
||||||
|
|
||||||
object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
|
object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
|
||||||
|
private val deprecatedSinceKotlinClassId = ClassId.fromString("kotlin/DeprecatedSinceKotlin")
|
||||||
|
private val sinceKotlinClassId = ClassId.fromString("kotlin/SinceKotlin")
|
||||||
|
|
||||||
|
private val annotationClassIdsWithVersion = setOf(
|
||||||
|
ClassId.fromString("kotlin/internal/RequireKotlin"),
|
||||||
|
sinceKotlinClassId,
|
||||||
|
deprecatedSinceKotlinClassId
|
||||||
|
)
|
||||||
|
|
||||||
override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val argumentMapping = expression.argumentMapping ?: return
|
val argumentMapping = expression.argumentMapping ?: return
|
||||||
|
val classId = ((expression.annotationTypeRef as? FirResolvedTypeRef)?.type as? ConeClassLikeType)?.lookupTag?.classId
|
||||||
for ((arg, _) in argumentMapping) {
|
for ((arg, _) in argumentMapping) {
|
||||||
val argExpression = (arg as? FirNamedArgumentExpression)?.expression ?: arg
|
val argExpression = (arg as? FirNamedArgumentExpression)?.expression ?: arg
|
||||||
|
checkAnnotationArgumentWithSubElements(argExpression, classId, context.session, reporter, context)
|
||||||
checkAnnotationArgumentWithSubElements(argExpression, context.session, reporter, context)
|
|
||||||
?.let { reporter.reportOn(argExpression.source, it, context) }
|
?.let { reporter.reportOn(argExpression.source, it, context) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkDeprecatedSinceKotlin(expression.source, classId, argumentMapping, context, reporter)
|
||||||
|
|
||||||
|
val args = expression.argumentList.arguments
|
||||||
|
for (arg in args) {
|
||||||
|
for (ann in arg.unwrapArgument().annotations) {
|
||||||
|
reporter.reportOn(ann.source, FirErrors.ANNOTATION_USED_AS_ANNOTATION_ARGUMENT, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkAnnotationArgumentWithSubElements(
|
private fun checkAnnotationArgumentWithSubElements(
|
||||||
expression: FirExpression,
|
expression: FirExpression,
|
||||||
|
classId: ClassId?,
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
reporter: DiagnosticReporter,
|
reporter: DiagnosticReporter,
|
||||||
context: CheckerContext
|
context: CheckerContext
|
||||||
@@ -40,7 +67,7 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
|
|||||||
for (arg in expression.argumentList.arguments) {
|
for (arg in expression.argumentList.arguments) {
|
||||||
val sourceForReport = arg.source
|
val sourceForReport = arg.source
|
||||||
|
|
||||||
when (val err = checkAnnotationArgumentWithSubElements(arg, session, reporter, context)) {
|
when (val err = checkAnnotationArgumentWithSubElements(arg, classId, session, reporter, context)) {
|
||||||
null -> {
|
null -> {
|
||||||
//DO NOTHING
|
//DO NOTHING
|
||||||
}
|
}
|
||||||
@@ -55,11 +82,11 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
|
|||||||
}
|
}
|
||||||
is FirVarargArgumentsExpression -> {
|
is FirVarargArgumentsExpression -> {
|
||||||
for (arg in expression.arguments)
|
for (arg in expression.arguments)
|
||||||
checkAnnotationArgumentWithSubElements(arg, session, reporter, context)
|
checkAnnotationArgumentWithSubElements(arg, classId, session, reporter, context)
|
||||||
?.let { reporter.reportOn(arg.source, it, context) }
|
?.let { reporter.reportOn(arg.source, it, context) }
|
||||||
}
|
}
|
||||||
else ->
|
else -> {
|
||||||
return when (checkConstantArguments(expression, session)) {
|
val error = when (checkConstantArguments(expression, session)) {
|
||||||
ConstantArgumentKind.NOT_CONST -> FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST
|
ConstantArgumentKind.NOT_CONST -> FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST
|
||||||
ConstantArgumentKind.ENUM_NOT_CONST -> FirErrors.ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST
|
ConstantArgumentKind.ENUM_NOT_CONST -> FirErrors.ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST
|
||||||
ConstantArgumentKind.NOT_KCLASS_LITERAL -> FirErrors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL
|
ConstantArgumentKind.NOT_KCLASS_LITERAL -> FirErrors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL
|
||||||
@@ -67,7 +94,85 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
|
|||||||
ConstantArgumentKind.NOT_CONST_VAL_IN_CONST_EXPRESSION -> FirErrors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION
|
ConstantArgumentKind.NOT_CONST_VAL_IN_CONST_EXPRESSION -> FirErrors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION
|
||||||
null -> null
|
null -> null
|
||||||
}
|
}
|
||||||
|
if (error != null) {
|
||||||
|
return error
|
||||||
|
} else if (classId != null && annotationClassIdsWithVersion.contains(classId)) {
|
||||||
|
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) {
|
||||||
|
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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun checkDeprecatedSinceKotlin(
|
||||||
|
source: FirSourceElement?,
|
||||||
|
classId: ClassId?,
|
||||||
|
argumentMapping: LinkedHashMap<FirExpression, FirValueParameter>,
|
||||||
|
context: CheckerContext,
|
||||||
|
reporter: DiagnosticReporter
|
||||||
|
) {
|
||||||
|
if (classId != deprecatedSinceKotlinClassId)
|
||||||
|
return
|
||||||
|
|
||||||
|
if (argumentMapping.size == 0) {
|
||||||
|
reporter.reportOn(source, FirErrors.DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
var warningSince: ApiVersion? = null
|
||||||
|
var errorSince: ApiVersion? = null
|
||||||
|
var hiddenSince: ApiVersion? = null
|
||||||
|
for (argument in argumentMapping) {
|
||||||
|
val identifier = argument.value.name.identifier
|
||||||
|
if (identifier == "warningSince" || identifier == "errorSince" || identifier == "hiddenSince") {
|
||||||
|
val argKey = argument.key
|
||||||
|
val constExpression = (argKey as? FirConstExpression<*>)
|
||||||
|
?: ((argKey as? FirNamedArgumentExpression)?.expression as? FirConstExpression<*>)
|
||||||
|
val stringValue = constExpression?.value as? String
|
||||||
|
if (stringValue != null) {
|
||||||
|
val version = ApiVersion.parse(stringValue)
|
||||||
|
when (identifier) {
|
||||||
|
"warningSince" -> warningSince = version
|
||||||
|
"errorSince" -> errorSince = version
|
||||||
|
"hiddenSince" -> hiddenSince = version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var isReportDeprecatedSinceKotlinWithUnorderedVersions = false
|
||||||
|
if (warningSince != null) {
|
||||||
|
if (errorSince != null) {
|
||||||
|
isReportDeprecatedSinceKotlinWithUnorderedVersions = warningSince > errorSince
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hiddenSince != null && !isReportDeprecatedSinceKotlinWithUnorderedVersions) {
|
||||||
|
isReportDeprecatedSinceKotlinWithUnorderedVersions = warningSince > hiddenSince
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorSince != null && hiddenSince != null && !isReportDeprecatedSinceKotlinWithUnorderedVersions) {
|
||||||
|
isReportDeprecatedSinceKotlinWithUnorderedVersions = errorSince > hiddenSince
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isReportDeprecatedSinceKotlinWithUnorderedVersions) {
|
||||||
|
reporter.reportOn(source, FirErrors.DEPRECATED_SINCE_KOTLIN_WITH_UNORDERED_VERSIONS, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-72
@@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.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
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
|
||||||
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
|
|
||||||
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"),
|
|
||||||
sinceKotlinClassId,
|
|
||||||
deprecatedSinceKotlinClassId
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
|
||||||
val classId = ((expression.annotationTypeRef as? FirResolvedTypeRef)?.type as? ConeClassLikeType)?.lookupTag?.classId
|
|
||||||
if (annotationClassIdsWithVersion.contains(classId)) {
|
|
||||||
for (argIndex in expression.argumentList.arguments.withIndex()) {
|
|
||||||
if (argIndex.index > 0 && classId != deprecatedSinceKotlinClassId) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
val arg = argIndex.value
|
|
||||||
val argSource = arg.source
|
|
||||||
if (argSource != null) {
|
|
||||||
val constExpression = (arg as? FirConstExpression<*>)
|
|
||||||
?: ((arg as? FirNamedArgumentExpression)?.expression as? FirConstExpression<*>)
|
|
||||||
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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val args = expression.argumentList.arguments
|
|
||||||
for (arg in args) {
|
|
||||||
for (ann in arg.unwrapArgument().annotations) {
|
|
||||||
reporter.reportOn(ann.source, FirErrors.ANNOTATION_USED_AS_ANNOTATION_ARGUMENT, context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+5
@@ -86,6 +86,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATE_SPECIAL_
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATION_IN_INTERFACE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATION_IN_INTERFACE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR
|
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_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_WITH_UNORDERED_VERSIONS
|
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.DEPRECATED_TYPE_PARAMETER_SYNTAX
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DESERIALIZATION_ERROR
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DESERIALIZATION_ERROR
|
||||||
@@ -433,6 +434,10 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
|||||||
DEPRECATED_SINCE_KOTLIN_WITH_UNORDERED_VERSIONS,
|
DEPRECATED_SINCE_KOTLIN_WITH_UNORDERED_VERSIONS,
|
||||||
"Values of DeprecatedSinceKotlin annotation should be ordered so 'warningSince' <= 'errorSince' <= 'hiddenSince' if specified"
|
"Values of DeprecatedSinceKotlin annotation should be ordered so 'warningSince' <= 'errorSince' <= 'hiddenSince' if specified"
|
||||||
)
|
)
|
||||||
|
map.put(
|
||||||
|
DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS,
|
||||||
|
"DeprecatedSinceKotlin annotation should have at least one argument"
|
||||||
|
)
|
||||||
|
|
||||||
// Exposed visibility group // #
|
// Exposed visibility group // #
|
||||||
map.put(
|
map.put(
|
||||||
|
|||||||
-1
@@ -143,7 +143,6 @@ private fun mapInapplicableCandidateError(
|
|||||||
)
|
)
|
||||||
is UnsafeCall -> mapUnsafeCallError(diagnostic.candidate, rootCause, source, qualifiedAccessSource)
|
is UnsafeCall -> mapUnsafeCallError(diagnostic.candidate, rootCause, source, qualifiedAccessSource)
|
||||||
is ManyLambdaExpressionArguments -> FirErrors.MANY_LAMBDA_EXPRESSION_ARGUMENTS.on(rootCause.argument.source ?: source)
|
is ManyLambdaExpressionArguments -> FirErrors.MANY_LAMBDA_EXPRESSION_ARGUMENTS.on(rootCause.argument.source ?: source)
|
||||||
is DeprecatedSinceKotlinWithUnorderedVersions -> FirErrors.DEPRECATED_SINCE_KOTLIN_WITH_UNORDERED_VERSIONS.on(source)
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}.ifEmpty { listOf(FirErrors.INAPPLICABLE_CANDIDATE.on(source, diagnostic.candidate.symbol)) }
|
}.ifEmpty { listOf(FirErrors.INAPPLICABLE_CANDIDATE.on(source, diagnostic.candidate.symbol)) }
|
||||||
|
|||||||
-1
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirAnonymousFunctionSyn
|
|||||||
object CommonExpressionCheckers : ExpressionCheckers() {
|
object CommonExpressionCheckers : ExpressionCheckers() {
|
||||||
override val annotationCallCheckers: Set<FirAnnotationCallChecker>
|
override val annotationCallCheckers: Set<FirAnnotationCallChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirAnnotationChecker,
|
|
||||||
FirAnnotationArgumentChecker
|
FirAnnotationArgumentChecker
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
-2
@@ -102,5 +102,3 @@ class NullForNotNullType(
|
|||||||
class ManyLambdaExpressionArguments(
|
class ManyLambdaExpressionArguments(
|
||||||
val argument: FirExpression
|
val argument: FirExpression
|
||||||
) : ResolutionDiagnostic(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR)
|
) : ResolutionDiagnostic(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR)
|
||||||
|
|
||||||
object DeprecatedSinceKotlinWithUnorderedVersions : ResolutionDiagnostic(INAPPLICABLE)
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.calls
|
package org.jetbrains.kotlin.fir.resolve.calls
|
||||||
|
|
||||||
import org.jetbrains.kotlin.config.ApiVersion
|
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.fir.FirSymbolOwner
|
import org.jetbrains.kotlin.fir.FirSymbolOwner
|
||||||
import org.jetbrains.kotlin.fir.FirVisibilityChecker
|
import org.jetbrains.kotlin.fir.FirVisibilityChecker
|
||||||
@@ -157,8 +156,6 @@ internal object CheckArguments : CheckerStage() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkDeprecatedSinceKotlinArgs(candidate, argumentMapping, sink)
|
|
||||||
|
|
||||||
if (candidate.system.hasContradiction && callInfo.arguments.isNotEmpty()) {
|
if (candidate.system.hasContradiction && callInfo.arguments.isNotEmpty()) {
|
||||||
sink.yieldDiagnostic(InapplicableCandidate)
|
sink.yieldDiagnostic(InapplicableCandidate)
|
||||||
}
|
}
|
||||||
@@ -169,57 +166,6 @@ internal object CheckArguments : CheckerStage() {
|
|||||||
FqName("DeprecatedSinceKotlin"),
|
FqName("DeprecatedSinceKotlin"),
|
||||||
Name.identifier("DeprecatedSinceKotlin")
|
Name.identifier("DeprecatedSinceKotlin")
|
||||||
)
|
)
|
||||||
|
|
||||||
private suspend fun checkDeprecatedSinceKotlinArgs(
|
|
||||||
candidate: Candidate,
|
|
||||||
argumentMapping: LinkedHashMap<FirExpression, FirValueParameter>,
|
|
||||||
sink: CheckerSink
|
|
||||||
) {
|
|
||||||
val symbol = candidate.symbol
|
|
||||||
if (symbol is FirFunctionSymbol<*>) {
|
|
||||||
if (symbol.callableId == deprecatedSinceKotlin) {
|
|
||||||
var warningSince: ApiVersion? = null
|
|
||||||
var errorSince: ApiVersion? = null
|
|
||||||
var hiddenSince: ApiVersion? = null
|
|
||||||
for (argument in argumentMapping) {
|
|
||||||
val identifier = argument.value.name.identifier
|
|
||||||
if (identifier == "warningSince" || identifier == "errorSince" || identifier == "hiddenSince") {
|
|
||||||
val argKey = argument.key
|
|
||||||
val constExpression = (argKey as? FirConstExpression<*>)
|
|
||||||
?: ((argKey as? FirNamedArgumentExpression)?.expression as? FirConstExpression<*>)
|
|
||||||
val stringValue = constExpression?.value as? String
|
|
||||||
if (stringValue != null) {
|
|
||||||
val version = ApiVersion.parse(stringValue)
|
|
||||||
when (identifier) {
|
|
||||||
"warningSince" -> warningSince = version
|
|
||||||
"errorSince" -> errorSince = version
|
|
||||||
"hiddenSince" -> hiddenSince = version
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var isReportDeprecatedSinceKotlinWithUnorderedVersions = false
|
|
||||||
if (warningSince != null) {
|
|
||||||
if (errorSince != null) {
|
|
||||||
isReportDeprecatedSinceKotlinWithUnorderedVersions = warningSince > errorSince
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hiddenSince != null && !isReportDeprecatedSinceKotlinWithUnorderedVersions) {
|
|
||||||
isReportDeprecatedSinceKotlinWithUnorderedVersions = warningSince > hiddenSince
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errorSince != null && hiddenSince != null && !isReportDeprecatedSinceKotlinWithUnorderedVersions) {
|
|
||||||
isReportDeprecatedSinceKotlinWithUnorderedVersions = errorSince > hiddenSince
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isReportDeprecatedSinceKotlinWithUnorderedVersions) {
|
|
||||||
sink.yieldDiagnostic(DeprecatedSinceKotlinWithUnorderedVersions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal object EagerResolveOfCallableReferences : CheckerStage() {
|
internal object EagerResolveOfCallableReferences : CheckerStage() {
|
||||||
|
|||||||
+5
-5
@@ -5,23 +5,23 @@ package kotlin.sub
|
|||||||
@DeprecatedSinceKotlin(warningSince = "1.0", errorSince = "1.1", hiddenSince = "1.2")
|
@DeprecatedSinceKotlin(warningSince = "1.0", errorSince = "1.1", hiddenSince = "1.2")
|
||||||
fun good() {}
|
fun good() {}
|
||||||
|
|
||||||
@DeprecatedSinceKotlin()
|
<!DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS!>@DeprecatedSinceKotlin()<!>
|
||||||
class Clazz
|
class Clazz
|
||||||
|
|
||||||
@Deprecated("", level = DeprecationLevel.WARNING)
|
@Deprecated("", level = DeprecationLevel.WARNING)
|
||||||
@DeprecatedSinceKotlin()
|
<!DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS!>@DeprecatedSinceKotlin()<!>
|
||||||
fun fooWarning() {}
|
fun fooWarning() {}
|
||||||
|
|
||||||
@Deprecated("", ReplaceWith(""), DeprecationLevel.WARNING)
|
@Deprecated("", ReplaceWith(""), DeprecationLevel.WARNING)
|
||||||
@DeprecatedSinceKotlin()
|
<!DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS!>@DeprecatedSinceKotlin()<!>
|
||||||
fun fooDefaultWarning() {}
|
fun fooDefaultWarning() {}
|
||||||
|
|
||||||
@Deprecated("", level = DeprecationLevel.ERROR)
|
@Deprecated("", level = DeprecationLevel.ERROR)
|
||||||
@DeprecatedSinceKotlin()
|
<!DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS!>@DeprecatedSinceKotlin()<!>
|
||||||
fun fooError() {}
|
fun fooError() {}
|
||||||
|
|
||||||
@Deprecated("", level = DeprecationLevel.HIDDEN)
|
@Deprecated("", level = DeprecationLevel.HIDDEN)
|
||||||
@DeprecatedSinceKotlin()
|
<!DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS!>@DeprecatedSinceKotlin()<!>
|
||||||
fun fooHidden() {}
|
fun fooHidden() {}
|
||||||
|
|
||||||
@Deprecated("")
|
@Deprecated("")
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
package kotlin
|
package kotlin
|
||||||
|
|
||||||
@Deprecated("")
|
@Deprecated("")
|
||||||
@DeprecatedSinceKotlin
|
<!DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS!>@DeprecatedSinceKotlin<!>
|
||||||
fun foo() {}
|
fun foo() {}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
|
|||||||
+6
@@ -533,6 +533,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.DEPRECATED_SINCE_KOTLIN_WITHOUT_ARGUMENTS) { firDiagnostic ->
|
||||||
|
DeprecatedSinceKotlinWithoutArgumentsImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE) { firDiagnostic ->
|
add(FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE) { firDiagnostic ->
|
||||||
ExposedTypealiasExpandedTypeImpl(
|
ExposedTypealiasExpandedTypeImpl(
|
||||||
firDiagnostic.a,
|
firDiagnostic.a,
|
||||||
|
|||||||
+4
@@ -384,6 +384,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = DeprecatedSinceKotlinWithUnorderedVersions::class
|
override val diagnosticClass get() = DeprecatedSinceKotlinWithUnorderedVersions::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class DeprecatedSinceKotlinWithoutArguments : KtFirDiagnostic<PsiElement>() {
|
||||||
|
override val diagnosticClass get() = DeprecatedSinceKotlinWithoutArguments::class
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
+7
@@ -619,6 +619,13 @@ internal class DeprecatedSinceKotlinWithUnorderedVersionsImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class DeprecatedSinceKotlinWithoutArgumentsImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.DeprecatedSinceKotlinWithoutArguments(), KtAbstractFirDiagnostic<PsiElement> {
|
||||||
|
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