Use separate module analysis in CliReplAnalyzerEngine
This commit is contained in:
+1
-1
@@ -422,7 +422,7 @@ object KotlinToJVMBytecodeCompiler {
|
|||||||
CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace(),
|
CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace(),
|
||||||
environment.configuration,
|
environment.configuration,
|
||||||
{ scope -> JvmPackagePartProvider(environment, scope) },
|
{ scope -> JvmPackagePartProvider(environment, scope) },
|
||||||
scope
|
sourceModuleSearchScope = scope
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,22 +16,19 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.cli.jvm.repl
|
package org.jetbrains.kotlin.cli.jvm.repl
|
||||||
|
|
||||||
import com.intellij.psi.search.ProjectScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
|
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
|
import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.container.get
|
import org.jetbrains.kotlin.container.get
|
||||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||||
import org.jetbrains.kotlin.diagnostics.Severity
|
import org.jetbrains.kotlin.diagnostics.Severity
|
||||||
import org.jetbrains.kotlin.frontend.java.di.createContainerForTopDownSingleModuleAnalyzerForJvm
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.*
|
import org.jetbrains.kotlin.resolve.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory
|
||||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
|
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
|
||||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||||
import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo
|
import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo
|
||||||
@@ -49,32 +46,26 @@ class CliReplAnalyzerEngine(environment: KotlinCoreEnvironment) {
|
|||||||
val trace: BindingTraceContext = CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace()
|
val trace: BindingTraceContext = CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val moduleContext = TopDownAnalyzerFacadeForJVM.createContextWithSealedModule(environment.project, environment.configuration)
|
// Module source scope is empty because all binary classes are in the dependency module, and all source classes are guaranteed
|
||||||
this.module = moduleContext.module
|
// to be found via ResolveSession. The latter is true as long as light classes are not needed in REPL (which is currently true
|
||||||
|
// because no symbol declared in the REPL session can be used from Java)
|
||||||
this.scriptDeclarationFactory = ScriptMutableDeclarationProviderFactory()
|
val container = TopDownAnalyzerFacadeForJVM.createContainer(
|
||||||
|
environment.project,
|
||||||
val moduleContentScope = ProjectScope.getAllScope(environment.project)
|
emptyList(),
|
||||||
val container = createContainerForTopDownSingleModuleAnalyzerForJvm(
|
|
||||||
moduleContext,
|
|
||||||
trace,
|
trace,
|
||||||
scriptDeclarationFactory,
|
environment.configuration,
|
||||||
moduleContentScope,
|
{ scope -> JvmPackagePartProvider(environment, scope) },
|
||||||
JvmPackagePartProvider(environment, moduleContentScope)
|
{ storageManager, files -> ScriptMutableDeclarationProviderFactory() },
|
||||||
|
GlobalSearchScope.EMPTY_SCOPE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
this.module = container.get<ModuleDescriptorImpl>()
|
||||||
|
this.scriptDeclarationFactory = container.get<ScriptMutableDeclarationProviderFactory>()
|
||||||
this.resolveSession = container.get<ResolveSession>()
|
this.resolveSession = container.get<ResolveSession>()
|
||||||
this.topDownAnalysisContext = TopDownAnalysisContext(
|
this.topDownAnalysisContext = TopDownAnalysisContext(
|
||||||
TopDownAnalysisMode.LocalDeclarations, DataFlowInfoFactory.EMPTY, resolveSession.declarationScopeProvider
|
TopDownAnalysisMode.LocalDeclarations, DataFlowInfoFactory.EMPTY, resolveSession.declarationScopeProvider
|
||||||
)
|
)
|
||||||
this.topDownAnalyzer = container.get<LazyTopDownAnalyzer>()
|
this.topDownAnalyzer = container.get<LazyTopDownAnalyzer>()
|
||||||
|
|
||||||
moduleContext.initializeModuleContents(CompositePackageFragmentProvider(
|
|
||||||
listOf(
|
|
||||||
resolveSession.packageFragmentProvider,
|
|
||||||
container.get<JavaDescriptorResolver>().packageFragmentProvider
|
|
||||||
)
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ReplLineAnalysisResult {
|
interface ReplLineAnalysisResult {
|
||||||
|
|||||||
+33
-12
@@ -26,11 +26,13 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
|||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||||
|
import org.jetbrains.kotlin.container.ComponentProvider
|
||||||
import org.jetbrains.kotlin.container.get
|
import org.jetbrains.kotlin.container.get
|
||||||
import org.jetbrains.kotlin.context.ContextForNewModule
|
import org.jetbrains.kotlin.context.ContextForNewModule
|
||||||
import org.jetbrains.kotlin.context.MutableModuleContext
|
import org.jetbrains.kotlin.context.MutableModuleContext
|
||||||
import org.jetbrains.kotlin.context.ProjectContext
|
import org.jetbrains.kotlin.context.ProjectContext
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
||||||
import org.jetbrains.kotlin.descriptors.PackagePartProvider
|
import org.jetbrains.kotlin.descriptors.PackagePartProvider
|
||||||
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
|
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
|
||||||
@@ -57,6 +59,7 @@ import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
|||||||
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
|
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
|
||||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
||||||
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
|
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
|
||||||
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
object TopDownAnalyzerFacadeForJVM {
|
object TopDownAnalyzerFacadeForJVM {
|
||||||
@@ -67,9 +70,34 @@ object TopDownAnalyzerFacadeForJVM {
|
|||||||
files: Collection<KtFile>,
|
files: Collection<KtFile>,
|
||||||
trace: BindingTrace,
|
trace: BindingTrace,
|
||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
packagePartProviderFactory: (GlobalSearchScope) -> PackagePartProvider,
|
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
|
||||||
|
declarationProviderFactory: (StorageManager, Collection<KtFile>) -> DeclarationProviderFactory = ::FileBasedDeclarationProviderFactory,
|
||||||
sourceModuleSearchScope: GlobalSearchScope = newModuleSearchScope(project, files)
|
sourceModuleSearchScope: GlobalSearchScope = newModuleSearchScope(project, files)
|
||||||
): AnalysisResult {
|
): AnalysisResult {
|
||||||
|
val container = createContainer(
|
||||||
|
project, files, trace, configuration, packagePartProvider, declarationProviderFactory, sourceModuleSearchScope
|
||||||
|
)
|
||||||
|
|
||||||
|
container.get<LazyTopDownAnalyzer>().analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
|
||||||
|
|
||||||
|
val module = container.get<ModuleDescriptor>()
|
||||||
|
for (extension in AnalysisCompletedHandlerExtension.getInstances(project)) {
|
||||||
|
val result = extension.analysisCompleted(project, module, trace, files)
|
||||||
|
if (result != null) return result
|
||||||
|
}
|
||||||
|
|
||||||
|
return AnalysisResult.success(trace.bindingContext, module)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createContainer(
|
||||||
|
project: Project,
|
||||||
|
files: Collection<KtFile>,
|
||||||
|
trace: BindingTrace,
|
||||||
|
configuration: CompilerConfiguration,
|
||||||
|
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
|
||||||
|
declarationProviderFactory: (StorageManager, Collection<KtFile>) -> DeclarationProviderFactory,
|
||||||
|
sourceModuleSearchScope: GlobalSearchScope
|
||||||
|
): ComponentProvider {
|
||||||
val moduleContext = createModuleContext(project, configuration)
|
val moduleContext = createModuleContext(project, configuration)
|
||||||
|
|
||||||
val storageManager = moduleContext.storageManager
|
val storageManager = moduleContext.storageManager
|
||||||
@@ -98,7 +126,7 @@ object TopDownAnalyzerFacadeForJVM {
|
|||||||
|
|
||||||
val dependenciesContainer = createContainerForTopDownAnalyzerForJvm(
|
val dependenciesContainer = createContainerForTopDownAnalyzerForJvm(
|
||||||
dependenciesContext, trace, DeclarationProviderFactory.EMPTY, dependencyScope, lookupTracker,
|
dependenciesContext, trace, DeclarationProviderFactory.EMPTY, dependencyScope, lookupTracker,
|
||||||
packagePartProviderFactory(dependencyScope), languageVersionSettings, moduleClassResolver
|
packagePartProvider(dependencyScope), languageVersionSettings, moduleClassResolver
|
||||||
)
|
)
|
||||||
|
|
||||||
moduleClassResolver.compiledCodeResolver = dependenciesContainer.get<JavaDescriptorResolver>()
|
moduleClassResolver.compiledCodeResolver = dependenciesContainer.get<JavaDescriptorResolver>()
|
||||||
@@ -114,9 +142,9 @@ object TopDownAnalyzerFacadeForJVM {
|
|||||||
// to be stored in CliLightClassGenerationSupport, and it better be the source one (otherwise light classes would not be found)
|
// to be stored in CliLightClassGenerationSupport, and it better be the source one (otherwise light classes would not be found)
|
||||||
// TODO: get rid of duplicate invocation of CodeAnalyzerInitializer#initialize, or refactor CliLightClassGenerationSupport
|
// TODO: get rid of duplicate invocation of CodeAnalyzerInitializer#initialize, or refactor CliLightClassGenerationSupport
|
||||||
val container = createContainerForTopDownAnalyzerForJvm(
|
val container = createContainerForTopDownAnalyzerForJvm(
|
||||||
moduleContext, trace, FileBasedDeclarationProviderFactory(storageManager, files), sourceScope, lookupTracker,
|
moduleContext, trace, declarationProviderFactory(storageManager, files), sourceScope, lookupTracker,
|
||||||
IncrementalPackagePartProvider.create(
|
IncrementalPackagePartProvider.create(
|
||||||
packagePartProviderFactory(sourceScope), targetIds, incrementalComponents, storageManager
|
packagePartProvider(sourceScope), targetIds, incrementalComponents, storageManager
|
||||||
),
|
),
|
||||||
languageVersionSettings, moduleClassResolver
|
languageVersionSettings, moduleClassResolver
|
||||||
).apply {
|
).apply {
|
||||||
@@ -152,14 +180,7 @@ object TopDownAnalyzerFacadeForJVM {
|
|||||||
additionalProviders
|
additionalProviders
|
||||||
))
|
))
|
||||||
|
|
||||||
container.get<LazyTopDownAnalyzer>().analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
|
return container
|
||||||
|
|
||||||
for (extension in AnalysisCompletedHandlerExtension.getInstances(project)) {
|
|
||||||
val result = extension.analysisCompleted(project, module, trace, files)
|
|
||||||
if (result != null) return result
|
|
||||||
}
|
|
||||||
|
|
||||||
return AnalysisResult.success(trace.bindingContext, module)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun newModuleSearchScope(project: Project, files: Collection<KtFile>): GlobalSearchScope {
|
fun newModuleSearchScope(project: Project, files: Collection<KtFile>): GlobalSearchScope {
|
||||||
|
|||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
>>> val x: Pair<Any?, Any?> = null to null
|
||||||
|
>>> if (x.first != null) x.first.hashCode()
|
||||||
|
error: smart cast to 'Any' is impossible, because 'x.first' is a public API property declared in different module
|
||||||
|
if (x.first != null) x.first.hashCode()
|
||||||
|
^
|
||||||
@@ -200,6 +200,21 @@ public class ReplInterpreterTestGenerated extends AbstractReplInterpreterTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/repl/modules")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Modules extends AbstractReplInterpreterTest {
|
||||||
|
public void testAllFilesPresentInModules() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/repl/modules"), Pattern.compile("^(.+)\\.repl$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt10001.repl")
|
||||||
|
public void testKt10001() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/repl/modules/kt10001.repl");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/repl/multiline")
|
@TestMetadata("compiler/testData/repl/multiline")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user