From 971e551bae3a4db8c026e4357eaf1510dd76c062 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Thu, 8 Oct 2020 21:20:47 +0300 Subject: [PATCH] FIR IDE: implement lazy delegate initializers --- .../kotlin/fir/builder/RawFirBuilder.kt | 9 +++- .../FirLambdaArgumentExpression.kt | 2 + .../expressions/FirNamedArgumentExpression.kt | 2 + .../FirSpreadArgumentExpression.kt | 2 + .../FirWrappedArgumentExpression.kt | 2 + .../FirWrappedDelegateExpression.kt | 2 + .../fir/expressions/FirWrappedExpression.kt | 2 + .../impl/FirLambdaArgumentExpressionImpl.kt | 4 ++ .../impl/FirNamedArgumentExpressionImpl.kt | 4 ++ .../impl/FirSpreadArgumentExpressionImpl.kt | 4 ++ .../impl/FirWrappedDelegateExpressionImpl.kt | 4 ++ .../fir/tree/generator/NodeConfigurator.kt | 2 +- .../lazy/resolve/FirLazyBodiesCalculator.kt | 8 ++++ .../testdata/lazyResolve/delegates.kt | 23 ++++++++++ .../testdata/lazyResolve/delegates.txt | 45 +++++++++++++++++++ .../AbstractFirLazyDeclarationResolveTest.kt | 4 ++ ...irLazyDeclarationResolveTestGenerated.java | 5 +++ 17 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/delegates.kt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/delegates.txt diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 60e9522d260..7fd8158136e 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -1246,7 +1246,14 @@ class RawFirBuilder( FirWrappedDelegateExpressionBuilder().apply { source = if (stubMode) null else delegateExpression?.toFirSourceElement(FirFakeSourceElementKind.WrappedDelegate) - expression = { delegateExpression }.toFirExpression("Should have delegate") + expression = when (mode) { + RawFirBuilderMode.NORMAL -> delegateExpression.toFirExpression("Should have delegate") + RawFirBuilderMode.STUBS -> buildExpressionStub() + RawFirBuilderMode.LAZY_BODIES -> buildLazyExpression { + source = delegateExpression!!.toFirSourceElement() + } + } + } } else null diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirLambdaArgumentExpression.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirLambdaArgumentExpression.kt index 8321ad3989f..d718b29c034 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirLambdaArgumentExpression.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirLambdaArgumentExpression.kt @@ -25,5 +25,7 @@ abstract class FirLambdaArgumentExpression : FirWrappedArgumentExpression() { abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) + abstract override fun replaceExpression(newExpression: FirExpression) + abstract override fun transformAnnotations(transformer: FirTransformer, data: D): FirLambdaArgumentExpression } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirNamedArgumentExpression.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirNamedArgumentExpression.kt index 7a46bc94b11..13f3457544b 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirNamedArgumentExpression.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirNamedArgumentExpression.kt @@ -27,5 +27,7 @@ abstract class FirNamedArgumentExpression : FirWrappedArgumentExpression() { abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) + abstract override fun replaceExpression(newExpression: FirExpression) + abstract override fun transformAnnotations(transformer: FirTransformer, data: D): FirNamedArgumentExpression } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirSpreadArgumentExpression.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirSpreadArgumentExpression.kt index ac8b77473bc..d46c25e0095 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirSpreadArgumentExpression.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirSpreadArgumentExpression.kt @@ -25,5 +25,7 @@ abstract class FirSpreadArgumentExpression : FirWrappedArgumentExpression() { abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) + abstract override fun replaceExpression(newExpression: FirExpression) + abstract override fun transformAnnotations(transformer: FirTransformer, data: D): FirSpreadArgumentExpression } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWrappedArgumentExpression.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWrappedArgumentExpression.kt index c5fc599b8ce..e11a6a35ecc 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWrappedArgumentExpression.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWrappedArgumentExpression.kt @@ -25,5 +25,7 @@ abstract class FirWrappedArgumentExpression : FirWrappedExpression() { abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) + abstract override fun replaceExpression(newExpression: FirExpression) + abstract override fun transformAnnotations(transformer: FirTransformer, data: D): FirWrappedArgumentExpression } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWrappedDelegateExpression.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWrappedDelegateExpression.kt index 65d5ab3cca2..52cdf4402d9 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWrappedDelegateExpression.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWrappedDelegateExpression.kt @@ -25,5 +25,7 @@ abstract class FirWrappedDelegateExpression : FirWrappedExpression() { abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) + abstract override fun replaceExpression(newExpression: FirExpression) + abstract override fun transformAnnotations(transformer: FirTransformer, data: D): FirWrappedDelegateExpression } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWrappedExpression.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWrappedExpression.kt index f13c0d6e158..23f5c8859ce 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWrappedExpression.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWrappedExpression.kt @@ -24,5 +24,7 @@ abstract class FirWrappedExpression : FirExpression() { abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) + abstract fun replaceExpression(newExpression: FirExpression) + abstract override fun transformAnnotations(transformer: FirTransformer, data: D): FirWrappedExpression } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirLambdaArgumentExpressionImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirLambdaArgumentExpressionImpl.kt index 6aaf5100715..e830279a84c 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirLambdaArgumentExpressionImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirLambdaArgumentExpressionImpl.kt @@ -42,4 +42,8 @@ internal class FirLambdaArgumentExpressionImpl( } override fun replaceTypeRef(newTypeRef: FirTypeRef) {} + + override fun replaceExpression(newExpression: FirExpression) { + expression = newExpression + } } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirNamedArgumentExpressionImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirNamedArgumentExpressionImpl.kt index c3f947394f4..d6af2239c34 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirNamedArgumentExpressionImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirNamedArgumentExpressionImpl.kt @@ -44,4 +44,8 @@ internal class FirNamedArgumentExpressionImpl( } override fun replaceTypeRef(newTypeRef: FirTypeRef) {} + + override fun replaceExpression(newExpression: FirExpression) { + expression = newExpression + } } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirSpreadArgumentExpressionImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirSpreadArgumentExpressionImpl.kt index 3e9412ead14..45e053dbf8c 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirSpreadArgumentExpressionImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirSpreadArgumentExpressionImpl.kt @@ -42,4 +42,8 @@ internal class FirSpreadArgumentExpressionImpl( } override fun replaceTypeRef(newTypeRef: FirTypeRef) {} + + override fun replaceExpression(newExpression: FirExpression) { + expression = newExpression + } } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirWrappedDelegateExpressionImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirWrappedDelegateExpressionImpl.kt index 160cf351a23..e0a025b52a8 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirWrappedDelegateExpressionImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirWrappedDelegateExpressionImpl.kt @@ -44,4 +44,8 @@ internal class FirWrappedDelegateExpressionImpl( } override fun replaceTypeRef(newTypeRef: FirTypeRef) {} + + override fun replaceExpression(newExpression: FirExpression) { + expression = newExpression + } } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt index ac99a70324b..786c1d5ebb3 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt @@ -516,7 +516,7 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild } wrappedExpression.configure { - +field(expression) + +field(expression).withReplace() } wrappedDelegateExpression.configure { diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyBodiesCalculator.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyBodiesCalculator.kt index edf626f2451..d8279c8403a 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyBodiesCalculator.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyBodiesCalculator.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.builder.RawFirBuilder import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression import org.jetbrains.kotlin.fir.expressions.impl.FirLazyBlock import org.jetbrains.kotlin.fir.expressions.impl.FirLazyExpression import org.jetbrains.kotlin.fir.psi @@ -67,6 +68,12 @@ internal object FirLazyBodiesCalculator { if (firProperty.initializer is FirLazyExpression) { firProperty.replaceInitializer(newProperty.initializer) } + + val delegate = firProperty.delegate + if (delegate is FirWrappedDelegateExpression && delegate.expression is FirLazyExpression) { + val newDelegate = newProperty.delegate as FirWrappedDelegateExpression + delegate.replaceExpression(newDelegate.expression) + } } } @@ -74,6 +81,7 @@ internal object FirLazyBodiesCalculator { firProperty.getter?.body is FirLazyBlock || firProperty.setter?.body is FirLazyBlock || firProperty.initializer is FirLazyExpression + || (firProperty.delegate as? FirWrappedDelegateExpression)?.expression is FirLazyExpression private fun createRawFirBuilder(firDeclaration: FirDeclaration): RawFirBuilder { diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/delegates.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/delegates.kt new file mode 100644 index 00000000000..d102484706e --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/delegates.kt @@ -0,0 +1,23 @@ +import kotlin.properties.ReadWriteProperty +import kotlin.reflect.KProperty + +fun resolveMe() { + receive(valueWithExplicitType) + receive(valueWithImplicitType) + + variableWithExplicitType = 10 + variableWithImplicitType = 10 +} + +fun receive(value: Int){} + +val delegate = object: ReadWriteProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Int = 1 + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {} +} + +val valueWithExplicitType: Int by delegate +val valueWithImplicitType by delegate + +var variableWithExplicitType: Int by delegate +var variableWithImplicitType by delegate diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/delegates.txt b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/delegates.txt new file mode 100644 index 00000000000..8d6ef9a75e0 --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/delegates.txt @@ -0,0 +1,45 @@ +FILE: delegates.kt + public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| { + R|/receive|(R|/valueWithExplicitType|) + R|/receive|(R|/valueWithImplicitType|) + R|/variableWithExplicitType| = Int(10) + R|/variableWithImplicitType| = Int(10) + } + public final [STATUS] fun receive(value: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } + public final [IMPLICIT_TYPES_BODY_RESOLVE] val delegate: R|kotlin/properties/ReadWriteProperty| = object : R|kotlin/properties/ReadWriteProperty| { + private constructor(): R|| { + super() + } + + public final override [BODY_RESOLVE] fun getValue(thisRef: R|kotlin/Any?|, property: R|kotlin/reflect/KProperty<*>|): R|kotlin/Int| { + ^getValue Int(1) + } + + public final override [BODY_RESOLVE] fun setValue(thisRef: R|kotlin/Any?|, property: R|kotlin/reflect/KProperty<*>|, value: R|kotlin/Int|): R|kotlin/Unit| { + } + + } + + public get(): R|kotlin/properties/ReadWriteProperty| + public final [STATUS] val valueWithExplicitType: R|kotlin/Int|by LAZY_EXPRESSION + public get(): { + ^ D|/valueWithExplicitType|.getValue#(Null(null), ::R|/valueWithExplicitType|) + } + public final [IMPLICIT_TYPES_BODY_RESOLVE] val valueWithImplicitType: R|kotlin/Int|by R|/delegate| + public get(): R|kotlin/Int| { + ^ D|/valueWithImplicitType|.R|FakeOverride|(Null(null), ::R|/valueWithImplicitType|) + } + public final [STATUS] var variableWithExplicitType: R|kotlin/Int|by LAZY_EXPRESSION + public get(): { + ^ D|/variableWithExplicitType|.getValue#(Null(null), ::R|/variableWithExplicitType|) + } + public set(: ): R|kotlin/Unit| { + D|/variableWithExplicitType|.setValue#(Null(null), ::R|/variableWithExplicitType|, R|/variableWithExplicitType|) + } + public final [IMPLICIT_TYPES_BODY_RESOLVE] var variableWithImplicitType: R|kotlin/Int|by R|/delegate| + public get(): R|kotlin/Int| { + ^ D|/variableWithImplicitType|.R|FakeOverride|(Null(null), ::R|/variableWithImplicitType|) + } + public set(: R|kotlin/Int|): R|kotlin/Unit| { + D|/variableWithImplicitType|.R|FakeOverride|(Null(null), ::R|/variableWithImplicitType|, R|/variableWithImplicitType|) + } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/AbstractFirLazyDeclarationResolveTest.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/AbstractFirLazyDeclarationResolveTest.kt index 522eed89e4e..8afdc6e18a2 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/AbstractFirLazyDeclarationResolveTest.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/AbstractFirLazyDeclarationResolveTest.kt @@ -6,11 +6,13 @@ package org.jetbrains.kotlin.idea.fir.low.level.api import com.intellij.openapi.util.io.FileUtil +import com.intellij.testFramework.LightProjectDescriptor import org.jetbrains.kotlin.fir.FirRenderer import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.idea.fir.low.level.api.api.LowLevelFirApiFacade import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase +import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtPsiUtil @@ -44,4 +46,6 @@ abstract class AbstractFirLazyDeclarationResolveTest : KotlinLightCodeInsightFix KotlinTestUtils.assertEqualsToFile(testDataFile.parentFile.resolve(expectedFileName), rendered) } } + + override fun getProjectDescriptor(): LightProjectDescriptor = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE } \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/FirLazyDeclarationResolveTestGenerated.java b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/FirLazyDeclarationResolveTestGenerated.java index a48f359a3e0..5b91809221e 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/FirLazyDeclarationResolveTestGenerated.java +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/FirLazyDeclarationResolveTestGenerated.java @@ -33,6 +33,11 @@ public class FirLazyDeclarationResolveTestGenerated extends AbstractFirLazyDecla runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/classMembers.kt"); } + @TestMetadata("delegates.kt") + public void testDelegates() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/delegates.kt"); + } + @TestMetadata("propertyWithGetter.kt") public void testPropertyWithGetter() throws Exception { runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetter.kt");