/
CompilerConfigurationProvider.kt
171 lines (143 loc) · 7.6 KB
/
CompilerConfigurationProvider.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
* Copyright 2010-2020 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.test.services
import com.intellij.openapi.Disposable
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation
import org.jetbrains.kotlin.cli.common.messages.IrMessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar
import org.jetbrains.kotlin.compiler.plugin.registerInProject
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.CompilerConfigurationKey
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.ir.util.IrMessageLogger
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.isCommon
import org.jetbrains.kotlin.platform.isJs
import org.jetbrains.kotlin.platform.isWasm
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.platform.konan.isNative
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.TestInfrastructureInternals
import org.jetbrains.kotlin.test.directives.JsEnvironmentConfigurationDirectives
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.model.TestModule
import java.io.File
abstract class CompilerConfigurationProvider(val testServices: TestServices) : TestService {
abstract val testRootDisposable: Disposable
abstract val configurators: List<AbstractEnvironmentConfigurator>
protected abstract fun getKotlinCoreEnvironment(module: TestModule): KotlinCoreEnvironment
open fun getProject(module: TestModule): Project {
return getKotlinCoreEnvironment(module).project
}
fun registerCompilerExtensions(project: Project, module: TestModule, configuration: CompilerConfiguration) {
val extensionStorage = CompilerPluginRegistrar.ExtensionStorage()
for (configurator in configurators) {
configurator.legacyRegisterCompilerExtensions(project, module, configuration)
with(configurator) {
extensionStorage.registerCompilerExtensions(module, configuration)
}
}
extensionStorage.registerInProject(project)
}
open fun getPackagePartProviderFactory(module: TestModule): (GlobalSearchScope) -> JvmPackagePartProvider {
return getKotlinCoreEnvironment(module)::createPackagePartProvider
}
open fun getCompilerConfiguration(module: TestModule): CompilerConfiguration {
return getKotlinCoreEnvironment(module).configuration
}
fun registerJavacForModule(module: TestModule, ktFiles: List<KtFile>, mockJdk: File?) {
val environment = getKotlinCoreEnvironment(module)
val bootClasspath = mockJdk?.let { listOf(it) }
environment.registerJavac(kotlinFiles = ktFiles, bootClasspath = bootClasspath)
}
}
val TestServices.compilerConfigurationProvider: CompilerConfigurationProvider by TestServices.testServiceAccessor()
open class CompilerConfigurationProviderImpl(
testServices: TestServices,
override val testRootDisposable: Disposable,
override val configurators: List<AbstractEnvironmentConfigurator>
) : CompilerConfigurationProvider(testServices) {
private val cache: MutableMap<TestModule, KotlinCoreEnvironment> = mutableMapOf()
override fun getKotlinCoreEnvironment(module: TestModule): KotlinCoreEnvironment {
return cache.getOrPut(module) {
createKotlinCoreEnvironment(module)
}
}
@OptIn(TestInfrastructureInternals::class)
protected open fun createKotlinCoreEnvironment(module: TestModule): KotlinCoreEnvironment {
val platform = module.targetPlatform
val configFiles = platform.platformToEnvironmentConfigFiles()
val applicationEnvironment = KotlinCoreEnvironment.getOrCreateApplicationEnvironmentForTests(
testServices.applicationDisposableProvider.getApplicationRootDisposable(),
CompilerConfiguration()
)
val configuration = createCompilerConfiguration(module, configurators)
val projectEnv = KotlinCoreEnvironment.ProjectEnvironment(testRootDisposable, applicationEnvironment, configuration)
return KotlinCoreEnvironment.createForTests(
projectEnv,
configuration,
configFiles
).also { registerCompilerExtensions(projectEnv.project, module, configuration) }
}
@OptIn(TestInfrastructureInternals::class)
fun createCompilerConfiguration(module: TestModule): CompilerConfiguration {
return createCompilerConfiguration(module, configurators)
}
}
@TestInfrastructureInternals
fun TargetPlatform.platformToEnvironmentConfigFiles() = when {
isJvm() -> EnvironmentConfigFiles.JVM_CONFIG_FILES
isJs() -> EnvironmentConfigFiles.JS_CONFIG_FILES
isNative() -> EnvironmentConfigFiles.NATIVE_CONFIG_FILES
isWasm() -> EnvironmentConfigFiles.WASM_CONFIG_FILES
// TODO: is it correct?
isCommon() -> EnvironmentConfigFiles.METADATA_CONFIG_FILES
else -> error("Unknown platform: ${this}")
}
@TestInfrastructureInternals
fun createCompilerConfiguration(module: TestModule, configurators: List<AbstractEnvironmentConfigurator>): CompilerConfiguration {
val configuration = CompilerConfiguration()
configuration[CommonConfigurationKeys.MODULE_NAME] = module.name
if (JsEnvironmentConfigurationDirectives.GENERATE_STRICT_IMPLICIT_EXPORT in module.directives) {
configuration.put(JSConfigurationKeys.GENERATE_STRICT_IMPLICIT_EXPORT, true)
}
if (JsEnvironmentConfigurationDirectives.GENERATE_DTS in module.directives) {
configuration.put(JSConfigurationKeys.GENERATE_DTS, true)
}
if (JsEnvironmentConfigurationDirectives.ES6_MODE in module.directives) {
configuration.put(JSConfigurationKeys.USE_ES6_CLASSES, true)
}
if (module.frontendKind == FrontendKinds.FIR) {
configuration[CommonConfigurationKeys.USE_FIR] = true
}
val messageCollector = object : MessageCollector {
override fun clear() {}
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) {
if (severity == CompilerMessageSeverity.ERROR) {
val prefix = if (location == null) "" else "(" + location.path + ":" + location.line + ":" + location.column + ") "
throw AssertionError(prefix + message)
}
}
override fun hasErrors(): Boolean = false
}
configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY] = messageCollector
configuration[IrMessageLogger.IR_MESSAGE_LOGGER] = IrMessageCollector(messageCollector)
configuration.languageVersionSettings = module.languageVersionSettings
configurators.forEach { it.configureCompileConfigurationWithAdditionalConfigurationKeys(configuration, module) }
return configuration
}
private operator fun <T : Any> CompilerConfiguration.set(key: CompilerConfigurationKey<T>, value: T) {
put(key, value)
}