[FIR] Refactor: extract ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT checker
...into separate object. ^KT-62559
This commit is contained in:
committed by
Space Team
parent
3e88fc80d2
commit
a466b14264
+1
@@ -29,6 +29,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
FirExposedVisibilityDeclarationChecker,
|
FirExposedVisibilityDeclarationChecker,
|
||||||
FirCyclicTypeBoundsChecker,
|
FirCyclicTypeBoundsChecker,
|
||||||
FirExpectActualDeclarationChecker,
|
FirExpectActualDeclarationChecker,
|
||||||
|
FirActualAnnotationsMatchExpectChecker,
|
||||||
FirAmbiguousAnonymousTypeChecker,
|
FirAmbiguousAnonymousTypeChecker,
|
||||||
FirExplicitApiDeclarationChecker,
|
FirExplicitApiDeclarationChecker,
|
||||||
FirAnnotationChecker,
|
FirAnnotationChecker,
|
||||||
|
|||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.config.LanguageFeature
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.diagnostics.InternalDiagnosticFactoryMethod
|
||||||
|
import org.jetbrains.kotlin.diagnostics.requireNotNull
|
||||||
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.getSingleMatchedExpectForActualOrNull
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isActual
|
||||||
|
import org.jetbrains.kotlin.fir.expectActualMatchingContextFactory
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualAnnotationMatchChecker
|
||||||
|
|
||||||
|
// TODO(Roman.Efremov): KT-62559 prevent reporting ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT twice in CLI mode in K2
|
||||||
|
internal object FirActualAnnotationsMatchExpectChecker : FirBasicDeclarationChecker() {
|
||||||
|
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration !is FirMemberDeclaration) return
|
||||||
|
if (!context.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)) return
|
||||||
|
if (!context.languageVersionSettings.supportsFeature(LanguageFeature.MultiplatformRestrictions)) return
|
||||||
|
if (!declaration.isActual) return
|
||||||
|
|
||||||
|
val actualSymbol = declaration.symbol
|
||||||
|
val expectSymbol = actualSymbol.getSingleMatchedExpectForActualOrNull() ?: return
|
||||||
|
checkAnnotationsMatch(expectSymbol, actualSymbol, context, reporter)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(InternalDiagnosticFactoryMethod::class)
|
||||||
|
private fun checkAnnotationsMatch(
|
||||||
|
expectSymbol: FirBasedSymbol<*>,
|
||||||
|
actualSymbol: FirBasedSymbol<*>,
|
||||||
|
context: CheckerContext,
|
||||||
|
reporter: DiagnosticReporter,
|
||||||
|
) {
|
||||||
|
val matchingContext = context.session.expectActualMatchingContextFactory.create(context.session, context.scopeSession)
|
||||||
|
val incompatibility =
|
||||||
|
AbstractExpectActualAnnotationMatchChecker.areAnnotationsCompatible(expectSymbol, actualSymbol, matchingContext) ?: return
|
||||||
|
val actualAnnotationTargetSourceElement = (incompatibility.actualAnnotationTargetElement as FirSourceElement).element
|
||||||
|
|
||||||
|
reporter.report(
|
||||||
|
FirErrors.ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT.on(
|
||||||
|
actualSymbol.source.requireNotNull(),
|
||||||
|
incompatibility.expectSymbol as FirBasedSymbol<*>,
|
||||||
|
incompatibility.actualSymbol as FirBasedSymbol<*>,
|
||||||
|
actualAnnotationTargetSourceElement,
|
||||||
|
incompatibility.type.mapAnnotationType { it.annotationSymbol as FirAnnotation },
|
||||||
|
positioningStrategy = null,
|
||||||
|
),
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-32
@@ -8,8 +8,11 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
|||||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.diagnostics.*
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies
|
||||||
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.FirExpectActualMatchingContext
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList
|
import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
@@ -18,7 +21,8 @@ import org.jetbrains.kotlin.fir.declarations.utils.isActual
|
|||||||
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isExternal
|
import org.jetbrains.kotlin.fir.declarations.utils.isExternal
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isTailRec
|
import org.jetbrains.kotlin.fir.declarations.utils.isTailRec
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
import org.jetbrains.kotlin.fir.expectActualMatchingContextFactory
|
||||||
|
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
@@ -28,7 +32,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
|
|||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.mpp.RegularClassSymbolMarker
|
import org.jetbrains.kotlin.mpp.RegularClassSymbolMarker
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualAnnotationMatchChecker
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualChecker
|
import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualChecker
|
||||||
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCheckingCompatibility
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCheckingCompatibility
|
||||||
@@ -212,7 +215,6 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() {
|
|||||||
}
|
}
|
||||||
if (expectedSingleCandidate != null) {
|
if (expectedSingleCandidate != null) {
|
||||||
checkOptInAnnotation(declaration, expectedSingleCandidate, context, reporter)
|
checkOptInAnnotation(declaration, expectedSingleCandidate, context, reporter)
|
||||||
checkAnnotationsMatch(expectedSingleCandidate, symbol, context, reporter)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,33 +272,6 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(Roman.Efremov): KT-62559 prevent reporting ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT twice in CLI mode in K2
|
|
||||||
@OptIn(InternalDiagnosticFactoryMethod::class)
|
|
||||||
private fun checkAnnotationsMatch(
|
|
||||||
expectSymbol: FirBasedSymbol<*>,
|
|
||||||
actualSymbol: FirBasedSymbol<*>,
|
|
||||||
context: CheckerContext,
|
|
||||||
reporter: DiagnosticReporter
|
|
||||||
) {
|
|
||||||
if (!context.languageVersionSettings.supportsFeature(LanguageFeature.MultiplatformRestrictions)) return
|
|
||||||
val matchingContext = context.session.expectActualMatchingContextFactory.create(context.session, context.scopeSession)
|
|
||||||
val incompatibility =
|
|
||||||
AbstractExpectActualAnnotationMatchChecker.areAnnotationsCompatible(expectSymbol, actualSymbol, matchingContext) ?: return
|
|
||||||
val actualAnnotationTargetSourceElement = (incompatibility.actualAnnotationTargetElement as FirSourceElement).element
|
|
||||||
|
|
||||||
reporter.report(
|
|
||||||
FirErrors.ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT.on(
|
|
||||||
actualSymbol.source.requireNotNull(),
|
|
||||||
incompatibility.expectSymbol as FirBasedSymbol<*>,
|
|
||||||
incompatibility.actualSymbol as FirBasedSymbol<*>,
|
|
||||||
actualAnnotationTargetSourceElement,
|
|
||||||
incompatibility.type.mapAnnotationType { it.annotationSymbol as FirAnnotation },
|
|
||||||
positioningStrategy = null,
|
|
||||||
),
|
|
||||||
context,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// we don't require `actual` modifier on
|
// we don't require `actual` modifier on
|
||||||
// - annotation constructors, because annotation classes can only have one constructor
|
// - annotation constructors, because annotation classes can only have one constructor
|
||||||
// - value class primary constructors, because value class must have primary constructor
|
// - value class primary constructors, because value class must have primary constructor
|
||||||
|
|||||||
Reference in New Issue
Block a user