[AA LC] Implement default values for methods of annotations

This commit is contained in:
Dmitriy Novozhilov
2022-08-03 16:00:15 +03:00
parent 3a51a8a655
commit a88fdd5eb7
10 changed files with 85 additions and 21 deletions
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
import org.jetbrains.kotlin.analysis.api.types.KtType
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.containingClass
@@ -39,6 +40,7 @@ import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirSyntheticPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.isExtension
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.Name
@@ -68,7 +70,7 @@ internal class KtFirKotlinPropertySymbol(
override val contextReceivers: List<KtContextReceiver> by cached { firSymbol.createContextReceivers(builder) }
override val isExtension: Boolean get() = withValidityAssertion { firSymbol.isExtension }
override val initializer: KtInitializerValue? by cached { firSymbol.getKtConstantInitializer() }
override val initializer: KtInitializerValue? by cached { firSymbol.getKtConstantInitializer(firResolveSession) }
override val symbolKind: KtSymbolKind
get() = withValidityAssertion {
@@ -51,7 +51,7 @@ internal class KtFirSyntheticJavaPropertySymbol(
override val isExtension: Boolean get() = withValidityAssertion { firSymbol.isExtension }
override val initializer: KtInitializerValue? by cached { firSymbol.getKtConstantInitializer() }
override val initializer: KtInitializerValue? by cached { firSymbol.getKtConstantInitializer(firResolveSession) }
override val modality: Modality get() = withValidityAssertion { firSymbol.modality ?: firSymbol.invalidModalityError() }
override val visibility: Visibility get() = withValidityAssertion { firSymbol.visibility }
@@ -15,16 +15,18 @@ import org.jetbrains.kotlin.analysis.api.fir.utils.asKtInitializerValue
import org.jetbrains.kotlin.analysis.api.impl.base.KtContextReceiverImpl
import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol
import org.jetbrains.kotlin.analysis.api.types.KtType
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
import org.jetbrains.kotlin.analysis.utils.printer.getElementTextInContext
import org.jetbrains.kotlin.fir.declarations.FirContextReceiver
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRefsOwner
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.references.impl.FirPropertyFromParameterResolvedNamedReference
import org.jetbrains.kotlin.fir.renderer.FirRenderer
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtDeclaration
@@ -89,8 +91,21 @@ internal fun FirCallableSymbol<*>.dispatchReceiverType(
return dispatchReceiverType?.let { builder.typeBuilder.buildKtType(it) }
}
internal fun FirVariableSymbol<*>.getKtConstantInitializer(): KtInitializerValue? {
internal fun FirVariableSymbol<*>.getKtConstantInitializer(resolveSession: LLFirResolveSession): KtInitializerValue? {
lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
val firInitializer = fir.initializer ?: return null
return firInitializer.asKtInitializerValue()
}
var firInitializer = fir.initializer ?: return null
if (firInitializer is FirPropertyAccessExpression) {
val calleeReference = firInitializer.calleeReference
if (calleeReference is FirPropertyFromParameterResolvedNamedReference) {
val valueParameterSymbol = calleeReference.resolvedSymbol as? FirValueParameterSymbol
if (valueParameterSymbol != null) {
valueParameterSymbol.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
firInitializer = valueParameterSymbol.fir.defaultValue ?: firInitializer
}
}
}
val parentIsAnnotation = dispatchReceiverType
?.toRegularClassSymbol(resolveSession.useSiteFirSession)
?.classKind == ClassKind.ANNOTATION_CLASS
return firInitializer.asKtInitializerValue(moduleData.session, parentIsAnnotation)
}
@@ -6,9 +6,11 @@ package org.jetbrains.kotlin.analysis.api.fir.utils
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.api.KtConstantInitializerValue
import org.jetbrains.kotlin.analysis.api.KtConstantValueForAnnotation
import org.jetbrains.kotlin.analysis.api.KtInitializerValue
import org.jetbrains.kotlin.analysis.api.KtNonConstantInitializerValue
import org.jetbrains.kotlin.analysis.api.components.KtConstantEvaluationMode
import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirAnnotationValueConverter
import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirCompileTimeConstantEvaluator
import org.jetbrains.kotlin.analysis.api.fir.getCandidateSymbols
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
@@ -89,12 +91,24 @@ internal fun FirCallableSymbol<*>.computeImportableName(useSiteSession: FirSessi
return if (canBeImported) callableId.asSingleFqName() else null
}
internal fun FirExpression.asKtInitializerValue(): KtInitializerValue {
internal fun FirExpression.asKtInitializerValue(
session: FirSession,
forAnnotationDefaultValue: Boolean
): KtInitializerValue {
val ktExpression = psi as? KtExpression
val evaluated =
FirCompileTimeConstantEvaluator.evaluateAsKtConstantValue(this, KtConstantEvaluationMode.CONSTANT_EXPRESSION_EVALUATION)
return when (evaluated) {
null -> KtNonConstantInitializerValue(ktExpression)
null -> if (forAnnotationDefaultValue) {
val annotationConstantValue = FirAnnotationValueConverter.toConstantValue(this, session)
if (annotationConstantValue != null) {
KtConstantValueForAnnotation(annotationConstantValue, ktExpression)
} else {
KtNonConstantInitializerValue(ktExpression)
}
} else {
KtNonConstantInitializerValue(ktExpression)
}
else -> KtConstantInitializerValue(evaluated, ktExpression)
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.analysis.api
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationValue
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
import org.jetbrains.kotlin.psi.KtExpression
@@ -29,10 +30,19 @@ public class KtConstantInitializerValue(
) : KtInitializerValue()
/**
* Property intialzer which cannot be represented as Kotlin const value.
* Property initializer which cannot be represented as Kotlin const value.
*
* See [KtConstantInitializerValue] for more info.
*/
public class KtNonConstantInitializerValue(
override val initializerPsi: KtExpression?
) : KtInitializerValue()
) : KtInitializerValue()
/**
* Initializer of property of annotation, which can not be which cannot be represented as Kotlin const value,
* but can be represented as [KtAnnotationValue]
*/
public class KtConstantValueForAnnotation(
public val annotationValue: KtAnnotationValue,
override val initializerPsi: KtExpression?
) : KtInitializerValue()
@@ -6,10 +6,7 @@
package org.jetbrains.kotlin.analysis.api.symbols
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.KtConstantInitializerValue
import org.jetbrains.kotlin.analysis.api.KtInitializerValue
import org.jetbrains.kotlin.analysis.api.KtNonConstantInitializerValue
import org.jetbrains.kotlin.analysis.api.*
import org.jetbrains.kotlin.analysis.api.annotations.*
import org.jetbrains.kotlin.analysis.api.base.KtContextReceiver
import org.jetbrains.kotlin.analysis.api.components.KtSymbolContainingDeclarationProviderMixIn
@@ -262,11 +259,18 @@ public object DebugSymbolRenderer {
append(value.constant.renderAsKotlinConstant())
append(")")
}
is KtNonConstantInitializerValue -> {
append("KtNonConstantInitializerValue(")
append(value.initializerPsi?.firstLineOfPsi() ?: "NO_PSI")
append(")")
}
is KtConstantValueForAnnotation -> {
append("KtConstantValueForAnnotation(")
append(value.annotationValue.renderAsSourceCode())
append(")")
}
}
}
@@ -299,4 +303,4 @@ public object DebugSymbolRenderer {
"org.jetbrains.kotlin.analysis.api.fir",
"org.jetbrains.kotlin.analysis.api.descriptors",
)
}
}
@@ -7,6 +7,9 @@ package org.jetbrains.kotlin.light.classes.symbol.methods
import com.intellij.psi.*
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.KtConstantInitializerValue
import org.jetbrains.kotlin.analysis.api.KtConstantValueForAnnotation
import org.jetbrains.kotlin.analysis.api.KtNonConstantInitializerValue
import org.jetbrains.kotlin.analysis.api.lifetime.isValid
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.types.KtTypeMappingMode
@@ -193,4 +196,18 @@ internal class SymbolLightAccessorMethod(
override fun isValid(): Boolean = super.isValid() && propertyAccessorSymbol.isValid()
override fun isOverride(): Boolean = propertyAccessorSymbol.isOverride
private val _defaultValue: PsiAnnotationMemberValue? by lazyPub {
if (!containingClass.isAnnotationType) return@lazyPub null
when (val initializer = containingPropertySymbol.initializer) {
is KtConstantInitializerValue -> initializer.constant.createPsiLiteral(this)
is KtConstantValueForAnnotation -> initializer.annotationValue.toAnnotationMemberValue(this)
is KtNonConstantInitializerValue -> null
null -> null
}
}
override fun getDefaultValue(): PsiAnnotationMemberValue? {
return _defaultValue
}
}
@@ -88,7 +88,7 @@ internal abstract class SymbolLightMethodBase(
override fun getThrowsList(): PsiReferenceList =
KotlinLightReferenceListBuilder(manager, language, PsiReferenceList.Role.THROWS_LIST) //TODO()
override fun getDefaultValue(): PsiAnnotationMemberValue? = null //TODO()
override fun getDefaultValue(): PsiAnnotationMemberValue? = null
protected fun <T> T.computeJvmMethodName(
defaultName: String,
@@ -1,4 +1,6 @@
// Anno
// IGNORE_FIR
// Ignored due to KT-53573
annotation class Anno(
val i: Int,
@@ -44,7 +44,7 @@ public static final class Companion /* AnnoWithCompanion.Companion*/ {
public abstract @interface Anno /* Anno*/ {
public abstract Anno[] x();// x()
public abstract java.lang.String p();// p()
public abstract java.lang.String p() default "";// p()
}