diff --git a/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/FirNativeObjCOverrideInitChecker.kt b/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/FirNativeObjCOverrideInitChecker.kt index d7dad9a7963..2da4b02eaf4 100644 --- a/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/FirNativeObjCOverrideInitChecker.kt +++ b/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/FirNativeObjCOverrideInitChecker.kt @@ -18,28 +18,35 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.isExpect import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.getSuperClassSymbolOrAny -import org.jetbrains.kotlin.fir.symbols.SymbolInternals +import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope +import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol -import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.name.NativeStandardInteropNames.objCOverrideInitClassId object FirNativeObjCOverrideInitChecker : FirClassChecker() { - @OptIn(SymbolInternals::class) override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) { val session = context.session - fun FirConstructor.overridesConstructor(other: FirConstructor): Boolean { - if (valueParameters.size != other.valueParameters.size) + fun FirClassSymbol<*>.constructors(session: FirSession): List { + val result = mutableListOf() + session.declaredMemberScope(this, memberRequiredPhase = null).processDeclaredConstructors { result += it } + return result + } + + fun FirConstructorSymbol.overridesConstructor(other: FirConstructorSymbol): Boolean { + val aParams = this.valueParameterSymbols + val bParams = other.valueParameterSymbols + if (aParams.size != bParams.size) return false - return valueParameters.zip(other.valueParameters).all { (thisParameter, otherParameter) -> - thisParameter.name == otherParameter.name && thisParameter.returnTypeRef.coneType == otherParameter.returnTypeRef.coneType + return aParams.zip(bParams).all { (thisParameter, otherParameter) -> + thisParameter.name == otherParameter.name && thisParameter.resolvedReturnType == otherParameter.resolvedReturnType } } fun checkCanGenerateOverrideInit(firClass: FirClass, constructor: FirConstructor) { val superClass = (firClass as FirRegularClass).symbol.getSuperClassSymbolOrAny(session) - val superConstructors = superClass.fir.constructors(session).filter { - constructor.overridesConstructor(it.fir) + val superConstructors = superClass.constructors(session).filter { + constructor.symbol.overridesConstructor(it) }.toList() val superConstructor: FirConstructorSymbol = superConstructors.singleOrNull() ?: run { @@ -60,11 +67,11 @@ object FirNativeObjCOverrideInitChecker : FirClassChecker() { return } - val initMethod = superConstructor.fir.getObjCInitMethod(session, ScopeSession())!! + val initMethod = superConstructor.getObjCInitMethod(session, ScopeSession())!! // Remove fake overrides of this init method, also check for explicit overriding: firClass.declarations.forEach { - if (it is FirSimpleFunction && initMethod.symbol in it.getOverriddenSymbols(context) && !it.isSubstitutionOrIntersectionOverride) { + if (it is FirSimpleFunction && initMethod in it.getOverriddenSymbols(context) && !it.isSubstitutionOrIntersectionOverride) { reporter.reportOn( constructor.source, FirNativeErrors.CONSTRUCTOR_OVERRIDES_ALREADY_OVERRIDDEN_OBJC_INITIALIZER, diff --git a/compiler/fir/native/src/org/jetbrains/kotlin/fir/backend/native/interop/FirObjCInterop.kt b/compiler/fir/native/src/org/jetbrains/kotlin/fir/backend/native/interop/FirObjCInterop.kt index bff1ead2e12..4547d4bb08a 100644 --- a/compiler/fir/native/src/org/jetbrains/kotlin/fir/backend/native/interop/FirObjCInterop.kt +++ b/compiler/fir/native/src/org/jetbrains/kotlin/fir/backend/native/interop/FirObjCInterop.kt @@ -13,12 +13,15 @@ import org.jetbrains.kotlin.fir.expressions.FirConstExpression import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions +import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope import org.jetbrains.kotlin.fir.scopes.processAllFunctions import org.jetbrains.kotlin.fir.scopes.scopeForClass import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.name.Name @@ -69,18 +72,40 @@ fun FirConstructor.getObjCInitMethod(session: FirSession, scopeSession: ScopeSes return null } +fun FirConstructorSymbol.getObjCInitMethod(session: FirSession, scopeSession: ScopeSession): FirFunctionSymbol<*>? { + this.annotations.getAnnotationByClassId(NativeStandardInteropNames.objCConstructorClassId, session)?.let { annotation -> + val initSelector: String = annotation.constStringArgument("initSelector") + val classSymbol = containingClassLookupTag()?.toSymbol(session) as FirClassSymbol<*> + val initSelectors = mutableListOf>() + session.declaredMemberScope(classSymbol, memberRequiredPhase = null) + .processAllFunctions { + if (it.decodeObjCMethodAnnotation(session)?.selector == initSelector) + initSelectors.add(it) + } + return initSelectors.singleOrNull() + ?: error("expected one init method for $classSymbol $initSelector, got ${initSelectors.size}") + } + return null +} + /** * mimics FunctionDescriptor.decodeObjCMethodAnnotation() */ +internal fun List.decodeObjCMethodAnnotation(session: FirSession): ObjCMethodInfo? = + getAnnotationByClassId(NativeStandardInteropNames.objCMethodClassId, session)?.let { + ObjCMethodInfo( + selector = it.constStringArgument("selector"), + encoding = it.constStringArgument("encoding"), + isStret = it.constBooleanArgumentOrNull("isStret") ?: false, + directSymbol = getAnnotationByClassId(NativeStandardInteropNames.objCDirectClassId, session)?.constStringArgument("symbol"), + ) + } + internal fun FirFunction.decodeObjCMethodAnnotation(session: FirSession): ObjCMethodInfo? = - annotations.getAnnotationByClassId(NativeStandardInteropNames.objCMethodClassId, session)?.let { - ObjCMethodInfo( - selector = it.constStringArgument("selector"), - encoding = it.constStringArgument("encoding"), - isStret = it.constBooleanArgumentOrNull("isStret") ?: false, - directSymbol = annotations.getAnnotationByClassId(NativeStandardInteropNames.objCDirectClassId, session)?.constStringArgument("symbol"), - ) - } + annotations.decodeObjCMethodAnnotation(session) + +internal fun FirFunctionSymbol<*>.decodeObjCMethodAnnotation(session: FirSession): ObjCMethodInfo? = + annotations.decodeObjCMethodAnnotation(session) private fun FirAnnotation.constStringArgument(argumentName: String): String =