[Analysis API] Generify 'KtCodeFragmentModule' to support ordinary files
This commit introduces dangling file modules, which may be either code fragments or ordinary Kotlin files. As before, code fragments are analyzed against some context element, however ordinary files only have a context module. Code fragments can also have a dangling file module as a contextual one, including other code fragment. This is done to support potential usages in completion, intentions and refactorings.
This commit is contained in:
+2
-2
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirMo
|
|||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.codeFragment
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.codeFragment
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtCodeFragmentModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtDanglingFileModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
||||||
@@ -248,7 +248,7 @@ internal class KtFirCompilerFacility(
|
|||||||
|
|
||||||
private fun computeTargetModules(module: KtModule): List<KtModule> {
|
private fun computeTargetModules(module: KtModule): List<KtModule> {
|
||||||
return when (module) {
|
return when (module) {
|
||||||
is KtCodeFragmentModule -> listOf(module.contextModule, module)
|
is KtDanglingFileModule -> listOf(module.contextModule, module)
|
||||||
else -> listOf(module)
|
else -> listOf(module)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.analysis.api.standalone.base.project.structure
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiFileSystemItem
|
import com.intellij.psi.PsiFileSystemItem
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.*
|
import org.jetbrains.kotlin.analysis.project.structure.*
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.impl.KtCodeFragmentModuleImpl
|
import org.jetbrains.kotlin.analysis.project.structure.impl.KtDanglingFileModuleImpl
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.contains
|
import org.jetbrains.kotlin.psi.psiUtil.contains
|
||||||
@@ -31,7 +31,7 @@ class KtStaticModuleProvider(
|
|||||||
.withAttachment("codeFragment.kt", containingPsiFile.text)
|
.withAttachment("codeFragment.kt", containingPsiFile.text)
|
||||||
|
|
||||||
val contextModule = getModule(contextElement, contextualModule)
|
val contextModule = getModule(contextElement, contextualModule)
|
||||||
return KtCodeFragmentModuleImpl(containingPsiFile, contextModule)
|
return KtDanglingFileModuleImpl(containingPsiFile, contextModule)
|
||||||
}
|
}
|
||||||
|
|
||||||
val containingVirtualFile = containingPsiFile.virtualFile
|
val containingVirtualFile = containingPsiFile.virtualFile
|
||||||
|
|||||||
+7
-12
@@ -54,15 +54,10 @@ class LLFirResolveSessionService(project: Project) {
|
|||||||
is KtSourceModule -> LLSourceModuleResolutionStrategyProvider
|
is KtSourceModule -> LLSourceModuleResolutionStrategyProvider
|
||||||
is KtLibraryModule, is KtLibrarySourceModule -> LLLibraryModuleResolutionStrategyProvider(module)
|
is KtLibraryModule, is KtLibrarySourceModule -> LLLibraryModuleResolutionStrategyProvider(module)
|
||||||
is KtScriptModule -> LLScriptModuleResolutionStrategyProvider(module)
|
is KtScriptModule -> LLScriptModuleResolutionStrategyProvider(module)
|
||||||
is KtCodeFragmentModule -> {
|
is KtDanglingFileModule -> {
|
||||||
val contextElement = module.codeFragment.context
|
val contextModule = module.contextModule
|
||||||
if (contextElement != null) {
|
val contextResolutionStrategyProvider = createResolutionStrategyProvider(contextModule, moduleProvider)
|
||||||
val contextModule = moduleProvider.getModule(contextElement)
|
LLDanglingFileResolutionStrategyProvider(contextResolutionStrategyProvider)
|
||||||
val contextResolutionStrategyProvider = createResolutionStrategyProvider(contextModule, moduleProvider)
|
|
||||||
LLCodeFragmentResolutionStrategyProvider(contextResolutionStrategyProvider)
|
|
||||||
} else {
|
|
||||||
LLSimpleResolutionStrategyProvider(module)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
is KtNotUnderContentRootModule -> LLSimpleResolutionStrategyProvider(module)
|
is KtNotUnderContentRootModule -> LLSimpleResolutionStrategyProvider(module)
|
||||||
else -> {
|
else -> {
|
||||||
@@ -77,7 +72,7 @@ class LLFirResolveSessionService(project: Project) {
|
|||||||
return when (moduleProvider.useSiteModule) {
|
return when (moduleProvider.useSiteModule) {
|
||||||
is KtSourceModule,
|
is KtSourceModule,
|
||||||
is KtScriptModule,
|
is KtScriptModule,
|
||||||
is KtCodeFragmentModule -> LLSourceDiagnosticProvider(moduleProvider, sessionProvider)
|
is KtDanglingFileModule -> LLSourceDiagnosticProvider(moduleProvider, sessionProvider)
|
||||||
else -> LLEmptyDiagnosticProvider
|
else -> LLEmptyDiagnosticProvider
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,10 +110,10 @@ private class LLScriptModuleResolutionStrategyProvider(private val useSiteModule
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LLCodeFragmentResolutionStrategyProvider(private val delegate: LLModuleResolutionStrategyProvider) : LLModuleResolutionStrategyProvider {
|
private class LLDanglingFileResolutionStrategyProvider(private val delegate: LLModuleResolutionStrategyProvider) : LLModuleResolutionStrategyProvider {
|
||||||
override fun getKind(module: KtModule): LLModuleResolutionStrategy {
|
override fun getKind(module: KtModule): LLModuleResolutionStrategy {
|
||||||
return when (module) {
|
return when (module) {
|
||||||
is KtCodeFragmentModule -> LLModuleResolutionStrategy.LAZY
|
is KtDanglingFileModule -> LLModuleResolutionStrategy.LAZY
|
||||||
else -> delegate.getKind(module)
|
else -> delegate.getKind(module)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
|
||||||
class LLFirCodeFragmentDependenciesSymbolProvider(private val delegate: FirSymbolProvider) : FirSymbolProvider(delegate.session) {
|
class LLFirDanglingFileDependenciesSymbolProvider(private val delegate: FirSymbolProvider) : FirSymbolProvider(delegate.session) {
|
||||||
override val symbolNamesProvider: FirSymbolNamesProvider
|
override val symbolNamesProvider: FirSymbolNamesProvider
|
||||||
get() = delegate.symbolNamesProvider
|
get() = delegate.symbolNamesProvider
|
||||||
|
|
||||||
+11
-15
@@ -44,8 +44,6 @@ import org.jetbrains.kotlin.fir.resolve.transformers.FirDummyCompilerLazyDeclara
|
|||||||
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
|
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
|
||||||
import org.jetbrains.kotlin.fir.session.*
|
import org.jetbrains.kotlin.fir.session.*
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirLazyDeclarationResolver
|
import org.jetbrains.kotlin.fir.symbols.FirLazyDeclarationResolver
|
||||||
import org.jetbrains.kotlin.platform.has
|
|
||||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatform
|
|
||||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
|
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
|
||||||
@@ -461,12 +459,12 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun createCodeFragmentSession(module: KtCodeFragmentModule, contextSession: LLFirSession): LLFirSession
|
abstract fun createDanglingFileSession(module: KtDanglingFileModule, contextSession: LLFirSession): LLFirSession
|
||||||
|
|
||||||
protected fun doCreateCodeFragmentSession(
|
protected fun doCreateDanglingFileSession(
|
||||||
module: KtCodeFragmentModule,
|
module: KtDanglingFileModule,
|
||||||
contextSession: LLFirSession,
|
contextSession: LLFirSession,
|
||||||
additionalSessionConfiguration: context(CodeFragmentSessionCreationContext) LLFirCodeFragmentSession.() -> Unit,
|
additionalSessionConfiguration: context(DanglingFileSessionCreationContext) LLFirDanglingFileSession.() -> Unit,
|
||||||
): LLFirSession {
|
): LLFirSession {
|
||||||
val platform = module.platform
|
val platform = module.platform
|
||||||
val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform)
|
val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform)
|
||||||
@@ -475,7 +473,7 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje
|
|||||||
|
|
||||||
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
||||||
|
|
||||||
val session = LLFirCodeFragmentSession(module, components, builtinsSession.builtinTypes)
|
val session = LLFirDanglingFileSession(module, components, builtinsSession.builtinTypes)
|
||||||
components.session = session
|
components.session = session
|
||||||
|
|
||||||
val moduleData = createModuleData(session)
|
val moduleData = createModuleData(session)
|
||||||
@@ -492,9 +490,8 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje
|
|||||||
this,
|
this,
|
||||||
components,
|
components,
|
||||||
canContainKotlinPackage = true,
|
canContainKotlinPackage = true,
|
||||||
) { scope ->
|
declarationProviderFactory = { scope -> scope.createScopedDeclarationProviderForFile(module.file) }
|
||||||
scope.createScopedDeclarationProviderForFile(module.codeFragment)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
register(FirProvider::class, firProvider)
|
register(FirProvider::class, firProvider)
|
||||||
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
|
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
|
||||||
@@ -518,7 +515,7 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wrap dependencies into a single classpath-filtering provider
|
// Wrap dependencies into a single classpath-filtering provider
|
||||||
listOf(LLFirCodeFragmentDependenciesSymbolProvider(FirCompositeSymbolProvider(session, providers)))
|
listOf(LLFirDanglingFileDependenciesSymbolProvider(FirCompositeSymbolProvider(session, providers)))
|
||||||
}
|
}
|
||||||
|
|
||||||
register(DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY, dependencyProvider)
|
register(DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY, dependencyProvider)
|
||||||
@@ -535,7 +532,7 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje
|
|||||||
.createIfNeeded(this)
|
.createIfNeeded(this)
|
||||||
?.also { register(FirSwitchableExtensionDeclarationsSymbolProvider::class, it) }
|
?.also { register(FirSwitchableExtensionDeclarationsSymbolProvider::class, it) }
|
||||||
|
|
||||||
val context = CodeFragmentSessionCreationContext(
|
val context = DanglingFileSessionCreationContext(
|
||||||
moduleData,
|
moduleData,
|
||||||
firProvider,
|
firProvider,
|
||||||
dependencyProvider,
|
dependencyProvider,
|
||||||
@@ -547,7 +544,7 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class CodeFragmentSessionCreationContext(
|
protected class DanglingFileSessionCreationContext(
|
||||||
val moduleData: LLFirModuleData,
|
val moduleData: LLFirModuleData,
|
||||||
val firProvider: LLFirProvider,
|
val firProvider: LLFirProvider,
|
||||||
val dependencyProvider: LLFirDependenciesSymbolProvider,
|
val dependencyProvider: LLFirDependenciesSymbolProvider,
|
||||||
@@ -579,11 +576,10 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje
|
|||||||
fun getOrCreateSessionForDependency(dependency: KtModule): LLFirSession? = when (dependency) {
|
fun getOrCreateSessionForDependency(dependency: KtModule): LLFirSession? = when (dependency) {
|
||||||
is KtBuiltinsModule -> null // Built-ins are already added
|
is KtBuiltinsModule -> null // Built-ins are already added
|
||||||
is KtBinaryModule -> llFirSessionCache.getSession(dependency, preferBinary = true)
|
is KtBinaryModule -> llFirSessionCache.getSession(dependency, preferBinary = true)
|
||||||
is KtSourceModule -> llFirSessionCache.getSession(dependency)
|
is KtSourceModule, is KtDanglingFileModule -> llFirSessionCache.getSession(dependency)
|
||||||
|
|
||||||
is KtScriptModule,
|
is KtScriptModule,
|
||||||
is KtScriptDependencyModule,
|
is KtScriptDependencyModule,
|
||||||
is KtCodeFragmentModule,
|
|
||||||
is KtNotUnderContentRootModule,
|
is KtNotUnderContentRootModule,
|
||||||
is KtLibrarySourceModule,
|
is KtLibrarySourceModule,
|
||||||
-> {
|
-> {
|
||||||
|
|||||||
+3
-3
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirLi
|
|||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirModuleData
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirModuleData
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirModuleWithDependenciesSymbolProvider
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirModuleWithDependenciesSymbolProvider
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtBinaryModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtBinaryModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtCodeFragmentModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtDanglingFileModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||||
import org.jetbrains.kotlin.analysis.providers.createPackagePartProvider
|
import org.jetbrains.kotlin.analysis.providers.createPackagePartProvider
|
||||||
@@ -74,8 +74,8 @@ internal class LLFirCommonSessionFactory(project: Project) : LLFirAbstractSessio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createCodeFragmentSession(module: KtCodeFragmentModule, contextSession: LLFirSession): LLFirSession {
|
override fun createDanglingFileSession(module: KtDanglingFileModule, contextSession: LLFirSession): LLFirSession {
|
||||||
return doCreateCodeFragmentSession(module, contextSession) {
|
return doCreateDanglingFileSession(module, contextSession) {
|
||||||
registerDefaultComponents()
|
registerDefaultComponents()
|
||||||
|
|
||||||
register(
|
register(
|
||||||
|
|||||||
+3
-3
@@ -6,12 +6,12 @@
|
|||||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||||
|
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtCodeFragmentModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtDanglingFileModule
|
||||||
import org.jetbrains.kotlin.fir.BuiltinTypes
|
import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||||
import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
||||||
|
|
||||||
internal class LLFirCodeFragmentSession @PrivateSessionConstructor constructor(
|
internal class LLFirDanglingFileSession @PrivateSessionConstructor constructor(
|
||||||
ktModule: KtCodeFragmentModule,
|
ktModule: KtDanglingFileModule,
|
||||||
override val moduleComponents: LLFirModuleResolveComponents,
|
override val moduleComponents: LLFirModuleResolveComponents,
|
||||||
builtinTypes: BuiltinTypes,
|
builtinTypes: BuiltinTypes,
|
||||||
) : LLFirResolvableModuleSession(ktModule, builtinTypes)
|
) : LLFirResolvableModuleSession(ktModule, builtinTypes)
|
||||||
+3
-3
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirLi
|
|||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirModuleData
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirModuleData
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirModuleWithDependenciesSymbolProvider
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirModuleWithDependenciesSymbolProvider
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtBinaryModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtBinaryModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtCodeFragmentModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtDanglingFileModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||||
import org.jetbrains.kotlin.fir.BuiltinTypes
|
import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||||
@@ -75,8 +75,8 @@ internal class LLFirJsSessionFactory(project: Project) : LLFirAbstractSessionFac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createCodeFragmentSession(module: KtCodeFragmentModule, contextSession: LLFirSession): LLFirSession {
|
override fun createDanglingFileSession(module: KtDanglingFileModule, contextSession: LLFirSession): LLFirSession {
|
||||||
return doCreateCodeFragmentSession(module, contextSession) {
|
return doCreateDanglingFileSession(module, contextSession) {
|
||||||
registerDefaultComponents()
|
registerDefaultComponents()
|
||||||
registerModuleIndependentJsComponents()
|
registerModuleIndependentJsComponents()
|
||||||
|
|
||||||
|
|||||||
+7
-5
@@ -78,12 +78,14 @@ internal class LLFirJvmSessionFactory(project: Project) : LLFirAbstractSessionFa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createCodeFragmentSession(module: KtCodeFragmentModule, contextSession: LLFirSession): LLFirSession {
|
override fun createDanglingFileSession(module: KtDanglingFileModule, contextSession: LLFirSession): LLFirSession {
|
||||||
return doCreateCodeFragmentSession(module, contextSession) {
|
return doCreateDanglingFileSession(module, contextSession) {
|
||||||
registerJavaComponents(JavaModuleResolver.getInstance(project))
|
registerJavaComponents(JavaModuleResolver.getInstance(project))
|
||||||
|
|
||||||
val javaSymbolProvider = LLFirJavaSymbolProvider(this, moduleData, project, firProvider.searchScope)
|
val contextJavaSymbolProvider = contextSession.nullableJavaSymbolProvider
|
||||||
register(JavaSymbolProvider::class, javaSymbolProvider)
|
if (contextJavaSymbolProvider != null) {
|
||||||
|
register(JavaSymbolProvider::class, contextJavaSymbolProvider)
|
||||||
|
}
|
||||||
|
|
||||||
register(
|
register(
|
||||||
FirSymbolProvider::class,
|
FirSymbolProvider::class,
|
||||||
@@ -93,7 +95,7 @@ internal class LLFirJvmSessionFactory(project: Project) : LLFirAbstractSessionFa
|
|||||||
firProvider.symbolProvider,
|
firProvider.symbolProvider,
|
||||||
switchableExtensionDeclarationsSymbolProvider,
|
switchableExtensionDeclarationsSymbolProvider,
|
||||||
syntheticFunctionInterfaceProvider,
|
syntheticFunctionInterfaceProvider,
|
||||||
javaSymbolProvider
|
contextJavaSymbolProvider
|
||||||
),
|
),
|
||||||
dependencyProvider
|
dependencyProvider
|
||||||
)
|
)
|
||||||
|
|||||||
+3
-3
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirLi
|
|||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirModuleData
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirModuleData
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirModuleWithDependenciesSymbolProvider
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirModuleWithDependenciesSymbolProvider
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtBinaryModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtBinaryModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtCodeFragmentModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtDanglingFileModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||||
import org.jetbrains.kotlin.analysis.providers.createPackagePartProvider
|
import org.jetbrains.kotlin.analysis.providers.createPackagePartProvider
|
||||||
@@ -72,8 +72,8 @@ internal class LLFirNativeSessionFactory(project: Project) : LLFirAbstractSessio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createCodeFragmentSession(module: KtCodeFragmentModule, contextSession: LLFirSession): LLFirSession {
|
override fun createDanglingFileSession(module: KtDanglingFileModule, contextSession: LLFirSession): LLFirSession {
|
||||||
return doCreateCodeFragmentSession(module, contextSession) {
|
return doCreateDanglingFileSession(module, contextSession) {
|
||||||
registerModuleIndependentNativeComponents()
|
registerModuleIndependentNativeComponents()
|
||||||
|
|
||||||
register(
|
register(
|
||||||
|
|||||||
+11
-11
@@ -35,7 +35,7 @@ class LLFirSessionCache(private val project: Project) {
|
|||||||
|
|
||||||
private val sourceCache: SessionStorage = CollectionFactory.createConcurrentSoftValueMap()
|
private val sourceCache: SessionStorage = CollectionFactory.createConcurrentSoftValueMap()
|
||||||
private val binaryCache: SessionStorage = CollectionFactory.createConcurrentSoftValueMap()
|
private val binaryCache: SessionStorage = CollectionFactory.createConcurrentSoftValueMap()
|
||||||
private val codeFragmentSessionCache: SessionStorage = CollectionFactory.createConcurrentSoftValueMap()
|
private val danglingFileSessionCache: SessionStorage = CollectionFactory.createConcurrentSoftValueMap()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the existing session if found, or creates a new session and caches it.
|
* Returns the existing session if found, or creates a new session and caches it.
|
||||||
@@ -49,7 +49,7 @@ class LLFirSessionCache(private val project: Project) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val targetCache = when (module) {
|
val targetCache = when (module) {
|
||||||
is KtCodeFragmentModule -> codeFragmentSessionCache
|
is KtDanglingFileModule -> danglingFileSessionCache
|
||||||
else -> sourceCache
|
else -> sourceCache
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,9 +86,9 @@ class LLFirSessionCache(private val project: Project) {
|
|||||||
|
|
||||||
val didSourceSessionExist = removeSessionFrom(module, sourceCache)
|
val didSourceSessionExist = removeSessionFrom(module, sourceCache)
|
||||||
val didBinarySessionExist = module is KtBinaryModule && removeSessionFrom(module, binaryCache)
|
val didBinarySessionExist = module is KtBinaryModule && removeSessionFrom(module, binaryCache)
|
||||||
val didCodeFragmentSessionExist = module is KtCodeFragmentModule && removeSessionFrom(module, codeFragmentSessionCache)
|
val didDanglingFileSessionExist = module is KtDanglingFileModule && removeSessionFrom(module, danglingFileSessionCache)
|
||||||
|
|
||||||
return didSourceSessionExist || didBinarySessionExist || didCodeFragmentSessionExist
|
return didSourceSessionExist || didBinarySessionExist || didDanglingFileSessionExist
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeSessionFrom(module: KtModule, storage: SessionStorage): Boolean {
|
private fun removeSessionFrom(module: KtModule, storage: SessionStorage): Boolean {
|
||||||
@@ -114,11 +114,11 @@ class LLFirSessionCache(private val project: Project) {
|
|||||||
removeAllMatchingSessionsFrom(sourceCache) { it !is KtBinaryModule && it !is KtLibrarySourceModule }
|
removeAllMatchingSessionsFrom(sourceCache) { it !is KtBinaryModule && it !is KtLibrarySourceModule }
|
||||||
}
|
}
|
||||||
|
|
||||||
removeAllCodeFragmentSessions()
|
removeAllDanglingFileSessions()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeAllCodeFragmentSessions() {
|
fun removeAllDanglingFileSessions() {
|
||||||
removeAllSessionsFrom(codeFragmentSessionCache)
|
removeAllSessionsFrom(danglingFileSessionCache)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removing script sessions is only needed temporarily until KTIJ-25620 has been implemented.
|
// Removing script sessions is only needed temporarily until KTIJ-25620 has been implemented.
|
||||||
@@ -159,11 +159,11 @@ class LLFirSessionCache(private val project: Project) {
|
|||||||
is KtLibraryModule, is KtLibrarySourceModule -> sessionFactory.createLibrarySession(module)
|
is KtLibraryModule, is KtLibrarySourceModule -> sessionFactory.createLibrarySession(module)
|
||||||
is KtSdkModule -> sessionFactory.createBinaryLibrarySession(module)
|
is KtSdkModule -> sessionFactory.createBinaryLibrarySession(module)
|
||||||
is KtScriptModule -> sessionFactory.createScriptSession(module)
|
is KtScriptModule -> sessionFactory.createScriptSession(module)
|
||||||
is KtCodeFragmentModule -> {
|
is KtDanglingFileModule -> {
|
||||||
// 'KtCodeFragment' context must have an analyzable session, so we can properly compile code against it.
|
// Dangling file context must have an analyzable session, so we can properly compile code against it.
|
||||||
// 'KtCodeFragmentModule' is always a leaf module, there might not be a circular reference.
|
// 'KtDanglingFileModule' is always a leaf module, so there might not be a circular reference.
|
||||||
val contextSession = getSession(module.contextModule, preferBinary = false)
|
val contextSession = getSession(module.contextModule, preferBinary = false)
|
||||||
sessionFactory.createCodeFragmentSession(module, contextSession)
|
sessionFactory.createDanglingFileSession(module, contextSession)
|
||||||
}
|
}
|
||||||
is KtNotUnderContentRootModule -> sessionFactory.createNotUnderContentRootResolvableSession(module)
|
is KtNotUnderContentRootModule -> sessionFactory.createNotUnderContentRootResolvableSession(module)
|
||||||
else -> error("Unexpected module kind: ${module::class.simpleName}")
|
else -> error("Unexpected module kind: ${module::class.simpleName}")
|
||||||
|
|||||||
+4
-4
@@ -54,7 +54,7 @@ class LLFirSessionInvalidationService(private val project: Project) : Disposable
|
|||||||
)
|
)
|
||||||
busConnection.subscribe(
|
busConnection.subscribe(
|
||||||
PsiModificationTracker.TOPIC,
|
PsiModificationTracker.TOPIC,
|
||||||
PsiModificationTracker.Listener { invalidateAllCodeFragments() }
|
PsiModificationTracker.Listener { invalidateAllDanglingFiles() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ class LLFirSessionInvalidationService(private val project: Project) : Disposable
|
|||||||
sessionCache.removeAllScriptSessions()
|
sessionCache.removeAllScriptSessions()
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionCache.removeAllCodeFragmentSessions()
|
sessionCache.removeAllDanglingFileSessions()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun invalidateAll(includeLibraryModules: Boolean) {
|
private fun invalidateAll(includeLibraryModules: Boolean) {
|
||||||
@@ -105,8 +105,8 @@ class LLFirSessionInvalidationService(private val project: Project) : Disposable
|
|||||||
LLFirSessionCache.getInstance(project).removeAllSessions(includeLibraryModules)
|
LLFirSessionCache.getInstance(project).removeAllSessions(includeLibraryModules)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun invalidateAllCodeFragments() {
|
private fun invalidateAllDanglingFiles() {
|
||||||
LLFirSessionCache.getInstance(project).removeAllCodeFragmentSessions()
|
LLFirSessionCache.getInstance(project).removeAllDanglingFileSessions()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
|
|||||||
+7
-4
@@ -63,9 +63,10 @@ internal class LLFirResolvableResolveSession(
|
|||||||
phase: FirResolvePhase,
|
phase: FirResolvePhase,
|
||||||
): FirBasedSymbol<*> {
|
): FirBasedSymbol<*> {
|
||||||
val containingKtFile = ktDeclaration.containingKtFile
|
val containingKtFile = ktDeclaration.containingKtFile
|
||||||
val module = getModule(containingKtFile.originalKtFile ?: containingKtFile)
|
val module = getModule(containingKtFile)
|
||||||
|
|
||||||
return when (getModuleResolutionStrategy(module)) {
|
return when (getModuleResolutionStrategy(module)) {
|
||||||
LLModuleResolutionStrategy.LAZY -> findSourceFirSymbol(ktDeclaration, module).also { resolveFirToPhase(it.fir, phase) }
|
LLModuleResolutionStrategy.LAZY -> findSourceFirSymbol(ktDeclaration).also { resolveFirToPhase(it.fir, phase) }
|
||||||
LLModuleResolutionStrategy.STATIC -> findFirCompiledSymbol(ktDeclaration, module)
|
LLModuleResolutionStrategy.STATIC -> findFirCompiledSymbol(ktDeclaration, module)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,8 +82,10 @@ internal class LLFirResolvableResolveSession(
|
|||||||
return firDeclaration.symbol
|
return firDeclaration.symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findSourceFirSymbol(ktDeclaration: KtDeclaration, module: KtModule): FirBasedSymbol<*> {
|
private fun findSourceFirSymbol(ktDeclaration: KtDeclaration): FirBasedSymbol<*> {
|
||||||
return findSourceFirDeclarationByDeclaration(ktDeclaration.originalDeclaration ?: ktDeclaration, module)
|
val targetDeclaration = ktDeclaration.originalDeclaration ?: ktDeclaration
|
||||||
|
val targetModule = getModule(targetDeclaration)
|
||||||
|
return findSourceFirDeclarationByDeclaration(targetDeclaration, targetModule)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findSourceFirDeclarationByDeclaration(ktDeclaration: KtDeclaration, module: KtModule): FirBasedSymbol<*> {
|
private fun findSourceFirDeclarationByDeclaration(ktDeclaration: KtDeclaration, module: KtModule): FirBasedSymbol<*> {
|
||||||
|
|||||||
+14
-7
@@ -10,7 +10,6 @@ import com.intellij.psi.PsiFile
|
|||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
@@ -216,21 +215,29 @@ public interface KtScriptDependencyModule : KtModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A module for a Kotlin code fragment – a piece of code analyzed against a specific context element.
|
* A module for a dangling file. Such files are usually temporary and are stored in-memory.
|
||||||
|
* Dangling files may be created for various purposes, such as: a code fragment for the evaluator, a sandbox for testing code modification
|
||||||
|
* applicability, etc.
|
||||||
*/
|
*/
|
||||||
public interface KtCodeFragmentModule : KtModule {
|
public interface KtDanglingFileModule : KtModule {
|
||||||
/**
|
/**
|
||||||
* A code fragment PSI.
|
* A temporary file PSI.
|
||||||
*/
|
*/
|
||||||
public val codeFragment: KtCodeFragment
|
public val file: KtFile
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module of the context element.
|
* The module against which the [file] is analyzed.
|
||||||
*/
|
*/
|
||||||
public val contextModule: KtModule
|
public val contextModule: KtModule
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the [file] is a code fragment.
|
||||||
|
* Useful to recognize code fragments when their PSI was collected.
|
||||||
|
*/
|
||||||
|
public val isCodeFragment: Boolean
|
||||||
|
|
||||||
override val moduleDescription: String
|
override val moduleDescription: String
|
||||||
get() = "Code fragment"
|
get() = "Temporary file"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+26
-13
@@ -7,22 +7,35 @@ package org.jetbrains.kotlin.analysis.project.structure.impl
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtCodeFragmentModule
|
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||||
|
import org.jetbrains.kotlin.analysis.project.structure.KtDanglingFileModule
|
||||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
||||||
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
||||||
import java.util.Objects
|
import java.util.Objects
|
||||||
|
|
||||||
public class KtCodeFragmentModuleImpl(
|
public class KtDanglingFileModuleImpl(
|
||||||
codeFragment: KtCodeFragment,
|
file: KtFile,
|
||||||
override val contextModule: KtModule
|
override val contextModule: KtModule
|
||||||
) : KtCodeFragmentModule {
|
) : KtDanglingFileModule {
|
||||||
private val codeFragmentRef = codeFragment.createSmartPointer()
|
override val isCodeFragment: Boolean = file is KtCodeFragment
|
||||||
|
|
||||||
override val codeFragment: KtCodeFragment
|
private val fileRef = file.createSmartPointer()
|
||||||
get() = codeFragmentRef.element?.takeIf { it.isValid } ?: error("Code fragment module is invalid")
|
|
||||||
|
init {
|
||||||
|
require(contextModule != this)
|
||||||
|
|
||||||
|
if (contextModule is KtDanglingFileModule) {
|
||||||
|
// Only code fragments can depend on dangling files.
|
||||||
|
// This is needed for completion, inspections and refactorings.
|
||||||
|
require(file is KtCodeFragment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val file: KtFile
|
||||||
|
get() = fileRef.element?.takeIf { it.isValid } ?: error("Dangling file module is invalid")
|
||||||
|
|
||||||
override val project: Project
|
override val project: Project
|
||||||
get() = contextModule.project
|
get() = contextModule.project
|
||||||
@@ -34,7 +47,7 @@ public class KtCodeFragmentModuleImpl(
|
|||||||
get() = contextModule.analyzerServices
|
get() = contextModule.analyzerServices
|
||||||
|
|
||||||
override val contentScope: GlobalSearchScope
|
override val contentScope: GlobalSearchScope
|
||||||
get() = GlobalSearchScope.fileScope(codeFragment)
|
get() = GlobalSearchScope.fileScope(file)
|
||||||
|
|
||||||
override val directRegularDependencies: List<KtModule>
|
override val directRegularDependencies: List<KtModule>
|
||||||
get() = contextModule.directRegularDependencies
|
get() = contextModule.directRegularDependencies
|
||||||
@@ -51,16 +64,16 @@ public class KtCodeFragmentModuleImpl(
|
|||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
|
|
||||||
if (other is KtCodeFragmentModuleImpl) {
|
if (other is KtDanglingFileModuleImpl) {
|
||||||
val selfCodeFragment = this.codeFragmentRef.element
|
val selfFile = this.fileRef.element
|
||||||
val otherCodeFragment = other.codeFragmentRef.element
|
val otherFile = other.fileRef.element
|
||||||
return selfCodeFragment != null && selfCodeFragment == otherCodeFragment && contextModule == other.contextModule
|
return selfFile != null && selfFile == otherFile && contextModule == other.contextModule
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
return Objects.hash(codeFragmentRef.element, contextModule)
|
return Objects.hash(fileRef.element, contextModule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-4
@@ -194,10 +194,13 @@ class SymbolKotlinAsJavaSupport(project: Project) : KotlinAsJavaSupportBase<KtMo
|
|||||||
|
|
||||||
private fun KtElement.isFromSourceOrLibraryBinary(): Boolean = getModuleIfSupportEnabled()?.isFromSourceOrLibraryBinary() == true
|
private fun KtElement.isFromSourceOrLibraryBinary(): Boolean = getModuleIfSupportEnabled()?.isFromSourceOrLibraryBinary() == true
|
||||||
|
|
||||||
private fun KtModule.isFromSourceOrLibraryBinary() = when (this) {
|
private fun KtModule.isFromSourceOrLibraryBinary(): Boolean {
|
||||||
is KtSourceModule -> true
|
return when (this) {
|
||||||
is KtLibraryModule -> true
|
is KtSourceModule -> true
|
||||||
else -> false
|
is KtLibraryModule -> true
|
||||||
|
is KtDanglingFileModule -> contextModule.isFromSourceOrLibraryBinary()
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user