[FIR] Part 1. Group checkers by the MPP kind

This commit introduces MppChecker kind, which represents the new property
  of checkers
- `MppCheckerKind.Common` means that this checker should run from the same
  session to which corresponding declaration belongs
- `MppCheckerKind.Platform` means that in case of MPP compilation this
  checker should run with session of leaf platform module for sources
  of all modules

An example of a platform checker is a checker that checks class scopes
  and reports ABSTRACT_NOT_IMPLEMENTED and similar diagnostics. If some
  regular class in the common module contains expect supertypes, the
  checker should consider the actualization of those supertypes to get
  a complete type scope

^KT-58881
This commit is contained in:
Dmitriy Novozhilov
2024-01-08 14:37:30 +02:00
committed by Nikolay Lunyak
parent ff063f553e
commit 727d2f46f8
338 changed files with 1216 additions and 728 deletions
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.assignment.plugin.k2.diagnostics.FirErrorsAssignment
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirFunctionCallChecker
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
@@ -27,7 +28,7 @@ import org.jetbrains.kotlin.fir.types.resolvedType
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
import org.jetbrains.kotlin.types.expressions.OperatorConventions.ASSIGN_METHOD
object FirAssignmentPluginFunctionCallChecker : FirFunctionCallChecker() {
object FirAssignmentPluginFunctionCallChecker : FirFunctionCallChecker(MppCheckerKind.Common) {
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
if (!expression.isOverloadAssignCallCandidate()) return
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.assignment.plugin.k2.annotationMatchingService
import org.jetbrains.kotlin.assignment.plugin.k2.diagnostics.FirErrorsAssignmentPlugin.DECLARATION_ERROR_ASSIGN_METHOD_SHOULD_RETURN_UNIT
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirSimpleFunctionChecker
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
@@ -20,7 +21,7 @@ import org.jetbrains.kotlin.fir.types.isUnit
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
import org.jetbrains.kotlin.types.expressions.OperatorConventions.ASSIGN_METHOD
object FirAssignmentPluginFunctionChecker : FirSimpleFunctionChecker() {
object FirAssignmentPluginFunctionChecker : FirSimpleFunctionChecker(MppCheckerKind.Common) {
override fun check(declaration: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration.origin != FirDeclarationOrigin.Source) return
@@ -5,13 +5,14 @@
package org.jetbrains.kotlin.fir.plugin.checkers
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirSimpleFunctionChecker
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirSimpleFunctionChecker
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
object DummyNameChecker : FirSimpleFunctionChecker() {
object DummyNameChecker : FirSimpleFunctionChecker(MppCheckerKind.Common) {
override fun check(declaration: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) {
val name = declaration.name.asString()
if (name == "dummy") {
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.plugin.checkers
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.InternalDiagnosticFactoryMethod
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirFunctionCallChecker
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
@@ -17,8 +18,7 @@ import org.jetbrains.kotlin.fir.plugin.types.numberSign
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.resolvedType
object SignedNumberCallChecker : FirFunctionCallChecker() {
@OptIn(InternalDiagnosticFactoryMethod::class)
object SignedNumberCallChecker : FirFunctionCallChecker(MppCheckerKind.Common) {
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
val argumentMapping = expression.resolvedArgumentMapping ?: return
for ((argument, parameter) in argumentMapping.entries) {
@@ -8,6 +8,7 @@ package org.jetbrains.kotlinx.jspo.compiler.fir.checkers
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassChecker
import org.jetbrains.kotlin.fir.declarations.FirClass
@@ -26,7 +27,7 @@ import org.jetbrains.kotlin.fir.types.isAny
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
import org.jetbrains.kotlinx.jspo.compiler.resolve.JsPlainObjectsAnnotations
object FirJsPlainObjectsPluginClassChecker : FirClassChecker() {
object FirJsPlainObjectsPluginClassChecker : FirClassChecker(MppCheckerKind.Platform) {
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
with(context) {
val classSymbol = declaration.symbol as? FirRegularClassSymbol ?: return
@@ -39,7 +39,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds
object FirSerializationPluginClassChecker : FirClassChecker() {
object FirSerializationPluginClassChecker : FirClassChecker(MppCheckerKind.Common) {
private val JAVA_SERIALIZABLE_ID = ClassId.topLevel(FqName("java.io.Serializable"))
private const val TOO_LOW = "too low"
private const val UNKNOWN = "unknown"
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.noarg.fir
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirRegularClassChecker
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
@@ -16,7 +17,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.resolve.getSuperClassSymbolOrAny
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
object FirNoArgDeclarationChecker : FirRegularClassChecker() {
object FirNoArgDeclarationChecker : FirRegularClassChecker(MppCheckerKind.Common) {
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
val source = declaration.source ?: return
if (declaration.classKind != ClassKind.CLASS) return
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.parcelize.fir.diagnostics
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirAnnotationCallChecker
import org.jetbrains.kotlin.fir.analysis.checkers.findClosestClassOrObject
@@ -27,7 +28,8 @@ import org.jetbrains.kotlin.parcelize.ParcelizeNames.RAW_VALUE_ANNOTATION_CLASS_
import org.jetbrains.kotlin.parcelize.ParcelizeNames.TYPE_PARCELER_CLASS_IDS
import org.jetbrains.kotlin.parcelize.ParcelizeNames.WRITE_WITH_CLASS_IDS
object FirParcelizeAnnotationChecker : FirAnnotationCallChecker() {
// TODO: extract common checker for expect interfaces
object FirParcelizeAnnotationChecker : FirAnnotationCallChecker(MppCheckerKind.Platform) {
override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
val annotationType = expression.annotationTypeRef.coneType.fullyExpandedType(context.session) as? ConeClassLikeType ?: return
val resolvedAnnotationSymbol = annotationType.lookupTag.toFirRegularClassSymbol(context.session) ?: return
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassChecker
import org.jetbrains.kotlin.fir.declarations.*
@@ -29,7 +30,7 @@ import org.jetbrains.kotlin.parcelize.ParcelizeNames.PARCELIZE_CLASS_CLASS_IDS
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
object FirParcelizeClassChecker : FirClassChecker() {
object FirParcelizeClassChecker : FirClassChecker(MppCheckerKind.Common) {
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
checkParcelableClass(declaration, context, reporter)
checkParcelerClass(declaration, context, reporter)
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.hasValOrVar
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirConstructorChecker
import org.jetbrains.kotlin.fir.correspondingProperty
@@ -17,7 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
import org.jetbrains.kotlin.parcelize.ParcelizeNames
object FirParcelizeConstructorChecker : FirConstructorChecker() {
object FirParcelizeConstructorChecker : FirConstructorChecker(MppCheckerKind.Common) {
override fun check(declaration: FirConstructor, context: CheckerContext, reporter: DiagnosticReporter) {
if (!declaration.isPrimary) return
val source = declaration.source ?: return
@@ -7,17 +7,18 @@ package org.jetbrains.kotlin.parcelize.fir.diagnostics
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirSimpleFunctionChecker
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.utils.isOverride
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.isInt
import org.jetbrains.kotlin.fir.types.isUnit
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
object FirParcelizeFunctionChecker : FirSimpleFunctionChecker() {
object FirParcelizeFunctionChecker : FirSimpleFunctionChecker(MppCheckerKind.Common) {
override fun check(declaration: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) {
val containingClassSymbol = declaration.dispatchReceiverType?.toRegularClassSymbol(context.session)
if (!containingClassSymbol.isParcelize(context.session)) return
@@ -11,15 +11,16 @@ import org.jetbrains.kotlin.descriptors.isEnumClass
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirPropertyChecker
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.java.hasJvmFieldAnnotation
import org.jetbrains.kotlin.fir.declarations.utils.fromPrimaryConstructor
import org.jetbrains.kotlin.fir.declarations.utils.hasBackingField
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.java.hasJvmFieldAnnotation
import org.jetbrains.kotlin.fir.resolve.fqName
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
@@ -31,7 +32,7 @@ import org.jetbrains.kotlin.parcelize.ParcelizeNames.CREATOR_NAME
import org.jetbrains.kotlin.parcelize.ParcelizeNames.IGNORED_ON_PARCEL_CLASS_IDS
import org.jetbrains.kotlin.parcelize.ParcelizeNames.PARCELER_ID
object FirParcelizePropertyChecker : FirPropertyChecker() {
object FirParcelizePropertyChecker : FirPropertyChecker(MppCheckerKind.Common) {
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
val session = context.session
val containingClassSymbol = declaration.dispatchReceiverType?.toRegularClassSymbol(session) ?: return