[FIR] Report warning when error is suppressed
#KT-61129
This commit is contained in:
committed by
Space Team
parent
769e4ac0ac
commit
c32a0a83f9
+7
@@ -271,6 +271,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.ERROR_SUPPRESSION) { firDiagnostic ->
|
||||
ErrorSuppressionImpl(
|
||||
firDiagnostic.a,
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.INVISIBLE_REFERENCE) { firDiagnostic ->
|
||||
InvisibleReferenceImpl(
|
||||
firSymbolBuilder.buildSymbol(firDiagnostic.a),
|
||||
|
||||
+5
@@ -232,6 +232,11 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = InnerOnTopLevelScriptClassWarning::class
|
||||
}
|
||||
|
||||
interface ErrorSuppression : KtFirDiagnostic<PsiElement> {
|
||||
override val diagnosticClass get() = ErrorSuppression::class
|
||||
val diagnosticName: String
|
||||
}
|
||||
|
||||
interface InvisibleReference : KtFirDiagnostic<PsiElement> {
|
||||
override val diagnosticClass get() = InvisibleReference::class
|
||||
val reference: KtSymbol
|
||||
|
||||
+6
@@ -264,6 +264,12 @@ internal class InnerOnTopLevelScriptClassWarningImpl(
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.InnerOnTopLevelScriptClassWarning
|
||||
|
||||
internal class ErrorSuppressionImpl(
|
||||
override val diagnosticName: String,
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.ErrorSuppression
|
||||
|
||||
internal class InvisibleReferenceImpl(
|
||||
override val reference: KtSymbol,
|
||||
override val visible: Visibility,
|
||||
|
||||
+3
@@ -105,6 +105,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<CallableId>("callableId")
|
||||
}
|
||||
val INNER_ON_TOP_LEVEL_SCRIPT_CLASS by deprecationError<PsiElement>(LanguageFeature.ProhibitScriptTopLevelInnerClasses)
|
||||
val ERROR_SUPPRESSION by warning<PsiElement> {
|
||||
parameter<String>("diagnosticName")
|
||||
}
|
||||
}
|
||||
|
||||
val UNRESOLVED by object : DiagnosticGroup("Unresolved") {
|
||||
|
||||
@@ -152,6 +152,7 @@ object FirErrors {
|
||||
val VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER by error1<KtParameter, KtKeywordToken>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
|
||||
val INVISIBLE_SETTER by error3<PsiElement, FirPropertySymbol, Visibility, CallableId>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
|
||||
val INNER_ON_TOP_LEVEL_SCRIPT_CLASS by deprecationError0<PsiElement>(ProhibitScriptTopLevelInnerClasses)
|
||||
val ERROR_SUPPRESSION by warning1<PsiElement, String>()
|
||||
|
||||
// Unresolved
|
||||
val INVISIBLE_REFERENCE by error3<PsiElement, FirBasedSymbol<*>, Visibility, ClassId?>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
|
||||
+7
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlineDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
||||
@@ -58,6 +59,12 @@ abstract class CheckerContext : DiagnosticContext {
|
||||
override fun isDiagnosticSuppressed(diagnostic: KtDiagnostic): Boolean {
|
||||
val factory = diagnostic.factory
|
||||
val name = factory.name
|
||||
|
||||
if (name == FirErrors.ERROR_SUPPRESSION.name) {
|
||||
// Can't suppress warning about suppressed error
|
||||
return false
|
||||
}
|
||||
|
||||
val suppressedByAll = when (factory.severity) {
|
||||
Severity.INFO -> allInfosSuppressed
|
||||
Severity.WARNING -> allWarningsSuppressed
|
||||
|
||||
+28
-2
@@ -14,17 +14,22 @@ import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.ConstantArgumentKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.checkConstantArguments
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FIR_NON_SUPPRESSIBLE_ERROR_NAMES
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.findArgumentByName
|
||||
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
|
||||
import org.jetbrains.kotlin.fir.declarations.unwrapVarargValue
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.fqName
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.resolve.RequireKotlinConstants
|
||||
|
||||
object FirAnnotationExpressionChecker : FirAnnotationCallChecker() {
|
||||
@@ -39,7 +44,8 @@ object FirAnnotationExpressionChecker : FirAnnotationCallChecker() {
|
||||
|
||||
override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val argumentMapping = expression.argumentMapping.mapping
|
||||
val fqName = expression.fqName(context.session)
|
||||
val annotationClassId = expression.toAnnotationClassId(context.session)
|
||||
val fqName = annotationClassId?.asSingleFqName()
|
||||
for (arg in argumentMapping.values) {
|
||||
val argExpression = (arg as? FirNamedArgumentExpression)?.expression ?: (arg as? FirErrorExpression)?.expression ?: arg
|
||||
checkAnnotationArgumentWithSubElements(argExpression, context.session, reporter, context)
|
||||
@@ -50,6 +56,7 @@ object FirAnnotationExpressionChecker : FirAnnotationCallChecker() {
|
||||
checkDeprecatedSinceKotlin(expression.source, fqName, argumentMapping, context, reporter)
|
||||
checkAnnotationUsedAsAnnotationArgument(expression, context, reporter)
|
||||
checkNotAClass(expression, context, reporter)
|
||||
checkErrorSuppression(annotationClassId, argumentMapping, reporter, context)
|
||||
}
|
||||
|
||||
private fun checkAnnotationArgumentWithSubElements(
|
||||
@@ -220,4 +227,23 @@ object FirAnnotationExpressionChecker : FirAnnotationCallChecker() {
|
||||
reporter.reportOn(annotationTypeRef.source, FirErrors.NOT_A_CLASS, context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkErrorSuppression(
|
||||
annotationClassId: ClassId?,
|
||||
argumentMapping: Map<Name, FirExpression>,
|
||||
reporter: DiagnosticReporter,
|
||||
context: CheckerContext,
|
||||
) {
|
||||
if (annotationClassId != StandardClassIds.Annotations.Suppress) return
|
||||
val nameExpressions = argumentMapping[StandardClassIds.Annotations.ParameterNames.suppressNames]?.unwrapVarargValue() ?: return
|
||||
for (nameExpression in nameExpressions) {
|
||||
val name = (nameExpression as? FirConstExpression<*>)?.value as? String ?: continue
|
||||
val parameter = when (name) {
|
||||
in FIR_NON_SUPPRESSIBLE_ERROR_NAMES -> name
|
||||
AbstractDiagnosticCollector.SUPPRESS_ALL_ERRORS -> "all errors"
|
||||
else -> continue
|
||||
}
|
||||
reporter.reportOn(nameExpression.source, FirErrors.ERROR_SUPPRESSION, parameter, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-4
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.fir.resolve.SessionHolder
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyDeclarationResolver
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
|
||||
abstract class AbstractDiagnosticCollector(
|
||||
@@ -45,8 +44,6 @@ abstract class AbstractDiagnosticCollector(
|
||||
const val SUPPRESS_ALL_WARNINGS = "warnings"
|
||||
const val SUPPRESS_ALL_ERRORS = "errors"
|
||||
|
||||
private val SUPPRESS_NAMES_NAME = Name.identifier("names")
|
||||
|
||||
private fun correctDiagnosticCase(diagnostic: String): String = when (diagnostic) {
|
||||
SUPPRESS_ALL_INFOS, SUPPRESS_ALL_WARNINGS, SUPPRESS_ALL_ERRORS -> diagnostic
|
||||
else -> diagnostic.uppercase()
|
||||
@@ -58,7 +55,9 @@ abstract class AbstractDiagnosticCollector(
|
||||
for (annotation in annotationContainer.annotations) {
|
||||
val type = annotation.annotationTypeRef.coneType as? ConeClassLikeType ?: continue
|
||||
if (type.lookupTag.classId != StandardClassIds.Annotations.Suppress) continue
|
||||
val argumentValues = annotation.findArgumentByName(SUPPRESS_NAMES_NAME)?.unwrapVarargValue() ?: continue
|
||||
val argumentValues =
|
||||
annotation.findArgumentByName(StandardClassIds.Annotations.ParameterNames.suppressNames)?.unwrapVarargValue()
|
||||
?: continue
|
||||
|
||||
for (argumentValue in argumentValues) {
|
||||
val value = (argumentValue as? FirConstExpression<*>)?.value as? String ?: continue
|
||||
|
||||
+6
@@ -205,6 +205,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EQUALITY_NOT_APPL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EQUALITY_NOT_APPLICABLE_WARNING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ERROR_FROM_JAVA_RESOLUTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ERROR_IN_CONTRACT_DESCRIPTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ERROR_SUPPRESSION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPANDED_TYPE_CANNOT_BE_INHERITED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_CLASS_CONSTRUCTOR_DELEGATION_CALL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER
|
||||
@@ -748,6 +749,11 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
NAME_OF_CONTAINING_DECLARATION_OR_FILE
|
||||
)
|
||||
map.put(INNER_ON_TOP_LEVEL_SCRIPT_CLASS, "Top level script class cannot be inner.")
|
||||
map.put(
|
||||
ERROR_SUPPRESSION,
|
||||
"This code uses error suppression for ''{0}''. While it might compile and work, the compiler behavior is UNSPECIFIED and WON''T BE PRESERVED. Please report your use case to the Kotlin issue tracker instead: https://kotl.in/issue",
|
||||
TO_STRING
|
||||
)
|
||||
map.put(UNRESOLVED_REFERENCE, "Unresolved reference: {0}", NULLABLE_STRING)
|
||||
map.put(UNRESOLVED_IMPORT, "Unresolved reference: {0}", NULLABLE_STRING) // &
|
||||
map.put(UNRESOLVED_LABEL, "Unresolved label")
|
||||
|
||||
@@ -223,6 +223,8 @@ object StandardClassIds {
|
||||
val deprecatedSinceKotlinErrorSince = Name.identifier("errorSince")
|
||||
val deprecatedSinceKotlinHiddenSince = Name.identifier("hiddenSince")
|
||||
|
||||
val suppressNames = Name.identifier("names")
|
||||
|
||||
val parameterNameName = StandardNames.NAME
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user