FIR IDE: split KtPropertySymbol into KtKotlinPropertySymbol and KtJavaSyntheticPropertySymbol

This commit is contained in:
Ilya Kirillov
2020-12-10 19:40:08 +01:00
parent 2201dd5198
commit 48b7150566
15 changed files with 173 additions and 35 deletions
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
sealed class KtVariableLikeSymbol : KtCallableSymbol(), KtTypedSymbol, KtNamedSymbol, KtSymbolWithKind {
abstract override fun createPointer(): KtSymbolPointer<KtVariableLikeSymbol>
@@ -39,24 +40,23 @@ abstract class KtJavaFieldSymbol :
abstract override fun createPointer(): KtSymbolPointer<KtJavaFieldSymbol>
}
abstract class KtPropertySymbol : KtVariableSymbol(),
sealed class KtPropertySymbol : KtVariableSymbol(),
KtPossibleExtensionSymbol,
KtSymbolWithModality<KtCommonSymbolModality>,
KtSymbolWithVisibility,
KtAnnotatedSymbol,
KtSymbolWithKind {
abstract val callableIdIfNonLocal: FqName?
abstract val hasGetter: Boolean
abstract val hasSetter: Boolean
abstract val getter: KtPropertyGetterSymbol?
abstract val setter: KtPropertySetterSymbol?
abstract val callableIdIfNonLocal: FqName?
abstract val hasBackingField: Boolean
abstract val isLateInit: Boolean
abstract val isConst: Boolean
abstract val isOverride: Boolean
abstract val initializer: KtConstantValue?
@@ -64,6 +64,23 @@ abstract class KtPropertySymbol : KtVariableSymbol(),
abstract override fun createPointer(): KtSymbolPointer<KtPropertySymbol>
}
abstract class KtKotlinPropertySymbol : KtPropertySymbol() {
abstract val isLateInit: Boolean
abstract val isConst: Boolean
}
abstract class KtSyntheticJavaPropertySymbol : KtPropertySymbol() {
final override val hasBackingField: Boolean get() = true
final override val hasGetter: Boolean get() = true
final override val symbolKind: KtSymbolKind get() = KtSymbolKind.MEMBER
abstract override val getter: KtPropertyGetterSymbol
abstract val javaGetterName: Name
abstract val javaSetterName: Name?
}
abstract class KtLocalVariableSymbol : KtVariableSymbol(), KtSymbolWithKind {
abstract override fun createPointer(): KtSymbolPointer<KtLocalVariableSymbol>
}
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.idea.asJava.classes.createField
import org.jetbrains.kotlin.idea.asJava.classes.createMethods
import org.jetbrains.kotlin.idea.frontend.api.analyze
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtKotlinPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
@@ -116,7 +117,8 @@ class FirLightClassForFacade(
}
for (propertySymbol in propertySymbols) {
val forceStaticAndPropertyVisibility = propertySymbol.isConst || propertySymbol.hasJvmFieldAnnotation()
val forceStaticAndPropertyVisibility = propertySymbol is KtKotlinPropertySymbol && propertySymbol.isConst
|| propertySymbol.hasJvmFieldAnnotation()
createField(
propertySymbol,
nameGenerator,
@@ -96,7 +96,7 @@ internal open class FirLightClassForSymbol(
}
}.applyIf(classOrObjectSymbol.classKind == KtClassKind.OBJECT) {
filterNot {
it is KtPropertySymbol && it.isConst
it is KtKotlinPropertySymbol && it.isConst
}
}
@@ -124,7 +124,7 @@ internal open class FirLightClassForSymbol(
analyzeWithSymbolAsContext(this) {
getDeclaredMemberScope().getCallableSymbols()
.filterIsInstance<KtPropertySymbol>()
.filter { it.hasJvmFieldAnnotation() || it.hasJvmStaticAnnotation() || it.isConst }
.filter { it.hasJvmFieldAnnotation() || it.hasJvmStaticAnnotation() || it is KtKotlinPropertySymbol && it.isConst }
.mapTo(result) {
FirLightFieldForPropertySymbol(
propertySymbol = it,
@@ -159,7 +159,7 @@ internal open class FirLightClassForSymbol(
val propertySymbols = classOrObjectSymbol.getDeclaredMemberScope().getCallableSymbols()
.filterIsInstance<KtPropertySymbol>()
.applyIf(classOrObjectSymbol.classKind == KtClassKind.COMPANION_OBJECT) {
filterNot { it.hasJvmFieldAnnotation() || it.isConst }
filterNot { it.hasJvmFieldAnnotation() || it is KtKotlinPropertySymbol && it.isConst }
}
val nameGenerator = FirLightField.FieldNameGenerator()
@@ -169,7 +169,7 @@ internal open class FirLightClassForSymbol(
for (propertySymbol in propertySymbols) {
val isJvmField = propertySymbol.hasJvmFieldAnnotation()
val isJvmStatic = propertySymbol.hasJvmStaticAnnotation()
val forceStatic = isObject && (propertySymbol.isConst || isJvmStatic || isJvmField)
val forceStatic = isObject && (propertySymbol is KtKotlinPropertySymbol && propertySymbol.isConst || isJvmStatic || isJvmField)
val takePropertyVisibility = !isCompanionObject && (isJvmField || (isObject && isJvmStatic))
createField(
@@ -210,13 +210,16 @@ internal fun FirLightClassBase.createField(
takePropertyVisibility: Boolean,
result: MutableList<KtLightField>
) {
fun hasBackingField(property: KtPropertySymbol): Boolean {
if (property.modality == KtCommonSymbolModality.ABSTRACT) return false
if (property.isLateInit) return true
//IS PARAMETER -> true
if (property.getter == null && property.setter == null) return true
if (property.hasJvmSyntheticAnnotation(AnnotationUseSiteTarget.FIELD)) return false
return property.hasBackingField
fun hasBackingField(property: KtPropertySymbol): Boolean = when (property) {
is KtSyntheticJavaPropertySymbol -> true
is KtKotlinPropertySymbol -> when {
property.modality == KtCommonSymbolModality.ABSTRACT -> false
property.isLateInit -> true
//IS PARAMETER -> true
!property.hasGetter && !property.hasSetter -> true
property.hasJvmSyntheticAnnotation(AnnotationUseSiteTarget.FIELD) -> false
else -> property.hasBackingField
}
}
if (!hasBackingField(declaration)) return
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtKotlinPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSimpleConstantValue
import org.jetbrains.kotlin.psi.KtDeclaration
@@ -97,6 +98,7 @@ internal class FirLightFieldForPropertySymbol(
override fun getModifierList(): PsiModifierList = _modifierList
private val _initializer by lazyPub {
if (propertySymbol !is KtKotlinPropertySymbol) return@lazyPub null
if (!propertySymbol.isConst) return@lazyPub null
if (!propertySymbol.isVal) return@lazyPub null
(propertySymbol.initializer as? KtSimpleConstantValue<*>)?.createPsiLiteral(this)
@@ -10,7 +10,7 @@ import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
import org.jetbrains.kotlin.fir.resolve.getSymbolByLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
import org.jetbrains.kotlin.idea.frontend.api.*
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.fir.types.*
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.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
@@ -143,7 +142,8 @@ internal class KtSymbolByFirBuilder private constructor(
fun buildVariableSymbol(fir: FirProperty): KtVariableSymbol = symbolsCache.cache(fir) {
when {
fir.isLocal -> KtFirLocalVariableSymbol(fir, resolveState, token, this)
else -> KtFirPropertySymbol(fir, resolveState, token, this)
fir is FirSyntheticProperty -> KtFirSyntheticJavaPropertySymbol(fir, resolveState, token, this)
else -> KtFirKotlinPropertySymbol(fir, resolveState, token, this)
}
}
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.components
import com.jetbrains.rd.util.getOrCreate
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue
@@ -19,7 +18,7 @@ import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.components.KtCompletionCandidateChecker
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirFunctionSymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirKotlinPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.EnclosingDeclarationContext
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.buildCompletionContext
@@ -52,7 +51,7 @@ internal class KtFirCompletionCandidateChecker(
val functionFits = firSymbolForCandidate.withResolvedFirOfType<KtFirFunctionSymbol, FirSimpleFunction, Boolean> { firFunction ->
checkExtension(firFunction, originalFile, nameExpression, possibleExplicitReceiver)
}
val propertyFits = firSymbolForCandidate.withResolvedFirOfType<KtFirPropertySymbol, FirProperty, Boolean> { firProperty ->
val propertyFits = firSymbolForCandidate.withResolvedFirOfType<KtFirKotlinPropertySymbol, FirProperty, Boolean> { firProperty ->
checkExtension(firProperty, originalFile, nameExpression, possibleExplicitReceiver)
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.containingClass
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
@@ -17,6 +18,7 @@ import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.createSignatu
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.convertAnnotation
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.convertConstantExpression
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtKotlinPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertyGetterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySetterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
@@ -28,14 +30,15 @@ import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
internal class KtFirPropertySymbol(
internal class KtFirKotlinPropertySymbol(
fir: FirProperty,
resolveState: FirModuleResolveState,
override val token: ValidityToken,
private val builder: KtSymbolByFirBuilder
) : KtPropertySymbol(), KtFirSymbol<FirProperty> {
) : KtKotlinPropertySymbol(), KtFirSymbol<FirProperty> {
init {
assert(!fir.isLocal)
check(fir !is FirSyntheticProperty)
}
override val firRef = firRef(fir, resolveState)
@@ -84,6 +87,9 @@ internal class KtFirPropertySymbol(
override val isOverride: Boolean get() = firRef.withFir { it.isOverride }
override val hasGetter: Boolean get() = firRef.withFir { it.getter != null }
override val hasSetter: Boolean get() = firRef.withFir { it.setter != null }
override fun createPointer(): KtSymbolPointer<KtPropertySymbol> {
KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it }
return when (symbolKind) {
@@ -0,0 +1,91 @@
/*
* 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.symbols
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.containingClass
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.KtFirMemberPropertySymbolPointer
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.createSignature
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.convertAnnotation
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.convertConstantExpression
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertyGetterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySetterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSyntheticJavaPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.CanNotCreateSymbolPointerForLocalLibraryDeclarationException
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
internal class KtFirSyntheticJavaPropertySymbol(
fir: FirSyntheticProperty,
resolveState: FirModuleResolveState,
override val token: ValidityToken,
private val builder: KtSymbolByFirBuilder
) : KtSyntheticJavaPropertySymbol(), KtFirSymbol<FirSyntheticProperty> {
override val firRef = firRef(fir, resolveState)
override val psi: PsiElement? by firRef.withFirAndCache { fir -> fir.findPsi(fir.session) }
override val isVal: Boolean get() = firRef.withFir { it.isVal }
override val name: Name get() = firRef.withFir { it.name }
override val type: KtType by firRef.withFirAndCache(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) { fir -> builder.buildKtType(fir.returnTypeRef) }
override val receiverType: KtType? by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir -> fir.receiverTypeRef?.let(builder::buildKtType) }
override val isExtension: Boolean get() = firRef.withFir { it.receiverTypeRef != null }
override val initializer: KtConstantValue? by firRef.withFirAndCache(FirResolvePhase.BODY_RESOLVE) { fir -> fir.initializer?.convertConstantExpression() }
override val modality: KtCommonSymbolModality get() = getModality()
override val visibility: KtSymbolVisibility get() = getVisibility()
override val annotations: List<KtAnnotationCall> by firRef.withFirAndCache(FirResolvePhase.TYPES) {
convertAnnotation(it)
}
override val callableIdIfNonLocal: FqName?
get() = firRef.withFir { fir ->
fir.symbol.callableId.takeUnless { fir.isLocal }?.asFqNameForDebugInfo()
}
override val getter: KtPropertyGetterSymbol by firRef.withFirAndCache(FirResolvePhase.RAW_FIR) { property ->
property.getter.let { builder.buildPropertyAccessorSymbol(it) } as KtPropertyGetterSymbol
}
override val setter: KtPropertySetterSymbol? by firRef.withFirAndCache(FirResolvePhase.RAW_FIR) { property ->
property.setter?.let { builder.buildPropertyAccessorSymbol(it) } as? KtPropertySetterSymbol
}
override val javaGetterName: Name get() = firRef.withFir { it.getter.delegate.name }
override val javaSetterName: Name? get() = firRef.withFir { it.setter?.delegate?.name }
override val isOverride: Boolean get() = firRef.withFir { it.isOverride }
override val hasSetter: Boolean get() = firRef.withFir { it.setter != null }
override fun createPointer(): KtSymbolPointer<KtPropertySymbol> {
KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it }
return when (symbolKind) {
KtSymbolKind.TOP_LEVEL -> TODO("Creating symbol for top level fun is not supported yet")
KtSymbolKind.NON_PROPERTY_PARAMETER -> TODO("Creating symbol for top level parameters is not supported yet")
KtSymbolKind.MEMBER -> KtFirMemberPropertySymbolPointer(
firRef.withFir { it.containingClass()?.classId ?: error("ClassId should not be null for member property") },
firRef.withFir { it.createSignature() }
)
KtSymbolKind.LOCAL -> throw CanNotCreateSymbolPointerForLocalLibraryDeclarationException(name.asString())
}
}
}
@@ -381,11 +381,13 @@ KtFirFunctionSymbol:
valueParameters: [KtFirFunctionValueParameterSymbol(element)]
visibility: PUBLIC
KtFirPropertySymbol:
KtFirKotlinPropertySymbol:
annotations: []
callableIdIfNonLocal: kotlin.collections.List.size
getter: null
hasBackingField: false
hasGetter: false
hasSetter: false
initializer: null
isConst: false
isExtension: false
@@ -69,11 +69,13 @@ KtFirFunctionSymbol:
valueParameters: []
visibility: PUBLIC
KtFirPropertySymbol:
KtFirKotlinPropertySymbol:
annotations: []
callableIdIfNonLocal: kotlin.CharSequence.length
getter: KtFirPropertyGetterSymbol(<getter>)
hasBackingField: true
hasGetter: true
hasSetter: false
initializer: null
isConst: false
isExtension: false
@@ -4,11 +4,13 @@ class A {
}
// SYMBOLS:
KtFirPropertySymbol:
KtFirKotlinPropertySymbol:
annotations: []
callableIdIfNonLocal: A.x
getter: KtFirPropertyGetterSymbol(<getter>)
hasBackingField: true
hasGetter: true
hasSetter: false
initializer: 10
isConst: false
isExtension: false
@@ -35,11 +37,13 @@ KtFirPropertyGetterSymbol:
type: kotlin/Int
visibility: PUBLIC
KtFirPropertySymbol:
KtFirKotlinPropertySymbol:
annotations: []
callableIdIfNonLocal: A.y
getter: KtFirPropertyGetterSymbol(<getter>)
hasBackingField: false
hasGetter: true
hasSetter: false
initializer: null
isConst: false
isExtension: true
@@ -2,11 +2,13 @@ val x: Int = 10
val Int.y get() = this
// SYMBOLS:
KtFirPropertySymbol:
KtFirKotlinPropertySymbol:
annotations: []
callableIdIfNonLocal: x
getter: KtFirPropertyGetterSymbol(<getter>)
hasBackingField: true
hasGetter: true
hasSetter: false
initializer: 10
isConst: false
isExtension: false
@@ -33,11 +35,13 @@ KtFirPropertyGetterSymbol:
type: kotlin/Int
visibility: PUBLIC
KtFirPropertySymbol:
KtFirKotlinPropertySymbol:
annotations: []
callableIdIfNonLocal: y
getter: KtFirPropertyGetterSymbol(<getter>)
hasBackingField: false
hasGetter: true
hasSetter: false
initializer: null
isConst: false
isExtension: true
@@ -28,11 +28,13 @@ KtFirFunctionSymbol:
valueParameters: []
visibility: PUBLIC
KtFirPropertySymbol:
KtFirKotlinPropertySymbol:
annotations: []
callableIdIfNonLocal: <anonymous>.data
getter: KtFirPropertyGetterSymbol(<getter>)
hasBackingField: true
hasGetter: true
hasSetter: false
initializer: 123
isConst: false
isExtension: false
@@ -54,11 +56,13 @@ KtFirAnonymousObjectSymbol:
superTypes: [java/lang/Runnable]
symbolKind: LOCAL
KtFirPropertySymbol:
KtFirKotlinPropertySymbol:
annotations: []
callableIdIfNonLocal: AnonymousContainer.anonymousObject
getter: KtFirPropertyGetterSymbol(<getter>)
hasBackingField: true
hasGetter: true
hasSetter: false
initializer: KtUnsupportedConstantValue
isConst: false
isExtension: false
@@ -5,11 +5,13 @@ class A {
// SYMBOLS:
/*
KtFirPropertySymbol:
KtFirKotlinPropertySymbol:
annotations: []
callableIdIfNonLocal: A.a
getter: KtFirPropertyGetterSymbol(<getter>)
hasBackingField: true
hasGetter: true
hasSetter: false
initializer: 10
isConst: false
isExtension: false