FIR LC: fix inheritance checking for light classes
Before it was not able to check inheritance with type parameters substitutions like class A<T> class B: A<Int>
This commit is contained in:
committed by
TeamCityServer
parent
767af0dae0
commit
e4992176c1
+9
@@ -13,6 +13,9 @@ public abstract class KtSymbolDeclarationOverridesProvider : KtAnalysisSessionCo
|
|||||||
public abstract fun <T : KtSymbol> getAllOverriddenSymbols(callableSymbol: T): List<KtCallableSymbol>
|
public abstract fun <T : KtSymbol> getAllOverriddenSymbols(callableSymbol: T): List<KtCallableSymbol>
|
||||||
public abstract fun <T : KtSymbol> getDirectlyOverriddenSymbols(callableSymbol: T): List<KtCallableSymbol>
|
public abstract fun <T : KtSymbol> getDirectlyOverriddenSymbols(callableSymbol: T): List<KtCallableSymbol>
|
||||||
|
|
||||||
|
public abstract fun isSubClassOf(subClass: KtClassOrObjectSymbol, superClass: KtClassOrObjectSymbol): Boolean
|
||||||
|
public abstract fun isDirectSubClassOf(subClass: KtClassOrObjectSymbol, superClass: KtClassOrObjectSymbol): Boolean
|
||||||
|
|
||||||
public abstract fun getIntersectionOverriddenSymbols(symbol: KtCallableSymbol): Collection<KtCallableSymbol>
|
public abstract fun getIntersectionOverriddenSymbols(symbol: KtCallableSymbol): Collection<KtCallableSymbol>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,6 +44,12 @@ public interface KtSymbolDeclarationOverridesProviderMixIn : KtAnalysisSessionMi
|
|||||||
public fun KtCallableSymbol.getDirectlyOverriddenSymbols(): List<KtCallableSymbol> =
|
public fun KtCallableSymbol.getDirectlyOverriddenSymbols(): List<KtCallableSymbol> =
|
||||||
analysisSession.symbolDeclarationOverridesProvider.getDirectlyOverriddenSymbols(this)
|
analysisSession.symbolDeclarationOverridesProvider.getDirectlyOverriddenSymbols(this)
|
||||||
|
|
||||||
|
public fun KtClassOrObjectSymbol.isSubClassOf(superClass: KtClassOrObjectSymbol): Boolean =
|
||||||
|
analysisSession.symbolDeclarationOverridesProvider.isSubClassOf(this, superClass)
|
||||||
|
|
||||||
|
public fun KtClassOrObjectSymbol.isDirectSubClassOf(superClass: KtClassOrObjectSymbol): Boolean =
|
||||||
|
analysisSession.symbolDeclarationOverridesProvider.isDirectSubClassOf(this, superClass)
|
||||||
|
|
||||||
public fun KtCallableSymbol.getIntersectionOverriddenSymbols(): Collection<KtCallableSymbol> =
|
public fun KtCallableSymbol.getIntersectionOverriddenSymbols(): Collection<KtCallableSymbol> =
|
||||||
analysisSession.symbolDeclarationOverridesProvider.getIntersectionOverriddenSymbols(this)
|
analysisSession.symbolDeclarationOverridesProvider.getIntersectionOverriddenSymbols(this)
|
||||||
}
|
}
|
||||||
+5
-7
@@ -332,17 +332,15 @@ internal fun KtSymbolWithMembers.createInnerClasses(manager: PsiManager): List<F
|
|||||||
|
|
||||||
internal fun KtClassOrObject.checkIsInheritor(baseClassOrigin: KtClassOrObject, checkDeep: Boolean): Boolean {
|
internal fun KtClassOrObject.checkIsInheritor(baseClassOrigin: KtClassOrObject, checkDeep: Boolean): Boolean {
|
||||||
return analyseForLightClasses(this) {
|
return analyseForLightClasses(this) {
|
||||||
val thisSymbol = this@checkIsInheritor.getNamedClassOrObjectSymbol() ?: return false
|
val subClassSymbol = this@checkIsInheritor.getNamedClassOrObjectSymbol() ?: return false
|
||||||
val baseSymbol = baseClassOrigin.getNamedClassOrObjectSymbol() ?: return false
|
val superClassSymbol = baseClassOrigin.getNamedClassOrObjectSymbol() ?: return false
|
||||||
|
|
||||||
if (thisSymbol == baseSymbol) return@analyseForLightClasses false
|
if (subClassSymbol == superClassSymbol) return@analyseForLightClasses false
|
||||||
|
|
||||||
val baseType = baseSymbol.buildSelfClassType()
|
|
||||||
|
|
||||||
if (checkDeep) {
|
if (checkDeep) {
|
||||||
thisSymbol.buildSelfClassType().isSubTypeOf(baseType)
|
subClassSymbol.isSubClassOf(superClassSymbol)
|
||||||
} else {
|
} else {
|
||||||
thisSymbol.superTypes.any { baseType.isEqualTo(it.type) }
|
subClassSymbol.isDirectSubClassOf(superClassSymbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-1
@@ -5,18 +5,23 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.frontend.api.fir.components
|
package org.jetbrains.kotlin.idea.frontend.api.fir.components
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
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
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.ensureResolved
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverrideFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverrideFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverridePropertySymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverridePropertySymbol
|
||||||
|
import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.ResolveType
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtSymbolDeclarationOverridesProvider
|
import org.jetbrains.kotlin.idea.frontend.api.components.KtSymbolDeclarationOverridesProvider
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirNamedClassOrObjectSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirNamedClassOrObjectSymbol
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbol
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
|
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
|
||||||
@@ -129,12 +134,46 @@ internal class KtFirSymbolDeclarationOverridesProvider(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun isSubClassOf(subClass: KtClassOrObjectSymbol, superClass: KtClassOrObjectSymbol): Boolean {
|
||||||
|
return isSubClassOf(subClass, superClass, checkDeep = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isDirectSubClassOf(subClass: KtClassOrObjectSymbol, superClass: KtClassOrObjectSymbol): Boolean {
|
||||||
|
return isSubClassOf(subClass, superClass, checkDeep = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isSubClassOf(subClass: KtClassOrObjectSymbol, superClass: KtClassOrObjectSymbol, checkDeep: Boolean): Boolean {
|
||||||
|
require(subClass is KtFirSymbol<*>)
|
||||||
|
require(superClass is KtFirSymbol<*>)
|
||||||
|
|
||||||
|
if (subClass == superClass) return false
|
||||||
|
return subClass.firRef.withFirByType(ResolveType.ClassSuperTypes) { subClassFir ->
|
||||||
|
check(subClassFir is FirRegularClass)
|
||||||
|
superClass.firRef.withFir { superClassFir ->
|
||||||
|
check(superClassFir is FirRegularClass)
|
||||||
|
isSubClassOf(subClassFir, superClassFir, checkDeep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isSubClassOf(subClass: FirRegularClass, superClass: FirRegularClass, checkDeep: Boolean): Boolean {
|
||||||
|
if (subClass.superConeTypes.any { it.toRegularClassSymbol(rootModuleSession) == superClass.symbol }) return true
|
||||||
|
if (!checkDeep) return false
|
||||||
|
subClass.superConeTypes.forEach { superType ->
|
||||||
|
val superOfSub = superType.toRegularClassSymbol(rootModuleSession) ?: return@forEach
|
||||||
|
superOfSub.ensureResolved(FirResolvePhase.SUPER_TYPES)
|
||||||
|
if (isSubClassOf(superOfSub.fir, superClass, checkDeep = true)) return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
override fun getIntersectionOverriddenSymbols(symbol: KtCallableSymbol): Collection<KtCallableSymbol> {
|
override fun getIntersectionOverriddenSymbols(symbol: KtCallableSymbol): Collection<KtCallableSymbol> {
|
||||||
require(symbol is KtFirSymbol<*>)
|
require(symbol is KtFirSymbol<*>)
|
||||||
if (symbol.origin != KtSymbolOrigin.INTERSECTION_OVERRIDE) return emptyList()
|
if (symbol.origin != KtSymbolOrigin.INTERSECTION_OVERRIDE) return emptyList()
|
||||||
return symbol.firRef.withFir { fir ->
|
return symbol.firRef.withFir { fir ->
|
||||||
val firSymbol = fir.symbol
|
val firSymbol = fir.symbol
|
||||||
firSymbol.getIntersectionOverriddenSymbols().map { analysisSession.firSymbolBuilder.callableBuilder.buildCallableSymbol(it.fir) }
|
firSymbol.getIntersectionOverriddenSymbols()
|
||||||
|
.map { analysisSession.firSymbolBuilder.callableBuilder.buildCallableSymbol(it.fir) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user