diff --git a/benchmarks/src/org/jetbrains/kotlin/benchmarks/AbstractSimpleFileBenchmark.kt b/benchmarks/src/org/jetbrains/kotlin/benchmarks/AbstractSimpleFileBenchmark.kt index 2c74d915dd9..c1b7c44b7a6 100644 --- a/benchmarks/src/org/jetbrains/kotlin/benchmarks/AbstractSimpleFileBenchmark.kt +++ b/benchmarks/src/org/jetbrains/kotlin/benchmarks/AbstractSimpleFileBenchmark.kt @@ -153,7 +153,7 @@ abstract class AbstractSimpleFileBenchmark { private fun analyzeGreenFileIr(bh: Blackhole) { val scope = GlobalSearchScope.filesScope(env.project, listOf(file.virtualFile)) .uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(env.project)) - val session = createSessionForTests(env, scope) + val session = createSessionForTests(env.toAbstractProjectEnvironment(), scope.toAbstractProjectFileSearchScope()) val firProvider = session.firProvider as FirProviderImpl val builder = RawFirBuilder(session, firProvider.kotlinScopeProvider, PsiHandlingMode.COMPILER) diff --git a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java index 4a7352703c2..d08ea9469cd 100644 --- a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java +++ b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java @@ -20,10 +20,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.analyzer.AnalysisResult; import org.jetbrains.kotlin.backend.common.output.OutputFileCollection; -import org.jetbrains.kotlin.cli.common.CLICompiler; -import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys; -import org.jetbrains.kotlin.cli.common.CommonCompilerPerformanceManager; -import org.jetbrains.kotlin.cli.common.ExitCode; +import org.jetbrains.kotlin.cli.common.*; import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments; import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArgumentsKt; import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants; @@ -68,7 +65,6 @@ import java.util.stream.Collectors; import static org.jetbrains.kotlin.cli.common.ExitCode.COMPILATION_ERROR; import static org.jetbrains.kotlin.cli.common.ExitCode.OK; -import static org.jetbrains.kotlin.cli.common.UtilsKt.checkKotlinPackageUsage; import static org.jetbrains.kotlin.cli.common.UtilsKt.getLibraryFromHome; import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*; @@ -212,7 +208,7 @@ public class K2JSCompiler extends CLICompiler { environmentForJS.getConfiguration().put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.getAllowKotlinPackage()); - if (!checkKotlinPackageUsage(environmentForJS, sourcesFiles)) return ExitCode.COMPILATION_ERROR; + if (!UtilsKt.checkKotlinPackageUsage(environmentForJS.getConfiguration(), sourcesFiles)) return ExitCode.COMPILATION_ERROR; if (arguments.getOutputFile() == null) { messageCollector.report(ERROR, "Specify output file via -output", null); diff --git a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt index da92ac03ca3..1c5b77a971b 100644 --- a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt +++ b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt @@ -139,7 +139,7 @@ class K2JsIrCompiler : CLICompiler() { configurationJs.put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage) - if (!checkKotlinPackageUsage(environmentForJS, sourcesFiles)) return ExitCode.COMPILATION_ERROR + if (!checkKotlinPackageUsage(environmentForJS.configuration, sourcesFiles)) return ExitCode.COMPILATION_ERROR val outputFilePath = arguments.outputFile if (outputFilePath == null) { diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/utils.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/utils.kt index a54ec942858..8e20dc6ab62 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/utils.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/utils.kt @@ -19,7 +19,7 @@ package org.jetbrains.kotlin.cli.common import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageUtil -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.isSubpackageOf import org.jetbrains.kotlin.psi.KtFile @@ -28,11 +28,11 @@ import org.jetbrains.kotlin.utils.KotlinPaths import java.io.File import kotlin.system.exitProcess -fun checkKotlinPackageUsage(environment: KotlinCoreEnvironment, files: Collection): Boolean { - if (environment.configuration.getBoolean(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE)) { +fun checkKotlinPackageUsage(configuration: CompilerConfiguration, files: Collection): Boolean { + if (configuration.getBoolean(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE)) { return true } - val messageCollector = environment.configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE) + val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE) val kotlinPackage = FqName("kotlin") for (file in files) { if (file.packageFqName.isSubpackageOf(kotlinPackage)) { diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/FirKotlinToJvmBytecodeCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/FirKotlinToJvmBytecodeCompiler.kt index a9b91023486..0e63db29f3c 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/FirKotlinToJvmBytecodeCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/FirKotlinToJvmBytecodeCompiler.kt @@ -5,17 +5,8 @@ package org.jetbrains.kotlin.cli.jvm.compiler -import com.intellij.openapi.project.Project -import com.intellij.openapi.util.Disposer -import com.intellij.openapi.vfs.StandardFileSystems -import com.intellij.openapi.vfs.VirtualFileManager -import com.intellij.openapi.vfs.VirtualFileSystem -import com.intellij.psi.PsiElementFinder -import com.intellij.psi.search.GlobalSearchScope -import com.intellij.psi.search.ProjectScope import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices import org.jetbrains.kotlin.asJava.FilteredJvmDiagnostics -import org.jetbrains.kotlin.asJava.finder.JavaElementFinder import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.jvm.JvmGeneratorExtensionsImpl import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory @@ -26,6 +17,7 @@ import org.jetbrains.kotlin.cli.common.checkKotlinPackageUsage import org.jetbrains.kotlin.cli.common.fir.FirDiagnosticsCompilerResultsReporter import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING +import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots import org.jetbrains.kotlin.codegen.ClassBuilderFactories @@ -34,16 +26,23 @@ import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.fir.DependencyListForCliModule import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic import org.jetbrains.kotlin.fir.backend.Fir2IrResult import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers +import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider import org.jetbrains.kotlin.fir.moduleData +import org.jetbrains.kotlin.fir.pipeline.buildFirFromKtFiles +import org.jetbrains.kotlin.fir.pipeline.convertToIr +import org.jetbrains.kotlin.fir.pipeline.runCheckers +import org.jetbrains.kotlin.fir.pipeline.runResolution +import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.session.FirSessionFactory import org.jetbrains.kotlin.fir.session.FirSessionFactory.createSessionWithDependencies +import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment +import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackagePartProvider import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents import org.jetbrains.kotlin.modules.Module @@ -66,42 +65,36 @@ import kotlin.collections.set object FirKotlinToJvmBytecodeCompiler { fun compileModulesUsingFrontendIR( - environment: KotlinCoreEnvironment, + projectEnvironment: AbstractProjectEnvironment, + projectConfiguration: CompilerConfiguration, + messageCollector: MessageCollector, + allSources: List, buildFile: File?, chunk: List, extendedAnalysisMode: Boolean ): Boolean { - val project = environment.project - val performanceManager = environment.configuration.get(CLIConfigurationKeys.PERF_MANAGER) + val performanceManager = projectConfiguration.get(CLIConfigurationKeys.PERF_MANAGER) - environment.messageCollector.report( + messageCollector.report( STRONG_WARNING, "ATTENTION!\n This build uses in-dev FIR: \n -Xuse-fir" ) - - val psiFinderExtensionPoint = PsiElementFinder.EP.getPoint(project) - if (psiFinderExtensionPoint.extensionList.any { it is JavaElementFinder }) { - psiFinderExtensionPoint.unregisterExtension(JavaElementFinder::class.java) - } - - val projectConfiguration = environment.configuration - val localFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL) val outputs = newLinkedHashMapWithExpectedSize(chunk.size) - val targetIds = environment.configuration.get(JVMConfigurationKeys.MODULES)?.map(::TargetId) - val incrementalComponents = environment.configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS) + val targetIds = projectConfiguration.get(JVMConfigurationKeys.MODULES)?.map(::TargetId) + val incrementalComponents = projectConfiguration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS) val isMultiModuleChunk = chunk.size > 1 for (module in chunk) { val moduleConfiguration = projectConfiguration.applyModuleProperties(module, buildFile) val context = CompilationContext( module, - project, - environment, + module.getSourceFiles( + allSources, (projectEnvironment as? PsiBasedProjectEnvironment)?.localFileSystem, isMultiModuleChunk, buildFile + ), + projectEnvironment, + messageCollector, moduleConfiguration, - localFileSystem, - isMultiModuleChunk, - buildFile, performanceManager, targetIds, incrementalComponents, @@ -109,8 +102,6 @@ object FirKotlinToJvmBytecodeCompiler { ) val generationState = context.compileModule() ?: return false outputs[module] = generationState - - Disposer.dispose(environment.project) } val mainClassFqName: FqName? = @@ -118,17 +109,18 @@ object FirKotlinToJvmBytecodeCompiler { TODO(".jar output is not yet supported for -Xuse-fir: KT-42868") else null - return writeOutputs(environment, projectConfiguration, chunk, outputs, mainClassFqName) + return writeOutputs( + (projectEnvironment as? PsiBasedProjectEnvironment)?.project, projectConfiguration, chunk, outputs, mainClassFqName + ) } private fun CompilationContext.compileModule(): GenerationState? { performanceManager?.notifyAnalysisStarted() ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - val ktFiles = module.getSourceFiles(environment, localFileSystem, isMultiModuleChunk, buildFile) - if (!checkKotlinPackageUsage(environment, ktFiles)) return null + if (!checkKotlinPackageUsage(moduleConfiguration, allSources)) return null - val firAnalyzerFacade = runFrontend(ktFiles).also { + val firResult = runFrontend(allSources).also { performanceManager?.notifyAnalysisFinished() } ?: return null @@ -136,16 +128,15 @@ object FirKotlinToJvmBytecodeCompiler { performanceManager?.notifyIRTranslationStarted() val extensions = JvmGeneratorExtensionsImpl(moduleConfiguration) - val fir2IrResult = firAnalyzerFacade.convertToIr(extensions) - val session = firAnalyzerFacade.session + val fir2IrResult = firResult.session.convertToIr(firResult.scopeSession, firResult.fir, extensions) performanceManager?.notifyIRTranslationFinished() val generationState = runBackend( - ktFiles, + allSources, fir2IrResult, extensions, - session + firResult.session ) performanceManager?.notifyIRGenerationFinished() @@ -155,22 +146,28 @@ object FirKotlinToJvmBytecodeCompiler { return generationState } - private fun CompilationContext.runFrontend(ktFiles: List): FirAnalyzerFacade? { + private class FirResult( + val session: FirSession, + val scopeSession: ScopeSession, + val fir: List + ) + + private fun CompilationContext.runFrontend(ktFiles: List): FirResult? { @Suppress("NAME_SHADOWING") var ktFiles = ktFiles val syntaxErrors = ktFiles.fold(false) { errorsFound, ktFile -> - AnalyzerWithCompilerReport.reportSyntaxErrors(ktFile, environment.messageCollector).isHasErrors or errorsFound + AnalyzerWithCompilerReport.reportSyntaxErrors(ktFile, messageCollector).isHasErrors or errorsFound } - var sourceScope = GlobalSearchScope.filesWithoutLibrariesScope(project, ktFiles.map { it.virtualFile }) - .uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(project)) + var sourceScope = (projectEnvironment as PsiBasedProjectEnvironment).getSearchScopeByPsiFiles(ktFiles) + + projectEnvironment.getSearchScopeForProjectJavaSources() - var librariesScope = ProjectScope.getLibrariesScope(project) + var librariesScope = projectEnvironment.getSearchScopeForProjectLibraries() val providerAndScopeForIncrementalCompilation = createComponentsForIncrementalCompilation(sourceScope) providerAndScopeForIncrementalCompilation?.scope?.let { - librariesScope = librariesScope.intersectWith(GlobalSearchScope.notScope(it)) + librariesScope -= it } val languageVersionSettings = moduleConfiguration.languageVersionSettings @@ -183,7 +180,7 @@ object FirKotlinToJvmBytecodeCompiler { name: String, platform: TargetPlatform, analyzerServices: PlatformDependentAnalyzerServices, - sourceScope: GlobalSearchScope, + sourceScope: AbstractProjectFileSearchScope, dependenciesConfigurator: DependencyListForCliModule.Builder.() -> Unit = {} ): FirSession { return createSessionWithDependencies( @@ -191,32 +188,30 @@ object FirKotlinToJvmBytecodeCompiler { platform, analyzerServices, externalSessionProvider = sessionProvider, - project, + projectEnvironment, languageVersionSettings, sourceScope, librariesScope, - lookupTracker = environment.configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER), + lookupTracker = moduleConfiguration.get(CommonConfigurationKeys.LOOKUP_TRACKER), providerAndScopeForIncrementalCompilation, - getPackagePartProvider = { environment.createPackagePartProvider(it) }, dependenciesConfigurator = { dependencies(moduleConfiguration.jvmClasspathRoots.map { it.toPath() }) dependencies(moduleConfiguration.jvmModularRoots.map { it.toPath() }) friendDependencies(moduleConfiguration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList()) dependenciesConfigurator() - }, - sessionConfigurator = { - if (extendedAnalysisMode) { - registerExtendedCommonCheckers() - } } - ) + ) { + if (extendedAnalysisMode) { + registerExtendedCommonCheckers() + } + } } val commonSession = runIf( languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects) && commonKtFiles.isNotEmpty() ) { - val commonSourcesScope = GlobalSearchScope.filesWithoutLibrariesScope(project, commonKtFiles.map { it.virtualFile }) - sourceScope = sourceScope.intersectWith(GlobalSearchScope.notScope(commonSourcesScope)) + val commonSourcesScope = projectEnvironment.getSearchScopeByPsiFiles(commonKtFiles) + sourceScope -= commonSourcesScope ktFiles = ktFiles.filterNot { it.isCommonSource == true } createSession( "${module.getModuleName()}-common", @@ -238,41 +233,39 @@ object FirKotlinToJvmBytecodeCompiler { friendDependencies(module.getFriendPaths()) } - val commonAnalyzerFacade = commonSession?.let { FirAnalyzerFacade(it, languageVersionSettings, commonKtFiles) } - val firAnalyzerFacade = FirAnalyzerFacade(session, languageVersionSettings, ktFiles) + val commonRawFir = commonSession?.buildFirFromKtFiles(commonKtFiles) + val rawFir = session.buildFirFromKtFiles(ktFiles) - commonAnalyzerFacade?.runResolution() val allFirDiagnostics = mutableListOf() - commonAnalyzerFacade?.runCheckers()?.values?.flattenTo(allFirDiagnostics) - firAnalyzerFacade.runResolution() - firAnalyzerFacade.runCheckers().values.flattenTo(allFirDiagnostics) - val hasErrors = FirDiagnosticsCompilerResultsReporter.reportDiagnostics(allFirDiagnostics, environment.messageCollector) + commonSession?.apply { + val (commonScopeSession, commonFir) = runResolution(commonRawFir!!) + runCheckers(commonScopeSession, commonFir).values.flattenTo(allFirDiagnostics) + } - return firAnalyzerFacade.takeUnless { syntaxErrors || hasErrors } + val (scopeSession, fir) = session.runResolution(rawFir) + session.runCheckers(scopeSession, fir).values.flattenTo(allFirDiagnostics) + + val hasErrors = FirDiagnosticsCompilerResultsReporter.reportDiagnostics(allFirDiagnostics, messageCollector) + + return if (syntaxErrors || hasErrors) null else FirResult(session, scopeSession, fir) } private fun CompilationContext.createComponentsForIncrementalCompilation( - sourceScope: GlobalSearchScope + sourceScope: AbstractProjectFileSearchScope ): FirSessionFactory.ProviderAndScopeForIncrementalCompilation? { if (targetIds == null || incrementalComponents == null) return null - val fileSystem = environment.projectEnvironment.environment.localFileSystem val directoryWithIncrementalPartsFromPreviousCompilation = moduleConfiguration[JVMConfigurationKeys.OUTPUT_DIRECTORY] ?: return null - val previouslyCompiledFiles = directoryWithIncrementalPartsFromPreviousCompilation.walk() + val incrementalCompilationScope = directoryWithIncrementalPartsFromPreviousCompilation.walk() .filter { it.extension == "class" } - .mapNotNull { fileSystem.findFileByIoFile(it) } - .toList() - .takeIf { it.isNotEmpty() } + .let { projectEnvironment.getSearchScopeByIoFiles(it.asIterable()) } + .takeIf { !it.isEmpty } ?: return null val packagePartProvider = IncrementalPackagePartProvider( - environment.createPackagePartProvider(sourceScope), + projectEnvironment.getPackagePartProvider(sourceScope), targetIds.map(incrementalComponents::getIncrementalCache) ) - val incrementalCompilationScope = GlobalSearchScope.filesWithoutLibrariesScope( - project, - previouslyCompiledFiles - ) return FirSessionFactory.ProviderAndScopeForIncrementalCompilation(packagePartProvider, incrementalCompilationScope) } @@ -291,7 +284,7 @@ object FirKotlinToJvmBytecodeCompiler { ) val generationState = GenerationState.Builder( - environment.project, ClassBuilderFactories.BINARIES, + (projectEnvironment as PsiBasedProjectEnvironment).project, ClassBuilderFactories.BINARIES, moduleFragment.descriptor, dummyBindingContext, ktFiles, moduleConfiguration ).codegenFactory( @@ -326,7 +319,7 @@ object FirKotlinToJvmBytecodeCompiler { generationState.collectedExtraJvmDiagnostics, dummyBindingContext.diagnostics ), - environment.messageCollector + messageCollector ) ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() @@ -335,12 +328,10 @@ object FirKotlinToJvmBytecodeCompiler { private class CompilationContext( val module: Module, - val project: Project, - val environment: KotlinCoreEnvironment, + val allSources: List, + val projectEnvironment: AbstractProjectEnvironment, + val messageCollector: MessageCollector, val moduleConfiguration: CompilerConfiguration, - val localFileSystem: VirtualFileSystem, - val isMultiModuleChunk: Boolean, - val buildFile: File?, val performanceManager: CommonCompilerPerformanceManager?, val targetIds: List?, val incrementalComponents: IncrementalCompilationComponents?, diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt index a0fba83314d..72c38c37880 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt @@ -84,7 +84,19 @@ object KotlinToJVMBytecodeCompiler { val projectConfiguration = environment.configuration if (projectConfiguration.getBoolean(CommonConfigurationKeys.USE_FIR)) { val extendedAnalysisMode = projectConfiguration.getBoolean(CommonConfigurationKeys.USE_FIR_EXTENDED_CHECKERS) - return FirKotlinToJvmBytecodeCompiler.compileModulesUsingFrontendIR(environment, buildFile, chunk, extendedAnalysisMode) + val projectEnvironment = + PsiBasedProjectEnvironment( + environment.project, + VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL), + { environment.createPackagePartProvider(it) } + ) + return FirKotlinToJvmBytecodeCompiler.compileModulesUsingFrontendIR( + projectEnvironment, + environment.configuration, + environment.messageCollector, + environment.getSourceFiles(), + buildFile, chunk, extendedAnalysisMode + ) } val result = repeatAnalysisIfNeeded(analyze(environment), environment) @@ -106,14 +118,14 @@ object KotlinToJVMBytecodeCompiler { for (module in chunk) { ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - val ktFiles = module.getSourceFiles(environment, localFileSystem, chunk.size > 1, buildFile) - if (!checkKotlinPackageUsage(environment, ktFiles)) return false + val ktFiles = module.getSourceFiles(environment.getSourceFiles(), localFileSystem, chunk.size > 1, buildFile) + if (!checkKotlinPackageUsage(environment.configuration, ktFiles)) return false val moduleConfiguration = projectConfiguration.applyModuleProperties(module, buildFile) outputs[module] = generate(environment, moduleConfiguration, result, ktFiles, module) } - return writeOutputs(environment, projectConfiguration, chunk, outputs, mainClassFqName) + return writeOutputs(environment.project, projectConfiguration, chunk, outputs, mainClassFqName) } @@ -171,7 +183,7 @@ object KotlinToJVMBytecodeCompiler { moduleVisibilityManager.addFriendPath(path) } - if (!checkKotlinPackageUsage(environment, environment.getSourceFiles())) return false + if (!checkKotlinPackageUsage(environment.configuration, environment.getSourceFiles())) return false val generationState = analyzeAndGenerate(environment) ?: return false diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/PsiBasedProjectEnvironment.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/PsiBasedProjectEnvironment.kt new file mode 100644 index 00000000000..793e08210a4 --- /dev/null +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/PsiBasedProjectEnvironment.kt @@ -0,0 +1,120 @@ +/* + * Copyright 2010-2021 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.cli.jvm.compiler + +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.StandardFileSystems +import com.intellij.openapi.vfs.VirtualFileManager +import com.intellij.openapi.vfs.VirtualFileSystem +import com.intellij.psi.PsiElementFinder +import com.intellij.psi.PsiFile +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.search.ProjectScope +import org.jetbrains.kotlin.asJava.finder.JavaElementFinder +import org.jetbrains.kotlin.fir.FirModuleData +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.java.FirJavaElementFinder +import org.jetbrains.kotlin.fir.java.JavaSymbolProvider +import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment +import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope +import org.jetbrains.kotlin.load.java.JavaClassFinder +import org.jetbrains.kotlin.load.java.JavaClassFinderImpl +import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder +import org.jetbrains.kotlin.load.kotlin.PackagePartProvider +import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory +import java.io.File + +class PsiBasedProjectFileSearchScope(val psiSearchScope: GlobalSearchScope) : AbstractProjectFileSearchScope { + + override val isEmpty: Boolean + get() = psiSearchScope == GlobalSearchScope.EMPTY_SCOPE + + override operator fun minus(other: AbstractProjectFileSearchScope): AbstractProjectFileSearchScope = + PsiBasedProjectFileSearchScope(psiSearchScope.intersectWith(GlobalSearchScope.notScope(other.asPsiSearchScope()))) + + override operator fun plus(other: AbstractProjectFileSearchScope): AbstractProjectFileSearchScope = + PsiBasedProjectFileSearchScope(psiSearchScope.uniteWith(other.asPsiSearchScope())) + + override operator fun not(): AbstractProjectFileSearchScope = + PsiBasedProjectFileSearchScope(GlobalSearchScope.notScope(psiSearchScope)) +} + +class PsiBasedProjectEnvironment( + val project: Project, + val localFileSystem: VirtualFileSystem, + val getPackagePartProviderFn: (GlobalSearchScope) -> PackagePartProvider +) : AbstractProjectEnvironment { + + override fun getKotlinClassFinder(fileSearchScope: AbstractProjectFileSearchScope): KotlinClassFinder = + VirtualFileFinderFactory.getInstance(project).create(fileSearchScope.asPsiSearchScope()) + + override fun getJavaClassFinder(fileSearchScope: AbstractProjectFileSearchScope): JavaClassFinder = + JavaClassFinderImpl().apply { + this.setProjectInstance(project) + this.setScope(fileSearchScope.asPsiSearchScope()) + } + + override fun getJavaSymbolProvider( + firSession: FirSession, + baseModuleData: FirModuleData, + fileSearchScope: AbstractProjectFileSearchScope + ): JavaSymbolProvider = + JavaSymbolProvider(firSession, baseModuleData, project, fileSearchScope.asPsiSearchScope()) + + override fun getPackagePartProvider(fileSearchScope: AbstractProjectFileSearchScope): PackagePartProvider = + getPackagePartProviderFn(fileSearchScope.asPsiSearchScope()) + + override fun registerAsJavaElementFinder(firSession: FirSession) { + val psiFinderExtensionPoint = PsiElementFinder.EP.getPoint(project) + if (psiFinderExtensionPoint.extensionList.any { it is JavaElementFinder }) { + psiFinderExtensionPoint.unregisterExtension(JavaElementFinder::class.java) + } + psiFinderExtensionPoint.registerExtension(FirJavaElementFinder(firSession, project), project) + } + + override fun getSearchScopeByIoFiles(files: Iterable, allowOutOfProjectRoots: Boolean): AbstractProjectFileSearchScope = + PsiBasedProjectFileSearchScope( + files + .mapNotNull { localFileSystem.findFileByPath(it.absolutePath) } + .toList() + .takeIf { it.isNotEmpty() } + ?.let { + if (allowOutOfProjectRoots) GlobalSearchScope.filesWithLibrariesScope(project, it) + else GlobalSearchScope.filesWithoutLibrariesScope(project, it) + } ?: GlobalSearchScope.EMPTY_SCOPE + ) + + fun getSearchScopeByPsiFiles(files: Iterable, allowOutOfProjectRoots: Boolean= false): AbstractProjectFileSearchScope = + PsiBasedProjectFileSearchScope( + files.map { it.virtualFile }.let { + if (allowOutOfProjectRoots) GlobalSearchScope.filesWithLibrariesScope(project, it) + else GlobalSearchScope.filesWithoutLibrariesScope(project, it) + } + ) + + override fun getSearchScopeForProjectLibraries(): AbstractProjectFileSearchScope = + PsiBasedProjectFileSearchScope(ProjectScope.getLibrariesScope(project)) + + override fun getSearchScopeForProjectJavaSources(): AbstractProjectFileSearchScope = + PsiBasedProjectFileSearchScope(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(project)) + +} + +private fun AbstractProjectFileSearchScope.asPsiSearchScope() = + when { + this === AbstractProjectFileSearchScope.EMPTY -> GlobalSearchScope.EMPTY_SCOPE + this === AbstractProjectFileSearchScope.ANY -> GlobalSearchScope.notScope(GlobalSearchScope.EMPTY_SCOPE) + else -> (this as PsiBasedProjectFileSearchScope).psiSearchScope + } + +fun KotlinCoreEnvironment.toAbstractProjectEnvironment(): AbstractProjectEnvironment = + PsiBasedProjectEnvironment( + project, VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL), + { createPackagePartProvider(it) } + ) + +fun GlobalSearchScope.toAbstractProjectFileSearchScope(): AbstractProjectFileSearchScope = + PsiBasedProjectFileSearchScope(this) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/cliCompilerUtils.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/cliCompilerUtils.kt index 56412344fcd..187247f5b6c 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/cliCompilerUtils.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/cliCompilerUtils.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.cli.jvm.compiler +import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VfsUtilCore import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileSystem @@ -29,8 +30,8 @@ import org.jetbrains.kotlin.psi.KtFile import java.io.File fun Module.getSourceFiles( - environment: KotlinCoreEnvironment, - localFileSystem: VirtualFileSystem, + allSourceFiles: List, + localFileSystem: VirtualFileSystem?, multiModuleChunk: Boolean, buildFile: File? ): List { @@ -39,17 +40,17 @@ fun Module.getSourceFiles( assert(buildFile != null) { "Compiling multiple modules, but build file is null" } val (moduleSourceDirs, moduleSourceFiles) = getBuildFilePaths(buildFile, getSourceFiles()) - .mapNotNull(localFileSystem::findFileByPath) + .mapNotNull(localFileSystem!!::findFileByPath) .partition(VirtualFile::isDirectory) - environment.getSourceFiles().filter { file -> + allSourceFiles.filter { file -> val virtualFile = file.virtualFile virtualFile in moduleSourceFiles || moduleSourceDirs.any { dir -> VfsUtilCore.isAncestor(dir, virtualFile, true) } } } else { - environment.getSourceFiles() + allSourceFiles } } @@ -115,7 +116,7 @@ fun writeOutput( } fun writeOutputs( - environment: KotlinCoreEnvironment, + project: Project?, projectConfiguration: CompilerConfiguration, chunk: List, outputs: Map, @@ -133,7 +134,7 @@ fun writeOutputs( if (projectConfiguration.getBoolean(JVMConfigurationKeys.COMPILE_JAVA)) { val singleModule = chunk.singleOrNull() if (singleModule != null) { - return JavacWrapper.getInstance(environment.project).use { + return JavacWrapper.getInstance(project!!).use { it.compile(File(singleModule.getOutputDirectory())) } } else { @@ -142,7 +143,6 @@ fun writeOutputs( "A chunk contains multiple modules (${chunk.joinToString { it.getModuleName() }}). " + "-Xuse-javac option couldn't be used to compile java files" ) - JavacWrapper.getInstance(environment.project).close() } } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataCompiler.kt index 17830b66d88..e35fa2a6577 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataCompiler.kt @@ -101,7 +101,7 @@ class K2MetadataCompiler : CLICompiler() { return ExitCode.COMPILATION_ERROR } - checkKotlinPackageUsage(environment, environment.getSourceFiles()) + checkKotlinPackageUsage(environment.configuration, environment.getSourceFiles()) try { val metadataVersion = diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/AbstractFirLoadCompiledKotlin.kt b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/AbstractFirLoadCompiledKotlin.kt index e00a2282c7b..2945226ec84 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/AbstractFirLoadCompiledKotlin.kt +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/AbstractFirLoadCompiledKotlin.kt @@ -5,11 +5,12 @@ package org.jetbrains.kotlin.fir -import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.ObsoleteTestInfrastructure import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.cli.jvm.compiler.toAbstractProjectEnvironment import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope import org.jetbrains.kotlin.jvm.compiler.AbstractLoadJavaTest import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil.compileKotlinToDirAndGetModule import org.jetbrains.kotlin.name.FqName @@ -41,7 +42,7 @@ abstract class AbstractFirLoadCompiledKotlin : AbstractFirLoadBinariesTest() { val environment = KotlinCoreEnvironment.createForTests(testRootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) prepareProjectExtensions(environment.project) - val sessionWithDependency = createSessionForTests(environment, GlobalSearchScope.EMPTY_SCOPE) + val sessionWithDependency = createSessionForTests(environment.toAbstractProjectEnvironment(), AbstractProjectFileSearchScope.EMPTY) val testDataDirectoryPath = "compiler/fir/analysis-tests/testData/loadCompiledKotlin/" + diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/BuiltInsDeserializationForFirTestCase.kt b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/BuiltInsDeserializationForFirTestCase.kt index d1da405cfe7..02b4d9ec5a2 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/BuiltInsDeserializationForFirTestCase.kt +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/BuiltInsDeserializationForFirTestCase.kt @@ -8,6 +8,8 @@ package org.jetbrains.kotlin.fir import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.ObsoleteTestInfrastructure import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.cli.jvm.compiler.toAbstractProjectEnvironment +import org.jetbrains.kotlin.cli.jvm.compiler.toAbstractProjectFileSearchScope import org.jetbrains.kotlin.serialization.builtins.BuiltinsTestUtils import org.jetbrains.kotlin.test.ConfigurationKind import org.jetbrains.kotlin.test.TestJdkKind @@ -20,7 +22,10 @@ class BuiltInsDeserializationForFirTestCase : AbstractFirLoadBinariesTest() { @OptIn(ObsoleteTestInfrastructure::class) fun testBuiltInPackagesContent() { val moduleDescriptor = BuiltinsTestUtils.compileBuiltinsModule(environment) - val session = createSessionForTests(environment, GlobalSearchScope.allScope(project)) + val session = createSessionForTests( + environment.toAbstractProjectEnvironment(), + GlobalSearchScope.allScope(project).toAbstractProjectFileSearchScope() + ) for (packageFqName in BuiltinsTestUtils.BUILTIN_PACKAGE_NAMES) { val path = "compiler/fir/analysis-tests/testData/builtIns/" + packageFqName.asString().replace('.', '-') + ".txt" checkPackageContent(session, packageFqName, moduleDescriptor, path) diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt index 2d7f23b62c2..3cda3c54ff5 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt @@ -18,15 +18,13 @@ import com.intellij.psi.search.GlobalSearchScope import com.intellij.testFramework.LightVirtualFile import org.jetbrains.kotlin.ObsoleteTestInfrastructure import org.jetbrains.kotlin.asJava.finder.JavaElementFinder -import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM +import org.jetbrains.kotlin.cli.jvm.compiler.* import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime import org.jetbrains.kotlin.fir.FirRenderer import org.jetbrains.kotlin.fir.createSessionForTests import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass -import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCompositeSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName @@ -135,7 +133,10 @@ abstract class AbstractFirTypeEnhancementTest : KtUsefulTestCase() { val scope = GlobalSearchScope.filesScope(project, virtualFiles) .uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(project)) - val session = createSessionForTests(environment, scope) + val session = createSessionForTests( + environment.toAbstractProjectEnvironment(), + scope.toAbstractProjectFileSearchScope() + ) val topPsiClasses = psiFiles.flatMap { it.getChildrenOfType().toList() } diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/analyse.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/analyse.kt new file mode 100644 index 00000000000..64cf72e691f --- /dev/null +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/analyse.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2021 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.fir.pipeline + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.analysis.collectors.FirDiagnosticsCollector +import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporterFactory +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic +import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveProcessor + +fun FirSession.runResolution(firFiles: List): Pair> { + val resolveProcessor = FirTotalResolveProcessor(this) + resolveProcessor.process(firFiles) + return resolveProcessor.scopeSession to firFiles +} + +@OptIn(ExperimentalStdlibApi::class) +fun FirSession.runCheckers(scopeSession: ScopeSession, firFiles: List): Map> { + val collector = FirDiagnosticsCollector.create(this, scopeSession) + return buildMap { + for (file in firFiles) { + val reporter = DiagnosticReporterFactory.createReporter() + collector.collectDiagnostics(file, reporter) + put(file, reporter.diagnostics) + } + } +} \ No newline at end of file diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/buildFir.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/buildFir.kt new file mode 100644 index 00000000000..c883ffd06e5 --- /dev/null +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/buildFir.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2021 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.fir.pipeline + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.builder.PsiHandlingMode +import org.jetbrains.kotlin.fir.builder.RawFirBuilder +import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir +import org.jetbrains.kotlin.fir.resolve.firProvider +import org.jetbrains.kotlin.fir.resolve.providers.impl.FirProviderImpl +import org.jetbrains.kotlin.psi.KtFile +import java.io.File + +fun FirSession.buildFirViaLightTree(files: Collection): List { + val firProvider = (firProvider as FirProviderImpl) + val builder = LightTree2Fir(this, firProvider.kotlinScopeProvider) + return files.map { + builder.buildFirFile(it).also { firFile -> + firProvider.recordFile(firFile) + } + } +} + +fun FirSession.buildFirFromKtFiles(ktFiles: Collection): List { + val firProvider = (firProvider as FirProviderImpl) + val builder = RawFirBuilder(this, firProvider.kotlinScopeProvider, PsiHandlingMode.COMPILER) + return ktFiles.map { + builder.buildFirFile(it).also { firFile -> + firProvider.recordFile(firFile) + } + } +} diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt new file mode 100644 index 00000000000..16cdd1cb14a --- /dev/null +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2021 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.fir.pipeline + +import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.backend.Fir2IrConverter +import org.jetbrains.kotlin.fir.backend.Fir2IrResult +import org.jetbrains.kotlin.fir.backend.jvm.Fir2IrJvmSpecialAnnotationSymbolProvider +import org.jetbrains.kotlin.fir.backend.jvm.FirJvmKotlinMangler +import org.jetbrains.kotlin.fir.backend.jvm.FirJvmVisibilityConverter +import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.languageVersionSettings +import org.jetbrains.kotlin.fir.moduleData +import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.firProvider +import org.jetbrains.kotlin.fir.resolve.providers.impl.FirProviderImpl +import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmDescriptorMangler +import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl +import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions + +fun FirSession.convertToIr(scopeSession: ScopeSession, firFiles: List, extensions: GeneratorExtensions): Fir2IrResult { + val signaturer = JvmIdSignatureDescriptor(JvmDescriptorMangler(null)) + + val commonFirFiles = moduleData.dependsOnDependencies + .map { it.session } + .filter { it.kind == FirSession.Kind.Source } + .flatMap { (it.firProvider as FirProviderImpl).getAllFirFiles() } + + return Fir2IrConverter.createModuleFragment( + this, scopeSession, firFiles + commonFirFiles, + languageVersionSettings, signaturer, + extensions, FirJvmKotlinMangler(this), IrFactoryImpl, + FirJvmVisibilityConverter, + Fir2IrJvmSpecialAnnotationSymbolProvider() + ) +} diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt index 0ef8dcd2a0f..16c46f6df28 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt @@ -5,8 +5,6 @@ package org.jetbrains.kotlin.fir.session -import com.intellij.openapi.project.Project -import com.intellij.psi.PsiElementFinder import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.config.LanguageVersionSettings @@ -25,7 +23,8 @@ import org.jetbrains.kotlin.fir.deserialization.SingleModuleDataProvider import org.jetbrains.kotlin.fir.extensions.BunchOfRegisteredExtensions import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.extensions.registerExtensions -import org.jetbrains.kotlin.fir.java.* +import org.jetbrains.kotlin.fir.java.FirCliSession +import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider import org.jetbrains.kotlin.fir.java.deserialization.KotlinDeserializedJvmSymbolsProvider import org.jetbrains.kotlin.fir.resolve.providers.FirDependenciesSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirProvider @@ -33,10 +32,10 @@ import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.impl.* import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider +import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment +import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope import org.jetbrains.kotlin.incremental.components.LookupTracker -import org.jetbrains.kotlin.load.java.JavaClassFinderImpl import org.jetbrains.kotlin.load.kotlin.PackagePartProvider -import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.jvm.JvmPlatforms @@ -73,7 +72,7 @@ object FirSessionFactory { data class ProviderAndScopeForIncrementalCompilation( val packagePartProvider: PackagePartProvider, - val scope: GlobalSearchScope + val scope: AbstractProjectFileSearchScope ) inline fun createSessionWithDependencies( @@ -81,13 +80,12 @@ object FirSessionFactory { platform: TargetPlatform, analyzerServices: PlatformDependentAnalyzerServices, externalSessionProvider: FirProjectSessionProvider?, - project: Project, + projectEnvironment: AbstractProjectEnvironment, languageVersionSettings: LanguageVersionSettings, - sourceScope: GlobalSearchScope, - librariesScope: GlobalSearchScope, + sourceScope: AbstractProjectFileSearchScope, + librariesScope: AbstractProjectFileSearchScope, lookupTracker: LookupTracker?, providerAndScopeForIncrementalCompilation: ProviderAndScopeForIncrementalCompilation?, - getPackagePartProvider: (GlobalSearchScope) -> PackagePartProvider, dependenciesConfigurator: DependencyListForCliModule.Builder.() -> Unit = {}, noinline sessionConfigurator: FirSessionConfigurator.() -> Unit = {}, ): FirSession { @@ -98,8 +96,8 @@ object FirSessionFactory { sessionProvider, dependencyList.moduleDataProvider, librariesScope, - project, - getPackagePartProvider(librariesScope), + projectEnvironment, + projectEnvironment.getPackagePartProvider(librariesScope), languageVersionSettings ) @@ -115,7 +113,7 @@ object FirSessionFactory { mainModuleData, sessionProvider, sourceScope, - project, + projectEnvironment, providerAndScopeForIncrementalCompilation, languageVersionSettings = languageVersionSettings, lookupTracker = lookupTracker, @@ -126,8 +124,8 @@ object FirSessionFactory { fun createJavaModuleBasedSession( moduleData: FirModuleData, sessionProvider: FirProjectSessionProvider, - scope: GlobalSearchScope, - project: Project, + scope: AbstractProjectFileSearchScope, + projectEnvironment: AbstractProjectEnvironment, providerAndScopeForIncrementalCompilation: ProviderAndScopeForIncrementalCompilation?, languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT, lookupTracker: LookupTracker? = null, @@ -149,16 +147,16 @@ object FirSessionFactory { register(FirProvider::class, firProvider) val symbolProviderForBinariesFromIncrementalCompilation = providerAndScopeForIncrementalCompilation?.let { - val javaSymbolProvider = JavaSymbolProvider(this, moduleData, project, it.scope) + val javaSymbolProvider = projectEnvironment.getJavaSymbolProvider(this, moduleData, it.scope) - makeDeserializedJvmSymbolsProvider( + KotlinDeserializedJvmSymbolsProvider( this@session, SingleModuleDataProvider(moduleData), - project, - it.scope, + kotlinScopeProvider, it.packagePartProvider, + projectEnvironment.getKotlinClassFinder(it.scope), javaSymbolProvider, - kotlinScopeProvider + projectEnvironment.getJavaClassFinder(it.scope) ) } @@ -170,7 +168,7 @@ object FirSessionFactory { listOfNotNull( firProvider.symbolProvider, symbolProviderForBinariesFromIncrementalCompilation, - JavaSymbolProvider(this, moduleData, project, scope), + projectEnvironment.getJavaSymbolProvider(this, moduleData, scope), dependenciesSymbolProvider, ) ) @@ -187,7 +185,7 @@ object FirSessionFactory { registerJvmCheckers() init() }.configure() - PsiElementFinder.EP.getPoint(project).registerExtension(FirJavaElementFinder(this, project), project) + projectEnvironment.registerAsJavaElementFinder(this) } } @@ -195,8 +193,8 @@ object FirSessionFactory { mainModuleName: Name, sessionProvider: FirProjectSessionProvider, moduleDataProvider: ModuleDataProvider, - scope: GlobalSearchScope, - project: Project, + scope: AbstractProjectFileSearchScope, + projectEnvironment: AbstractProjectEnvironment, packagePartProvider: PackagePartProvider, languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT, ): FirSession { @@ -210,18 +208,18 @@ object FirSessionFactory { registerCommonComponents(languageVersionSettings) registerCommonJavaComponents() - val javaSymbolProvider = JavaSymbolProvider(this, moduleDataProvider.allModuleData.last(), project, scope) + val javaSymbolProvider = projectEnvironment.getJavaSymbolProvider(this, moduleDataProvider.allModuleData.last(), scope) val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped) - val deserializedProviderForIncrementalCompilation = makeDeserializedJvmSymbolsProvider( - librarySession = this, - moduleDataProvider, - project, - scope, - packagePartProvider, - javaSymbolProvider, - kotlinScopeProvider + val deserializedProviderForIncrementalCompilation = KotlinDeserializedJvmSymbolsProvider( + session = this, + moduleDataProvider = moduleDataProvider, + kotlinScopeProvider = kotlinScopeProvider, + packagePartProvider = packagePartProvider, + kotlinClassFinder = projectEnvironment.getKotlinClassFinder(scope), + javaSymbolProvider = javaSymbolProvider, + javaClassFinder = projectEnvironment.getJavaClassFinder(scope) ) val builtinsModuleData = createModuleDataForBuiltins( @@ -245,33 +243,6 @@ object FirSessionFactory { } } - private fun makeDeserializedJvmSymbolsProvider( - librarySession: FirSession, - moduleDataProvider: ModuleDataProvider, - project: Project, - scope: GlobalSearchScope, - packagePartProvider: PackagePartProvider, - javaSymbolProvider: JavaSymbolProvider, - kotlinScopeProvider: FirKotlinScopeProvider - ): KotlinDeserializedJvmSymbolsProvider { - - val kotlinClassFinder = VirtualFileFinderFactory.getInstance(project).create(scope) - val javaClassFinder = JavaClassFinderImpl().apply { - this.setProjectInstance(project) - this.setScope(scope) - } - - return KotlinDeserializedJvmSymbolsProvider( - librarySession, - moduleDataProvider, - kotlinScopeProvider, - packagePartProvider, - kotlinClassFinder, - javaSymbolProvider, - javaClassFinder - ) - } - @TestOnly fun createEmptySession(): FirSession { return object : FirSession(null, Kind.Source) {}.apply { diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/environment/AbstractProjectEnvironment.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/environment/AbstractProjectEnvironment.kt new file mode 100644 index 00000000000..3bcff73ef0a --- /dev/null +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/environment/AbstractProjectEnvironment.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2021 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.fir.session.environment + +import org.jetbrains.kotlin.fir.FirModuleData +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.java.JavaSymbolProvider +import org.jetbrains.kotlin.load.java.JavaClassFinder +import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder +import org.jetbrains.kotlin.load.kotlin.PackagePartProvider +import java.io.File + +interface AbstractProjectFileSearchScope { + val isEmpty: Boolean + + operator fun minus(other: AbstractProjectFileSearchScope): AbstractProjectFileSearchScope + + operator fun plus(other: AbstractProjectFileSearchScope): AbstractProjectFileSearchScope + + operator fun not(): AbstractProjectFileSearchScope + + + object EMPTY : AbstractProjectFileSearchScope { + override val isEmpty: Boolean = true + override fun minus(other: AbstractProjectFileSearchScope): AbstractProjectFileSearchScope = this + override fun plus(other: AbstractProjectFileSearchScope): AbstractProjectFileSearchScope = other + override fun not(): AbstractProjectFileSearchScope = ANY + } + + object ANY : AbstractProjectFileSearchScope { + override val isEmpty: Boolean = false + override fun minus(other: AbstractProjectFileSearchScope): AbstractProjectFileSearchScope = error("Operation not implemented") + override fun plus(other: AbstractProjectFileSearchScope): AbstractProjectFileSearchScope = this + override fun not(): AbstractProjectFileSearchScope = EMPTY + } +} + +interface AbstractProjectEnvironment { + + fun getKotlinClassFinder(fileSearchScope: AbstractProjectFileSearchScope): KotlinClassFinder + + fun getJavaClassFinder(fileSearchScope: AbstractProjectFileSearchScope): JavaClassFinder + + fun getJavaSymbolProvider( + firSession: FirSession, + baseModuleData: FirModuleData, + fileSearchScope: AbstractProjectFileSearchScope + ): JavaSymbolProvider + + fun getPackagePartProvider(fileSearchScope: AbstractProjectFileSearchScope): PackagePartProvider + + fun registerAsJavaElementFinder(firSession: FirSession) + + fun getSearchScopeByIoFiles(files: Iterable, allowOutOfProjectRoots: Boolean = false): AbstractProjectFileSearchScope + + fun getSearchScopeForProjectLibraries(): AbstractProjectFileSearchScope + + fun getSearchScopeForProjectJavaSources(): AbstractProjectFileSearchScope +} diff --git a/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FirResolveModularizedTotalKotlinTest.kt b/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FirResolveModularizedTotalKotlinTest.kt index ec2bffa6c5c..3847bafcc19 100644 --- a/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FirResolveModularizedTotalKotlinTest.kt +++ b/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FirResolveModularizedTotalKotlinTest.kt @@ -14,11 +14,8 @@ import com.sun.jna.Native import com.sun.management.HotSpotDiagnosticMXBean import org.jetbrains.kotlin.ObsoleteTestInfrastructure import org.jetbrains.kotlin.asJava.finder.JavaElementFinder -import org.jetbrains.kotlin.cli.common.profiling.AsyncProfilerHelper import org.jetbrains.kotlin.cli.common.toBooleanLenient -import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM +import org.jetbrains.kotlin.cli.jvm.compiler.* import org.jetbrains.kotlin.fir.analysis.FirCheckersResolveProcessor import org.jetbrains.kotlin.fir.builder.PsiHandlingMode import org.jetbrains.kotlin.fir.builder.RawFirBuilder @@ -128,9 +125,9 @@ class FirResolveModularizedTotalKotlinTest : AbstractModularizedTest() { .uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(project)) val librariesScope = ProjectScope.getLibrariesScope(project) val session = createSessionForTests( - environment, - scope, - librariesScope, + environment.toAbstractProjectEnvironment(), + scope.toAbstractProjectFileSearchScope(), + librariesScope.toAbstractProjectFileSearchScope(), moduleData.qualifiedName, moduleData.friendDirs.map { it.toPath() } ) diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirFrontendFacade.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirFrontendFacade.kt index fa5e902fb15..98d2d7b98c2 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirFrontendFacade.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirFrontendFacade.kt @@ -5,10 +5,14 @@ package org.jetbrains.kotlin.test.frontend.fir +import com.intellij.openapi.vfs.StandardFileSystems +import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiElementFinder import com.intellij.psi.search.ProjectScope import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices import org.jetbrains.kotlin.asJava.finder.JavaElementFinder +import org.jetbrains.kotlin.cli.jvm.compiler.PsiBasedProjectEnvironment +import org.jetbrains.kotlin.cli.jvm.compiler.PsiBasedProjectFileSearchScope import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots @@ -71,13 +75,15 @@ class FirFrontendFacade( module.targetPlatform, module.targetPlatform.getAnalyzerServices(), moduleInfoProvider.firSessionProvider, - project, + PsiBasedProjectEnvironment( + project, VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL), + { packagePartProviderFactory.invoke(it) } + ), languageVersionSettings, - sourcesScope, - librariesScope, + PsiBasedProjectFileSearchScope(sourcesScope), + PsiBasedProjectFileSearchScope(librariesScope), lookupTracker = null, providerAndScopeForIncrementalCompilation = null, - getPackagePartProvider = packagePartProviderFactory, dependenciesConfigurator = { dependencies(configuration.jvmModularRoots.map { it.toPath() }) dependencies(configuration.jvmClasspathRoots.map { it.toPath() }) @@ -87,13 +93,12 @@ class FirFrontendFacade( sourceDependencies(moduleInfoProvider.getRegularDependentSourceModules(module)) sourceFriendsDependencies(moduleInfoProvider.getDependentFriendSourceModules(module)) sourceDependsOnDependencies(moduleInfoProvider.getDependentDependsOnSourceModules(module)) - }, - sessionConfigurator = { - if (FirDiagnosticsDirectives.WITH_EXTENDED_CHECKERS in module.directives) { - registerExtendedCommonCheckers() - } } - ) + ) { + if (FirDiagnosticsDirectives.WITH_EXTENDED_CHECKERS in module.directives) { + registerExtendedCommonCheckers() + } + } moduleInfoProvider.registerModuleData(module, session.moduleData) diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirBaseDiagnosticsTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirBaseDiagnosticsTest.kt index c1fafbb70a7..16b25936df3 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirBaseDiagnosticsTest.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirBaseDiagnosticsTest.kt @@ -6,6 +6,8 @@ package org.jetbrains.kotlin.fir import com.intellij.openapi.util.TextRange +import com.intellij.openapi.vfs.StandardFileSystems +import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiElement import com.intellij.psi.PsiElementFinder import com.intellij.psi.search.GlobalSearchScope @@ -19,6 +21,8 @@ import org.jetbrains.kotlin.checkers.diagnostics.SyntaxErrorDiagnostic import org.jetbrains.kotlin.checkers.diagnostics.TextDiagnostic import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.cli.jvm.compiler.PsiBasedProjectEnvironment +import org.jetbrains.kotlin.cli.jvm.compiler.PsiBasedProjectFileSearchScope import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.diagnostics.Diagnostic @@ -85,13 +89,15 @@ abstract class AbstractFirBaseDiagnosticsTest : BaseDiagnosticsTest() { info.platform, info.analyzerServices, externalSessionProvider = sessionProvider, - project, + PsiBasedProjectEnvironment( + project, VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL), + { environment.createPackagePartProvider(it) } + ), config?.languageVersionSettings ?: LanguageVersionSettingsImpl.DEFAULT, - sourceScope = scope, - librariesScope = allProjectScope, + sourceScope = PsiBasedProjectFileSearchScope(scope), + librariesScope = PsiBasedProjectFileSearchScope(allProjectScope), lookupTracker = null, providerAndScopeForIncrementalCompilation = null, - getPackagePartProvider = { environment.createPackagePartProvider(it) }, ) { configureSession() getFirExtensions()?.let { diff --git a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/SessionTestUtils.kt b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/SessionTestUtils.kt index e53ae8192ba..ff9d082660d 100644 --- a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/SessionTestUtils.kt +++ b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/SessionTestUtils.kt @@ -6,11 +6,16 @@ package org.jetbrains.kotlin.fir import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.StandardFileSystems +import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.ObsoleteTestInfrastructure -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.cli.jvm.compiler.PsiBasedProjectEnvironment +import org.jetbrains.kotlin.cli.jvm.compiler.PsiBasedProjectFileSearchScope import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.fir.session.FirSessionFactory +import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment +import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope import org.jetbrains.kotlin.load.kotlin.PackagePartProvider import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.platform.jvm.JvmPlatforms @@ -19,18 +24,25 @@ import java.nio.file.Path @ObsoleteTestInfrastructure fun createSessionForTests( - environment: KotlinCoreEnvironment, - sourceScope: GlobalSearchScope, - librariesScope: GlobalSearchScope = GlobalSearchScope.notScope(sourceScope), + projectEnvironment: AbstractProjectEnvironment, + sourceScope: AbstractProjectFileSearchScope, + librariesScope: AbstractProjectFileSearchScope = !sourceScope, moduleName: String = "TestModule", friendsPaths: List = emptyList(), -): FirSession = createSessionForTests( - environment.project, +): FirSession = FirSessionFactory.createSessionWithDependencies( + Name.identifier(moduleName), + JvmPlatforms.unspecifiedJvmPlatform, + JvmPlatformAnalyzerServices, + externalSessionProvider = null, + projectEnvironment, + languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT, sourceScope, librariesScope, - moduleName, - friendsPaths, - environment::createPackagePartProvider + lookupTracker = null, + providerAndScopeForIncrementalCompilation = null, + dependenciesConfigurator = { + friendDependencies(friendsPaths) + } ) @ObsoleteTestInfrastructure @@ -47,13 +59,12 @@ fun createSessionForTests( JvmPlatforms.unspecifiedJvmPlatform, JvmPlatformAnalyzerServices, externalSessionProvider = null, - project, + PsiBasedProjectEnvironment(project, VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL), getPackagePartProvider), languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT, - sourceScope, - librariesScope, + PsiBasedProjectFileSearchScope(sourceScope), + PsiBasedProjectFileSearchScope(librariesScope), lookupTracker = null, providerAndScopeForIncrementalCompilation = null, - getPackagePartProvider, dependenciesConfigurator = { friendDependencies(friendsPaths) }