diff --git a/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/KtStaticModuleProvider.kt b/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/KtStaticModuleProvider.kt index 9b788955a26..d2abf2ab7b1 100644 --- a/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/KtStaticModuleProvider.kt +++ b/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/KtStaticModuleProvider.kt @@ -8,7 +8,9 @@ package org.jetbrains.kotlin.analysis.api.standalone.base.project.structure import com.intellij.psi.PsiElement import com.intellij.psi.PsiFileSystemItem import org.jetbrains.kotlin.analysis.project.structure.* +import org.jetbrains.kotlin.analysis.project.structure.impl.KtCodeFragmentModuleImpl import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.psi.KtCodeFragment import org.jetbrains.kotlin.psi.psiUtil.contains import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments @@ -23,6 +25,15 @@ class KtStaticModuleProvider( // Unwrap context-dependent file copies coming from dependent sessions val containingPsiFile = element.containingFile.originalFile + if (containingPsiFile is KtCodeFragment) { + val contextElement = containingPsiFile.context + ?: throw KotlinExceptionWithAttachments("Context not found for a code fragment") + .withAttachment("codeFragment.kt", containingPsiFile.text) + + val contextModule = getModule(contextElement, contextualModule) + return KtCodeFragmentModuleImpl(containingPsiFile, contextModule) + } + val containingVirtualFile = containingPsiFile.virtualFile if (containingVirtualFile.extension == BuiltInSerializerProtocol.BUILTINS_FILE_EXTENSION) { return builtinsModule diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.ir.txt index 1b80a2db838..c594bc13296 100644 --- a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.ir.txt +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.ir.txt @@ -9,4 +9,4 @@ MODULE_FRAGMENT EXPRESSION_BODY BLOCK type=kotlin.Unit origin=null CALL 'public final fun call (): kotlin.Unit declared in .Foo' type=kotlin.Unit origin=null - $this: GET_OBJECT 'CLASS OBJECT name:Foo modality:FINAL visibility:public superTypes:[kotlin.Any]' type=.Foo + $this: GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Foo modality:FINAL visibility:public superTypes:[kotlin.Any]' type=.Foo diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.fragment.kt index 805d25da792..b73cd2955ac 100644 --- a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.fragment.kt +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.fragment.kt @@ -1 +1,2 @@ +@Suppress("INVISIBLE_SETTER") a = "bar" \ No newline at end of file diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/LLFirResolveStateService.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/LLFirResolveStateService.kt index 80e985a008f..ac121e36949 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/LLFirResolveStateService.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/LLFirResolveStateService.kt @@ -43,17 +43,27 @@ class LLFirResolveSessionService(project: Project) { private fun create(module: KtModule, factory: (KtModule) -> LLFirSession): LLFirResolvableResolveSession { val moduleProvider = LLModuleProvider(module) val sessionProvider = LLSessionProvider(module, factory) - val moduleKindProvider = createModuleKindProvider(module) + val moduleKindProvider = createModuleKindProvider(module, moduleProvider) val diagnosticProvider = createDiagnosticProvider(moduleProvider, sessionProvider) return LLFirResolvableResolveSession(moduleProvider, moduleKindProvider, sessionProvider, diagnosticProvider) } - private fun createModuleKindProvider(module: KtModule): LLModuleKindProvider { + private fun createModuleKindProvider(module: KtModule, moduleProvider: LLModuleProvider): LLModuleKindProvider { return when (module) { is KtSourceModule -> LLSourceModuleKindProvider is KtLibraryModule, is KtLibrarySourceModule -> LLLibraryModuleKindProvider(module) is KtScriptModule -> LLScriptModuleKindProvider(module) + is KtCodeFragmentModule -> { + val contextElement = module.codeFragment.context + if (contextElement != null) { + val contextModule = moduleProvider.getModule(contextElement) + val contextModuleKindProvider = createModuleKindProvider(contextModule, moduleProvider) + LLCodeFragmentKindProvider(contextModuleKindProvider) + } else { + LLSimpleResolvableModuleKindProvider(module) + } + } is KtNotUnderContentRootModule -> LLSimpleResolvableModuleKindProvider(module) else -> { errorWithFirSpecificEntries("Unexpected ${module::class.java}") { @@ -65,7 +75,9 @@ class LLFirResolveSessionService(project: Project) { private fun createDiagnosticProvider(moduleProvider: LLModuleProvider, sessionProvider: LLSessionProvider): LLDiagnosticProvider { return when (moduleProvider.useSiteModule) { - is KtSourceModule, is KtScriptModule -> LLSourceDiagnosticProvider(moduleProvider, sessionProvider) + is KtSourceModule, + is KtScriptModule, + is KtCodeFragmentModule -> LLSourceDiagnosticProvider(moduleProvider, sessionProvider) else -> LLEmptyDiagnosticProvider } } @@ -101,4 +113,13 @@ private class LLScriptModuleKindProvider(private val useSiteModule: KtModule) : else -> unexpectedElementError("module", module) } } +} + +private class LLCodeFragmentKindProvider(private val delegate: LLModuleKindProvider) : LLModuleKindProvider { + override fun getKind(module: KtModule): KtModuleKind { + return when (module) { + is KtCodeFragmentModule -> KtModuleKind.RESOLVABLE_MODULE + else -> delegate.getKind(module) + } + } } \ No newline at end of file diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirAbstractSessionFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirAbstractSessionFactory.kt index 6482b19972a..5c8e29e9568 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirAbstractSessionFactory.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirAbstractSessionFactory.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirLazyDeclarationResol import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.* import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.* +import org.jetbrains.kotlin.analysis.low.level.api.fir.resolver.LLLibraryScopeAwareCallConflictResolverFactory import org.jetbrains.kotlin.analysis.project.structure.* import org.jetbrains.kotlin.analysis.providers.KotlinAnchorModuleProvider import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider @@ -31,9 +32,13 @@ import org.jetbrains.kotlin.fir.analysis.extensions.additionalCheckers import org.jetbrains.kotlin.fir.backend.jvm.FirJvmTypeMapper import org.jetbrains.kotlin.fir.extensions.* import org.jetbrains.kotlin.fir.java.JavaSymbolProvider +import org.jetbrains.kotlin.fir.languageVersionSettings +import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory +import org.jetbrains.kotlin.fir.resolve.calls.callConflictResolverFactory import org.jetbrains.kotlin.fir.resolve.providers.DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY import org.jetbrains.kotlin.fir.resolve.providers.FirProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider +import org.jetbrains.kotlin.fir.resolve.providers.dependenciesSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.impl.FirExtensionSyntheticFunctionInterfaceProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped @@ -41,6 +46,8 @@ import org.jetbrains.kotlin.fir.resolve.transformers.FirDummyCompilerLazyDeclara import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider import org.jetbrains.kotlin.fir.session.* 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.psi.KtFile import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver @@ -128,7 +135,7 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje val dependencyProvider = LLFirDependenciesSymbolProvider(this) { buildList { - addDependencySymbolProvidersTo(session, collectSourceModuleDependencies(module), this) + addMerged(collectDependencySymbolProviders(module)) add(builtinsSession.symbolProvider) } } @@ -282,7 +289,7 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje val dependencyProvider = LLFirDependenciesSymbolProvider(this) { buildList { - addDependencySymbolProvidersTo(session, collectSourceModuleDependencies(module), this) + addMerged(collectDependencySymbolProviders(module)) add(builtinsSession.symbolProvider) } } @@ -450,6 +457,87 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje } } + fun createCodeFragmentSession(module: KtCodeFragmentModule, contextSession: LLFirSession): LLFirSession { + val platform = module.platform + require(platform.has()) + + val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform) + val languageVersionSettings = wrapLanguageVersionSettings(contextSession.languageVersionSettings) + val scopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped) + + val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider) + + val session = LLFirCodeFragmentSession(module, components, builtinsSession.builtinTypes) + components.session = session + + val moduleData = createModuleData(session) + + return session.apply { + registerModuleData(moduleData) + register(FirKotlinScopeProvider::class, scopeProvider) + + registerIdeComponents(project) + registerCommonComponents(languageVersionSettings) + registerResolveComponents() + + val firProvider = LLFirProvider( + this, + components, + canContainKotlinPackage = true, + ) { scope -> + scope.createScopedDeclarationProviderForFile(module.codeFragment) + } + + register(FirProvider::class, firProvider) + register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver()) + + registerCommonComponentsAfterExtensionsAreConfigured() + + val dependencyProvider = LLFirDependenciesSymbolProvider(this) { + buildList { + addMerged(computeFlattenedSymbolProviders(listOf(contextSession))) + add(contextSession.dependenciesSymbolProvider) // Add the context module dependency symbol provider as is + add(builtinsSession.symbolProvider) + } + } + + register(DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY, dependencyProvider) + register(LLFirFirClassByPsiClassProvider::class, LLFirFirClassByPsiClassProvider(this)) + + LLFirSessionConfigurator.configure(this) + + extensionService.additionalCheckers.forEach(session.checkersComponent::register) + + register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider) + register(FirRegisteredPluginAnnotations::class, FirRegisteredPluginAnnotationsImpl(this)) + + registerJavaComponents(JavaModuleResolver.getInstance(project)) + + val javaSymbolProvider = LLFirJavaSymbolProvider(this, moduleData, project, firProvider.searchScope) + register(JavaSymbolProvider::class, javaSymbolProvider) + + val syntheticFunctionInterfaceProvider = FirExtensionSyntheticFunctionInterfaceProvider + .createIfNeeded(this, moduleData, scopeProvider) + + register( + FirSymbolProvider::class, + LLFirModuleWithDependenciesSymbolProvider( + this, + providers = listOfNotNull( + firProvider.symbolProvider, + syntheticFunctionInterfaceProvider, + javaSymbolProvider + ), + dependencyProvider + ) + ) + + register(FirJvmTypeMapper::class, FirJvmTypeMapper(this)) + + register(ConeCallConflictResolverFactory::class, LLLibraryScopeAwareCallConflictResolverFactory(callConflictResolverFactory)) + } + } + private fun wrapLanguageVersionSettings(original: LanguageVersionSettings): LanguageVersionSettings { return object : LanguageVersionSettings by original { override fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State { @@ -468,7 +556,7 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje } } - private fun collectSourceModuleDependencies(module: KtModule): List { + private fun collectDependencySymbolProviders(module: KtModule): List { val llFirSessionCache = LLFirSessionCache.getInstance(project) fun getOrCreateSessionForDependency(dependency: KtModule): LLFirSession? = when (dependency) { @@ -478,6 +566,7 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje is KtScriptModule, is KtScriptDependencyModule, + is KtCodeFragmentModule, is KtNotUnderContentRootModule, is KtLibrarySourceModule, -> { @@ -496,7 +585,17 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje addAll(module.transitiveDependsOnDependencies) } - return dependencyModules.mapNotNull(::getOrCreateSessionForDependency) + val dependencySessions = dependencyModules.mapNotNull(::getOrCreateSessionForDependency) + return computeFlattenedSymbolProviders(dependencySessions) + } + + private fun computeFlattenedSymbolProviders(dependencySessions: List): List { + return dependencySessions.flatMap { session -> + when (val dependencyProvider = session.symbolProvider) { + is LLFirModuleWithDependenciesSymbolProvider -> dependencyProvider.providers + else -> listOf(dependencyProvider) + } + } } private fun createModuleData(session: LLFirSession): LLFirModuleData { @@ -504,24 +603,12 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje } /** - * Adds dependency symbol providers from [dependencies] to [destination]. The function might combine, reorder, or exclude specific - * symbol providers for optimization. + * Merges dependency symbol providers of the same kind, and adds the result to the receiver [MutableList]. + * See [mergeDependencySymbolProvidersInto] for more information on symbol provider merging. */ - private fun addDependencySymbolProvidersTo( - session: LLFirSession, - dependencies: List, - destination: MutableList, - ) { - val dependencyProviders = buildList { - dependencies.forEach { session -> - when (val dependencyProvider = session.symbolProvider) { - is LLFirModuleWithDependenciesSymbolProvider -> addAll(dependencyProvider.providers) - else -> add(dependencyProvider) - } - } - } - - dependencyProviders.mergeDependencySymbolProvidersInto(session, destination) + context(LLFirSession) + private fun MutableList.addMerged(dependencies: List) { + dependencies.mergeDependencySymbolProvidersInto(this@LLFirSession, this) } /** diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirCodeFragmentSession.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirCodeFragmentSession.kt new file mode 100644 index 00000000000..3f7ab226e5d --- /dev/null +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirCodeFragmentSession.kt @@ -0,0 +1,17 @@ +/* + * 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.low.level.api.fir.sessions + +import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents +import org.jetbrains.kotlin.analysis.project.structure.KtCodeFragmentModule +import org.jetbrains.kotlin.fir.BuiltinTypes +import org.jetbrains.kotlin.fir.PrivateSessionConstructor + +internal class LLFirCodeFragmentSession @PrivateSessionConstructor constructor( + ktModule: KtCodeFragmentModule, + override val moduleComponents: LLFirModuleResolveComponents, + builtinTypes: BuiltinTypes, +) : LLFirResolvableModuleSession(ktModule, builtinTypes) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionCache.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionCache.kt index 2141f863852..526bbfa0e1e 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionCache.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionCache.kt @@ -146,6 +146,12 @@ class LLFirSessionCache(private val project: Project) { is KtLibraryModule, is KtLibrarySourceModule -> sessionFactory.createLibrarySession(module) is KtSdkModule -> sessionFactory.createBinaryLibrarySession(module) is KtScriptModule -> sessionFactory.createScriptSession(module) + is KtCodeFragmentModule -> { + // 'KtCodeFragment' 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. + val contextSession = getSession(module.contextModule, preferBinary = false) + sessionFactory.createCodeFragmentSession(module, contextSession) + } is KtNotUnderContentRootModule -> sessionFactory.createNotUnderContentRootResolvableSession(module) else -> error("Unexpected module kind: ${module::class.simpleName}") } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt index d6044116c4d..ef43c7d8a86 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getFirResolveSession +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getModule import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError import org.jetbrains.kotlin.analysis.low.level.api.fir.compile.codeFragmentScopeProvider @@ -38,6 +39,7 @@ import org.jetbrains.kotlin.fir.references.builder.buildExplicitSuperReference import org.jetbrains.kotlin.fir.references.builder.buildExplicitThisReference import org.jetbrains.kotlin.fir.resolve.FirCodeFragmentContext import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.SessionHolderImpl import org.jetbrains.kotlin.fir.resolve.dfa.FirControlFlowGraphReferenceImpl import org.jetbrains.kotlin.fir.resolve.codeFragmentContext import org.jetbrains.kotlin.fir.resolve.dfa.RealVariable @@ -219,9 +221,11 @@ private class LLFirBodyTargetResolver( val contextKtFile = contextPsiElement?.containingFile as? KtFile firCodeFragment.codeFragmentContext = if (contextKtFile != null) { + val contextModule = resolveSession.getModule(contextKtFile) + val contextSession = resolveSession.sessionProvider.getResolvableSession(contextModule) val contextFirFile = resolveSession.getOrBuildFirFile(contextKtFile) - val sessionHolder = transformer.components + val sessionHolder = SessionHolderImpl(contextSession, contextSession.getScopeSession()) val elementContext = ContextCollector.process(contextFirFile, sessionHolder, contextPsiElement) ?: errorWithAttachment("Cannot find enclosing context for ${contextPsiElement::class}") { withPsiEntry("contextPsiElement", contextPsiElement) diff --git a/analysis/project-structure/src/org/jetbrains/kotlin/analysis/project/structure/KtModule.kt b/analysis/project-structure/src/org/jetbrains/kotlin/analysis/project/structure/KtModule.kt index a75ff17cb61..5a753fc9202 100644 --- a/analysis/project-structure/src/org/jetbrains/kotlin/analysis/project/structure/KtModule.kt +++ b/analysis/project-structure/src/org/jetbrains/kotlin/analysis/project/structure/KtModule.kt @@ -10,6 +10,7 @@ import com.intellij.psi.PsiFile import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlin.psi.KtCodeFragment import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices import java.nio.file.Path @@ -214,6 +215,24 @@ public interface KtScriptDependencyModule : KtModule { public val file: KtFile? } +/** + * A module for a Kotlin code fragment – a piece of code analyzed against a specific context element. + */ +public interface KtCodeFragmentModule : KtModule { + /** + * A code fragment PSI. + */ + public val codeFragment: KtCodeFragment + + /** + * Module of the context element. + */ + public val contextModule: KtModule + + override val moduleDescription: String + get() = "Code fragment" +} + /** * A set of sources which live outside the project content root. E.g, testdata files or source files of some other project. */ diff --git a/analysis/project-structure/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtCodeFragmentModuleImpl.kt b/analysis/project-structure/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtCodeFragmentModuleImpl.kt new file mode 100644 index 00000000000..64461424918 --- /dev/null +++ b/analysis/project-structure/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtCodeFragmentModuleImpl.kt @@ -0,0 +1,58 @@ +/* + * 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.project.structure.impl + +import com.intellij.openapi.project.Project +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.platform.TargetPlatform +import org.jetbrains.kotlin.psi.KtCodeFragment +import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices +import java.util.Objects + +public class KtCodeFragmentModuleImpl( + override val codeFragment: KtCodeFragment, + override val contextModule: KtModule +) : KtCodeFragmentModule { + override val project: Project + get() = contextModule.project + + override val platform: TargetPlatform + get() = contextModule.platform + + override val analyzerServices: PlatformDependentAnalyzerServices + get() = contextModule.analyzerServices + + override val contentScope: GlobalSearchScope + get() = GlobalSearchScope.fileScope(codeFragment) + + override val directRegularDependencies: List + get() = contextModule.directRegularDependencies + + override val directDependsOnDependencies: List + get() = contextModule.directDependsOnDependencies + + override val directFriendDependencies: List + get() = listOf(contextModule) + contextModule.directFriendDependencies + + override val transitiveDependsOnDependencies: List + get() = contextModule.transitiveDependsOnDependencies + + override fun equals(other: Any?): Boolean { + if (this === other) return true + + if (other is KtCodeFragmentModuleImpl) { + return codeFragment == other.codeFragment && contextModule == other.contextModule + } + + return false + } + + override fun hashCode(): Int { + return Objects.hash(codeFragment, contextModule) + } +} \ No newline at end of file