Abstract FIR cli pipeline from core environment and related entities

This commit is contained in:
Ilya Chernikov
2021-08-03 12:17:22 +02:00
committed by TeamCityServer
parent 40614507d3
commit caa44e413d
21 changed files with 497 additions and 211 deletions
@@ -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)
@@ -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<K2JSCompilerArguments> {
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);
@@ -139,7 +139,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
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) {
@@ -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<KtFile>): Boolean {
if (environment.configuration.getBoolean(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE)) {
fun checkKotlinPackageUsage(configuration: CompilerConfiguration, files: Collection<KtFile>): 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)) {
@@ -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<KtFile>,
buildFile: File?,
chunk: List<Module>,
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<Module, GenerationState>(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<KtFile>): FirAnalyzerFacade? {
private class FirResult(
val session: FirSession,
val scopeSession: ScopeSession,
val fir: List<FirFile>
)
private fun CompilationContext.runFrontend(ktFiles: List<KtFile>): 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<FirDiagnostic>()
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<KtFile>,
val projectEnvironment: AbstractProjectEnvironment,
val messageCollector: MessageCollector,
val moduleConfiguration: CompilerConfiguration,
val localFileSystem: VirtualFileSystem,
val isMultiModuleChunk: Boolean,
val buildFile: File?,
val performanceManager: CommonCompilerPerformanceManager?,
val targetIds: List<TargetId>?,
val incrementalComponents: IncrementalCompilationComponents?,
@@ -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
@@ -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<File>, 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<PsiFile>, 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)
@@ -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<KtFile>,
localFileSystem: VirtualFileSystem?,
multiModuleChunk: Boolean,
buildFile: File?
): List<KtFile> {
@@ -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<Module>,
outputs: Map<Module, GenerationState>,
@@ -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()
}
}
@@ -101,7 +101,7 @@ class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
return ExitCode.COMPILATION_ERROR
}
checkKotlinPackageUsage(environment, environment.getSourceFiles())
checkKotlinPackageUsage(environment.configuration, environment.getSourceFiles())
try {
val metadataVersion =
@@ -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/" +
@@ -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)
@@ -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<PsiClass>().toList() }
@@ -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<FirFile>): Pair<ScopeSession, List<FirFile>> {
val resolveProcessor = FirTotalResolveProcessor(this)
resolveProcessor.process(firFiles)
return resolveProcessor.scopeSession to firFiles
}
@OptIn(ExperimentalStdlibApi::class)
fun FirSession.runCheckers(scopeSession: ScopeSession, firFiles: List<FirFile>): Map<FirFile, List<FirDiagnostic>> {
val collector = FirDiagnosticsCollector.create(this, scopeSession)
return buildMap {
for (file in firFiles) {
val reporter = DiagnosticReporterFactory.createReporter()
collector.collectDiagnostics(file, reporter)
put(file, reporter.diagnostics)
}
}
}
@@ -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<File>): List<FirFile> {
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<KtFile>): List<FirFile> {
val firProvider = (firProvider as FirProviderImpl)
val builder = RawFirBuilder(this, firProvider.kotlinScopeProvider, PsiHandlingMode.COMPILER)
return ktFiles.map {
builder.buildFirFile(it).also { firFile ->
firProvider.recordFile(firFile)
}
}
}
@@ -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<FirFile>, 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()
)
}
@@ -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 {
@@ -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<File>, allowOutOfProjectRoots: Boolean = false): AbstractProjectFileSearchScope
fun getSearchScopeForProjectLibraries(): AbstractProjectFileSearchScope
fun getSearchScopeForProjectJavaSources(): AbstractProjectFileSearchScope
}
@@ -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() }
)
@@ -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)
@@ -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 {
@@ -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<Path> = 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)
}