FIR IDE: correctly set symbol origin for fake overridden ones

This commit is contained in:
Ilya Kirillov
2020-07-04 00:40:09 +03:00
parent 88548d988a
commit 1d92fbaa7f
9 changed files with 72 additions and 18 deletions
@@ -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.fir.symbols
import org.jetbrains.kotlin.fir.FirSymbolOwner
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
interface PossiblyFirFakeOverrideSymbol<E, S : FirBasedSymbol<E>> : FirBasedSymbol<E> where E : FirSymbolOwner<E>, E : FirDeclaration {
// contract isFakeOverride == true <=> overriddenSymbol != null
val isFakeOverride: Boolean
val overriddenSymbol: S?
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.
*/
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.symbols.impl
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.symbols.AccessorSymbol
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.PossiblyFirFakeOverrideSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -23,10 +24,10 @@ sealed class FirFunctionSymbol<D : FirFunction<D>>(
open class FirNamedFunctionSymbol(
callableId: CallableId,
val isFakeOverride: Boolean = false,
override val isFakeOverride: Boolean = false,
// Actual for fake override only
override val overriddenSymbol: FirNamedFunctionSymbol? = null
) : FirFunctionSymbol<FirSimpleFunction>(callableId)
) : FirFunctionSymbol<FirSimpleFunction>(callableId), PossiblyFirFakeOverrideSymbol<FirSimpleFunction, FirNamedFunctionSymbol>
class FirConstructorSymbol(
callableId: CallableId,
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.
*/
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.PossiblyFirFakeOverrideSymbol
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -22,10 +23,10 @@ open class FirVariableSymbol<D : FirVariable<D>>(override val callableId: Callab
open class FirPropertySymbol(
callableId: CallableId,
val isFakeOverride: Boolean = false,
override val isFakeOverride: Boolean = false,
// Actual for fake override only
override val overriddenSymbol: FirPropertySymbol? = null
) : FirVariableSymbol<FirProperty>(callableId) {
) : FirVariableSymbol<FirProperty>(callableId), PossiblyFirFakeOverrideSymbol<FirProperty, FirPropertySymbol> {
// TODO: should we use this constructor for local variables?
constructor(name: Name) : this(CallableId(name))
}
@@ -46,9 +46,15 @@ constructor(
internal val firSession get() = LowLevelFirApiFacade.getSessionFor(element, firResolveState)
private val typeCheckerContext = ConeTypeCheckerContext(
isErrorTypeEqualsToAnything = true,
isStubTypeEqualsToAnything = true,
firSession
)
internal val firSymbolBuilder = KtSymbolByFirBuilder(
firSession.firSymbolProvider,
ConeTypeCheckerContext(isErrorTypeEqualsToAnything = true, isStubTypeEqualsToAnything = true, firSession),
typeCheckerContext,
element.project,
validityToken
)
@@ -11,7 +11,6 @@ import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
@@ -38,6 +37,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableSymbol
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil
import org.jetbrains.kotlin.name.FqName
/**
@@ -87,7 +87,10 @@ internal class KtSymbolByFirBuilder(
fun buildFirConstructorParameter(fir: FirValueParameterImpl) =
symbolsCache.cache(fir) { KtFirConstructorValueParameterSymbol(fir, token, this) }
fun buildFunctionSymbol(fir: FirSimpleFunction) = symbolsCache.cache(fir) { KtFirFunctionSymbol(fir, token, this) }
fun buildFunctionSymbol(fir: FirSimpleFunction, forcedOrigin: FirDeclarationOrigin? = null) = symbolsCache.cache(fir) {
KtFirFunctionSymbol(fir, token, this, forcedOrigin)
}
fun buildConstructorSymbol(fir: FirConstructor) = symbolsCache.cache(fir) { KtFirConstructorSymbol(fir, token, this) }
fun buildTypeParameterSymbol(fir: FirTypeParameter) = symbolsCache.cache(fir) { KtFirTypeParameterSymbol(fir, token) }
@@ -96,10 +99,10 @@ internal class KtSymbolByFirBuilder(
fun buildFieldSymbol(fir: FirField) = symbolsCache.cache(fir) { KtFirJavaFieldSymbol(fir, token, this) }
fun buildAnonymousFunctionSymbol(fir: FirAnonymousFunction) = symbolsCache.cache(fir) { KtFirAnonymousFunctionSymbol(fir, token, this) }
fun buildVariableSymbol(fir: FirProperty): KtVariableSymbol = symbolsCache.cache(fir) {
fun buildVariableSymbol(fir: FirProperty, forcedOrigin: FirDeclarationOrigin? = null): KtVariableSymbol = symbolsCache.cache(fir) {
when {
fir.isLocal -> KtFirLocalVariableSymbol(fir, token, this)
else -> KtFirPropertySymbol(fir, token, this)
else -> KtFirPropertySymbol(fir, token, this, forcedOrigin)
}
}
@@ -6,17 +6,20 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.scopes
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.processClassifiersByName
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.PossiblyFirFakeOverrideSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScope
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.name.Name
import org.jetbrains.kotlin.psi.KtClass
internal abstract class KtFirDelegatingScope(private val builder: KtSymbolByFirBuilder) : KtScope {
abstract val firScope: FirScope
@@ -51,11 +54,17 @@ internal abstract class KtFirDelegatingScope(private val builder: KtSymbolByFirB
val callables = mutableListOf<KtSymbol>()
firScope.processFunctionsByName(name) { firSymbol ->
(firSymbol.fir as? FirSimpleFunction)?.let { fir ->
callables.add(builder.buildFunctionSymbol(fir))
callables.add(builder.buildFunctionSymbol(fir, firSymbol.realDeclarationOrigin()))
}
}
firScope.processPropertiesByName(name) { firSymbol ->
callables.add(builder.buildSymbol(firSymbol.fir))
val symbol = when {
firSymbol is FirPropertySymbol && firSymbol.isFakeOverride -> {
builder.buildVariableSymbol(firSymbol.fir, firSymbol.realDeclarationOrigin())
}
else -> builder.buildSymbol(firSymbol.fir)
}
callables.add(symbol)
}
yieldAll(callables)
}
@@ -79,4 +88,15 @@ internal abstract class KtFirDelegatingScope(private val builder: KtSymbolByFirB
override fun containsName(name: Name): Boolean = withValidityAssertion {
name in getAllNames()
}
companion object {
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
}
}
}
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCommonSymbolModality
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -25,6 +26,7 @@ internal class KtFirFunctionSymbol(
fir: FirSimpleFunction,
override val token: ValidityOwner,
private val builder: KtSymbolByFirBuilder,
private val forcedOrigin: FirDeclarationOrigin? = null
) : KtFunctionSymbol(), KtFirSymbol<FirSimpleFunction> {
override val fir: FirSimpleFunction by weakRef(fir)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) }
@@ -41,6 +43,7 @@ internal class KtFirFunctionSymbol(
builder.buildTypeParameterSymbol(typeParameter.symbol.fir)
}
}
override val origin: KtSymbolOrigin get() = withValidityAssertion { forcedOrigin?.asKtSymbolOrigin() ?: super.origin }
override val isSuspend: Boolean get() = withValidityAssertion { fir.isSuspend }
override val receiverType: KtType? by cached { fir.receiverTypeRef?.let(builder::buildKtType) }
override val isOperator: Boolean get() = withValidityAssertion { fir.isOperator }
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.modality
import org.jetbrains.kotlin.idea.fir.findPsi
@@ -17,6 +18,7 @@ import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCommonSymbolModality
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -24,7 +26,8 @@ import org.jetbrains.kotlin.name.Name
internal class KtFirPropertySymbol(
fir: FirProperty,
override val token: ValidityOwner,
private val builder: KtSymbolByFirBuilder
private val builder: KtSymbolByFirBuilder,
private val forcedOrigin: FirDeclarationOrigin?
) : KtPropertySymbol(), KtFirSymbol<FirProperty> {
init {
assert(!fir.isLocal)
@@ -33,6 +36,8 @@ internal class KtFirPropertySymbol(
override val fir: FirProperty by weakRef(fir)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) }
override val origin: KtSymbolOrigin get() = withValidityAssertion { forcedOrigin?.asKtSymbolOrigin() ?: super.origin }
override val fqName: FqName get() = withValidityAssertion { fir.symbol.callableId.asFqNameForDebugInfo() }
override val isVal: Boolean get() = withValidityAssertion { fir.isVal }
override val name: Name get() = withValidityAssertion { fir.name }
@@ -17,7 +17,7 @@ internal interface KtFirSymbol<F : FirDeclaration> : KtSymbol, ValidityOwnerByVa
override val origin: KtSymbolOrigin get() = withValidityAssertion { fir.origin.asKtSymbolOrigin() }
}
private fun FirDeclarationOrigin.asKtSymbolOrigin() = when (this) {
internal fun FirDeclarationOrigin.asKtSymbolOrigin() = when (this) {
FirDeclarationOrigin.Source -> KtSymbolOrigin.SOURCE
FirDeclarationOrigin.Library -> KtSymbolOrigin.LIBRARY
FirDeclarationOrigin.Java -> KtSymbolOrigin.JAVA
@@ -26,7 +26,7 @@ private fun FirDeclarationOrigin.asKtSymbolOrigin() = when (this) {
FirDeclarationOrigin.FakeOverride -> throw InvalidFirDeclarationOriginForSymbol(this)
FirDeclarationOrigin.ImportedFromObject -> throw InvalidFirDeclarationOriginForSymbol(this)
FirDeclarationOrigin.IntersectionOverride -> throw InvalidFirDeclarationOriginForSymbol(this)
FirDeclarationOrigin.Enhancement -> throw InvalidFirDeclarationOriginForSymbol(this)
FirDeclarationOrigin.Enhancement -> KtSymbolOrigin.JAVA // TODO
is FirDeclarationOrigin.Plugin -> throw InvalidFirDeclarationOriginForSymbol(this)
}