Abstract FIR cli pipeline from core environment and related entities
This commit is contained in:
committed by
TeamCityServer
parent
40614507d3
commit
caa44e413d
@@ -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)) {
|
||||
|
||||
+74
-83
@@ -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?,
|
||||
|
||||
+17
-5
@@ -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 =
|
||||
|
||||
Reference in New Issue
Block a user