[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
+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.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||
|
||||
object FirNativeObjCNameCallableChecker : FirCallableDeclarationChecker(MppCheckerKind.Common) {
|
||||
override fun check(declaration: FirCallableDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (declaration !is FirSimpleFunction && declaration !is FirProperty) return
|
||||
val containingClass = context.containingDeclarations.lastOrNull() as? FirClass
|
||||
if (containingClass != null) {
|
||||
val firTypeScope = containingClass.unsubstitutedScope(context)
|
||||
FirNativeObjCNameUtilities.checkCallableMember(firTypeScope, declaration.symbol, declaration, context, reporter)
|
||||
sealed class FirNativeObjCNameCallableChecker(mppKind: MppCheckerKind) : FirCallableDeclarationChecker(mppKind) {
|
||||
object Regular : FirNativeObjCNameCallableChecker(MppCheckerKind.Platform) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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.native.checkers.FirNativeObjCNameUtilities.checkCallableMember
|
||||
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.scopes.processAllFunctions
|
||||
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) {
|
||||
// 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.unsubstitutedScope
|
||||
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.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
@@ -35,7 +34,15 @@ object FirNativeObjCRefinementChecker : FirCallableDeclarationChecker(MppChecker
|
||||
val containingClass = context.containingDeclarations.lastOrNull() as? FirClass
|
||||
if (containingClass != null) {
|
||||
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.toAnnotationClassId
|
||||
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.isIntersectionOverride
|
||||
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.symbols.impl.FirCallableSymbol
|
||||
|
||||
// TODO: extract common checker for expect interfaces
|
||||
object FirNativeObjCRefinementOverridesChecker : FirClassChecker(MppCheckerKind.Platform) {
|
||||
sealed class FirNativeObjCRefinementOverridesChecker(mppKind: MppCheckerKind) : FirClassChecker(mppKind) {
|
||||
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) {
|
||||
// We just need to check intersection overrides, all other declarations are checked by FirNativeObjCRefinementChecker
|
||||
@@ -45,80 +58,83 @@ object FirNativeObjCRefinementOverridesChecker : FirClassChecker(MppCheckerKind.
|
||||
}
|
||||
}
|
||||
|
||||
fun check(
|
||||
baseScope: FirTypeScope,
|
||||
memberSymbol: FirCallableSymbol<*>,
|
||||
declarationToReport: FirDeclaration,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
objCAnnotations: List<FirAnnotation>,
|
||||
swiftAnnotations: List<FirAnnotation>
|
||||
) {
|
||||
val overriddenMemberSymbols = baseScope.getDirectOverriddenMembersWithBaseScope(memberSymbol)
|
||||
if (overriddenMemberSymbols.isEmpty()) return
|
||||
var isHiddenFromObjC = objCAnnotations.isNotEmpty()
|
||||
var isRefinedInSwift = swiftAnnotations.isNotEmpty()
|
||||
val supersNotHiddenFromObjC = mutableListOf<FirCallableSymbol<*>>()
|
||||
val supersNotRefinedInSwift = mutableListOf<FirCallableSymbol<*>>()
|
||||
for ((symbol, scope) in overriddenMemberSymbols) {
|
||||
val (superIsHiddenFromObjC, superIsRefinedInSwift) = symbol.inheritsRefinedAnnotations(context.session, scope)
|
||||
if (superIsHiddenFromObjC) isHiddenFromObjC = true else supersNotHiddenFromObjC.add(symbol)
|
||||
if (superIsRefinedInSwift) isRefinedInSwift = true else supersNotRefinedInSwift.add(symbol)
|
||||
companion object {
|
||||
fun check(
|
||||
baseScope: FirTypeScope,
|
||||
memberSymbol: FirCallableSymbol<*>,
|
||||
declarationToReport: FirDeclaration,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
objCAnnotations: List<FirAnnotation>,
|
||||
swiftAnnotations: List<FirAnnotation>
|
||||
) {
|
||||
val overriddenMemberSymbols = baseScope.getDirectOverriddenMembersWithBaseScope(memberSymbol)
|
||||
if (overriddenMemberSymbols.isEmpty()) return
|
||||
var isHiddenFromObjC = objCAnnotations.isNotEmpty()
|
||||
var isRefinedInSwift = swiftAnnotations.isNotEmpty()
|
||||
val supersNotHiddenFromObjC = mutableListOf<FirCallableSymbol<*>>()
|
||||
val supersNotRefinedInSwift = mutableListOf<FirCallableSymbol<*>>()
|
||||
for ((symbol, scope) in overriddenMemberSymbols) {
|
||||
val (superIsHiddenFromObjC, superIsRefinedInSwift) = symbol.inheritsRefinedAnnotations(context.session, scope)
|
||||
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> {
|
||||
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)
|
||||
}
|
||||
private fun FirCallableSymbol<*>.hasRefinedAnnotations(session: FirSession): Pair<Boolean, Boolean> {
|
||||
var hasObjC = false
|
||||
var hasSwift = false
|
||||
for (annotation in resolvedAnnotationsWithClassIds) {
|
||||
val metaAnnotations = annotation.toAnnotationClassLikeSymbol(session)?.resolvedAnnotationsWithClassIds.orEmpty()
|
||||
for (metaAnnotation in metaAnnotations) {
|
||||
when (metaAnnotation.toAnnotationClassId(session)) {
|
||||
hidesFromObjCClassId -> {
|
||||
hasObjC = true
|
||||
break
|
||||
}
|
||||
|
||||
private fun FirCallableSymbol<*>.hasRefinedAnnotations(session: FirSession): Pair<Boolean, Boolean> {
|
||||
var hasObjC = false
|
||||
var hasSwift = false
|
||||
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
|
||||
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(
|
||||
declaration: FirDeclaration,
|
||||
annotations: List<FirAnnotation>,
|
||||
notRefinedSupers: List<FirCallableSymbol<*>>,
|
||||
context: CheckerContext
|
||||
) {
|
||||
val containingDeclarations = notRefinedSupers.mapNotNull { it.containingClassLookupTag()?.toFirRegularClassSymbol(context.session) }
|
||||
if (annotations.isEmpty()) {
|
||||
reportOn(declaration.source, INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE, declaration.symbol, containingDeclarations, context)
|
||||
} else {
|
||||
for (annotation in annotations) {
|
||||
reportOn(annotation.source, INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE, declaration.symbol, containingDeclarations, context)
|
||||
private fun DiagnosticReporter.reportIncompatibleOverride(
|
||||
declaration: FirDeclaration,
|
||||
annotations: List<FirAnnotation>,
|
||||
notRefinedSupers: List<FirCallableSymbol<*>>,
|
||||
context: CheckerContext
|
||||
) {
|
||||
val containingDeclarations = notRefinedSupers.mapNotNull { it.containingClassLookupTag()?.toFirRegularClassSymbol(context.session) }
|
||||
if (annotations.isEmpty()) {
|
||||
reportOn(declaration.source, INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE, declaration.symbol, containingDeclarations, context)
|
||||
} else {
|
||||
for (annotation in annotations) {
|
||||
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.containingClassLookupTag
|
||||
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.getAnnotationByClassId
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
|
||||
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.resolve.annotations.KOTLIN_THROWS_ANNOTATION_FQ_NAME
|
||||
|
||||
// TODO: extract common checker for expect interfaces
|
||||
object FirNativeThrowsChecker : FirBasicDeclarationChecker(MppCheckerKind.Platform) {
|
||||
private val throwsClassId = ClassId.topLevel(KOTLIN_THROWS_ANNOTATION_FQ_NAME)
|
||||
sealed class FirNativeThrowsChecker(mppKind: MppCheckerKind) : FirBasicDeclarationChecker(mppKind) {
|
||||
object Regular : FirNativeThrowsChecker(MppCheckerKind.Platform) {
|
||||
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(
|
||||
ClassId.topLevel(StandardNames.FqNames.throwable),
|
||||
ClassId.topLevel(FqName("kotlin.Exception")),
|
||||
ClassId.topLevel(FqName("kotlin.RuntimeException")),
|
||||
ClassId.topLevel(FqName("kotlin.IllegalStateException")),
|
||||
ClassId.topLevel(cancellationExceptionFqName)
|
||||
)
|
||||
companion object {
|
||||
private val throwsClassId = ClassId.topLevel(KOTLIN_THROWS_ANNOTATION_FQ_NAME)
|
||||
|
||||
private val cancellationExceptionFqName = FqName("kotlin.coroutines.cancellation.CancellationException")
|
||||
|
||||
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) {
|
||||
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() {
|
||||
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker>
|
||||
get() = setOf(
|
||||
FirNativeThrowsChecker,
|
||||
FirNativeThrowsChecker.Regular,
|
||||
FirNativeThrowsChecker.ForExpectClass,
|
||||
FirNativeSharedImmutableChecker,
|
||||
FirNativeThreadLocalChecker,
|
||||
FirNativeIdentifierChecker,
|
||||
@@ -20,13 +21,16 @@ object NativeDeclarationCheckers : DeclarationCheckers() {
|
||||
override val callableDeclarationCheckers: Set<FirCallableDeclarationChecker>
|
||||
get() = setOf(
|
||||
FirNativeObjCRefinementChecker,
|
||||
FirNativeObjCNameCallableChecker,
|
||||
FirNativeObjCNameCallableChecker.Regular,
|
||||
FirNativeObjCNameCallableChecker.ForExpectClass,
|
||||
)
|
||||
|
||||
override val classCheckers: Set<FirClassChecker>
|
||||
get() = setOf(
|
||||
FirNativeObjCRefinementOverridesChecker,
|
||||
FirNativeObjCNameOverridesChecker,
|
||||
FirNativeObjCRefinementOverridesChecker.Regular,
|
||||
FirNativeObjCRefinementOverridesChecker.ForExpectClass,
|
||||
FirNativeObjCNameOverridesChecker.Regular,
|
||||
FirNativeObjCNameOverridesChecker.ForExpectClass,
|
||||
FirNativeObjCOutletChecker,
|
||||
FirNativeObjCActionChecker,
|
||||
FirNativeObjCOverrideInitChecker,
|
||||
|
||||
Reference in New Issue
Block a user