FIR IDE: always try to find symbol origin in overridden symbols
This commit is contained in:
+22
-15
@@ -9,9 +9,11 @@ import com.google.common.collect.MapMaker
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
|
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.firProvider
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||||
@@ -32,10 +34,12 @@ import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirFlexibleType
|
|||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirIntersectionType
|
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirIntersectionType
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirTypeArgumentWithVariance
|
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirTypeArgumentWithVariance
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirTypeParameterType
|
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirTypeParameterType
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.threadLocal
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
|
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||||
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil
|
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import java.util.concurrent.ConcurrentMap
|
import java.util.concurrent.ConcurrentMap
|
||||||
|
|
||||||
@@ -43,8 +47,6 @@ import java.util.concurrent.ConcurrentMap
|
|||||||
* Maps FirElement to KtSymbol & ConeType to KtType, thread safe
|
* Maps FirElement to KtSymbol & ConeType to KtType, thread safe
|
||||||
*/
|
*/
|
||||||
internal class KtSymbolByFirBuilder private constructor(
|
internal class KtSymbolByFirBuilder private constructor(
|
||||||
firProvider: FirSymbolProvider,
|
|
||||||
typeCheckerContext: ConeTypeCheckerContext,
|
|
||||||
private val project: Project,
|
private val project: Project,
|
||||||
resolveState: FirModuleResolveState,
|
resolveState: FirModuleResolveState,
|
||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
@@ -52,16 +54,21 @@ internal class KtSymbolByFirBuilder private constructor(
|
|||||||
private val symbolsCache: BuilderCache<FirDeclaration, KtSymbol>,
|
private val symbolsCache: BuilderCache<FirDeclaration, KtSymbol>,
|
||||||
private val typesCache: BuilderCache<ConeKotlinType, KtType>
|
private val typesCache: BuilderCache<ConeKotlinType, KtType>
|
||||||
) : ValidityTokenOwner {
|
) : ValidityTokenOwner {
|
||||||
|
private val typeCheckerContext by threadLocal {
|
||||||
|
ConeTypeCheckerContext(
|
||||||
|
isErrorTypeEqualsToAnything = true,
|
||||||
|
isStubTypeEqualsToAnything = true,
|
||||||
|
resolveState.firIdeLibrariesSession
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val firProvider get() = resolveState.firIdeSourcesSession.firSymbolProvider
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
firProvider: FirSymbolProvider,
|
|
||||||
typeCheckerContext: ConeTypeCheckerContext,
|
|
||||||
resolveState: FirModuleResolveState,
|
resolveState: FirModuleResolveState,
|
||||||
project: Project,
|
project: Project,
|
||||||
token: ValidityToken
|
token: ValidityToken
|
||||||
) : this(
|
) : this(
|
||||||
firProvider = firProvider,
|
|
||||||
typeCheckerContext = typeCheckerContext,
|
|
||||||
project = project,
|
project = project,
|
||||||
token = token,
|
token = token,
|
||||||
resolveState = resolveState,
|
resolveState = resolveState,
|
||||||
@@ -70,15 +77,11 @@ internal class KtSymbolByFirBuilder private constructor(
|
|||||||
typesCache = BuilderCache()
|
typesCache = BuilderCache()
|
||||||
)
|
)
|
||||||
|
|
||||||
private val firProvider by weakRef(firProvider)
|
|
||||||
private val resolveState by weakRef(resolveState)
|
private val resolveState by weakRef(resolveState)
|
||||||
private val typeCheckerContext by weakRef(typeCheckerContext)
|
|
||||||
|
|
||||||
fun createReadOnlyCopy(newResolveState: FirModuleResolveState): KtSymbolByFirBuilder {
|
fun createReadOnlyCopy(newResolveState: FirModuleResolveState): KtSymbolByFirBuilder {
|
||||||
check(!withReadOnlyCaching) { "Cannot create readOnly KtSymbolByFirBuilder from a readonly one" }
|
check(!withReadOnlyCaching) { "Cannot create readOnly KtSymbolByFirBuilder from a readonly one" }
|
||||||
return KtSymbolByFirBuilder(
|
return KtSymbolByFirBuilder(
|
||||||
firProvider,
|
|
||||||
typeCheckerContext,
|
|
||||||
project,
|
project,
|
||||||
token = token,
|
token = token,
|
||||||
resolveState = newResolveState,
|
resolveState = newResolveState,
|
||||||
@@ -126,8 +129,8 @@ internal class KtSymbolByFirBuilder private constructor(
|
|||||||
fun buildFirConstructorParameter(fir: FirValueParameterImpl) =
|
fun buildFirConstructorParameter(fir: FirValueParameterImpl) =
|
||||||
symbolsCache.cache(fir) { KtFirConstructorValueParameterSymbol(fir, resolveState, token, this) }
|
symbolsCache.cache(fir) { KtFirConstructorValueParameterSymbol(fir, resolveState, token, this) }
|
||||||
|
|
||||||
fun buildFunctionSymbol(fir: FirSimpleFunction, forcedOrigin: FirDeclarationOrigin? = null) = symbolsCache.cache(fir) {
|
fun buildFunctionSymbol(fir: FirSimpleFunction) = symbolsCache.cache(fir) {
|
||||||
KtFirFunctionSymbol(fir, resolveState, token, this, forcedOrigin)
|
KtFirFunctionSymbol(fir, resolveState, token, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildConstructorSymbol(fir: FirConstructor) = symbolsCache.cache(fir) { KtFirConstructorSymbol(fir, resolveState, token, this) }
|
fun buildConstructorSymbol(fir: FirConstructor) = symbolsCache.cache(fir) { KtFirConstructorSymbol(fir, resolveState, token, this) }
|
||||||
@@ -139,10 +142,10 @@ internal class KtSymbolByFirBuilder private constructor(
|
|||||||
fun buildAnonymousFunctionSymbol(fir: FirAnonymousFunction) =
|
fun buildAnonymousFunctionSymbol(fir: FirAnonymousFunction) =
|
||||||
symbolsCache.cache(fir) { KtFirAnonymousFunctionSymbol(fir, resolveState, token, this) }
|
symbolsCache.cache(fir) { KtFirAnonymousFunctionSymbol(fir, resolveState, token, this) }
|
||||||
|
|
||||||
fun buildVariableSymbol(fir: FirProperty, forcedOrigin: FirDeclarationOrigin? = null): KtVariableSymbol = symbolsCache.cache(fir) {
|
fun buildVariableSymbol(fir: FirProperty): KtVariableSymbol = symbolsCache.cache(fir) {
|
||||||
when {
|
when {
|
||||||
fir.isLocal -> KtFirLocalVariableSymbol(fir, resolveState, token, this)
|
fir.isLocal -> KtFirLocalVariableSymbol(fir, resolveState, token, this)
|
||||||
else -> KtFirPropertySymbol(fir, resolveState, token, this, forcedOrigin)
|
else -> KtFirPropertySymbol(fir, resolveState, token, this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +157,10 @@ internal class KtSymbolByFirBuilder private constructor(
|
|||||||
(firProvider.getSymbolByLookupTag(lookupTag) as? FirTypeParameterSymbol)?.fir?.let(::buildTypeParameterSymbol)
|
(firProvider.getSymbolByLookupTag(lookupTag) as? FirTypeParameterSymbol)?.fir?.let(::buildTypeParameterSymbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun buildClassLikeSymbolByClassId(classId: ClassId, firSession: FirSession): FirRegularClass? = withValidityAssertion {
|
||||||
|
firSession.firProvider.getClassLikeSymbolByFqName(classId)?.fir as? FirRegularClass
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun createPackageSymbolIfOneExists(packageFqName: FqName): KtFirPackageSymbol? {
|
fun createPackageSymbolIfOneExists(packageFqName: FqName): KtFirPackageSymbol? {
|
||||||
val exists = PackageIndexUtil.packageExists(packageFqName, GlobalSearchScope.allScope(project), project)
|
val exists = PackageIndexUtil.packageExists(packageFqName, GlobalSearchScope.allScope(project), project)
|
||||||
|
|||||||
+2
-12
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
|
|||||||
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScope
|
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScope
|
||||||
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.KtClassLikeSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
|
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
@@ -60,27 +59,18 @@ internal abstract class KtFirDelegatingScope<S>(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirBasedSymbol<*>.realDeclarationOrigin(): FirDeclarationOrigin? {
|
|
||||||
if (this !is PossiblyFirFakeOverrideSymbol<*, *> || !isFakeOverride) return null
|
|
||||||
var current: FirBasedSymbol<*>? = this.overriddenSymbol
|
|
||||||
while (current is PossiblyFirFakeOverrideSymbol<*, *> && current.isFakeOverride) {
|
|
||||||
current = current.overriddenSymbol
|
|
||||||
}
|
|
||||||
return (current?.fir as? FirDeclaration)?.origin
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun FirScope.getCallableSymbols(callableNames: Collection<Name>, builder: KtSymbolByFirBuilder) = sequence {
|
internal fun FirScope.getCallableSymbols(callableNames: Collection<Name>, builder: KtSymbolByFirBuilder) = sequence {
|
||||||
callableNames.forEach { name ->
|
callableNames.forEach { name ->
|
||||||
val callables = mutableListOf<KtCallableSymbol>()
|
val callables = mutableListOf<KtCallableSymbol>()
|
||||||
processFunctionsByName(name) { firSymbol ->
|
processFunctionsByName(name) { firSymbol ->
|
||||||
(firSymbol.fir as? FirSimpleFunction)?.let { fir ->
|
(firSymbol.fir as? FirSimpleFunction)?.let { fir ->
|
||||||
callables.add(builder.buildFunctionSymbol(fir, firSymbol.realDeclarationOrigin()))
|
callables.add(builder.buildFunctionSymbol(fir))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
processPropertiesByName(name) { firSymbol ->
|
processPropertiesByName(name) { firSymbol ->
|
||||||
val symbol = when {
|
val symbol = when {
|
||||||
firSymbol is FirPropertySymbol && firSymbol.isFakeOverride -> {
|
firSymbol is FirPropertySymbol && firSymbol.isFakeOverride -> {
|
||||||
builder.buildVariableSymbol(firSymbol.fir, firSymbol.realDeclarationOrigin())
|
builder.buildVariableSymbol(firSymbol.fir)
|
||||||
}
|
}
|
||||||
else -> builder.buildCallableSymbol(firSymbol.fir)
|
else -> builder.buildCallableSymbol(firSymbol.fir)
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-10
@@ -7,30 +7,29 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
|
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.FirRef
|
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.FirRef
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.overriddenDeclaration
|
||||||
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.withValidityAssertion
|
|
||||||
|
|
||||||
internal interface KtFirSymbol<F : FirDeclaration> : KtSymbol, ValidityTokenOwner {
|
internal interface KtFirSymbol<F : FirDeclaration> : KtSymbol, ValidityTokenOwner {
|
||||||
val firRef: FirRef<F>
|
val firRef: FirRef<F>
|
||||||
|
|
||||||
override val origin: KtSymbolOrigin get() = firRef.withFir { it.origin.asKtSymbolOrigin() }
|
override val origin: KtSymbolOrigin get() = firRef.withFir { it.ktSymbolOrigin() }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun FirDeclarationOrigin.asKtSymbolOrigin() = when (this) {
|
|
||||||
|
private tailrec fun FirDeclaration.ktSymbolOrigin(): KtSymbolOrigin = when (origin) {
|
||||||
FirDeclarationOrigin.Source -> KtSymbolOrigin.SOURCE
|
FirDeclarationOrigin.Source -> KtSymbolOrigin.SOURCE
|
||||||
FirDeclarationOrigin.Library -> KtSymbolOrigin.LIBRARY
|
FirDeclarationOrigin.Library -> KtSymbolOrigin.LIBRARY
|
||||||
FirDeclarationOrigin.Java -> KtSymbolOrigin.JAVA
|
FirDeclarationOrigin.Java -> KtSymbolOrigin.JAVA
|
||||||
FirDeclarationOrigin.SamConstructor -> KtSymbolOrigin.SAM_CONSTRUCTOR
|
FirDeclarationOrigin.SamConstructor -> KtSymbolOrigin.SAM_CONSTRUCTOR
|
||||||
FirDeclarationOrigin.Synthetic -> throw InvalidFirDeclarationOriginForSymbol(this)
|
FirDeclarationOrigin.Enhancement -> KtSymbolOrigin.JAVA
|
||||||
FirDeclarationOrigin.FakeOverride -> throw InvalidFirDeclarationOriginForSymbol(this)
|
else -> {
|
||||||
FirDeclarationOrigin.ImportedFromObject -> throw InvalidFirDeclarationOriginForSymbol(this)
|
val overridden = overriddenDeclaration ?: throw InvalidFirDeclarationOriginForSymbol(origin)
|
||||||
FirDeclarationOrigin.IntersectionOverride -> throw InvalidFirDeclarationOriginForSymbol(this)
|
overridden.ktSymbolOrigin()
|
||||||
FirDeclarationOrigin.Enhancement -> KtSymbolOrigin.JAVA // TODO
|
}
|
||||||
is FirDeclarationOrigin.Plugin -> throw InvalidFirDeclarationOriginForSymbol(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class InvalidFirDeclarationOriginForSymbol(origin: FirDeclarationOrigin) :
|
class InvalidFirDeclarationOriginForSymbol(origin: FirDeclarationOrigin) :
|
||||||
|
|||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
package org.jetbrains.kotlin.idea.frontend.api.fir.utils
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSymbolOwner
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
|
|
||||||
|
internal inline val FirDeclaration.overriddenDeclaration: FirDeclaration?
|
||||||
|
get() {
|
||||||
|
val symbol = (this as? FirSymbolOwner<*>)?.symbol ?: return null
|
||||||
|
return (symbol as? FirCallableSymbol)?.overriddenSymbol?.fir as? FirDeclaration
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user