K2: use correct scope for overrides calculation in ObjCName checker

To call retrieveDirectOverriddenOf,
one must use directly the owner scope of a callable symbol we consider,
and not a scope of some derived class.

#KT-64276 Fixed
This commit is contained in:
Mikhail Glukhikh
2024-01-05 10:29:37 +01:00
committed by Space Team
parent e4c244d5db
commit 3d560cd92c
3 changed files with 30 additions and 6 deletions
@@ -15,9 +15,14 @@ import org.jetbrains.kotlin.fir.analysis.native.checkers.FirNativeObjCNameChecke
import org.jetbrains.kotlin.fir.containingClassLookupTag import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.FirClass 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.fullyExpandedClass
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
import org.jetbrains.kotlin.fir.scopes.* import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.processAllFunctions
import org.jetbrains.kotlin.fir.scopes.processAllProperties
import org.jetbrains.kotlin.fir.scopes.retrieveDirectOverriddenOf
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
object FirNativeObjCNameOverridesChecker : FirClassChecker() { object FirNativeObjCNameOverridesChecker : FirClassChecker() {
@@ -44,7 +49,7 @@ object FirNativeObjCNameOverridesChecker : FirClassChecker() {
) { ) {
val overriddenSymbols = firTypeScope.retrieveDirectOverriddenOf(memberSymbol) val overriddenSymbols = firTypeScope.retrieveDirectOverriddenOf(memberSymbol)
if (overriddenSymbols.isEmpty()) return if (overriddenSymbols.isEmpty()) return
val objCNames = overriddenSymbols.map { it.getFirstBaseSymbol(firTypeScope).getObjCNames(context.session) } val objCNames = overriddenSymbols.map { it.getFirstBaseSymbol(context).getObjCNames(context.session) }
if (!objCNames.allNamesEquals()) { if (!objCNames.allNamesEquals()) {
val containingDeclarations = overriddenSymbols.mapNotNull { val containingDeclarations = overriddenSymbols.mapNotNull {
it.containingClassLookupTag()?.toFirRegularClassSymbol(context.session) it.containingClassLookupTag()?.toFirRegularClassSymbol(context.session)
@@ -59,9 +64,12 @@ object FirNativeObjCNameOverridesChecker : FirClassChecker() {
} }
} }
private fun FirCallableSymbol<*>.getFirstBaseSymbol(firTypeScope: FirTypeScope): FirCallableSymbol<*> { private fun FirCallableSymbol<*>.getFirstBaseSymbol(context: CheckerContext): FirCallableSymbol<*> {
val overriddenMemberSymbols = firTypeScope.retrieveDirectOverriddenOf(this) val session = context.session
return if (overriddenMemberSymbols.isEmpty()) this else overriddenMemberSymbols.first().getFirstBaseSymbol(firTypeScope) val ownScope = containingClassLookupTag()?.toSymbol(session)?.fullyExpandedClass(session)?.unsubstitutedScope(context)
?: return this
val overriddenMemberSymbols = ownScope.retrieveDirectOverriddenOf(this)
return if (overriddenMemberSymbols.isEmpty()) this else overriddenMemberSymbols.first().getFirstBaseSymbol(context)
} }
private fun List<List<FirNativeObjCNameChecker.ObjCName?>>.allNamesEquals(): Boolean { private fun List<List<FirNativeObjCNameChecker.ObjCName?>>.allNamesEquals(): Boolean {
@@ -281,6 +281,22 @@ fun FirTypeScope.getDirectOverriddenProperties(
return overriddenProperties.toList() return overriddenProperties.toList()
} }
/**
* Provides a list of callables which are directly overridden by the given symbol
*
* Please be very accurate with using this function.
* It can be convenient if the only thing you need is to get directly overridden symbols and nothing more,
* but even in this case please check that you are using a correct scope.
* E.g. if you want to get overridden symbols of some Foo.bar,
* the scope in use must be built from the Foo-based type or Foo class itself.
*
* If you need to traverse some complex overridden hierarchy,
* please consider using processDirectOverriddenFunctions(Properties)WithBaseScope instead.
*
* @param memberSymbol A callable symbol to find its directly overridden symbols
* @receiver Must be an owner scope of the callable symbol to work properly
* @return A list of callable symbols which are directly overridden by the given symbol
*/
fun FirTypeScope.retrieveDirectOverriddenOf(memberSymbol: FirCallableSymbol<*>): List<FirCallableSymbol<*>> { fun FirTypeScope.retrieveDirectOverriddenOf(memberSymbol: FirCallableSymbol<*>): List<FirCallableSymbol<*>> {
return when (memberSymbol) { return when (memberSymbol) {
is FirNamedFunctionSymbol -> { is FirNamedFunctionSymbol -> {
+1 -1
View File
@@ -195,7 +195,7 @@ interface DerivedI1 : I1 {
override fun foo() override fun foo()
} }
<!INCOMPATIBLE_OBJC_NAME_OVERRIDE!>abstract class KT64276 : Base(), DerivedI1 {}<!> abstract class KT64276 : Base(), DerivedI1 {}
private const val exact = false private const val exact = false
private const val objcName = "nonLiteralArgsObjC" private const val objcName = "nonLiteralArgsObjC"