[Analysis API] Allow handling scopes from KtScopeContext separately

^KT-55527
This commit is contained in:
aleksandrina-streltsova
2023-02-07 11:21:02 +02:00
committed by teamcity
parent d89d774411
commit 4b7164a557
27 changed files with 3481 additions and 41 deletions
@@ -6,9 +6,7 @@
package org.jetbrains.kotlin.analysis.api.fir.components
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.api.components.KtImplicitReceiver
import org.jetbrains.kotlin.analysis.api.components.KtScopeContext
import org.jetbrains.kotlin.analysis.api.components.KtScopeProvider
import org.jetbrains.kotlin.analysis.api.components.*
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.analysis.api.fir.scopes.*
@@ -28,6 +26,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtPackageSymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithMembers
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.errors.unexpectedElementError
import org.jetbrains.kotlin.analysis.utils.printer.getElementTextInContext
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClass
@@ -142,7 +141,7 @@ internal class KtFirScopeProvider(
}
override fun getFileScope(fileSymbol: KtFileSymbol): KtScope {
check(fileSymbol is KtFirFileSymbol) { "KtFirScopeProvider can only work with KtFirFileSymbol, but ${fileSymbol::class} was provided" }
check(fileSymbol is KtFirFileSymbol) { "KtFirScopeProvider can only work with KtFirFileSymbol, but ${fileSymbol::class} was provided" }
return KtFirFileScope(fileSymbol, builder)
}
@@ -178,31 +177,29 @@ internal class KtFirScopeProvider(
val towerDataContext =
analysisSession.firResolveSession.getTowerContextProvider(originalFile).getClosestAvailableParentContext(positionInFakeFile)
?: error("Cannot find enclosing declaration for ${positionInFakeFile.getElementTextInContext()}")
val towerDataElementsIndexed = towerDataContext.towerDataElements.asReversed().withIndex()
val implicitReceivers = towerDataContext.nonLocalTowerDataElements.mapNotNull { it.implicitReceiver }.distinct()
val implicitKtReceivers = implicitReceivers.map { receiver ->
KtImplicitReceiver(
token,
builder.typeBuilder.buildKtType(receiver.type),
builder.buildSymbol(receiver.boundSymbol.fir),
)
val implicitReceivers = towerDataElementsIndexed.flatMap { (index, towerDataElement) ->
val receivers = listOfNotNull(towerDataElement.implicitReceiver) + towerDataElement.contextReceiverGroup.orEmpty()
receivers.map { receiver ->
KtImplicitReceiver(
token,
builder.typeBuilder.buildKtType(receiver.type),
builder.buildSymbol(receiver.boundSymbol.fir),
index
)
}
}
val implicitReceiverScopes = implicitReceivers.mapNotNull { it.implicitScope }
val nonLocalScopes = towerDataContext.nonLocalTowerDataElements.mapNotNull { it.scope }.distinct()
val firLocalScopes = towerDataContext.localScopes
val allKtScopes = buildList<KtScope> {
implicitReceiverScopes.mapTo(this, ::convertToKtScope)
nonLocalScopes.mapTo(this, ::convertToKtScope)
firLocalScopes.mapTo(this, ::convertToKtScope)
val firScopes = towerDataElementsIndexed.flatMap { (index, towerDataElement) ->
towerDataElement.getAvailableScopes().map { IndexedValue(index, it) }
}
val scopes = firScopes.map { (index, firScope) ->
KtScopeWithKind(convertToKtScope(firScope), getScopeKind(firScope, index), token)
}
return KtScopeContext(
getCompositeScope(allKtScopes.asReversed()),
implicitKtReceivers.asReversed(),
token
)
return KtScopeContext(scopes, implicitReceivers, token)
}
private fun convertToKtScope(firScope: FirScope): KtScope {
@@ -215,6 +212,28 @@ internal class KtFirScopeProvider(
}
}
private fun getScopeKind(firScope: FirScope, indexInTower: Int): KtScopeKind = when (firScope) {
is FirNameAwareOnlyCallablesScope -> getScopeKind(firScope.delegate, indexInTower)
is FirNameAwareOnlyClassifiersScope -> getScopeKind(firScope.delegate, indexInTower)
is FirLocalScope -> KtScopeKind.LocalScope(indexInTower)
is FirTypeScope -> KtScopeKind.SimpleTypeScope(indexInTower)
is FirTypeParameterScope -> KtScopeKind.TypeParameterScope(indexInTower)
is FirPackageMemberScope -> KtScopeKind.PackageMemberScope(indexInTower)
is FirNestedClassifierScope -> KtScopeKind.StaticMemberScope(indexInTower)
is FirNestedClassifierScopeWithSubstitution -> KtScopeKind.StaticMemberScope(indexInTower)
is FirLazyNestedClassifierScope -> KtScopeKind.StaticMemberScope(indexInTower)
is FirStaticScope -> KtScopeKind.StaticMemberScope(indexInTower)
is FirExplicitSimpleImportingScope -> KtScopeKind.ExplicitSimpleImportingScope(indexInTower)
is FirExplicitStarImportingScope -> KtScopeKind.ExplicitStarImportingScope(indexInTower)
is FirDefaultSimpleImportingScope -> KtScopeKind.DefaultSimpleImportingScope(indexInTower)
is FirDefaultStarImportingScope -> KtScopeKind.DefaultStarImportingScope(indexInTower)
else -> unexpectedElementError("scope", firScope)
}
private fun createPackageScope(fqName: FqName): KtFirPackageScope {
return KtFirPackageScope(
fqName,
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithKind
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalDeclaration
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
@@ -113,5 +114,5 @@ internal class KtFirSymbolContainingDeclarationProvider(
when (val container = this.parentOfType<KtDeclaration>()) {
is KtDestructuringDeclaration -> container.parentOfType()
else -> container
}
}?.let { it.originalDeclaration ?: it }
}
@@ -50,7 +50,7 @@ internal object KDocReferenceResolver {
context(KtAnalysisSession)
private fun MutableCollection<KtSymbol>.collectSymbolsFromPositionScopes(owner: KtDeclaration, fqName: FqName) {
val initialScope = owner.containingKtFile.getScopeContextForPosition(owner).scopes
val initialScope = owner.containingKtFile.getScopeContextForPosition(owner).getCompositeScope()
val scope = fqName.pathSegments()
.dropLast(1)
@@ -0,0 +1,78 @@
/*
* 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 org.jetbrains.kotlin.analysis.api.fir.test.cases.generated.cases.scopes;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.analysis.api.fir.test.configurators.AnalysisApiFirTestConfiguratorFactory;
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfiguratorFactoryData;
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator;
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.TestModuleKind;
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind;
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisSessionMode;
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiMode;
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.scopes.AbstractScopeContextForPositionTest;
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 org.jetbrains.kotlin.generators.tests.analysis.api.GenerateAnalysisApiTestsKt}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition")
@TestDataPath("$PROJECT_ROOT")
public class FirIdeDependentAnalysisSourceModuleScopeContextForPositionTestGenerated extends AbstractScopeContextForPositionTest {
@NotNull
@Override
public AnalysisApiTestConfigurator getConfigurator() {
return AnalysisApiFirTestConfiguratorFactory.INSTANCE.createConfigurator(
new AnalysisApiTestConfiguratorFactoryData(
FrontendKind.Fir,
TestModuleKind.Source,
AnalysisSessionMode.Dependent,
AnalysisApiMode.Ide
)
);
}
@Test
public void testAllFilesPresentInScopeContextForPosition() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("contextReceiver.kt")
public void testContextReceiver() throws Exception {
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/contextReceiver.kt");
}
@Test
@TestMetadata("enumEntry.kt")
public void testEnumEntry() throws Exception {
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/enumEntry.kt");
}
@Test
@TestMetadata("errorType.kt")
public void testErrorType() throws Exception {
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/errorType.kt");
}
@Test
@TestMetadata("localTypeScope.kt")
public void testLocalTypeScope() throws Exception {
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/localTypeScope.kt");
}
@Test
@TestMetadata("simpleScopeContextForPosition.kt")
public void testSimpleScopeContextForPosition() throws Exception {
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/simpleScopeContextForPosition.kt");
}
}
@@ -0,0 +1,78 @@
/*
* 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 org.jetbrains.kotlin.analysis.api.fir.test.cases.generated.cases.scopes;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.analysis.api.fir.test.configurators.AnalysisApiFirTestConfiguratorFactory;
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfiguratorFactoryData;
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator;
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.TestModuleKind;
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind;
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisSessionMode;
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiMode;
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.scopes.AbstractScopeContextForPositionTest;
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 org.jetbrains.kotlin.generators.tests.analysis.api.GenerateAnalysisApiTestsKt}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition")
@TestDataPath("$PROJECT_ROOT")
public class FirIdeNormalAnalysisSourceModuleScopeContextForPositionTestGenerated extends AbstractScopeContextForPositionTest {
@NotNull
@Override
public AnalysisApiTestConfigurator getConfigurator() {
return AnalysisApiFirTestConfiguratorFactory.INSTANCE.createConfigurator(
new AnalysisApiTestConfiguratorFactoryData(
FrontendKind.Fir,
TestModuleKind.Source,
AnalysisSessionMode.Normal,
AnalysisApiMode.Ide
)
);
}
@Test
public void testAllFilesPresentInScopeContextForPosition() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("contextReceiver.kt")
public void testContextReceiver() throws Exception {
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/contextReceiver.kt");
}
@Test
@TestMetadata("enumEntry.kt")
public void testEnumEntry() throws Exception {
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/enumEntry.kt");
}
@Test
@TestMetadata("errorType.kt")
public void testErrorType() throws Exception {
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/errorType.kt");
}
@Test
@TestMetadata("localTypeScope.kt")
public void testLocalTypeScope() throws Exception {
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/localTypeScope.kt");
}
@Test
@TestMetadata("simpleScopeContextForPosition.kt")
public void testSimpleScopeContextForPosition() throws Exception {
runTest("analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/simpleScopeContextForPosition.kt");
}
}