From 40bd222b788c4b064854396ab264b10db2e5b9e7 Mon Sep 17 00:00:00 2001 From: Dmitrii Gridin Date: Tue, 15 Nov 2022 17:33:01 +0100 Subject: [PATCH] [SLC] drop KtAnalysisSession from SymbolLightFieldForProperty ^KT-54051 --- .../kotlin/analysis/api/symbols/KtSymbol.kt | 24 +++ .../SymbolLightClassForClassOrObject.kt | 1 + .../symbol/classes/symbolLightClassUtils.kt | 3 +- .../fields/SymbolLightFieldForProperty.kt | 170 +++++++++++------- 4 files changed, 128 insertions(+), 70 deletions(-) diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtSymbol.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtSymbol.kt index a8781b27461..0d84f56a94a 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtSymbol.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtSymbol.kt @@ -40,6 +40,30 @@ public inline fun KtSymbol.psi(): PSI = public inline fun KtSymbol.psiSafe(): PSI? = psi as? PSI +/** + * Get symbol [PsiElement]. **null** if its [KtSymbol.origin] !is [KtSymbolOrigin.SOURCE]. throws **ClassCastException** if its type !is [PSI] + * + * @see KtSymbol.psi + */ +public inline fun KtSymbol.sourcePsi(): PSI? { + // TODO: support Java sources after KT-53669 + if (origin != KtSymbolOrigin.SOURCE) return null + + return psi as PSI +} + +/** + * Get symbol [PsiElement] if its type is [PSI] and [KtSymbol.origin] is [KtSymbolOrigin.SOURCE], otherwise null + * + * @see KtSymbol.psiSafe + */ +public inline fun KtSymbol.sourcePsiSafe(): PSI? { + // TODO: support Java sources after KT-53669 + if (origin != KtSymbolOrigin.SOURCE) return null + + return psi as? PSI +} + /** * A place where [KtSymbol] came from */ diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassOrObject.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassOrObject.kt index e86489060e6..0d3bc7cd169 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassOrObject.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassOrObject.kt @@ -168,6 +168,7 @@ abstract class SymbolLightClassForClassOrObject(protected val classOrObject: KtC isTopLevel = false, forceStatic = true, takePropertyVisibility = it.isConstOrJvmField, + ktModule = ktModule, ) } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt index 678d60fef5d..1a7d59b8b9e 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt @@ -354,7 +354,8 @@ internal fun SymbolLightClassBase.createField( lightMemberOrigin = null, isTopLevel = isTopLevel, forceStatic = forceStatic, - takePropertyVisibility = takePropertyVisibility + takePropertyVisibility = takePropertyVisibility, + ktModule = ktModule, ) ) } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForProperty.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForProperty.kt index 0235bb4cbc7..4c565c2993e 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForProperty.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForProperty.kt @@ -8,10 +8,13 @@ package org.jetbrains.kotlin.light.classes.symbol.fields import com.intellij.psi.* import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.KtConstantInitializerValue -import org.jetbrains.kotlin.analysis.api.lifetime.isValid +import org.jetbrains.kotlin.analysis.api.base.KtConstantValue import org.jetbrains.kotlin.analysis.api.symbols.KtKotlinPropertySymbol import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol +import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer +import org.jetbrains.kotlin.analysis.api.symbols.sourcePsiSafe import org.jetbrains.kotlin.analysis.api.types.KtTypeMappingMode +import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget @@ -20,47 +23,58 @@ import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations import org.jetbrains.kotlin.light.classes.symbol.annotations.hasAnnotation import org.jetbrains.kotlin.light.classes.symbol.annotations.hasDeprecatedAnnotation import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassBase +import org.jetbrains.kotlin.light.classes.symbol.classes.analyzeForLightClasses import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightMemberModifierList import org.jetbrains.kotlin.name.JvmNames.TRANSIENT_ANNOTATION_CLASS_ID import org.jetbrains.kotlin.name.JvmNames.VOLATILE_ANNOTATION_CLASS_ID -import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtCallableDeclaration import org.jetbrains.kotlin.psi.KtProperty -context(KtAnalysisSession) internal class SymbolLightFieldForProperty( - private val propertySymbol: KtPropertySymbol, + propertySymbol: KtPropertySymbol, private val fieldName: String, containingClass: SymbolLightClassBase, lightMemberOrigin: LightMemberOrigin?, isTopLevel: Boolean, forceStatic: Boolean, - takePropertyVisibility: Boolean + takePropertyVisibility: Boolean, + private val ktModule: KtModule, ) : SymbolLightField(containingClass, lightMemberOrigin) { + override val kotlinOrigin: KtCallableDeclaration? = propertySymbol.sourcePsiSafe() + private val propertySymbolPointer: KtSymbolPointer = propertySymbol.createPointer() - override val kotlinOrigin: KtDeclaration? = propertySymbol.psi as? KtDeclaration + private fun withPropertySymbol(action: KtAnalysisSession.(KtPropertySymbol) -> T): T = analyzeForLightClasses(ktModule) { + val restoreSymbol = propertySymbolPointer.restoreSymbol() + requireNotNull(restoreSymbol) { "pointer already disposed" } + action(restoreSymbol) + } private val _returnedType: PsiType by lazyPub { - val isDelegated = (propertySymbol as? KtKotlinPropertySymbol)?.isDelegatedProperty == true - when { - isDelegated -> - (kotlinOrigin as? KtProperty)?.delegateExpression?.let { - it.getKtType()?.asPsiType(this@SymbolLightFieldForProperty, KtTypeMappingMode.RETURN_TYPE) - } + withPropertySymbol { propertySymbol -> + val isDelegated = (propertySymbol as? KtKotlinPropertySymbol)?.isDelegatedProperty == true + when { + isDelegated -> + (kotlinOrigin as? KtProperty)?.delegateExpression?.let { + it.getKtType()?.asPsiType(this@SymbolLightFieldForProperty, KtTypeMappingMode.RETURN_TYPE) + } - else -> { - propertySymbol.returnType.asPsiType(this@SymbolLightFieldForProperty, KtTypeMappingMode.RETURN_TYPE) - } - } ?: nonExistentType() + else -> propertySymbol.returnType.asPsiType(this@SymbolLightFieldForProperty, KtTypeMappingMode.RETURN_TYPE) + } ?: nonExistentType() + } } private val _isDeprecated: Boolean by lazyPub { - propertySymbol.hasDeprecatedAnnotation(AnnotationUseSiteTarget.FIELD) + withPropertySymbol { propertySymbol -> + propertySymbol.hasDeprecatedAnnotation(AnnotationUseSiteTarget.FIELD) + } } override fun isDeprecated(): Boolean = _isDeprecated private val _identifier: PsiIdentifier by lazyPub { - SymbolLightIdentifier(this, propertySymbol) + withPropertySymbol { propertySymbol -> + SymbolLightIdentifier(this@SymbolLightFieldForProperty, propertySymbol) + } } override fun getNameIdentifier(): PsiIdentifier = _identifier @@ -70,53 +84,57 @@ internal class SymbolLightFieldForProperty( override fun getName(): String = fieldName private val _modifierList: PsiModifierList by lazyPub { + withPropertySymbol { propertySymbol -> + val modifiers = mutableSetOf() - val modifiers = mutableSetOf() + val suppressFinal = !propertySymbol.isVal - val suppressFinal = !propertySymbol.isVal + propertySymbol.computeModalityForMethod( + isTopLevel = isTopLevel, + suppressFinal = suppressFinal, + result = modifiers + ) - propertySymbol.computeModalityForMethod( - isTopLevel = isTopLevel, - suppressFinal = suppressFinal, - result = modifiers - ) + if (forceStatic) { + modifiers.add(PsiModifier.STATIC) + } - if (forceStatic) { - modifiers.add(PsiModifier.STATIC) + val visibility = if (takePropertyVisibility) propertySymbol.toPsiVisibilityForMember() else PsiModifier.PRIVATE + modifiers.add(visibility) + + if (!suppressFinal) { + modifiers.add(PsiModifier.FINAL) + } + + if (propertySymbol.hasAnnotation(TRANSIENT_ANNOTATION_CLASS_ID, null)) { + modifiers.add(PsiModifier.TRANSIENT) + } + + if (propertySymbol.hasAnnotation(VOLATILE_ANNOTATION_CLASS_ID, null)) { + modifiers.add(PsiModifier.VOLATILE) + } + + val nullability = if (!(propertySymbol is KtKotlinPropertySymbol && propertySymbol.isLateInit)) { + getTypeNullability(propertySymbol.returnType) + } else NullabilityType.Unknown + + val annotations = propertySymbol.computeAnnotations( + parent = this@SymbolLightFieldForProperty, + nullability = nullability, + annotationUseSiteTarget = AnnotationUseSiteTarget.FIELD, + ) + + SymbolLightMemberModifierList(this@SymbolLightFieldForProperty, modifiers, annotations) } - - val visibility = - if (takePropertyVisibility) propertySymbol.toPsiVisibilityForMember() else PsiModifier.PRIVATE - modifiers.add(visibility) - - if (!suppressFinal) { - modifiers.add(PsiModifier.FINAL) - } - if (propertySymbol.hasAnnotation(TRANSIENT_ANNOTATION_CLASS_ID, null)) { - modifiers.add(PsiModifier.TRANSIENT) - } - if (propertySymbol.hasAnnotation(VOLATILE_ANNOTATION_CLASS_ID, null)) { - modifiers.add(PsiModifier.VOLATILE) - } - - val nullability = if (!(propertySymbol is KtKotlinPropertySymbol && propertySymbol.isLateInit)) { - getTypeNullability(propertySymbol.returnType) - } else NullabilityType.Unknown - - val annotations = propertySymbol.computeAnnotations( - parent = this, - nullability = nullability, - annotationUseSiteTarget = AnnotationUseSiteTarget.FIELD, - ) - - SymbolLightMemberModifierList(this, modifiers, annotations) } override fun getModifierList(): PsiModifierList = _modifierList - private val _initializerValue by lazyPub { - if (propertySymbol !is KtKotlinPropertySymbol) return@lazyPub null - (propertySymbol.initializer as? KtConstantInitializerValue)?.constant + private val _initializerValue: KtConstantValue? by lazyPub { + withPropertySymbol { propertySymbol -> + if (propertySymbol !is KtKotlinPropertySymbol) return@withPropertySymbol null + (propertySymbol.initializer as? KtConstantInitializerValue)?.constant + } } private val _initializer by lazyPub { @@ -127,24 +145,38 @@ internal class SymbolLightFieldForProperty( private val _constantValue by lazyPub { _initializerValue?.value?.takeIf { - // val => final - propertySymbol.isVal && - // NB: not as?, since _initializerValue already checks that - (propertySymbol as KtKotlinPropertySymbol).isConst && - // javac rejects all non-primitive and non String constants - (propertySymbol.returnType.isPrimitive || propertySymbol.returnType.isString) + withPropertySymbol { propertySymbol -> + // val => final + propertySymbol.isVal && + // NB: not as?, since _initializerValue already checks that + (propertySymbol as KtKotlinPropertySymbol).isConst && + // javac rejects all non-primitive and non String constants + (propertySymbol.returnType.isPrimitive || propertySymbol.returnType.isString) + } } } override fun computeConstantValue(): Any? = _constantValue - override fun equals(other: Any?): Boolean = - this === other || - (other is SymbolLightFieldForProperty && - kotlinOrigin == other.kotlinOrigin && - propertySymbol == other.propertySymbol) + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is SymbolLightFieldForProperty) return false + if (kotlinOrigin != null) { + return kotlinOrigin == other.kotlinOrigin && ktModule == other.ktModule + } - override fun hashCode(): Int = kotlinOrigin.hashCode() + return other.kotlinOrigin == null && + fieldName == other.fieldName && + containingClass == other.containingClass && + ktModule == other.ktModule && + analyzeForLightClasses(ktModule) { + propertySymbolPointer.restoreSymbol() == other.propertySymbolPointer.restoreSymbol() + } + } - override fun isValid(): Boolean = super.isValid() && propertySymbol.isValid() + override fun hashCode(): Int = kotlinOrigin?.hashCode() ?: fieldName.hashCode() + + override fun isValid(): Boolean = super.isValid() && kotlinOrigin?.isValid ?: analyzeForLightClasses(ktModule) { + propertySymbolPointer.restoreSymbol() != null + } }