From 3f2c86afb807efb3146048023d596808222a6963 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Wed, 20 Oct 2021 16:20:14 -0700 Subject: [PATCH] FIR IDE/LC: introduce/use delegated member scope --- .../components/KtFe10ScopeProvider.kt | 15 +++++++- .../api/fir/components/KtFirScopeProvider.kt | 23 +++++++++++ .../fir/scopes/KtFirDelegatedMemberScope.kt | 30 +++++++++++++++ .../api/fir/scopes/KtFirEmptyMemberScope.kt | 7 +++- .../AbstractFirDelegateMemberScopeTest.kt | 11 ++++++ .../FirDelegateMemberScopeTestGenerated.java | 38 +++++++++++++++++++ .../scopes/AbstractDelegateMemberScopeTest.kt | 28 ++++++++++++++ .../test/scopes/AbstractMemberScopeTest.kt | 7 +++- .../api/components/KtScopeProvider.kt | 11 +++++- .../kotlin/analysis/api/scopes/KtScope.kt | 6 ++- .../scopes/delegatedMemberScope/simple.kt | 12 ++++++ .../scopes/delegatedMemberScope/simple.txt | 24 ++++++++++++ .../delegatedMemberScope/withOverridden.kt | 27 +++++++++++++ .../delegatedMemberScope/withOverridden.txt | 24 ++++++++++++ .../symbol/classes/FirLightClassForSymbol.kt | 7 +--- .../fir/scopes/FirKotlinScopeProvider.kt | 7 +--- .../declarations/utils/FirDeclarationUtil.kt | 3 ++ .../analysis/api/GenerateAnalysisApiTests.kt | 11 ++++-- 18 files changed, 271 insertions(+), 20 deletions(-) create mode 100644 analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/KtFirDelegatedMemberScope.kt create mode 100644 analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/scopes/AbstractFirDelegateMemberScopeTest.kt create mode 100644 analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/scopes/FirDelegateMemberScopeTestGenerated.java create mode 100644 analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/scopes/AbstractDelegateMemberScopeTest.kt create mode 100644 analysis/analysis-api/testData/scopes/delegatedMemberScope/simple.kt create mode 100644 analysis/analysis-api/testData/scopes/delegatedMemberScope/simple.txt create mode 100644 analysis/analysis-api/testData/scopes/delegatedMemberScope/withOverridden.kt create mode 100644 analysis/analysis-api/testData/scopes/delegatedMemberScope/withOverridden.txt diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10ScopeProvider.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10ScopeProvider.kt index d9a3579c725..b19707b3793 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10ScopeProvider.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10ScopeProvider.kt @@ -66,11 +66,24 @@ internal class KtFe10ScopeProvider(override val analysisSession: KtFe10AnalysisS override val owner get() = classSymbol } + // TODO: need to return declared members only return object : KtFe10ScopeMember(descriptor.unsubstitutedMemberScope, analysisSession), KtDeclaredMemberScope { override val owner get() = classSymbol } } + override fun getDelegatedMemberScope(classSymbol: KtSymbolWithMembers): KtDelegatedMemberScope = withValidityAssertion { + val descriptor = getDescriptor(classSymbol) + ?: return object : KtFe10EmptyScope(token), KtDelegatedMemberScope { + override val owner get() = classSymbol + } + + // TODO: need to return delegated members only + return object : KtFe10ScopeMember(descriptor.unsubstitutedMemberScope, analysisSession), KtDelegatedMemberScope { + override val owner get() = classSymbol + } + } + override fun getStaticMemberScope(symbol: KtSymbolWithMembers): KtScope = withValidityAssertion { val descriptor = getDescriptor(symbol) ?: return KtFe10EmptyScope(token) return KtFe10ScopeMember(descriptor.staticScope, analysisSession) @@ -147,4 +160,4 @@ internal class KtFe10ScopeProvider(override val analysisSession: KtFe10AnalysisS return result } -} \ No newline at end of file +} diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirScopeProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirScopeProvider.kt index 13ddd7191a1..1324d201776 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirScopeProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirScopeProvider.kt @@ -37,6 +37,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithMembers import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.analysis.api.withValidityAssertion +import org.jetbrains.kotlin.fir.declarations.utils.delegateFields import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile import java.util.* @@ -54,6 +55,7 @@ internal class KtFirScopeProvider( private val memberScopeCache = IdentityHashMap() private val declaredMemberScopeCache = IdentityHashMap() + private val delegatedMemberScopeCache = IdentityHashMap() private val fileScopeCache = IdentityHashMap>() private val packageMemberScopeCache = IdentityHashMap() @@ -101,6 +103,27 @@ internal class KtFirScopeProvider( } } + override fun getDelegatedMemberScope(classSymbol: KtSymbolWithMembers): KtDelegatedMemberScope = withValidityAssertion { + val declaredScope = (getDeclaredMemberScope(classSymbol) as? KtFirDeclaredMemberScope)?.firScope + ?: return delegatedMemberScopeCache.getOrPut(classSymbol) { KtFirEmptyMemberScope(classSymbol) } + delegatedMemberScopeCache.getOrPut(classSymbol) { + val firScope = classSymbol.withFirForScope { fir -> + val delegateFields = fir.delegateFields + if (delegateFields.isNotEmpty()) { + FirDelegatedMemberScope( + analysisSession.rootModuleSession, + ScopeSession(), + fir, + declaredScope, + delegateFields + ) + } else null + } ?: return@getOrPut KtFirEmptyMemberScope(classSymbol) + + KtFirDelegatedMemberScope(classSymbol, firScope, token, builder) + } + } + override fun getFileScope(fileSymbol: KtFileSymbol): KtDeclarationScope = withValidityAssertion { fileScopeCache.getOrPut(fileSymbol) { check(fileSymbol is KtFirFileSymbol) { "KtFirScopeProvider can only work with KtFirFileSymbol, but ${fileSymbol::class} was provided" } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/KtFirDelegatedMemberScope.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/KtFirDelegatedMemberScope.kt new file mode 100644 index 00000000000..56d7b77b946 --- /dev/null +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/KtFirDelegatedMemberScope.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2021 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 org.jetbrains.kotlin.analysis.api.fir.scopes + +import org.jetbrains.kotlin.analysis.api.ValidityTokenOwner +import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder +import org.jetbrains.kotlin.analysis.api.scopes.KtDelegatedMemberScope +import org.jetbrains.kotlin.analysis.api.scopes.KtScopeNameFilter +import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin +import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithMembers +import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken +import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope + +internal class KtFirDelegatedMemberScope( + override val owner: KtSymbolWithMembers, + override val firScope: FirContainingNamesAwareScope, + token: ValidityToken, + builder: KtSymbolByFirBuilder +) : KtFirDelegatingScope(builder, token), + KtDelegatedMemberScope, + ValidityTokenOwner { + + override fun getCallableSymbols(nameFilter: KtScopeNameFilter): Sequence { + return super.getCallableSymbols(nameFilter).filter { it.origin == KtSymbolOrigin.DELEGATED } + } +} diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/KtFirEmptyMemberScope.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/KtFirEmptyMemberScope.kt index 81bba9df9a0..17e980e8fd3 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/KtFirEmptyMemberScope.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/KtFirEmptyMemberScope.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.analysis.api.fir.scopes import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken import org.jetbrains.kotlin.analysis.api.ValidityTokenOwner import org.jetbrains.kotlin.analysis.api.scopes.KtDeclaredMemberScope +import org.jetbrains.kotlin.analysis.api.scopes.KtDelegatedMemberScope import org.jetbrains.kotlin.analysis.api.scopes.KtMemberScope import org.jetbrains.kotlin.analysis.api.scopes.KtScopeNameFilter import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol @@ -16,7 +17,9 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtConstructorSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithMembers import org.jetbrains.kotlin.name.Name -internal class KtFirEmptyMemberScope(override val owner: KtSymbolWithMembers) : KtMemberScope, KtDeclaredMemberScope, ValidityTokenOwner { +internal class KtFirEmptyMemberScope( + override val owner: KtSymbolWithMembers +) : KtMemberScope, KtDeclaredMemberScope, KtDelegatedMemberScope, ValidityTokenOwner { override fun getPossibleCallableNames(): Set = emptySet() override fun getPossibleClassifierNames(): Set = emptySet() @@ -34,4 +37,4 @@ internal class KtFirEmptyMemberScope(override val owner: KtSymbolWithMembers) : override val token: ValidityToken get() = owner.token -} \ No newline at end of file +} diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/scopes/AbstractFirDelegateMemberScopeTest.kt b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/scopes/AbstractFirDelegateMemberScopeTest.kt new file mode 100644 index 00000000000..88b7ee5395d --- /dev/null +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/scopes/AbstractFirDelegateMemberScopeTest.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2010-2021 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 org.jetbrains.kotlin.analysis.api.fir.scopes + +import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService +import org.jetbrains.kotlin.analysis.api.impl.base.test.scopes.AbstractDelegateMemberScopeTest + +abstract class AbstractFirDelegateMemberScopeTest : AbstractDelegateMemberScopeTest(FirFrontendApiTestConfiguratorService) diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/scopes/FirDelegateMemberScopeTestGenerated.java b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/scopes/FirDelegateMemberScopeTestGenerated.java new file mode 100644 index 00000000000..f08ddbc3e3e --- /dev/null +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/scopes/FirDelegateMemberScopeTestGenerated.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2021 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 org.jetbrains.kotlin.analysis.api.fir.scopes; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link GenerateNewCompilerTests.kt}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("analysis/analysis-api/testData/scopes/delegatedMemberScope") +@TestDataPath("$PROJECT_ROOT") +public class FirDelegateMemberScopeTestGenerated extends AbstractFirDelegateMemberScopeTest { + @Test + public void testAllFilesPresentInDelegatedMemberScope() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/scopes/delegatedMemberScope"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("analysis/analysis-api/testData/scopes/delegatedMemberScope/simple.kt"); + } + + @Test + @TestMetadata("withOverridden.kt") + public void testWithOverridden() throws Exception { + runTest("analysis/analysis-api/testData/scopes/delegatedMemberScope/withOverridden.kt"); + } +} diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/scopes/AbstractDelegateMemberScopeTest.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/scopes/AbstractDelegateMemberScopeTest.kt new file mode 100644 index 00000000000..03e9b3490b8 --- /dev/null +++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/scopes/AbstractDelegateMemberScopeTest.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2021 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 org.jetbrains.kotlin.analysis.api.impl.base.test.scopes + +import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService +import org.jetbrains.kotlin.analysis.api.impl.base.test.SymbolByFqName +import org.jetbrains.kotlin.analysis.api.impl.base.test.symbols.AbstractSymbolByFqNameTest +import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.test.services.TestServices + +abstract class AbstractDelegateMemberScopeTest( + configurator: FrontendApiTestConfiguratorService +) : AbstractSymbolByFqNameTest(configurator) { + + override fun KtAnalysisSession.collectSymbols(ktFile: KtFile, testServices: TestServices): List { + val symbolData = SymbolByFqName.getSymbolDataFromFile(testDataPath) + val symbols = with(symbolData) { toSymbols() } + val classSymbol = symbols.singleOrNull() as? KtClassOrObjectSymbol + ?: error("Should be a single class symbol, but $symbols found") + return classSymbol.getDelegatedMemberScope().getCallableSymbols().toList() + } +} diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/scopes/AbstractMemberScopeTest.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/scopes/AbstractMemberScopeTest.kt index c873895dae1..ea39203f514 100644 --- a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/scopes/AbstractMemberScopeTest.kt +++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/scopes/AbstractMemberScopeTest.kt @@ -14,7 +14,10 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.services.TestServices -abstract class AbstractMemberScopeByFqNameTest(configurator: FrontendApiTestConfiguratorService) : AbstractSymbolByFqNameTest(configurator) { +abstract class AbstractMemberScopeByFqNameTest( + configurator: FrontendApiTestConfiguratorService +) : AbstractSymbolByFqNameTest(configurator) { + override fun KtAnalysisSession.collectSymbols(ktFile: KtFile, testServices: TestServices): List { val symbolData = SymbolByFqName.getSymbolDataFromFile(testDataPath) val symbols = with(symbolData) { toSymbols() } @@ -22,4 +25,4 @@ abstract class AbstractMemberScopeByFqNameTest(configurator: FrontendApiTestConf ?: error("Should be a single class symbol, but $symbols found") return classSymbol.getMemberScope().getAllSymbols().toList() } -} \ No newline at end of file +} diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtScopeProvider.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtScopeProvider.kt index 1b311a85a24..41b41ce9fae 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtScopeProvider.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtScopeProvider.kt @@ -19,11 +19,17 @@ import org.jetbrains.kotlin.psi.KtFile public abstract class KtScopeProvider : KtAnalysisSessionComponent() { public abstract fun getMemberScope(classSymbol: KtSymbolWithMembers): KtMemberScope - public abstract fun getStaticMemberScope(symbol: KtSymbolWithMembers): KtScope public abstract fun getDeclaredMemberScope(classSymbol: KtSymbolWithMembers): KtDeclaredMemberScope + + public abstract fun getDelegatedMemberScope(classSymbol: KtSymbolWithMembers): KtDelegatedMemberScope + + public abstract fun getStaticMemberScope(symbol: KtSymbolWithMembers): KtScope + public abstract fun getFileScope(fileSymbol: KtFileSymbol): KtDeclarationScope + public abstract fun getPackageScope(packageSymbol: KtPackageSymbol): KtPackageScope + public abstract fun getCompositeScope(subScopes: List): KtCompositeScope public abstract fun getTypeScope(type: KtType): KtScope? @@ -41,6 +47,9 @@ public interface KtScopeProviderMixIn : KtAnalysisSessionMixIn { public fun KtSymbolWithMembers.getDeclaredMemberScope(): KtDeclaredMemberScope = analysisSession.scopeProvider.getDeclaredMemberScope(this) + public fun KtSymbolWithMembers.getDelegatedMemberScope(): KtDelegatedMemberScope = + analysisSession.scopeProvider.getDelegatedMemberScope(this) + public fun KtSymbolWithMembers.getStaticMemberScope(): KtScope = analysisSession.scopeProvider.getStaticMemberScope(this) diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/scopes/KtScope.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/scopes/KtScope.kt index 3ccaaa21d74..c66c7500f73 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/scopes/KtScope.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/scopes/KtScope.kt @@ -86,6 +86,10 @@ public interface KtDeclaredMemberScope : KtDeclarationScope override val owner: KtSymbolWithMembers } +public interface KtDelegatedMemberScope : KtDeclarationScope { + override val owner: KtSymbolWithMembers +} + public interface KtDeclarationScope : KtScope { public val owner: T } @@ -100,4 +104,4 @@ public interface KtPackageScope : KtScope { } override fun getConstructors(): Sequence = withValidityAssertion { emptySequence() } -} \ No newline at end of file +} diff --git a/analysis/analysis-api/testData/scopes/delegatedMemberScope/simple.kt b/analysis/analysis-api/testData/scopes/delegatedMemberScope/simple.kt new file mode 100644 index 00000000000..d0e79564be0 --- /dev/null +++ b/analysis/analysis-api/testData/scopes/delegatedMemberScope/simple.kt @@ -0,0 +1,12 @@ +// DO_NOT_CHECK_SYMBOL_RESTORE + +interface I { + fun foo() +} + +class A( + private val p: I +) : I by p + +// class: A + diff --git a/analysis/analysis-api/testData/scopes/delegatedMemberScope/simple.txt b/analysis/analysis-api/testData/scopes/delegatedMemberScope/simple.txt new file mode 100644 index 00000000000..b29dc4edaee --- /dev/null +++ b/analysis/analysis-api/testData/scopes/delegatedMemberScope/simple.txt @@ -0,0 +1,24 @@ +KtFunctionSymbol: + annotatedType: [] kotlin/Unit + annotationClassIds: [] + annotations: [] + callableIdIfNonLocal: /I.foo + dispatchType: A + hasStableParameterNames: true + isExtension: false + isExternal: false + isInfix: false + isInline: false + isOperator: false + isOverride: false + isStatic: false + isSuspend: false + modality: OPEN + name: foo + origin: DELEGATED + receiverType: null + symbolKind: CLASS_MEMBER + typeParameters: [] + valueParameters: [] + visibility: Public + deprecationStatus: null diff --git a/analysis/analysis-api/testData/scopes/delegatedMemberScope/withOverridden.kt b/analysis/analysis-api/testData/scopes/delegatedMemberScope/withOverridden.kt new file mode 100644 index 00000000000..54fa53d376c --- /dev/null +++ b/analysis/analysis-api/testData/scopes/delegatedMemberScope/withOverridden.kt @@ -0,0 +1,27 @@ +// DO_NOT_CHECK_SYMBOL_RESTORE + +interface I1 { + fun foo() +} + +class I1Impl: I1 { + override fun foo() {} +} + +interface I2 { + fun bar() + fun baz() +} + +class I2Impl: I2 { + override fun bar() {} + override fun baz() {} +} + +open class A : I1 by I1Impl() + +class B : I2 by I2Impl(), A() { + override fun baz() {} +} + +// class: B diff --git a/analysis/analysis-api/testData/scopes/delegatedMemberScope/withOverridden.txt b/analysis/analysis-api/testData/scopes/delegatedMemberScope/withOverridden.txt new file mode 100644 index 00000000000..f8efd7f4906 --- /dev/null +++ b/analysis/analysis-api/testData/scopes/delegatedMemberScope/withOverridden.txt @@ -0,0 +1,24 @@ +KtFunctionSymbol: + annotatedType: [] kotlin/Unit + annotationClassIds: [] + annotations: [] + callableIdIfNonLocal: /I2.bar + dispatchType: B + hasStableParameterNames: true + isExtension: false + isExternal: false + isInfix: false + isInline: false + isOperator: false + isOverride: false + isStatic: false + isSuspend: false + modality: OPEN + name: bar + origin: DELEGATED + receiverType: null + symbolKind: CLASS_MEMBER + typeParameters: [] + valueParameters: [] + visibility: Public + deprecationStatus: null diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassForSymbol.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassForSymbol.kt index 1cef63b28d4..5a3b21980f6 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassForSymbol.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassForSymbol.kt @@ -204,11 +204,8 @@ internal class FirLightClassForSymbol( } analyzeWithSymbolAsContext(classOrObjectSymbol) { - // NB: delegated members are not available at _declared_ member scope. - // Thus, use member scope to get "all" callable members, including members from (interface) supertypes, - // and accept fake overrides with delegated origin to create delegate methods. - classOrObjectSymbol.getMemberScope().getCallableSymbols().forEach { functionSymbol -> - if (functionSymbol is KtFunctionSymbol && functionSymbol.origin == KtSymbolOrigin.DELEGATED) { + classOrObjectSymbol.getDelegatedMemberScope().getCallableSymbols().forEach { functionSymbol -> + if (functionSymbol is KtFunctionSymbol) { createDelegateMethod(functionSymbol) } } diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirKotlinScopeProvider.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirKotlinScopeProvider.kt index 627248b2209..16ba49de92d 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirKotlinScopeProvider.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FirKotlinScopeProvider.kt @@ -9,10 +9,9 @@ import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSessionComponent import org.jetbrains.kotlin.fir.declarations.FirClass -import org.jetbrains.kotlin.fir.declarations.FirField import org.jetbrains.kotlin.fir.declarations.FirRegularClass +import org.jetbrains.kotlin.fir.declarations.utils.delegateFields import org.jetbrains.kotlin.fir.declarations.utils.isExpect -import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap @@ -40,17 +39,15 @@ class FirKotlinScopeProvider( return scopeSession.getOrBuild(klass.symbol, USE_SITE) { val declaredScope = useSiteSession.declaredMemberScope(klass) - val delegateFields = klass.declarations.filterIsInstance().filter { it.isSynthetic } - val decoratedDeclaredMemberScope = declaredMemberScopeDecorator(klass, declaredScope, useSiteSession, scopeSession).let { + val delegateFields = klass.delegateFields if (delegateFields.isEmpty()) it else FirDelegatedMemberScope(useSiteSession, scopeSession, klass, it, delegateFields) } - val scopes = lookupSuperTypes( klass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession, substituteTypes = true ).mapNotNull { useSiteSuperType -> diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/utils/FirDeclarationUtil.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/utils/FirDeclarationUtil.kt index 38c91b999af..468551dfb1f 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/utils/FirDeclarationUtil.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/utils/FirDeclarationUtil.kt @@ -34,6 +34,9 @@ val FirClass.superConeTypes: List get() = superTypeRefs.mapNo val FirClass.anonymousInitializers: List get() = declarations.filterIsInstance() +val FirClass.delegateFields: List + get() = declarations.filterIsInstance().filter { it.isSynthetic } + val FirQualifiedAccess.referredPropertySymbol: FirPropertySymbol? get() { val reference = calleeReference as? FirResolvedNamedReference ?: return null diff --git a/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/GenerateAnalysisApiTests.kt b/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/GenerateAnalysisApiTests.kt index d28a5b8fc7e..23c93382d59 100644 --- a/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/GenerateAnalysisApiTests.kt +++ b/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/GenerateAnalysisApiTests.kt @@ -15,6 +15,9 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostic.compiler.based import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.AbstractFileStructureTest import org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.AbstractInnerDeclarationsResolvePhaseTest import org.jetbrains.kotlin.generators.util.TestGeneratorUtil +import org.jetbrains.kotlin.analysis.api.descriptors.test.components.* +import org.jetbrains.kotlin.analysis.api.descriptors.test.symbols.AbstractKtFe10SymbolByFqNameTest +import org.jetbrains.kotlin.analysis.api.descriptors.test.symbols.AbstractKtFe10SymbolByReferenceTest import org.jetbrains.kotlin.analysis.api.fir.components.AbstractFirExpectedExpressionTypeTest import org.jetbrains.kotlin.analysis.api.fir.components.AbstractFirHLExpressionTypeTest import org.jetbrains.kotlin.analysis.api.fir.components.AbstractFirOverriddenDeclarationProviderTest @@ -24,9 +27,7 @@ import org.jetbrains.kotlin.analysis.api.fir.scopes.AbstractFirMemberScopeByFqNa import org.jetbrains.kotlin.analysis.api.fir.symbols.AbstractFirSymbolByFqNameTest import org.jetbrains.kotlin.analysis.api.fir.symbols.AbstractFirSymbolByPsiTest import org.jetbrains.kotlin.analysis.api.fir.symbols.AbstractFirSymbolByReferenceTest -import org.jetbrains.kotlin.analysis.api.descriptors.test.components.* -import org.jetbrains.kotlin.analysis.api.descriptors.test.symbols.AbstractKtFe10SymbolByFqNameTest -import org.jetbrains.kotlin.analysis.api.descriptors.test.symbols.AbstractKtFe10SymbolByReferenceTest +import org.jetbrains.kotlin.analysis.api.fir.scopes.AbstractFirDelegateMemberScopeTest import org.jetbrains.kotlin.spec.utils.GeneralConfiguration import org.jetbrains.kotlin.spec.utils.tasks.detectDirsWithTestsMapFileOnly import org.jetbrains.kotlin.generators.generateTestGroupSuiteWithJUnit5 @@ -52,6 +53,10 @@ fun main(args: Array) { model("scopes/fileScopeTest", extension = "kt") } + testClass { + model("scopes/delegatedMemberScope") + } + testClass { model("symbols/symbolByPsi") }