FIR IDE: resolve reference to intersection override member to overridden members

This commit is contained in:
Ilya Kirillov
2021-01-08 12:34:38 +01:00
parent 95eb701f75
commit 2a9779cd89
11 changed files with 82 additions and 22 deletions
@@ -58,6 +58,9 @@ abstract class KtAnalysisSession(final override val token: ValidityToken) : Vali
fun KtCallableSymbol.getOverriddenSymbols(containingDeclaration: KtClassOrObjectSymbol): List<KtCallableSymbol> =
symbolDeclarationOverridesProvider.getOverriddenSymbols(this, containingDeclaration)
fun KtCallableSymbol.getIntersectionOverriddenSymbols(): Collection<KtCallableSymbol> =
symbolDeclarationOverridesProvider.getIntersectionOverriddenSymbols(this)
fun KtExpression.getSmartCasts(): Collection<KtType> = smartCastProvider.getSmartCastedToTypes(this)
fun KtExpression.getImplicitReceiverSmartCasts(): Collection<ImplicitReceiverSmartCast> =
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.idea.frontend.api.components
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.KtFunctionSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
abstract class KtSymbolDeclarationOverridesProvider : KtAnalysisSessionComponent() {
@@ -19,5 +18,9 @@ abstract class KtSymbolDeclarationOverridesProvider : KtAnalysisSessionComponent
containingDeclaration: KtClassOrObjectSymbol
): List<KtCallableSymbol>
//abstract fun getOverriddenSymbols(callableSymbol: KtCallableSymbol, containingDeclaration: KtClassOrObjectSymbol): List<KtCallableSymbol>
/**
* If [symbol] origin is [org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin.INTERSECTION_OVERRIDE]
* Then returns the symbols which [symbol] overrides, otherwise empty collection
*/
abstract fun getIntersectionOverriddenSymbols(symbol: KtCallableSymbol): Collection<KtCallableSymbol>
}
@@ -42,5 +42,17 @@ enum class KtSymbolOrigin {
*/
JAVA,
SAM_CONSTRUCTOR
SAM_CONSTRUCTOR,
/**
* Consider the following code:
* ```
* interface A { fun x() }
* interface B { fun x() }
*
* interface C : A, B
* ```
* The intersection of functions A.foo & B.foo will create a function C.foo which will be marked with [INTERSECTION_OVERRIDE]
*/
INTERSECTION_OVERRIDE,
}
@@ -26,6 +26,7 @@ internal class KtFirSymbolContainingDeclarationProvider(
KtSymbolOrigin.SOURCE, KtSymbolOrigin.SOURCE_MEMBER_GENERATED ->
getContainingDeclarationForKotlinInSourceSymbol(symbol)
KtSymbolOrigin.LIBRARY, KtSymbolOrigin.JAVA -> getContainingDeclarationForLibrarySymbol(symbol)
KtSymbolOrigin.INTERSECTION_OVERRIDE -> TODO()
KtSymbolOrigin.SAM_CONSTRUCTOR -> TODO()
}
}
@@ -5,9 +5,15 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.components
import org.jetbrains.kotlin.fir.FirSymbolOwner
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverrideFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverridePropertySymbol
import org.jetbrains.kotlin.fir.unwrapFakeOverrides
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.components.KtSymbolDeclarationOverridesProvider
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
@@ -63,4 +69,24 @@ internal class KtFirSymbolDeclarationOverridesProvider(
}
}
}
override fun getIntersectionOverriddenSymbols(symbol: KtCallableSymbol): Collection<KtCallableSymbol> {
require(symbol is KtFirSymbol<*>)
if (symbol.origin != KtSymbolOrigin.INTERSECTION_OVERRIDE) return emptyList()
return symbol.firRef.withFir { fir ->
val firSymbol = (fir as? FirSymbolOwner<*>)?.symbol ?: return@withFir emptyList()
firSymbol.getIntersectionOverriddenSymbols().map { analysisSession.firSymbolBuilder.buildCallableSymbol(it.fir) }
}
}
private fun AbstractFirBasedSymbol<*>.getIntersectionOverriddenSymbols(): Collection<FirCallableSymbol<*>> {
require(this is FirCallableSymbol<*>) {
"Required FirCallableSymbol but ${this::class} found"
}
return when (this) {
is FirIntersectionOverrideFunctionSymbol -> intersections
is FirIntersectionOverridePropertySymbol -> intersections
else -> listOf(this)
}
}
}
@@ -35,6 +35,7 @@ private tailrec fun FirDeclaration.ktSymbolOrigin(): KtSymbolOrigin = when (orig
FirDeclarationOrigin.Java -> KtSymbolOrigin.JAVA
FirDeclarationOrigin.SamConstructor -> KtSymbolOrigin.SAM_CONSTRUCTOR
FirDeclarationOrigin.Enhancement -> KtSymbolOrigin.JAVA
FirDeclarationOrigin.IntersectionOverride -> KtSymbolOrigin.INTERSECTION_OVERRIDE
else -> {
val overridden = (this as? FirCallableDeclaration<*>)?.originalIfFakeOverride()
?: throw InvalidFirDeclarationOriginForSymbol(this)
@@ -10,14 +10,32 @@ import org.jetbrains.kotlin.idea.fir.findReferencePsi
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.KtSymbolBasedReference
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.KtSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin
interface KtFirReference : KtReference, KtSymbolBasedReference {
fun getResolvedToPsi(analysisSession: KtAnalysisSession): Collection<PsiElement> =
analysisSession.resolveToSymbols().mapNotNull { symbol ->
(symbol as? KtFirSymbol<*>)?.firRef?.withFir { it.findReferencePsi() }
?: symbol.psi
fun getResolvedToPsi(analysisSession: KtAnalysisSession): Collection<PsiElement> = with(analysisSession) {
resolveToSymbols().flatMap { symbol ->
when (symbol) {
is KtFirSymbol<*> -> getPsiDeclarations(symbol)
else -> listOfNotNull(symbol.psi)
}
}
}
private fun KtAnalysisSession.getPsiDeclarations(symbol: KtFirSymbol<*>): Collection<PsiElement> {
val intersectionOverriddenSymbolsOrSingle = when {
symbol.origin == KtSymbolOrigin.INTERSECTION_OVERRIDE && symbol is KtCallableSymbol -> symbol.getIntersectionOverriddenSymbols()
else -> listOf(symbol)
}
return intersectionOverriddenSymbolsOrSingle.mapNotNull { it.findPsiForReferenceResolve() }
}
private fun KtSymbol.findPsiForReferenceResolve(): PsiElement? {
require(this is KtFirSymbol<*>)
return firRef.withFir { it.findReferencePsi() }
}
override val resolver get() = KtFirReferenceResolver
}
@@ -1233,7 +1233,7 @@ KtFirFunctionSymbol:
isSuspend: false
modality: OPEN
name: equals
origin: LIBRARY
origin: INTERSECTION_OVERRIDE
receiverType: null
symbolKind: MEMBER
typeParameters: []
@@ -1254,7 +1254,7 @@ KtFirFunctionSymbol:
isSuspend: false
modality: OPEN
name: hashCode
origin: LIBRARY
origin: INTERSECTION_OVERRIDE
receiverType: null
symbolKind: MEMBER
typeParameters: []
@@ -1275,7 +1275,7 @@ KtFirFunctionSymbol:
isSuspend: false
modality: OPEN
name: toString
origin: LIBRARY
origin: INTERSECTION_OVERRIDE
receiverType: null
symbolKind: MEMBER
typeParameters: []
@@ -288,7 +288,7 @@ KtFirFunctionSymbol:
isSuspend: false
modality: ABSTRACT
name: contains
origin: LIBRARY
origin: INTERSECTION_OVERRIDE
receiverType: null
symbolKind: MEMBER
typeParameters: []
@@ -309,7 +309,7 @@ KtFirFunctionSymbol:
isSuspend: false
modality: ABSTRACT
name: containsAll
origin: LIBRARY
origin: INTERSECTION_OVERRIDE
receiverType: null
symbolKind: MEMBER
typeParameters: []
@@ -372,7 +372,7 @@ KtFirFunctionSymbol:
isSuspend: false
modality: ABSTRACT
name: isEmpty
origin: LIBRARY
origin: INTERSECTION_OVERRIDE
receiverType: null
symbolKind: MEMBER
typeParameters: []
@@ -393,7 +393,7 @@ KtFirFunctionSymbol:
isSuspend: false
modality: ABSTRACT
name: iterator
origin: LIBRARY
origin: INTERSECTION_OVERRIDE
receiverType: null
symbolKind: MEMBER
typeParameters: []
@@ -439,7 +439,7 @@ KtFirKotlinPropertySymbol:
isVal: true
modality: ABSTRACT
name: size
origin: LIBRARY
origin: INTERSECTION_OVERRIDE
receiverType: null
setter: null
symbolKind: MEMBER
@@ -459,7 +459,7 @@ KtFirFunctionSymbol:
isSuspend: false
modality: OPEN
name: equals
origin: LIBRARY
origin: INTERSECTION_OVERRIDE
receiverType: null
symbolKind: MEMBER
typeParameters: []
@@ -480,7 +480,7 @@ KtFirFunctionSymbol:
isSuspend: false
modality: OPEN
name: hashCode
origin: LIBRARY
origin: INTERSECTION_OVERRIDE
receiverType: null
symbolKind: MEMBER
typeParameters: []
@@ -501,7 +501,7 @@ KtFirFunctionSymbol:
isSuspend: false
modality: OPEN
name: toString
origin: LIBRARY
origin: INTERSECTION_OVERRIDE
receiverType: null
symbolKind: MEMBER
typeParameters: []
-2
View File
@@ -1,5 +1,3 @@
// IGNORE_FIR
interface A {
fun foo()
}
@@ -1,5 +1,3 @@
// IGNORE_FIR
var x : Int <caret>by Baz()
interface Foo {