[Analysis API] Add source shadowing for resolve extensions.

KtResolveExtensions are designed to handle IDE analysis use cases where
source might not be available at analysis time, because that source is
generated by an external source generator, such as an annotation
processor or resource compiler. The sources generated by those external
generators can appear in the analysis scope, and cause issues with
source clash - resolution may find the virtual source from the
KtResolveExtension, the on-disk generated source from the external
generator, or both. This can cause issues, because that on-disk
generated source may be stale, and may not have symbols that will exist
the next time the generator is run (or, conversely, may have symbols
that will disappear on the next build).

To solve this, add a `getShadowedScope(): GlobalSearchScope` to
`KtResolveExtension`. Any files in the module that are included in that
scope will be hidden from resolution, allowing the resolve extension to
cleanly replace those files.

^KT-58834 fixed
This commit is contained in:
Justin Paupore
2023-05-22 17:59:47 -07:00
committed by Ilya Kirillov
parent 7c87eb098d
commit f590e88bdd
30 changed files with 357 additions and 82 deletions
@@ -114,7 +114,7 @@ private constructor(
override val typesCreatorImpl: KtTypeCreator = KtFirTypeCreator(this, token)
override val analysisScopeProviderImpl: KtAnalysisScopeProvider = KtAnalysisScopeProviderImpl(this, token)
override val analysisScopeProviderImpl: KtAnalysisScopeProvider
override val referenceResolveProviderImpl: KtReferenceResolveProvider = KtFirReferenceResolveProvider(this)
@@ -153,9 +153,10 @@ private constructor(
internal val firSymbolProvider: FirSymbolProvider get() = useSiteSession.symbolProvider
internal val targetPlatform: TargetPlatform get() = useSiteSession.moduleData.platform
val useSiteAnalysisScope: GlobalSearchScope = analysisScopeProviderImpl.getAnalysisScope()
val extensionTools: List<LLFirResolveExtensionTool>
val useSiteAnalysisScope: GlobalSearchScope
val useSiteScopeDeclarationProvider: KotlinDeclarationProvider
val useSitePackageProvider: KotlinPackageProvider
@@ -167,6 +168,20 @@ private constructor(
firResolveSession.getSessionFor(dependency).llResolveExtensionTool
}
}
val shadowedScope = GlobalSearchScope.union(
buildSet {
// Add an empty scope to the shadowed set to give GlobalSearchScope.union something
// to work with if there are no extension tools.
// If there are extension tools, any empty scopes, whether from shadowedSearchScope
// on the extension tools or from this add() call, will be ignored.
add(GlobalSearchScope.EMPTY_SCOPE)
extensionTools.mapTo(this) { it.shadowedSearchScope }
}
)
analysisScopeProviderImpl = KtAnalysisScopeProviderImpl(this, token, shadowedScope)
useSiteAnalysisScope = analysisScopeProviderImpl.getAnalysisScope()
useSiteScopeDeclarationProvider = CompositeKotlinDeclarationProvider.create(
buildList {
add(project.createDeclarationProvider(useSiteAnalysisScope, useSiteModule))
@@ -67,6 +67,24 @@ public class FirIdeNormalAnalysisSourceModuleMultiModuleReferenceResolveWithReso
runTest("analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/extensionFunction.kt");
}
@Test
@TestMetadata("shadowedDeclaration.kt")
public void testShadowedDeclaration() throws Exception {
runTest("analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedDeclaration.kt");
}
@Test
@TestMetadata("shadowedJava.kt")
public void testShadowedJava() throws Exception {
runTest("analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedJava.kt");
}
@Test
@TestMetadata("shadowedOverload.kt")
public void testShadowedOverload() throws Exception {
runTest("analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedOverload.kt");
}
@Test
@TestMetadata("topLevelFunction.kt")
public void testTopLevelFunction() throws Exception {
@@ -58,6 +58,24 @@ public class FirIdeNormalAnalysisSourceModuleSingleModuleReferenceResolveWithRes
runTest("analysis/analysis-api/testData/resolveExtensions/referenceResolve/extensionFunction.kt");
}
@Test
@TestMetadata("shadowedDeclaration.kt")
public void testShadowedDeclaration() throws Exception {
runTest("analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedDeclaration.kt");
}
@Test
@TestMetadata("shadowedJava.kt")
public void testShadowedJava() throws Exception {
runTest("analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedJava.kt");
}
@Test
@TestMetadata("shadowedOverload.kt")
public void testShadowedOverload() throws Exception {
runTest("analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedOverload.kt");
}
@Test
@TestMetadata("topLevelFunction.kt")
public void testTopLevelFunction() throws Exception {