Use separate module analysis in CliReplAnalyzerEngine
This commit is contained in:
+1
-1
@@ -422,7 +422,7 @@ object KotlinToJVMBytecodeCompiler {
|
||||
CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace(),
|
||||
environment.configuration,
|
||||
{ scope -> JvmPackagePartProvider(environment, scope) },
|
||||
scope
|
||||
sourceModuleSearchScope = scope
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -16,22 +16,19 @@
|
||||
|
||||
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.JvmPackagePartProvider
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.container.get
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.frontend.java.di.createContainerForTopDownSingleModuleAnalyzerForJvm
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory
|
||||
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.lazy.ResolveSession
|
||||
import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo
|
||||
@@ -49,32 +46,26 @@ class CliReplAnalyzerEngine(environment: KotlinCoreEnvironment) {
|
||||
val trace: BindingTraceContext = CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace()
|
||||
|
||||
init {
|
||||
val moduleContext = TopDownAnalyzerFacadeForJVM.createContextWithSealedModule(environment.project, environment.configuration)
|
||||
this.module = moduleContext.module
|
||||
|
||||
this.scriptDeclarationFactory = ScriptMutableDeclarationProviderFactory()
|
||||
|
||||
val moduleContentScope = ProjectScope.getAllScope(environment.project)
|
||||
val container = createContainerForTopDownSingleModuleAnalyzerForJvm(
|
||||
moduleContext,
|
||||
// Module source scope is empty because all binary classes are in the dependency module, and all source classes are guaranteed
|
||||
// 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)
|
||||
val container = TopDownAnalyzerFacadeForJVM.createContainer(
|
||||
environment.project,
|
||||
emptyList(),
|
||||
trace,
|
||||
scriptDeclarationFactory,
|
||||
moduleContentScope,
|
||||
JvmPackagePartProvider(environment, moduleContentScope)
|
||||
environment.configuration,
|
||||
{ scope -> JvmPackagePartProvider(environment, scope) },
|
||||
{ storageManager, files -> ScriptMutableDeclarationProviderFactory() },
|
||||
GlobalSearchScope.EMPTY_SCOPE
|
||||
)
|
||||
|
||||
this.module = container.get<ModuleDescriptorImpl>()
|
||||
this.scriptDeclarationFactory = container.get<ScriptMutableDeclarationProviderFactory>()
|
||||
this.resolveSession = container.get<ResolveSession>()
|
||||
this.topDownAnalysisContext = TopDownAnalysisContext(
|
||||
TopDownAnalysisMode.LocalDeclarations, DataFlowInfoFactory.EMPTY, resolveSession.declarationScopeProvider
|
||||
)
|
||||
this.topDownAnalyzer = container.get<LazyTopDownAnalyzer>()
|
||||
|
||||
moduleContext.initializeModuleContents(CompositePackageFragmentProvider(
|
||||
listOf(
|
||||
resolveSession.packageFragmentProvider,
|
||||
container.get<JavaDescriptorResolver>().packageFragmentProvider
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
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.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
import org.jetbrains.kotlin.container.ComponentProvider
|
||||
import org.jetbrains.kotlin.container.get
|
||||
import org.jetbrains.kotlin.context.ContextForNewModule
|
||||
import org.jetbrains.kotlin.context.MutableModuleContext
|
||||
import org.jetbrains.kotlin.context.ProjectContext
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
||||
import org.jetbrains.kotlin.descriptors.PackagePartProvider
|
||||
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.declarations.DeclarationProviderFactory
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import java.util.*
|
||||
|
||||
object TopDownAnalyzerFacadeForJVM {
|
||||
@@ -67,9 +70,34 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
files: Collection<KtFile>,
|
||||
trace: BindingTrace,
|
||||
configuration: CompilerConfiguration,
|
||||
packagePartProviderFactory: (GlobalSearchScope) -> PackagePartProvider,
|
||||
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
|
||||
declarationProviderFactory: (StorageManager, Collection<KtFile>) -> DeclarationProviderFactory = ::FileBasedDeclarationProviderFactory,
|
||||
sourceModuleSearchScope: GlobalSearchScope = newModuleSearchScope(project, files)
|
||||
): 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 storageManager = moduleContext.storageManager
|
||||
@@ -98,7 +126,7 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
|
||||
val dependenciesContainer = createContainerForTopDownAnalyzerForJvm(
|
||||
dependenciesContext, trace, DeclarationProviderFactory.EMPTY, dependencyScope, lookupTracker,
|
||||
packagePartProviderFactory(dependencyScope), languageVersionSettings, moduleClassResolver
|
||||
packagePartProvider(dependencyScope), languageVersionSettings, moduleClassResolver
|
||||
)
|
||||
|
||||
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)
|
||||
// TODO: get rid of duplicate invocation of CodeAnalyzerInitializer#initialize, or refactor CliLightClassGenerationSupport
|
||||
val container = createContainerForTopDownAnalyzerForJvm(
|
||||
moduleContext, trace, FileBasedDeclarationProviderFactory(storageManager, files), sourceScope, lookupTracker,
|
||||
moduleContext, trace, declarationProviderFactory(storageManager, files), sourceScope, lookupTracker,
|
||||
IncrementalPackagePartProvider.create(
|
||||
packagePartProviderFactory(sourceScope), targetIds, incrementalComponents, storageManager
|
||||
packagePartProvider(sourceScope), targetIds, incrementalComponents, storageManager
|
||||
),
|
||||
languageVersionSettings, moduleClassResolver
|
||||
).apply {
|
||||
@@ -152,14 +180,7 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
additionalProviders
|
||||
))
|
||||
|
||||
container.get<LazyTopDownAnalyzer>().analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
|
||||
|
||||
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)
|
||||
return container
|
||||
}
|
||||
|
||||
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")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user