diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/ContextCollector.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/ContextCollector.kt index ab8e63d8dbd..2eb31a8ca51 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/ContextCollector.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/ContextCollector.kt @@ -460,6 +460,35 @@ private class ContextCollectorVisitor( } } + /** + * We visit fields to properly handle supertypes delegation: + * + * ```kt + * class Foo : Bar by baz + * ``` + * + * In the code above, `baz` expression is saved into a separate synthetic field. + * It's not accessible from the delegated constructor, it's just added to the + * `Foo` class body. + */ + override fun visitField(field: FirField) = withProcessor { + dumpContext(field, ContextKind.SELF) + + processSignatureAnnotations(field) + + onActiveBody { + field.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE) + + context.withField(field) { + dumpContext(field, ContextKind.BODY) + + onActive { + process(field.initializer) + } + } + } + } + override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor) = withProcessor { dumpContext(propertyAccessor, ContextKind.SELF) diff --git a/analysis/low-level-api-fir/testdata/contextCollector/propertyDelegateInitializer.kt b/analysis/low-level-api-fir/testdata/contextCollector/propertyDelegateInitializer.kt new file mode 100644 index 00000000000..1ef1124e1eb --- /dev/null +++ b/analysis/low-level-api-fir/testdata/contextCollector/propertyDelegateInitializer.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2023 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 test + +interface MyInterface { + operator fun getValue(thisRef: Any, property: Any): MyInterface +} + +class Foo(constructorParam: MyInterface) { + val regularProperty: MyInterface + + val property: MyInterface by constructorParam +} \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/contextCollector/propertyDelegateInitializer.txt b/analysis/low-level-api-fir/testdata/contextCollector/propertyDelegateInitializer.txt new file mode 100644 index 00000000000..0743979e4cb --- /dev/null +++ b/analysis/low-level-api-fir/testdata/contextCollector/propertyDelegateInitializer.txt @@ -0,0 +1,43 @@ +Tower Data Context: + Element 0 + Scope: FirDefaultStarImportingScope + Element 1 + Scope: FirDefaultSimpleImportingScope + Element 2 + Scope: FirExplicitStarImportingScope + Element 3 + Scope: FirDefaultSimpleImportingScope + Element 4 + Scope: FirDefaultSimpleImportingScope + Element 5 + Scope: FirPackageMemberScope + Element 6 + Scope: FirExplicitSimpleImportingScope + Element 7 + Implicit receiver: + FirRegularClassSymbol public final class Foo : R|kotlin/Any| + Type: test/Foo + Element 8 + Scope: FirLocalScope + Properties: + FirValueParameterSymbol constructorParam: R|test/MyInterface| + +FILE: [ResolvedTo(IMPORTS)] propertyDelegateInitializer.kt + public abstract [ResolvedTo(STATUS)] interface MyInterface : R|kotlin/Any| { + public abstract operator [ResolvedTo(CONTRACTS)] fun getValue([ResolvedTo(CONTRACTS)] thisRef: R|kotlin/Any|, [ResolvedTo(CONTRACTS)] property: R|kotlin/Any|): R|test/MyInterface| + + } + public final [ResolvedTo(STATUS)] class Foo : R|kotlin/Any| { + public [ResolvedTo(STATUS)] constructor([ResolvedTo(STATUS)] constructorParam: R|test/MyInterface|): R|test/Foo| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] val regularProperty: R|test/MyInterface| + public [ResolvedTo(STATUS)] get(): R|test/MyInterface| + + public final [ResolvedTo(BODY_RESOLVE)] val property: R|test/MyInterface|by R|/constructorParam| + public [ResolvedTo(BODY_RESOLVE)] get(): R|test/MyInterface| { + ^ this@R|test/Foo|.D|test/Foo.property|.R|test/MyInterface.getValue|(this@R|test/Foo|, ::R|test/Foo.property|) + } + + } diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/ContextCollectorSourceTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/ContextCollectorSourceTestGenerated.java index 192562e60a1..484d9976d8d 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/ContextCollectorSourceTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/ContextCollectorSourceTestGenerated.java @@ -90,6 +90,12 @@ public class ContextCollectorSourceTestGenerated extends AbstractContextCollecto runTest("analysis/low-level-api-fir/testdata/contextCollector/primaryConstructorParameter.kt"); } + @Test + @TestMetadata("propertyDelegateInitializer.kt") + public void testPropertyDelegateInitializer() throws Exception { + runTest("analysis/low-level-api-fir/testdata/contextCollector/propertyDelegateInitializer.kt"); + } + @Test @TestMetadata("simple.kt") public void testSimple() throws Exception {