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.declarations.FirClass
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.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
object FirNativeObjCNameOverridesChecker : FirClassChecker() {
@@ -44,7 +49,7 @@ object FirNativeObjCNameOverridesChecker : FirClassChecker() {
) {
val overriddenSymbols = firTypeScope.retrieveDirectOverriddenOf(memberSymbol)
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()) {
val containingDeclarations = overriddenSymbols.mapNotNull {
it.containingClassLookupTag()?.toFirRegularClassSymbol(context.session)
@@ -59,9 +64,12 @@ object FirNativeObjCNameOverridesChecker : FirClassChecker() {
}
}
private fun FirCallableSymbol<*>.getFirstBaseSymbol(firTypeScope: FirTypeScope): FirCallableSymbol<*> {
val overriddenMemberSymbols = firTypeScope.retrieveDirectOverriddenOf(this)
return if (overriddenMemberSymbols.isEmpty()) this else overriddenMemberSymbols.first().getFirstBaseSymbol(firTypeScope)
private fun FirCallableSymbol<*>.getFirstBaseSymbol(context: CheckerContext): FirCallableSymbol<*> {
val session = context.session
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 {
@@ -281,6 +281,22 @@ fun FirTypeScope.getDirectOverriddenProperties(
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<*>> {
return when (memberSymbol) {
is FirNamedFunctionSymbol -> {
+1 -1
View File
@@ -195,7 +195,7 @@ interface DerivedI1 : I1 {
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 objcName = "nonLiteralArgsObjC"