[FIR] Part 5. Introduce paired common checkers for expect classes
There are some cases when we want to run some platform checker not from
platform session but from common session. All such cases appear when
we check some `expect` class
```kotlin
// MODULE: common
expect interface A
expect class B : A
class C : A
// MODULE: platform()()(common)
actual interface A {
fun foo()
}
actual class B : A {
override fun foo() {}
}
```
In this example we want to report "abstract foo not implemented" on
class `C`, but we don't want to report it on `expect class B` (as
its supertype is always `expect A`, never `actual A`)
So to cover such cases some platform checkers were split into two parts:
- `Regular`, which is platform checkers and runs for everything except
expect declaration
- `ForExpectClass`, which is common checkers and runs only for expect
declarations
^KT-58881 Fixed
^KT-58881 Fixed
^KT-64187 Fixed
This commit is contained in:
committed by
Nikolay Lunyak
parent
f5d8113de3
commit
990da9fa1a
+10
-5
@@ -12,7 +12,8 @@ import org.jetbrains.kotlin.fir.analysis.web.common.checkers.declaration.FirJsEx
|
|||||||
object JsDeclarationCheckers : DeclarationCheckers() {
|
object JsDeclarationCheckers : DeclarationCheckers() {
|
||||||
override val functionCheckers: Set<FirFunctionChecker>
|
override val functionCheckers: Set<FirFunctionChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirJsInheritanceFunctionChecker,
|
FirJsInheritanceFunctionChecker.Regular,
|
||||||
|
FirJsInheritanceFunctionChecker.ForExpectClass,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker>
|
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker>
|
||||||
@@ -30,11 +31,15 @@ object JsDeclarationCheckers : DeclarationCheckers() {
|
|||||||
|
|
||||||
override val classCheckers: Set<FirClassChecker>
|
override val classCheckers: Set<FirClassChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirJsMultipleInheritanceChecker,
|
FirJsMultipleInheritanceChecker.Regular,
|
||||||
|
FirJsMultipleInheritanceChecker.ForExpectClass,
|
||||||
FirJsDynamicDeclarationChecker,
|
FirJsDynamicDeclarationChecker,
|
||||||
FirJsInheritanceClassChecker,
|
FirJsInheritanceClassChecker.Regular,
|
||||||
FirJsExternalInheritorOnlyChecker,
|
FirJsInheritanceClassChecker.ForExpectClass,
|
||||||
FirJsNameClashClassMembersChecker
|
FirJsExternalInheritorOnlyChecker.Regular,
|
||||||
|
FirJsExternalInheritorOnlyChecker.ForExpectClass,
|
||||||
|
FirJsNameClashClassMembersChecker.Regular,
|
||||||
|
FirJsNameClashClassMembersChecker.ForExpectClass,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val simpleFunctionCheckers: Set<FirSimpleFunctionChecker>
|
override val simpleFunctionCheckers: Set<FirSimpleFunctionChecker>
|
||||||
|
|||||||
+16
-2
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors
|
|||||||
import org.jetbrains.kotlin.fir.analysis.js.checkers.isEffectivelyExternal
|
import org.jetbrains.kotlin.fir.analysis.js.checkers.isEffectivelyExternal
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.hasAnnotation
|
import org.jetbrains.kotlin.fir.declarations.hasAnnotation
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||||
@@ -21,8 +22,21 @@ import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
|
|||||||
import org.jetbrains.kotlin.name.JsStandardClassIds.Annotations.JsExternalInheritorsOnly
|
import org.jetbrains.kotlin.name.JsStandardClassIds.Annotations.JsExternalInheritorsOnly
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.popLast
|
import org.jetbrains.kotlin.utils.addToStdlib.popLast
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
sealed class FirJsExternalInheritorOnlyChecker(mppKind: MppCheckerKind) : FirClassChecker(mppKind) {
|
||||||
object FirJsExternalInheritorOnlyChecker : FirClassChecker(MppCheckerKind.Platform) {
|
object Regular : FirJsExternalInheritorOnlyChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirJsExternalInheritorOnlyChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun FirClass.forEachParents(context: CheckerContext, f: (FirRegularClassSymbol) -> Unit) {
|
private fun FirClass.forEachParents(context: CheckerContext, f: (FirRegularClassSymbol) -> Unit) {
|
||||||
val todo = superConeTypes.toMutableList()
|
val todo = superConeTypes.toMutableList()
|
||||||
val done = hashSetOf<FirRegularClassSymbol>()
|
val done = hashSetOf<FirRegularClassSymbol>()
|
||||||
|
|||||||
+16
-2
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors
|
|||||||
import org.jetbrains.kotlin.fir.analysis.js.checkers.isEffectivelyExternal
|
import org.jetbrains.kotlin.fir.analysis.js.checkers.isEffectivelyExternal
|
||||||
import org.jetbrains.kotlin.fir.analysis.js.checkers.isOverridingExternalWithOptionalParams
|
import org.jetbrains.kotlin.fir.analysis.js.checkers.isOverridingExternalWithOptionalParams
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
||||||
import org.jetbrains.kotlin.fir.scopes.collectAllFunctions
|
import org.jetbrains.kotlin.fir.scopes.collectAllFunctions
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverrideFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverrideFunctionSymbol
|
||||||
@@ -26,8 +27,21 @@ import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
|||||||
import org.jetbrains.kotlin.fir.types.isSuspendOrKSuspendFunctionType
|
import org.jetbrains.kotlin.fir.types.isSuspendOrKSuspendFunctionType
|
||||||
import org.jetbrains.kotlin.fir.types.typeContext
|
import org.jetbrains.kotlin.fir.types.typeContext
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
sealed class FirJsInheritanceClassChecker(mppKind: MppCheckerKind) : FirClassChecker(mppKind) {
|
||||||
object FirJsInheritanceClassChecker : FirClassChecker(MppCheckerKind.Platform) {
|
object Regular : FirJsInheritanceClassChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirJsInheritanceClassChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (!declaration.symbol.isEffectivelyExternal(context)) {
|
if (!declaration.symbol.isEffectivelyExternal(context)) {
|
||||||
val fakeOverriddenMethod = declaration.findFakeMethodOverridingExternalWithOptionalParams(context)
|
val fakeOverriddenMethod = declaration.findFakeMethodOverridingExternalWithOptionalParams(context)
|
||||||
|
|||||||
+17
-2
@@ -13,11 +13,26 @@ import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirFunctionChecker
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors
|
||||||
import org.jetbrains.kotlin.fir.analysis.js.checkers.isEffectivelyExternal
|
import org.jetbrains.kotlin.fir.analysis.js.checkers.isEffectivelyExternal
|
||||||
import org.jetbrains.kotlin.fir.analysis.js.checkers.isOverridingExternalWithOptionalParams
|
import org.jetbrains.kotlin.fir.analysis.js.checkers.isOverridingExternalWithOptionalParams
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
|
|
||||||
|
sealed class FirJsInheritanceFunctionChecker(mppKind: MppCheckerKind) : FirFunctionChecker(mppKind) {
|
||||||
|
object Regular : FirJsInheritanceFunctionChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if ((context.containingDeclarations.last() as? FirClass)?.isExpect == true) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirJsInheritanceFunctionChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if ((context.containingDeclarations.last() as? FirClass)?.isExpect != true) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
|
||||||
object FirJsInheritanceFunctionChecker : FirFunctionChecker(MppCheckerKind.Platform) {
|
|
||||||
override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (declaration.isNotEffectivelyExternalFunctionButOverridesExternal(context)) {
|
if (declaration.isNotEffectivelyExternalFunctionButOverridesExternal(context)) {
|
||||||
reporter.reportOn(declaration.source, FirJsErrors.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS, context)
|
reporter.reportOn(declaration.source, FirJsErrors.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS, context)
|
||||||
|
|||||||
+16
-2
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.overriddenFunctions
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||||
import org.jetbrains.kotlin.fir.scopes.getFunctions
|
import org.jetbrains.kotlin.fir.scopes.getFunctions
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
@@ -23,8 +24,21 @@ import org.jetbrains.kotlin.fir.types.isSubtypeOf
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
sealed class FirJsMultipleInheritanceChecker(mppKind: MppCheckerKind) : FirClassChecker(mppKind) {
|
||||||
object FirJsMultipleInheritanceChecker : FirClassChecker(MppCheckerKind.Platform) {
|
object Regular : FirJsMultipleInheritanceChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirJsMultipleInheritanceChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
declaration.checkFunctionIfSubtypeOf(
|
declaration.checkFunctionIfSubtypeOf(
|
||||||
functionToCheck = OperatorNameConventions.GET,
|
functionToCheck = OperatorNameConventions.GET,
|
||||||
|
|||||||
+16
-2
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.declarations.FirClass
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.fir.declarations.constructors
|
import org.jetbrains.kotlin.fir.declarations.constructors
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
|
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
|
||||||
import org.jetbrains.kotlin.fir.scopes.*
|
import org.jetbrains.kotlin.fir.scopes.*
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
@@ -31,8 +32,21 @@ import org.jetbrains.kotlin.fir.unwrapFakeOverridesOrDelegated
|
|||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.popLast
|
import org.jetbrains.kotlin.utils.addToStdlib.popLast
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
sealed class FirJsNameClashClassMembersChecker(mppKind: MppCheckerKind) : FirClassChecker(mppKind) {
|
||||||
object FirJsNameClashClassMembersChecker : FirClassChecker(MppCheckerKind.Platform) {
|
object Regular : FirJsNameClashClassMembersChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirJsNameClashClassMembersChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class StableNamesCollector {
|
private class StableNamesCollector {
|
||||||
val jsStableNames = mutableSetOf<FirJsStableName>()
|
val jsStableNames = mutableSetOf<FirJsStableName>()
|
||||||
val overrideIntersections = hashMapOf<FirCallableSymbol<*>, HashSet<FirCallableSymbol<*>>>()
|
val overrideIntersections = hashMapOf<FirCallableSymbol<*>, HashSet<FirCallableSymbol<*>>>()
|
||||||
|
|||||||
+2
-1
@@ -24,7 +24,8 @@ object JvmDeclarationCheckers : DeclarationCheckers() {
|
|||||||
override val classCheckers: Set<FirClassChecker>
|
override val classCheckers: Set<FirClassChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirStrictfpApplicabilityChecker,
|
FirStrictfpApplicabilityChecker,
|
||||||
FirOverrideJavaNullabilityWarningChecker,
|
FirOverrideJavaNullabilityWarningChecker.Regular,
|
||||||
|
FirOverrideJavaNullabilityWarningChecker.ForExpectClass,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val regularClassCheckers: Set<FirRegularClassChecker>
|
override val regularClassCheckers: Set<FirRegularClassChecker>
|
||||||
|
|||||||
+16
-2
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirAbstractOverrid
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.java.enhancement.EnhancedForWarningConeSubstitutor
|
import org.jetbrains.kotlin.fir.java.enhancement.EnhancedForWarningConeSubstitutor
|
||||||
import org.jetbrains.kotlin.fir.scopes.*
|
import org.jetbrains.kotlin.fir.scopes.*
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
|
import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
|
||||||
@@ -24,8 +25,21 @@ import org.jetbrains.kotlin.fir.types.coneType
|
|||||||
import org.jetbrains.kotlin.fir.types.typeContext
|
import org.jetbrains.kotlin.fir.types.typeContext
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
sealed class FirOverrideJavaNullabilityWarningChecker(mppKind: MppCheckerKind) : FirAbstractOverrideChecker(mppKind) {
|
||||||
object FirOverrideJavaNullabilityWarningChecker : FirAbstractOverrideChecker(MppCheckerKind.Platform) {
|
object Regular : FirOverrideJavaNullabilityWarningChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirOverrideJavaNullabilityWarningChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val substitutor = EnhancedForWarningConeSubstitutor(context.session.typeContext)
|
val substitutor = EnhancedForWarningConeSubstitutor(context.session.typeContext)
|
||||||
val scope = declaration.unsubstitutedScope(context)
|
val scope = declaration.unsubstitutedScope(context)
|
||||||
|
|||||||
+26
-7
@@ -14,14 +14,33 @@ import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
|
|
||||||
object FirNativeObjCNameCallableChecker : FirCallableDeclarationChecker(MppCheckerKind.Common) {
|
sealed class FirNativeObjCNameCallableChecker(mppKind: MppCheckerKind) : FirCallableDeclarationChecker(mppKind) {
|
||||||
override fun check(declaration: FirCallableDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
object Regular : FirNativeObjCNameCallableChecker(MppCheckerKind.Platform) {
|
||||||
if (declaration !is FirSimpleFunction && declaration !is FirProperty) return
|
override fun check(declaration: FirCallableDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val containingClass = context.containingDeclarations.lastOrNull() as? FirClass
|
val containingClass = context.containingDeclarations.lastOrNull() as? FirClass ?: return
|
||||||
if (containingClass != null) {
|
if (containingClass.isExpect) return
|
||||||
val firTypeScope = containingClass.unsubstitutedScope(context)
|
check(declaration, containingClass, context, reporter)
|
||||||
FirNativeObjCNameUtilities.checkCallableMember(firTypeScope, declaration.symbol, declaration, context, reporter)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirNativeObjCNameCallableChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirCallableDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
val containingClass = context.containingDeclarations.lastOrNull() as? FirClass ?: return
|
||||||
|
if (!containingClass.isExpect) return
|
||||||
|
check(declaration, containingClass, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun check(
|
||||||
|
declaration: FirCallableDeclaration,
|
||||||
|
containingClass: FirClass,
|
||||||
|
context: CheckerContext,
|
||||||
|
reporter: DiagnosticReporter,
|
||||||
|
) {
|
||||||
|
if (declaration !is FirSimpleFunction && declaration !is FirProperty) return
|
||||||
|
val firTypeScope = containingClass.unsubstitutedScope(context)
|
||||||
|
FirNativeObjCNameUtilities.checkCallableMember(firTypeScope, declaration.symbol, declaration, context, reporter)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-1
@@ -12,11 +12,25 @@ import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassChecker
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
||||||
import org.jetbrains.kotlin.fir.analysis.native.checkers.FirNativeObjCNameUtilities.checkCallableMember
|
import org.jetbrains.kotlin.fir.analysis.native.checkers.FirNativeObjCNameUtilities.checkCallableMember
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.isIntersectionOverride
|
import org.jetbrains.kotlin.fir.isIntersectionOverride
|
||||||
import org.jetbrains.kotlin.fir.scopes.processAllFunctions
|
import org.jetbrains.kotlin.fir.scopes.processAllFunctions
|
||||||
import org.jetbrains.kotlin.fir.scopes.processAllProperties
|
import org.jetbrains.kotlin.fir.scopes.processAllProperties
|
||||||
|
|
||||||
object FirNativeObjCNameOverridesChecker : FirClassChecker(MppCheckerKind.Platform) {
|
sealed class FirNativeObjCNameOverridesChecker(mppKind: MppCheckerKind) : FirClassChecker(mppKind) {
|
||||||
|
object Regular : FirNativeObjCNameOverridesChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirNativeObjCNameOverridesChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
// We just need to check intersection overrides, all other declarations are checked by FirNativeObjCNameChecker
|
// We just need to check intersection overrides, all other declarations are checked by FirNativeObjCNameChecker
|
||||||
|
|||||||
+9
-2
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirCallableDeclarationChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirCallableDeclarationChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.REDUNDANT_SWIFT_REFINEMENT
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.REDUNDANT_SWIFT_REFINEMENT
|
||||||
import org.jetbrains.kotlin.fir.analysis.native.checkers.FirNativeObjCRefinementOverridesChecker.check
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
@@ -35,7 +34,15 @@ object FirNativeObjCRefinementChecker : FirCallableDeclarationChecker(MppChecker
|
|||||||
val containingClass = context.containingDeclarations.lastOrNull() as? FirClass
|
val containingClass = context.containingDeclarations.lastOrNull() as? FirClass
|
||||||
if (containingClass != null) {
|
if (containingClass != null) {
|
||||||
val firTypeScope = containingClass.unsubstitutedScope(context)
|
val firTypeScope = containingClass.unsubstitutedScope(context)
|
||||||
check(firTypeScope, declaration.symbol, declaration, context, reporter, objCAnnotations, swiftAnnotations)
|
FirNativeObjCRefinementOverridesChecker.check(
|
||||||
|
firTypeScope,
|
||||||
|
declaration.symbol,
|
||||||
|
declaration,
|
||||||
|
context,
|
||||||
|
reporter,
|
||||||
|
objCAnnotations,
|
||||||
|
swiftAnnotations
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+82
-66
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.declarations.FirClass
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
|
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
|
||||||
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassLikeSymbol
|
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassLikeSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
import org.jetbrains.kotlin.fir.isIntersectionOverride
|
import org.jetbrains.kotlin.fir.isIntersectionOverride
|
||||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
||||||
@@ -29,8 +30,20 @@ import org.jetbrains.kotlin.fir.scopes.processAllFunctions
|
|||||||
import org.jetbrains.kotlin.fir.scopes.processAllProperties
|
import org.jetbrains.kotlin.fir.scopes.processAllProperties
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
sealed class FirNativeObjCRefinementOverridesChecker(mppKind: MppCheckerKind) : FirClassChecker(mppKind) {
|
||||||
object FirNativeObjCRefinementOverridesChecker : FirClassChecker(MppCheckerKind.Platform) {
|
object Regular : FirNativeObjCRefinementOverridesChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirNativeObjCRefinementOverridesChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
// We just need to check intersection overrides, all other declarations are checked by FirNativeObjCRefinementChecker
|
// We just need to check intersection overrides, all other declarations are checked by FirNativeObjCRefinementChecker
|
||||||
@@ -45,80 +58,83 @@ object FirNativeObjCRefinementOverridesChecker : FirClassChecker(MppCheckerKind.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun check(
|
companion object {
|
||||||
baseScope: FirTypeScope,
|
fun check(
|
||||||
memberSymbol: FirCallableSymbol<*>,
|
baseScope: FirTypeScope,
|
||||||
declarationToReport: FirDeclaration,
|
memberSymbol: FirCallableSymbol<*>,
|
||||||
context: CheckerContext,
|
declarationToReport: FirDeclaration,
|
||||||
reporter: DiagnosticReporter,
|
context: CheckerContext,
|
||||||
objCAnnotations: List<FirAnnotation>,
|
reporter: DiagnosticReporter,
|
||||||
swiftAnnotations: List<FirAnnotation>
|
objCAnnotations: List<FirAnnotation>,
|
||||||
) {
|
swiftAnnotations: List<FirAnnotation>
|
||||||
val overriddenMemberSymbols = baseScope.getDirectOverriddenMembersWithBaseScope(memberSymbol)
|
) {
|
||||||
if (overriddenMemberSymbols.isEmpty()) return
|
val overriddenMemberSymbols = baseScope.getDirectOverriddenMembersWithBaseScope(memberSymbol)
|
||||||
var isHiddenFromObjC = objCAnnotations.isNotEmpty()
|
if (overriddenMemberSymbols.isEmpty()) return
|
||||||
var isRefinedInSwift = swiftAnnotations.isNotEmpty()
|
var isHiddenFromObjC = objCAnnotations.isNotEmpty()
|
||||||
val supersNotHiddenFromObjC = mutableListOf<FirCallableSymbol<*>>()
|
var isRefinedInSwift = swiftAnnotations.isNotEmpty()
|
||||||
val supersNotRefinedInSwift = mutableListOf<FirCallableSymbol<*>>()
|
val supersNotHiddenFromObjC = mutableListOf<FirCallableSymbol<*>>()
|
||||||
for ((symbol, scope) in overriddenMemberSymbols) {
|
val supersNotRefinedInSwift = mutableListOf<FirCallableSymbol<*>>()
|
||||||
val (superIsHiddenFromObjC, superIsRefinedInSwift) = symbol.inheritsRefinedAnnotations(context.session, scope)
|
for ((symbol, scope) in overriddenMemberSymbols) {
|
||||||
if (superIsHiddenFromObjC) isHiddenFromObjC = true else supersNotHiddenFromObjC.add(symbol)
|
val (superIsHiddenFromObjC, superIsRefinedInSwift) = symbol.inheritsRefinedAnnotations(context.session, scope)
|
||||||
if (superIsRefinedInSwift) isRefinedInSwift = true else supersNotRefinedInSwift.add(symbol)
|
if (superIsHiddenFromObjC) isHiddenFromObjC = true else supersNotHiddenFromObjC.add(symbol)
|
||||||
|
if (superIsRefinedInSwift) isRefinedInSwift = true else supersNotRefinedInSwift.add(symbol)
|
||||||
|
}
|
||||||
|
if (isHiddenFromObjC && supersNotHiddenFromObjC.isNotEmpty()) {
|
||||||
|
reporter.reportIncompatibleOverride(declarationToReport, objCAnnotations, supersNotHiddenFromObjC, context)
|
||||||
|
}
|
||||||
|
if (isRefinedInSwift && supersNotRefinedInSwift.isNotEmpty()) {
|
||||||
|
reporter.reportIncompatibleOverride(declarationToReport, swiftAnnotations, supersNotRefinedInSwift, context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (isHiddenFromObjC && supersNotHiddenFromObjC.isNotEmpty()) {
|
|
||||||
reporter.reportIncompatibleOverride(declarationToReport, objCAnnotations, supersNotHiddenFromObjC, context)
|
private fun FirCallableSymbol<*>.inheritsRefinedAnnotations(session: FirSession, baseScope: FirTypeScope): Pair<Boolean, Boolean> {
|
||||||
|
val (hasObjC, hasSwift) = hasRefinedAnnotations(session)
|
||||||
|
if (hasObjC && hasSwift) return true to true
|
||||||
|
// Note: `checkMember` requires all overridden symbols to be either refined or not refined.
|
||||||
|
val (overriddenMemberSymbol, scope) = baseScope.getDirectOverriddenMembersWithBaseScope(this).firstOrNull()
|
||||||
|
?: return hasObjC to hasSwift
|
||||||
|
val (inheritsObjC, inheritsSwift) = overriddenMemberSymbol.inheritsRefinedAnnotations(session, scope)
|
||||||
|
return (hasObjC || inheritsObjC) to (hasSwift || inheritsSwift)
|
||||||
}
|
}
|
||||||
if (isRefinedInSwift && supersNotRefinedInSwift.isNotEmpty()) {
|
|
||||||
reporter.reportIncompatibleOverride(declarationToReport, swiftAnnotations, supersNotRefinedInSwift, context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun FirCallableSymbol<*>.inheritsRefinedAnnotations(session: FirSession, baseScope: FirTypeScope): Pair<Boolean, Boolean> {
|
private fun FirCallableSymbol<*>.hasRefinedAnnotations(session: FirSession): Pair<Boolean, Boolean> {
|
||||||
val (hasObjC, hasSwift) = hasRefinedAnnotations(session)
|
var hasObjC = false
|
||||||
if (hasObjC && hasSwift) return true to true
|
var hasSwift = false
|
||||||
// Note: `checkMember` requires all overridden symbols to be either refined or not refined.
|
for (annotation in resolvedAnnotationsWithClassIds) {
|
||||||
val (overriddenMemberSymbol, scope) = baseScope.getDirectOverriddenMembersWithBaseScope(this).firstOrNull()
|
val metaAnnotations = annotation.toAnnotationClassLikeSymbol(session)?.resolvedAnnotationsWithClassIds.orEmpty()
|
||||||
?: return hasObjC to hasSwift
|
for (metaAnnotation in metaAnnotations) {
|
||||||
val (inheritsObjC, inheritsSwift) = overriddenMemberSymbol.inheritsRefinedAnnotations(session, scope)
|
when (metaAnnotation.toAnnotationClassId(session)) {
|
||||||
return (hasObjC || inheritsObjC) to (hasSwift || inheritsSwift)
|
hidesFromObjCClassId -> {
|
||||||
}
|
hasObjC = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
private fun FirCallableSymbol<*>.hasRefinedAnnotations(session: FirSession): Pair<Boolean, Boolean> {
|
refinesInSwiftClassId -> {
|
||||||
var hasObjC = false
|
hasSwift = true
|
||||||
var hasSwift = false
|
break
|
||||||
for (annotation in resolvedAnnotationsWithClassIds) {
|
}
|
||||||
val metaAnnotations = annotation.toAnnotationClassLikeSymbol(session)?.resolvedAnnotationsWithClassIds.orEmpty()
|
|
||||||
for (metaAnnotation in metaAnnotations) {
|
|
||||||
when (metaAnnotation.toAnnotationClassId(session)) {
|
|
||||||
hidesFromObjCClassId -> {
|
|
||||||
hasObjC = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
refinesInSwiftClassId -> {
|
|
||||||
hasSwift = true
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (hasObjC && hasSwift) return true to true
|
||||||
}
|
}
|
||||||
if (hasObjC && hasSwift) return true to true
|
return hasObjC to hasSwift
|
||||||
}
|
}
|
||||||
return hasObjC to hasSwift
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportIncompatibleOverride(
|
private fun DiagnosticReporter.reportIncompatibleOverride(
|
||||||
declaration: FirDeclaration,
|
declaration: FirDeclaration,
|
||||||
annotations: List<FirAnnotation>,
|
annotations: List<FirAnnotation>,
|
||||||
notRefinedSupers: List<FirCallableSymbol<*>>,
|
notRefinedSupers: List<FirCallableSymbol<*>>,
|
||||||
context: CheckerContext
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
val containingDeclarations = notRefinedSupers.mapNotNull { it.containingClassLookupTag()?.toFirRegularClassSymbol(context.session) }
|
val containingDeclarations = notRefinedSupers.mapNotNull { it.containingClassLookupTag()?.toFirRegularClassSymbol(context.session) }
|
||||||
if (annotations.isEmpty()) {
|
if (annotations.isEmpty()) {
|
||||||
reportOn(declaration.source, INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE, declaration.symbol, containingDeclarations, context)
|
reportOn(declaration.source, INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE, declaration.symbol, containingDeclarations, context)
|
||||||
} else {
|
} else {
|
||||||
for (annotation in annotations) {
|
for (annotation in annotations) {
|
||||||
reportOn(annotation.source, INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE, declaration.symbol, containingDeclarations, context)
|
reportOn(annotation.source, INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE, declaration.symbol, containingDeclarations, context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-11
@@ -18,8 +18,10 @@ import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors
|
||||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId
|
import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
|
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
|
||||||
import org.jetbrains.kotlin.fir.references.isError
|
import org.jetbrains.kotlin.fir.references.isError
|
||||||
@@ -34,19 +36,34 @@ import org.jetbrains.kotlin.name.ClassId
|
|||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.annotations.KOTLIN_THROWS_ANNOTATION_FQ_NAME
|
import org.jetbrains.kotlin.resolve.annotations.KOTLIN_THROWS_ANNOTATION_FQ_NAME
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
sealed class FirNativeThrowsChecker(mppKind: MppCheckerKind) : FirBasicDeclarationChecker(mppKind) {
|
||||||
object FirNativeThrowsChecker : FirBasicDeclarationChecker(MppCheckerKind.Platform) {
|
object Regular : FirNativeThrowsChecker(MppCheckerKind.Platform) {
|
||||||
private val throwsClassId = ClassId.topLevel(KOTLIN_THROWS_ANNOTATION_FQ_NAME)
|
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if ((declaration as? FirMemberDeclaration)?.isExpect == true) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val cancellationExceptionFqName = FqName("kotlin.coroutines.cancellation.CancellationException")
|
object ForExpectClass : FirNativeThrowsChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if ((declaration as? FirMemberDeclaration)?.isExpect != true) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val cancellationExceptionAndSupersClassIds = setOf(
|
companion object {
|
||||||
ClassId.topLevel(StandardNames.FqNames.throwable),
|
private val throwsClassId = ClassId.topLevel(KOTLIN_THROWS_ANNOTATION_FQ_NAME)
|
||||||
ClassId.topLevel(FqName("kotlin.Exception")),
|
|
||||||
ClassId.topLevel(FqName("kotlin.RuntimeException")),
|
private val cancellationExceptionFqName = FqName("kotlin.coroutines.cancellation.CancellationException")
|
||||||
ClassId.topLevel(FqName("kotlin.IllegalStateException")),
|
|
||||||
ClassId.topLevel(cancellationExceptionFqName)
|
private val cancellationExceptionAndSupersClassIds = setOf(
|
||||||
)
|
ClassId.topLevel(StandardNames.FqNames.throwable),
|
||||||
|
ClassId.topLevel(FqName("kotlin.Exception")),
|
||||||
|
ClassId.topLevel(FqName("kotlin.RuntimeException")),
|
||||||
|
ClassId.topLevel(FqName("kotlin.IllegalStateException")),
|
||||||
|
ClassId.topLevel(cancellationExceptionFqName)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val throwsAnnotation = declaration.getAnnotationByClassId(throwsClassId, context.session) as? FirAnnotationCall
|
val throwsAnnotation = declaration.getAnnotationByClassId(throwsClassId, context.session) as? FirAnnotationCall
|
||||||
|
|||||||
+8
-4
@@ -10,7 +10,8 @@ import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
|
|||||||
object NativeDeclarationCheckers : DeclarationCheckers() {
|
object NativeDeclarationCheckers : DeclarationCheckers() {
|
||||||
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker>
|
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirNativeThrowsChecker,
|
FirNativeThrowsChecker.Regular,
|
||||||
|
FirNativeThrowsChecker.ForExpectClass,
|
||||||
FirNativeSharedImmutableChecker,
|
FirNativeSharedImmutableChecker,
|
||||||
FirNativeThreadLocalChecker,
|
FirNativeThreadLocalChecker,
|
||||||
FirNativeIdentifierChecker,
|
FirNativeIdentifierChecker,
|
||||||
@@ -20,13 +21,16 @@ object NativeDeclarationCheckers : DeclarationCheckers() {
|
|||||||
override val callableDeclarationCheckers: Set<FirCallableDeclarationChecker>
|
override val callableDeclarationCheckers: Set<FirCallableDeclarationChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirNativeObjCRefinementChecker,
|
FirNativeObjCRefinementChecker,
|
||||||
FirNativeObjCNameCallableChecker,
|
FirNativeObjCNameCallableChecker.Regular,
|
||||||
|
FirNativeObjCNameCallableChecker.ForExpectClass,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val classCheckers: Set<FirClassChecker>
|
override val classCheckers: Set<FirClassChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirNativeObjCRefinementOverridesChecker,
|
FirNativeObjCRefinementOverridesChecker.Regular,
|
||||||
FirNativeObjCNameOverridesChecker,
|
FirNativeObjCRefinementOverridesChecker.ForExpectClass,
|
||||||
|
FirNativeObjCNameOverridesChecker.Regular,
|
||||||
|
FirNativeObjCNameOverridesChecker.ForExpectClass,
|
||||||
FirNativeObjCOutletChecker,
|
FirNativeObjCOutletChecker,
|
||||||
FirNativeObjCActionChecker,
|
FirNativeObjCActionChecker,
|
||||||
FirNativeObjCOverrideInitChecker,
|
FirNativeObjCOverrideInitChecker,
|
||||||
|
|||||||
+5
-2
@@ -5,14 +5,17 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.wasm.checkers
|
package org.jetbrains.kotlin.fir.analysis.wasm.checkers
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.wasm.checkers.declaration.*
|
import org.jetbrains.kotlin.fir.analysis.wasm.checkers.declaration.*
|
||||||
import org.jetbrains.kotlin.fir.analysis.web.common.checkers.declaration.FirJsExportAnnotationChecker
|
import org.jetbrains.kotlin.fir.analysis.web.common.checkers.declaration.FirJsExportAnnotationChecker
|
||||||
|
|
||||||
object WasmBaseDeclarationCheckers : DeclarationCheckers() {
|
object WasmBaseDeclarationCheckers : DeclarationCheckers() {
|
||||||
override val classCheckers: Set<FirClassChecker>
|
override val classCheckers: Set<FirClassChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirWasmExternalInheritanceChecker,
|
FirWasmExternalInheritanceChecker.Regular,
|
||||||
|
FirWasmExternalInheritanceChecker.ForExpectClass,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker>
|
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker>
|
||||||
|
|||||||
+16
-2
@@ -15,11 +15,25 @@ import org.jetbrains.kotlin.fir.analysis.checkers.toClassLikeSymbol
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isEffectivelyExternal
|
import org.jetbrains.kotlin.fir.declarations.utils.isEffectivelyExternal
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
sealed class FirWasmExternalInheritanceChecker(mppKind: MppCheckerKind) : FirClassChecker(mppKind) {
|
||||||
object FirWasmExternalInheritanceChecker : FirClassChecker(MppCheckerKind.Platform) {
|
object Regular : FirWasmExternalInheritanceChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirWasmExternalInheritanceChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val session = context.session
|
val session = context.session
|
||||||
val isCurrentClassExternal = declaration.symbol.isEffectivelyExternal(session)
|
val isCurrentClassExternal = declaration.symbol.isEffectivelyExternal(session)
|
||||||
|
|||||||
@@ -143,3 +143,30 @@ So the author of each new checker should decide in which session this checker sh
|
|||||||
it most likely should be `Common`
|
it most likely should be `Common`
|
||||||
- if the checker is interested in the scope of some type, it should be carefully considered how the actualization of the scope may affect
|
- if the checker is interested in the scope of some type, it should be carefully considered how the actualization of the scope may affect
|
||||||
the checker
|
the checker
|
||||||
|
|
||||||
|
#### Checkers for expect classes
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// MODULE: common
|
||||||
|
expect interface A
|
||||||
|
expect class B : A
|
||||||
|
|
||||||
|
class C : A
|
||||||
|
|
||||||
|
// MODULE: platform()()(common)
|
||||||
|
actual interface A {
|
||||||
|
fun foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
actual class B : A {
|
||||||
|
override fun foo() {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example we want to report "abstract foo not implemented" on class `C`, but we don't want to report it on `expect class B` (as its supertype is always `expect A`, never `actual A`)
|
||||||
|
|
||||||
|
So to cover such cases, it's worth splitting the platform checker into two parts:
|
||||||
|
- `Regular`, which is platform checkers and runs for everything except `expect` declaration
|
||||||
|
- `ForExpectClass`, which is common checkers and runs only for `expect` declarations
|
||||||
|
|
||||||
|
As an example, check the implementation of [FirImplementationMismatchChecker](compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImplementationMismatchChecker.kt) checker
|
||||||
|
|||||||
+18
-10
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.fir.analysis.cfa.FirPropertyInitializationAnalyzer
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirAnonymousFunctionParametersChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirAnonymousFunctionParametersChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirFiniteBoundRestrictionChecker
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirInlinedLambdaNonSourceAnnotationsChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirInlinedLambdaNonSourceAnnotationsChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirMissingDependencySupertypeChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirMissingDependencySupertypeChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirSuspendAnonymousFunctionChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirSuspendAnonymousFunctionChecker
|
||||||
@@ -103,15 +102,19 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
|
|
||||||
override val classCheckers: Set<FirClassChecker>
|
override val classCheckers: Set<FirClassChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirOverrideChecker,
|
FirOverrideChecker.Regular,
|
||||||
FirNotImplementedOverrideChecker,
|
FirOverrideChecker.ForExpectClass,
|
||||||
FirNotImplementedOverrideSimpleEnumEntryChecker,
|
FirNotImplementedOverrideChecker.Regular,
|
||||||
|
FirNotImplementedOverrideChecker.ForExpectClass,
|
||||||
|
FirNotImplementedOverrideSimpleEnumEntryChecker.Regular,
|
||||||
|
FirNotImplementedOverrideSimpleEnumEntryChecker.ForExpectClass,
|
||||||
FirThrowableSubclassChecker,
|
FirThrowableSubclassChecker,
|
||||||
FirOpenMemberChecker,
|
FirOpenMemberChecker,
|
||||||
FirClassVarianceChecker,
|
FirClassVarianceChecker,
|
||||||
FirSealedSupertypeChecker,
|
FirSealedSupertypeChecker,
|
||||||
FirMemberPropertiesChecker,
|
FirMemberPropertiesChecker,
|
||||||
FirImplementationMismatchChecker,
|
FirImplementationMismatchChecker.Regular,
|
||||||
|
FirImplementationMismatchChecker.ForExpectClass,
|
||||||
FirTypeParametersInObjectChecker,
|
FirTypeParametersInObjectChecker,
|
||||||
FirSupertypesChecker,
|
FirSupertypesChecker,
|
||||||
FirPrimaryConstructorSuperTypeChecker,
|
FirPrimaryConstructorSuperTypeChecker,
|
||||||
@@ -119,7 +122,8 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
FirEnumCompanionInEnumConstructorCallChecker,
|
FirEnumCompanionInEnumConstructorCallChecker,
|
||||||
FirBadInheritedJavaSignaturesChecker,
|
FirBadInheritedJavaSignaturesChecker,
|
||||||
FirSealedInterfaceAllowedChecker,
|
FirSealedInterfaceAllowedChecker,
|
||||||
FirMixedFunctionalTypesInSupertypesChecker,
|
FirMixedFunctionalTypesInSupertypesChecker.Regular,
|
||||||
|
FirMixedFunctionalTypesInSupertypesChecker.ForExpectClass,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val regularClassCheckers: Set<FirRegularClassChecker>
|
override val regularClassCheckers: Set<FirRegularClassChecker>
|
||||||
@@ -135,13 +139,16 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
FirManyCompanionObjectsChecker,
|
FirManyCompanionObjectsChecker,
|
||||||
FirMethodOfAnyImplementedInInterfaceChecker,
|
FirMethodOfAnyImplementedInInterfaceChecker,
|
||||||
FirDataClassPrimaryConstructorChecker,
|
FirDataClassPrimaryConstructorChecker,
|
||||||
FirFunInterfaceDeclarationChecker,
|
FirFunInterfaceDeclarationChecker.Regular,
|
||||||
|
FirFunInterfaceDeclarationChecker.ForExpectClass,
|
||||||
FirNestedClassChecker,
|
FirNestedClassChecker,
|
||||||
FirValueClassDeclarationChecker,
|
FirValueClassDeclarationChecker.Regular,
|
||||||
|
FirValueClassDeclarationChecker.ForExpectClass,
|
||||||
FirOuterClassArgumentsRequiredChecker,
|
FirOuterClassArgumentsRequiredChecker,
|
||||||
FirPropertyInitializationChecker,
|
FirPropertyInitializationChecker,
|
||||||
FirDelegateFieldTypeMismatchChecker,
|
FirDelegateFieldTypeMismatchChecker,
|
||||||
FirMultipleDefaultsInheritedFromSupertypesChecker,
|
FirMultipleDefaultsInheritedFromSupertypesChecker.Regular,
|
||||||
|
FirMultipleDefaultsInheritedFromSupertypesChecker.ForExpectClass,
|
||||||
FirFiniteBoundRestrictionChecker,
|
FirFiniteBoundRestrictionChecker,
|
||||||
FirNonExpansiveInheritanceRestrictionChecker,
|
FirNonExpansiveInheritanceRestrictionChecker,
|
||||||
)
|
)
|
||||||
@@ -176,7 +183,8 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
|
|
||||||
override val typeParameterCheckers: Set<FirTypeParameterChecker>
|
override val typeParameterCheckers: Set<FirTypeParameterChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirTypeParameterBoundsChecker,
|
FirTypeParameterBoundsChecker.Regular,
|
||||||
|
FirTypeParameterBoundsChecker.ForExpectClass,
|
||||||
FirTypeParameterVarianceChecker,
|
FirTypeParameterVarianceChecker,
|
||||||
FirReifiedTypeParameterChecker,
|
FirReifiedTypeParameterChecker,
|
||||||
FirTypeParameterSyntaxChecker,
|
FirTypeParameterSyntaxChecker,
|
||||||
|
|||||||
+16
-6
@@ -18,18 +18,28 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_CAN
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_WITH_SUSPEND_FUNCTION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_WITH_SUSPEND_FUNCTION
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isAbstract
|
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isFun
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
|
|
||||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.fir.scopes.getFunctions
|
import org.jetbrains.kotlin.fir.scopes.getFunctions
|
||||||
import org.jetbrains.kotlin.fir.scopes.getProperties
|
import org.jetbrains.kotlin.fir.scopes.getProperties
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
|
||||||
object FirFunInterfaceDeclarationChecker : FirRegularClassChecker(MppCheckerKind.Platform) {
|
sealed class FirFunInterfaceDeclarationChecker(mppKind: MppCheckerKind) : FirRegularClassChecker(mppKind) {
|
||||||
|
object Regular : FirFunInterfaceDeclarationChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirFunInterfaceDeclarationChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (!declaration.isInterface || !declaration.isFun) return
|
if (!declaration.isInterface || !declaration.isFun) return
|
||||||
|
|||||||
+14
-2
@@ -40,8 +40,20 @@ import org.jetbrains.kotlin.types.AbstractTypeChecker
|
|||||||
import org.jetbrains.kotlin.types.TypeCheckerState
|
import org.jetbrains.kotlin.types.TypeCheckerState
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
sealed class FirImplementationMismatchChecker(mppKind: MppCheckerKind) : FirClassChecker(mppKind) {
|
||||||
object FirImplementationMismatchChecker : FirClassChecker(MppCheckerKind.Platform) {
|
object Regular : FirImplementationMismatchChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirImplementationMismatchChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val source = declaration.source ?: return
|
val source = declaration.source ?: return
|
||||||
|
|||||||
+16
-2
@@ -13,11 +13,25 @@ import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
|
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
|
||||||
import org.jetbrains.kotlin.fir.types.functionTypeKind
|
import org.jetbrains.kotlin.fir.types.functionTypeKind
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
sealed class FirMixedFunctionalTypesInSupertypesChecker(mppKind: MppCheckerKind) : FirClassChecker(mppKind) {
|
||||||
object FirMixedFunctionalTypesInSupertypesChecker : FirClassChecker(MppCheckerKind.Platform) {
|
object Regular : FirMixedFunctionalTypesInSupertypesChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirMixedFunctionalTypesInSupertypesChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val superKinds = lookupSuperTypes(declaration.symbol, lookupInterfaces = true, deep = true, context.session)
|
val superKinds = lookupSuperTypes(declaration.symbol, lookupInterfaces = true, deep = true, context.session)
|
||||||
.mapNotNullTo(mutableSetOf()) { it.functionTypeKind(context.session)?.nonReflectKind() }
|
.mapNotNullTo(mutableSetOf()) { it.functionTypeKind(context.session)?.nonReflectKind() }
|
||||||
|
|||||||
+16
-2
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
|||||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
||||||
import org.jetbrains.kotlin.fir.isSubstitutionOverride
|
import org.jetbrains.kotlin.fir.isSubstitutionOverride
|
||||||
import org.jetbrains.kotlin.fir.scopes.processAllFunctions
|
import org.jetbrains.kotlin.fir.scopes.processAllFunctions
|
||||||
@@ -24,8 +25,21 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
|
|||||||
import org.jetbrains.kotlin.fir.unwrapSubstitutionOverrides
|
import org.jetbrains.kotlin.fir.unwrapSubstitutionOverrides
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
sealed class FirMultipleDefaultsInheritedFromSupertypesChecker(mppKind: MppCheckerKind) : FirRegularClassChecker(mppKind) {
|
||||||
object FirMultipleDefaultsInheritedFromSupertypesChecker : FirRegularClassChecker(MppCheckerKind.Platform) {
|
object Regular : FirMultipleDefaultsInheritedFromSupertypesChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirMultipleDefaultsInheritedFromSupertypesChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
declaration.unsubstitutedScope(context).processAllFunctions {
|
declaration.unsubstitutedScope(context).processAllFunctions {
|
||||||
val originalIfSubstitutionOverride = it.unwrapSubstitutionOverrides()
|
val originalIfSubstitutionOverride = it.unwrapSubstitutionOverrides()
|
||||||
|
|||||||
+14
-2
@@ -41,8 +41,20 @@ import org.jetbrains.kotlin.util.ImplementationStatus
|
|||||||
import kotlin.contracts.ExperimentalContracts
|
import kotlin.contracts.ExperimentalContracts
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
sealed class FirNotImplementedOverrideChecker(mppKind: MppCheckerKind) : FirClassChecker(mppKind) {
|
||||||
object FirNotImplementedOverrideChecker : FirClassChecker(MppCheckerKind.Platform) {
|
object Regular : FirNotImplementedOverrideChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirNotImplementedOverrideChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val source = declaration.source ?: return
|
val source = declaration.source ?: return
|
||||||
|
|||||||
+16
-2
@@ -15,11 +15,25 @@ import org.jetbrains.kotlin.fir.declarations.FirClass
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
|
import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isAbstract
|
import org.jetbrains.kotlin.fir.declarations.utils.isAbstract
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
|
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.scopes.processAllCallables
|
import org.jetbrains.kotlin.fir.scopes.processAllCallables
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
sealed class FirNotImplementedOverrideSimpleEnumEntryChecker(mppKind: MppCheckerKind) : FirClassChecker(mppKind) {
|
||||||
object FirNotImplementedOverrideSimpleEnumEntryChecker : FirClassChecker(MppCheckerKind.Common) {
|
object Regular : FirNotImplementedOverrideSimpleEnumEntryChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirNotImplementedOverrideSimpleEnumEntryChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (!declaration.isEnumClass) return
|
if (!declaration.isEnumClass) return
|
||||||
|
|
||||||
|
|||||||
+16
-6
@@ -23,10 +23,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
|||||||
import org.jetbrains.kotlin.fir.analysis.overridesBackwardCompatibilityHelper
|
import org.jetbrains.kotlin.fir.analysis.overridesBackwardCompatibilityHelper
|
||||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
|
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isOverride
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
|
||||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.fir.originalOrSelf
|
import org.jetbrains.kotlin.fir.originalOrSelf
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||||
@@ -107,8 +104,21 @@ abstract class FirAbstractOverrideChecker(mppKind: MppCheckerKind) : FirClassChe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
sealed class FirOverrideChecker(mppKind: MppCheckerKind) : FirAbstractOverrideChecker(mppKind) {
|
||||||
object FirOverrideChecker : FirAbstractOverrideChecker(MppCheckerKind.Platform) {
|
object Regular : FirOverrideChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirOverrideChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val typeCheckerState = context.session.typeContext.newTypeCheckerState(
|
val typeCheckerState = context.session.typeContext.newTypeCheckerState(
|
||||||
errorTypesEqualToAnything = false,
|
errorTypesEqualToAnything = false,
|
||||||
|
|||||||
+23
-4
@@ -13,14 +13,29 @@ import org.jetbrains.kotlin.fir.analysis.checkers.*
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isOverride
|
import org.jetbrains.kotlin.fir.declarations.utils.isOverride
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||||
import org.jetbrains.kotlin.types.model.TypeCheckerProviderContext
|
import org.jetbrains.kotlin.types.model.TypeCheckerProviderContext
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
sealed class FirTypeParameterBoundsChecker(mppKind: MppCheckerKind) : FirTypeParameterChecker(mppKind) {
|
||||||
object FirTypeParameterBoundsChecker : FirTypeParameterChecker(MppCheckerKind.Platform) {
|
object Regular : FirTypeParameterBoundsChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirTypeParameter, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
val containingDeclaration = context.containingDeclarations.lastOrNull() ?: return
|
||||||
|
if ((containingDeclaration as? FirMemberDeclaration)?.isExpect == true) return
|
||||||
|
check(declaration, containingDeclaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ForExpectClass : FirTypeParameterBoundsChecker(MppCheckerKind.Common) {
|
||||||
|
override fun check(declaration: FirTypeParameter, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
val containingDeclaration = context.containingDeclarations.lastOrNull() ?: return
|
||||||
|
if ((containingDeclaration as? FirMemberDeclaration)?.isExpect != true) return
|
||||||
|
check(declaration, containingDeclaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val classKinds = setOf(
|
private val classKinds = setOf(
|
||||||
ClassKind.CLASS,
|
ClassKind.CLASS,
|
||||||
@@ -28,8 +43,12 @@ object FirTypeParameterBoundsChecker : FirTypeParameterChecker(MppCheckerKind.Pl
|
|||||||
ClassKind.OBJECT
|
ClassKind.OBJECT
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun check(declaration: FirTypeParameter, context: CheckerContext, reporter: DiagnosticReporter) {
|
protected fun check(
|
||||||
val containingDeclaration = context.containingDeclarations.lastOrNull() ?: return
|
declaration: FirTypeParameter,
|
||||||
|
containingDeclaration: FirDeclaration,
|
||||||
|
context: CheckerContext,
|
||||||
|
reporter: DiagnosticReporter,
|
||||||
|
) {
|
||||||
if (containingDeclaration is FirConstructor) return
|
if (containingDeclaration is FirConstructor) return
|
||||||
|
|
||||||
checkFinalUpperBounds(declaration, containingDeclaration, context, reporter)
|
checkFinalUpperBounds(declaration, containingDeclaration, context, reporter)
|
||||||
|
|||||||
+20
-6
@@ -33,13 +33,27 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
|
|
||||||
// TODO: extract common checker for expect interfaces
|
sealed class FirValueClassDeclarationChecker(mppKind: MppCheckerKind) : FirRegularClassChecker(mppKind) {
|
||||||
object FirValueClassDeclarationChecker : FirRegularClassChecker(MppCheckerKind.Platform) {
|
object Regular : FirValueClassDeclarationChecker(MppCheckerKind.Platform) {
|
||||||
|
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration.isExpect) return
|
||||||
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val boxAndUnboxNames = setOf("box", "unbox")
|
object ForExpectClass : FirValueClassDeclarationChecker(MppCheckerKind.Common) {
|
||||||
private val equalsAndHashCodeNames = setOf("equals", "hashCode")
|
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
private val javaLangFqName = FqName("java.lang")
|
if (!declaration.isExpect) return
|
||||||
private val cloneableFqName = FqName("Cloneable")
|
super.check(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val boxAndUnboxNames = setOf("box", "unbox")
|
||||||
|
private val equalsAndHashCodeNames = setOf("equals", "hashCode")
|
||||||
|
private val javaLangFqName = FqName("java.lang")
|
||||||
|
private val cloneableFqName = FqName("Cloneable")
|
||||||
|
}
|
||||||
|
|
||||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (!declaration.symbol.isInlineOrValueClass()) {
|
if (!declaration.symbol.isInlineOrValueClass()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user