[LL FIR] FirLazyBodiesCalculator: covert non-public api to private functions

^KT-56550
This commit is contained in:
Dmitrii Gridin
2023-05-10 10:49:11 +02:00
committed by Space Team
parent a7692ba2c5
commit 990f23a11b
@@ -61,159 +61,164 @@ internal object FirLazyBodiesCalculator {
FirLazyAnnotationTransformerData(firElement.moduleData.session, FirLazyAnnotationTransformerScope.COMPILER_ONLY)
)
}
private fun replaceValueParameterDefaultValues(valueParameters: List<FirValueParameter>, newValueParameters: List<FirValueParameter>) {
require(valueParameters.size == newValueParameters.size)
for ((valueParameter, newValueParameter) in valueParameters.zip(newValueParameters)) {
if (newValueParameter.defaultValue != null) {
valueParameter.replaceDefaultValue(newValueParameter.defaultValue)
}
}
}
fun calculateLazyArgumentsForAnnotation(annotationCall: FirAnnotationCall, session: FirSession) {
require(needCalculatingAnnotationCall(annotationCall))
val builder = RawFirBuilder(session, baseScopeProvider = session.kotlinScopeProvider)
val newAnnotationCall = builder.buildAnnotationCall(annotationCall.psi as KtAnnotationEntry)
annotationCall.replaceArgumentList(newAnnotationCall.argumentList)
}
fun calculateLazyBodiesForFunction(designation: FirDesignation) {
val simpleFunction = designation.target as FirSimpleFunction
require(needCalculatingLazyBodyForFunction(simpleFunction))
val newFunction = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
session = simpleFunction.moduleData.session,
scopeProvider = simpleFunction.moduleData.session.kotlinScopeProvider,
designation = designation,
rootNonLocalDeclaration = simpleFunction.psi as KtNamedFunction,
) as FirSimpleFunction
simpleFunction.apply {
replaceBody(newFunction.body)
replaceContractDescription(newFunction.contractDescription)
replaceValueParameterDefaultValues(valueParameters, newFunction.valueParameters)
}
}
fun calculateLazyBodyForConstructor(designation: FirDesignation) {
val constructor = designation.target as FirConstructor
require(needCalculatingLazyBodyForConstructor(constructor))
val newConstructor = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
session = constructor.moduleData.session,
scopeProvider = constructor.moduleData.session.kotlinScopeProvider,
designation = designation,
rootNonLocalDeclaration = constructor.psi as KtDeclaration,
) as FirConstructor
constructor.apply {
replaceBody(newConstructor.body)
replaceContractDescription(newConstructor.contractDescription)
replaceDelegatedConstructor(newConstructor.delegatedConstructor)
replaceValueParameterDefaultValues(valueParameters, newConstructor.valueParameters)
}
}
fun calculateLazyBodyForProperty(designation: FirDesignation) {
val firProperty = designation.target as FirProperty
if (!needCalculatingLazyBodyForProperty(firProperty)) return
val newProperty = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
session = firProperty.moduleData.session,
scopeProvider = firProperty.moduleData.session.kotlinScopeProvider,
designation = designation,
rootNonLocalDeclaration = firProperty.psi as KtProperty
) as FirProperty
firProperty.getter?.takeIf { it.body is FirLazyBlock }?.let { getter ->
val newGetter = newProperty.getter!!
getter.replaceBody(newGetter.body)
getter.replaceContractDescription(newGetter.contractDescription)
}
firProperty.setter?.takeIf { it.body is FirLazyBlock }?.let { setter ->
val newSetter = newProperty.setter!!
setter.replaceBody(newSetter.body)
setter.replaceContractDescription(newSetter.contractDescription)
}
if (firProperty.initializer is FirLazyExpression) {
firProperty.replaceInitializer(newProperty.initializer)
}
firProperty.getExplicitBackingField()?.takeIf { it.initializer is FirLazyExpression }?.let { backingField ->
val newInitializer = newProperty.getExplicitBackingField()?.initializer
backingField.replaceInitializer(newInitializer)
}
val delegate = firProperty.delegate as? FirWrappedDelegateExpression
val delegateExpression = delegate?.expression
if (delegateExpression is FirLazyExpression) {
val newDelegate = newProperty.delegate as? FirWrappedDelegateExpression
check(newDelegate != null) { "Invalid replacement delegate" }
delegate.replaceExpression(newDelegate.expression)
delegate.replaceDelegateProvider(newDelegate.delegateProvider)
}
}
fun calculateLazyInitializerForEnumEntry(designation: FirDesignation) {
val enumEntry = designation.target as FirEnumEntry
require(enumEntry.initializer is FirLazyExpression)
val newEntry = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
session = enumEntry.moduleData.session,
scopeProvider = enumEntry.moduleData.session.kotlinScopeProvider,
designation = designation,
rootNonLocalDeclaration = enumEntry.psi as KtEnumEntry,
) as FirEnumEntry
enumEntry.apply {
replaceInitializer(newEntry.initializer)
}
}
fun calculateLazyBodyForAnonymousInitializer(designation: FirDesignation) {
val initializer = designation.target as FirAnonymousInitializer
require(initializer.body is FirLazyBlock)
val newInitializer = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
session = initializer.moduleData.session,
scopeProvider = initializer.moduleData.session.kotlinScopeProvider,
designation = designation,
rootNonLocalDeclaration = initializer.psi as KtAnonymousInitializer,
) as FirAnonymousInitializer
initializer.apply {
replaceBody(newInitializer.body)
}
}
fun calculateLazyBodiesForField(designation: FirDesignation) {
val field = designation.target as FirField
require(field.initializer is FirLazyExpression)
val newField = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
session = field.moduleData.session,
scopeProvider = field.moduleData.session.kotlinScopeProvider,
designation = designation,
rootNonLocalDeclaration = designation.path.last().psi as KtClassOrObject,
) as FirField
field.apply {
replaceInitializer(newField.initializer)
}
}
fun needCalculatingLazyBodyForConstructor(firConstructor: FirConstructor): Boolean =
needCalculatingLazyBodyForFunction(firConstructor) || firConstructor.delegatedConstructor is FirLazyDelegatedConstructorCall
fun needCalculatingLazyBodyForFunction(firFunction: FirFunction): Boolean =
firFunction.body is FirLazyBlock || firFunction.valueParameters.any { it.defaultValue is FirLazyExpression }
fun needCalculatingLazyBodyForProperty(firProperty: FirProperty): Boolean =
firProperty.getter?.let { needCalculatingLazyBodyForFunction(it) } == true
|| firProperty.setter?.let { needCalculatingLazyBodyForFunction(it) } == true
|| firProperty.initializer is FirLazyExpression
|| (firProperty.delegate as? FirWrappedDelegateExpression)?.expression is FirLazyExpression
|| firProperty.getExplicitBackingField()?.initializer is FirLazyExpression
fun needCalculatingAnnotationCall(firAnnotationCall: FirAnnotationCall): Boolean =
firAnnotationCall.argumentList.arguments.any { it is FirLazyExpression }
}
private fun replaceValueParameterDefaultValues(valueParameters: List<FirValueParameter>, newValueParameters: List<FirValueParameter>) {
require(valueParameters.size == newValueParameters.size)
for ((valueParameter, newValueParameter) in valueParameters.zip(newValueParameters)) {
if (newValueParameter.defaultValue != null) {
valueParameter.replaceDefaultValue(newValueParameter.defaultValue)
}
}
}
private fun calculateLazyArgumentsForAnnotation(annotationCall: FirAnnotationCall, session: FirSession) {
require(needCalculatingAnnotationCall(annotationCall))
val builder = RawFirBuilder(session, baseScopeProvider = session.kotlinScopeProvider)
val newAnnotationCall = builder.buildAnnotationCall(annotationCall.psi as KtAnnotationEntry)
annotationCall.replaceArgumentList(newAnnotationCall.argumentList)
}
private fun calculateLazyBodiesForFunction(designation: FirDesignation) {
val simpleFunction = designation.target as FirSimpleFunction
require(needCalculatingLazyBodyForFunction(simpleFunction))
val newFunction = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
session = simpleFunction.moduleData.session,
scopeProvider = simpleFunction.moduleData.session.kotlinScopeProvider,
designation = designation,
rootNonLocalDeclaration = simpleFunction.psi as KtNamedFunction,
) as FirSimpleFunction
simpleFunction.apply {
replaceBody(newFunction.body)
replaceContractDescription(newFunction.contractDescription)
replaceValueParameterDefaultValues(valueParameters, newFunction.valueParameters)
}
}
private fun calculateLazyBodyForConstructor(designation: FirDesignation) {
val constructor = designation.target as FirConstructor
require(needCalculatingLazyBodyForConstructor(constructor))
val newConstructor = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
session = constructor.moduleData.session,
scopeProvider = constructor.moduleData.session.kotlinScopeProvider,
designation = designation,
rootNonLocalDeclaration = constructor.psi as KtDeclaration,
) as FirConstructor
constructor.apply {
replaceBody(newConstructor.body)
replaceContractDescription(newConstructor.contractDescription)
replaceDelegatedConstructor(newConstructor.delegatedConstructor)
replaceValueParameterDefaultValues(valueParameters, newConstructor.valueParameters)
}
}
private fun calculateLazyBodyForProperty(designation: FirDesignation) {
val firProperty = designation.target as FirProperty
if (!needCalculatingLazyBodyForProperty(firProperty)) return
val newProperty = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
session = firProperty.moduleData.session,
scopeProvider = firProperty.moduleData.session.kotlinScopeProvider,
designation = designation,
rootNonLocalDeclaration = firProperty.psi as KtProperty
) as FirProperty
firProperty.getter?.takeIf { it.body is FirLazyBlock }?.let { getter ->
val newGetter = newProperty.getter!!
getter.replaceBody(newGetter.body)
getter.replaceContractDescription(newGetter.contractDescription)
}
firProperty.setter?.takeIf { it.body is FirLazyBlock }?.let { setter ->
val newSetter = newProperty.setter!!
setter.replaceBody(newSetter.body)
setter.replaceContractDescription(newSetter.contractDescription)
}
if (firProperty.initializer is FirLazyExpression) {
firProperty.replaceInitializer(newProperty.initializer)
}
firProperty.getExplicitBackingField()?.takeIf { it.initializer is FirLazyExpression }?.let { backingField ->
val newInitializer = newProperty.getExplicitBackingField()?.initializer
backingField.replaceInitializer(newInitializer)
}
val delegate = firProperty.delegate as? FirWrappedDelegateExpression
val delegateExpression = delegate?.expression
if (delegateExpression is FirLazyExpression) {
val newDelegate = newProperty.delegate as? FirWrappedDelegateExpression
check(newDelegate != null) { "Invalid replacement delegate" }
delegate.replaceExpression(newDelegate.expression)
delegate.replaceDelegateProvider(newDelegate.delegateProvider)
}
}
private fun calculateLazyInitializerForEnumEntry(designation: FirDesignation) {
val enumEntry = designation.target as FirEnumEntry
require(enumEntry.initializer is FirLazyExpression)
val newEntry = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
session = enumEntry.moduleData.session,
scopeProvider = enumEntry.moduleData.session.kotlinScopeProvider,
designation = designation,
rootNonLocalDeclaration = enumEntry.psi as KtEnumEntry,
) as FirEnumEntry
enumEntry.apply {
replaceInitializer(newEntry.initializer)
}
}
private fun calculateLazyBodyForAnonymousInitializer(designation: FirDesignation) {
val initializer = designation.target as FirAnonymousInitializer
require(initializer.body is FirLazyBlock)
val newInitializer = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
session = initializer.moduleData.session,
scopeProvider = initializer.moduleData.session.kotlinScopeProvider,
designation = designation,
rootNonLocalDeclaration = initializer.psi as KtAnonymousInitializer,
) as FirAnonymousInitializer
initializer.apply {
replaceBody(newInitializer.body)
}
}
private fun needCalculatingLazyBodyForConstructor(firConstructor: FirConstructor): Boolean =
needCalculatingLazyBodyForFunction(firConstructor) || firConstructor.delegatedConstructor is FirLazyDelegatedConstructorCall
private fun calculateLazyBodiesForField(designation: FirDesignation) {
val field = designation.target as FirField
require(field.initializer is FirLazyExpression)
val newField = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
session = field.moduleData.session,
scopeProvider = field.moduleData.session.kotlinScopeProvider,
designation = designation,
rootNonLocalDeclaration = designation.path.last().psi as KtClassOrObject,
) as FirField
field.apply {
replaceInitializer(newField.initializer)
}
}
private fun needCalculatingLazyBodyForFunction(firFunction: FirFunction): Boolean =
firFunction.body is FirLazyBlock || firFunction.valueParameters.any { it.defaultValue is FirLazyExpression }
private fun needCalculatingLazyBodyForProperty(firProperty: FirProperty): Boolean =
firProperty.getter?.let { needCalculatingLazyBodyForFunction(it) } == true
|| firProperty.setter?.let { needCalculatingLazyBodyForFunction(it) } == true
|| firProperty.initializer is FirLazyExpression
|| (firProperty.delegate as? FirWrappedDelegateExpression)?.expression is FirLazyExpression
|| firProperty.getExplicitBackingField()?.initializer is FirLazyExpression
private fun needCalculatingAnnotationCall(firAnnotationCall: FirAnnotationCall): Boolean =
firAnnotationCall.argumentList.arguments.any { it is FirLazyExpression }
private enum class FirLazyAnnotationTransformerScope {
ALL_ANNOTATIONS,
COMPILER_ONLY;
@@ -221,7 +226,7 @@ private enum class FirLazyAnnotationTransformerScope {
private data class FirLazyAnnotationTransformerData(
val session: FirSession,
val compilerAnnotationsOnly: FirLazyAnnotationTransformerScope = FirLazyAnnotationTransformerScope.ALL_ANNOTATIONS
val compilerAnnotationsOnly: FirLazyAnnotationTransformerScope = FirLazyAnnotationTransformerScope.ALL_ANNOTATIONS,
)
private object FirLazyAnnotationTransformer : FirTransformer<FirLazyAnnotationTransformerData>() {
@@ -255,16 +260,17 @@ private object FirLazyAnnotationTransformer : FirTransformer<FirLazyAnnotationTr
override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: FirLazyAnnotationTransformerData): FirStatement {
val shouldCalculate = data.compilerAnnotationsOnly == FirLazyAnnotationTransformerScope.ALL_ANNOTATIONS ||
canBeCompilerAnnotation(annotationCall, data.session)
if (shouldCalculate && FirLazyBodiesCalculator.needCalculatingAnnotationCall(annotationCall)) {
FirLazyBodiesCalculator.calculateLazyArgumentsForAnnotation(annotationCall, data.session)
if (shouldCalculate && needCalculatingAnnotationCall(annotationCall)) {
calculateLazyArgumentsForAnnotation(annotationCall, data.session)
}
super.transformAnnotationCall(annotationCall, data)
return annotationCall
}
override fun transformErrorAnnotationCall(
errorAnnotationCall: FirErrorAnnotationCall,
data: FirLazyAnnotationTransformerData
data: FirLazyAnnotationTransformerData,
): FirStatement {
transformAnnotationCall(errorAnnotationCall, data)
return errorAnnotationCall
@@ -274,6 +280,7 @@ private object FirLazyAnnotationTransformer : FirTransformer<FirLazyAnnotationTr
if (expression is FirLazyExpression) {
return expression
}
return super.transformExpression(expression, data)
}
@@ -281,16 +288,18 @@ private object FirLazyAnnotationTransformer : FirTransformer<FirLazyAnnotationTr
if (block is FirLazyBlock) {
return block
}
return super.transformBlock(block, data)
}
override fun transformDelegatedConstructorCall(
delegatedConstructorCall: FirDelegatedConstructorCall,
data: FirLazyAnnotationTransformerData
data: FirLazyAnnotationTransformerData,
): FirStatement {
if (delegatedConstructorCall is FirLazyDelegatedConstructorCall) {
return delegatedConstructorCall
}
return super.transformDelegatedConstructorCall(delegatedConstructorCall, data)
}
}
@@ -325,18 +334,19 @@ private abstract class FirLazyBodiesCalculatorTransformer : FirTransformer<Persi
override fun transformField(field: FirField, data: PersistentList<FirRegularClass>): FirStatement {
if (field.initializer is FirLazyExpression) {
val designation = FirDesignation(data, field)
FirLazyBodiesCalculator.calculateLazyBodiesForField(designation)
calculateLazyBodiesForField(designation)
}
return field
}
override fun transformSimpleFunction(
simpleFunction: FirSimpleFunction,
data: PersistentList<FirRegularClass>
data: PersistentList<FirRegularClass>,
): FirSimpleFunction {
if (FirLazyBodiesCalculator.needCalculatingLazyBodyForFunction(simpleFunction)) {
if (needCalculatingLazyBodyForFunction(simpleFunction)) {
val designation = FirDesignation(data, simpleFunction)
FirLazyBodiesCalculator.calculateLazyBodiesForFunction(designation)
calculateLazyBodiesForFunction(designation)
}
return simpleFunction
@@ -344,20 +354,20 @@ private abstract class FirLazyBodiesCalculatorTransformer : FirTransformer<Persi
override fun transformConstructor(
constructor: FirConstructor,
data: PersistentList<FirRegularClass>
data: PersistentList<FirRegularClass>,
): FirConstructor {
if (FirLazyBodiesCalculator.needCalculatingLazyBodyForConstructor(constructor)) {
if (needCalculatingLazyBodyForConstructor(constructor)) {
val designation = FirDesignation(data, constructor)
FirLazyBodiesCalculator.calculateLazyBodyForConstructor(designation)
calculateLazyBodyForConstructor(designation)
}
return constructor
}
override fun transformProperty(property: FirProperty, data: PersistentList<FirRegularClass>): FirProperty {
if (FirLazyBodiesCalculator.needCalculatingLazyBodyForProperty(property)) {
if (needCalculatingLazyBodyForProperty(property)) {
val designation = FirDesignation(data, property)
FirLazyBodiesCalculator.calculateLazyBodyForProperty(designation)
calculateLazyBodyForProperty(designation)
}
return property
@@ -370,18 +380,18 @@ private abstract class FirLazyBodiesCalculatorTransformer : FirTransformer<Persi
override fun transformEnumEntry(enumEntry: FirEnumEntry, data: PersistentList<FirRegularClass>): FirStatement {
if (enumEntry.initializer is FirLazyExpression) {
val designation = FirDesignation(data, enumEntry)
FirLazyBodiesCalculator.calculateLazyInitializerForEnumEntry(designation)
calculateLazyInitializerForEnumEntry(designation)
}
return enumEntry
}
override fun transformAnonymousInitializer(
anonymousInitializer: FirAnonymousInitializer, data: PersistentList<FirRegularClass>
anonymousInitializer: FirAnonymousInitializer, data: PersistentList<FirRegularClass>,
): FirAnonymousInitializer {
if (anonymousInitializer.body is FirLazyBlock) {
val designation = FirDesignation(data, anonymousInitializer)
FirLazyBodiesCalculator.calculateLazyBodyForAnonymousInitializer(designation)
calculateLazyBodyForAnonymousInitializer(designation)
}
return anonymousInitializer