[JS SCRIPT] refactor js script infrastructure
- Implement proper script compiler proxy to correctly handle script and its closed-world dependencies - Clean up zoo of JsScriptCompilers
This commit is contained in:
@@ -44,7 +44,7 @@ class JsIrBackendContext(
|
|||||||
val symbolTable: SymbolTable,
|
val symbolTable: SymbolTable,
|
||||||
irModuleFragment: IrModuleFragment,
|
irModuleFragment: IrModuleFragment,
|
||||||
val additionalExportedDeclarations: Set<FqName>,
|
val additionalExportedDeclarations: Set<FqName>,
|
||||||
override val configuration: CompilerConfiguration,
|
override val configuration: CompilerConfiguration, // TODO: remove configuration from backend context
|
||||||
override val scriptMode: Boolean = false
|
override val scriptMode: Boolean = false
|
||||||
) : CommonBackendContext {
|
) : CommonBackendContext {
|
||||||
override val transformedFunction = mutableMapOf<IrFunctionSymbol, IrSimpleFunctionSymbol>()
|
override val transformedFunction = mutableMapOf<IrFunctionSymbol, IrSimpleFunctionSymbol>()
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ fun compile(
|
|||||||
return transformer.generateModule(moduleFragment)
|
return transformer.generateModule(moduleFragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun compileForRepl(
|
fun generateJsCode(
|
||||||
context: JsIrBackendContext,
|
context: JsIrBackendContext,
|
||||||
moduleFragment: IrModuleFragment,
|
moduleFragment: IrModuleFragment,
|
||||||
nameTables: NameTables
|
nameTables: NameTables
|
||||||
|
|||||||
+10
-12
@@ -21,8 +21,7 @@ import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigura
|
|||||||
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.platform
|
import org.jetbrains.kotlin.scripting.definitions.platform
|
||||||
import org.jetbrains.kotlin.scripting.repl.js.JsReplEvaluator
|
import org.jetbrains.kotlin.scripting.repl.js.*
|
||||||
import org.jetbrains.kotlin.scripting.repl.js.ReplMessageCollector
|
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
||||||
import kotlin.script.experimental.api.baseClass
|
import kotlin.script.experimental.api.baseClass
|
||||||
@@ -31,22 +30,24 @@ import kotlin.script.experimental.host.ScriptingHostConfiguration
|
|||||||
import kotlin.script.experimental.jvm.JsDependency
|
import kotlin.script.experimental.jvm.JsDependency
|
||||||
|
|
||||||
abstract class AbstractJsReplTest : Closeable {
|
abstract class AbstractJsReplTest : Closeable {
|
||||||
abstract fun createCompiler(): ReplCompiler
|
protected lateinit var compilationState: JsReplCompilationState
|
||||||
abstract fun preprocessEvaluation()
|
protected lateinit var evaluationState: JsEvaluationState
|
||||||
|
|
||||||
|
protected abstract fun createCompilationState(): JsReplCompilationState
|
||||||
|
protected abstract fun createEvaluationState(): JsEvaluationState
|
||||||
|
|
||||||
fun compile(codeLine: ReplCodeLine): ReplCompileResult {
|
fun compile(codeLine: ReplCodeLine): ReplCompileResult {
|
||||||
return compiler.compile(compiler.createState(), codeLine)
|
return JsReplCompiler(environment).compile(compilationState, codeLine)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun evaluate(compileResult: ReplCompileResult.CompiledClasses): ReplEvalResult {
|
fun evaluate(compileResult: ReplCompileResult.CompiledClasses): ReplEvalResult {
|
||||||
return jsEvaluator.eval(jsEvaluator.createState(), compileResult)
|
return JsReplEvaluator().eval(evaluationState, compileResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reset() {
|
fun reset() {
|
||||||
collector.clear()
|
collector.clear()
|
||||||
compiler = createCompiler()
|
compilationState = createCompilationState()
|
||||||
jsEvaluator = JsReplEvaluator()
|
evaluationState = createEvaluationState()
|
||||||
preprocessEvaluation()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val collector: MessageCollector = ReplMessageCollector()
|
private val collector: MessageCollector = ReplMessageCollector()
|
||||||
@@ -55,9 +56,6 @@ abstract class AbstractJsReplTest : Closeable {
|
|||||||
disposable, loadConfiguration(), EnvironmentConfigFiles.JS_CONFIG_FILES
|
disposable, loadConfiguration(), EnvironmentConfigFiles.JS_CONFIG_FILES
|
||||||
)
|
)
|
||||||
|
|
||||||
lateinit var compiler: ReplCompiler
|
|
||||||
lateinit var jsEvaluator: JsReplEvaluator
|
|
||||||
|
|
||||||
private var snippetId: Int = 1 //index 0 for klib
|
private var snippetId: Int = 1 //index 0 for klib
|
||||||
fun newSnippetId(): Int = snippetId++
|
fun newSnippetId(): Int = snippetId++
|
||||||
|
|
||||||
|
|||||||
+18
-17
@@ -5,37 +5,38 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.scripting.repl.js.test
|
package org.jetbrains.kotlin.scripting.repl.js.test
|
||||||
|
|
||||||
import org.jetbrains.kotlin.cli.common.repl.ReplCompiler
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||||
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
|
import org.jetbrains.kotlin.js.engine.ScriptEngineNashorn
|
||||||
|
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzer
|
||||||
import org.jetbrains.kotlin.scripting.repl.js.*
|
import org.jetbrains.kotlin.scripting.repl.js.*
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
|
|
||||||
|
// 1. Compile dependencies
|
||||||
|
// 2. Save them as a binary dependency (name table and js string)
|
||||||
|
// 3. For each new state load dependency's table and js code
|
||||||
class JsReplTestAgainstBinaries : AbstractJsReplTest() {
|
class JsReplTestAgainstBinaries : AbstractJsReplTest() {
|
||||||
private val dependencyLoader = DependencyLoader()
|
private val dependencyLoader = DependencyLoader()
|
||||||
|
private val dependencies = readLibrariesFromConfiguration(environment.configuration)
|
||||||
private val runtimeBinary: String
|
|
||||||
private val nameTable: NameTables
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val dependencies = readLibrariesFromConfiguration(environment.configuration)
|
val nameTable = NameTables(emptyList())
|
||||||
val compiler = ScriptDependencyCompiler(environment)
|
val compiler = JsScriptDependencyCompiler(environment.configuration, nameTable, SymbolTable())
|
||||||
|
val runtimeBinary = compiler.compile(dependencies)
|
||||||
val result = compiler.compile(dependencies)
|
|
||||||
runtimeBinary = result.first
|
|
||||||
nameTable = result.second
|
|
||||||
|
|
||||||
dependencyLoader.saveScriptDependencyBinary(runtimeBinary)
|
dependencyLoader.saveScriptDependencyBinary(runtimeBinary)
|
||||||
dependencyLoader.saveNames(nameTable)
|
dependencyLoader.saveNames(nameTable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createCompiler(): ReplCompiler {
|
override fun createCompilationState(): JsReplCompilationState {
|
||||||
return JsDebuggerCompiler(environment, dependencyLoader.loadNames())
|
val replState = ReplCodeAnalyzer.ResettableAnalyzerState()
|
||||||
|
return JsReplCompilationState(ReentrantReadWriteLock(), dependencyLoader.loadNames(), dependencies, replState, SymbolTable())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun preprocessEvaluation() {
|
override fun createEvaluationState(): JsEvaluationState {
|
||||||
jsEvaluator.eval(
|
val state = JsEvaluationState(ReentrantReadWriteLock(), ScriptEngineNashorn())
|
||||||
jsEvaluator.createState(),
|
JsReplEvaluator().eval(state, createCompileResult(dependencyLoader.loadScriptDependencyBinary()))
|
||||||
createCompileResult(dependencyLoader.loadScriptDependencyBinary())
|
return state
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
|
|||||||
+29
-7
@@ -6,21 +6,43 @@
|
|||||||
package org.jetbrains.kotlin.scripting.repl.js.test
|
package org.jetbrains.kotlin.scripting.repl.js.test
|
||||||
|
|
||||||
import com.intellij.openapi.util.Disposer
|
import com.intellij.openapi.util.Disposer
|
||||||
import org.jetbrains.kotlin.cli.common.repl.ReplCompiler
|
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||||
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
|
import org.jetbrains.kotlin.js.engine.ScriptEngineNashorn
|
||||||
|
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzer
|
||||||
import org.jetbrains.kotlin.scripting.repl.js.*
|
import org.jetbrains.kotlin.scripting.repl.js.*
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
|
|
||||||
class JsReplTestAgainstKlib : AbstractJsReplTest() {
|
class JsReplTestAgainstKlib : AbstractJsReplTest() {
|
||||||
override fun createCompiler(): ReplCompiler = JsReplCompiler(environment)
|
|
||||||
|
|
||||||
override fun preprocessEvaluation() {
|
private var dependencyCode: String? = null
|
||||||
val scriptDependencyBinary = (compiler as JsReplCompiler).scriptDependencyBinary
|
|
||||||
|
|
||||||
jsEvaluator.eval(
|
override fun createCompilationState(): JsReplCompilationState {
|
||||||
jsEvaluator.createState(),
|
val nameTables = NameTables(emptyList())
|
||||||
createCompileResult(scriptDependencyBinary)
|
val symbolTable = SymbolTable()
|
||||||
|
val dependencyCompiler = JsScriptDependencyCompiler(environment.configuration, nameTables, symbolTable)
|
||||||
|
val dependencies = readLibrariesFromConfiguration(environment.configuration)
|
||||||
|
dependencyCode = dependencyCompiler.compile(dependencies)
|
||||||
|
|
||||||
|
return JsReplCompilationState(
|
||||||
|
ReentrantReadWriteLock(),
|
||||||
|
nameTables,
|
||||||
|
dependencies,
|
||||||
|
ReplCodeAnalyzer.ResettableAnalyzerState(),
|
||||||
|
symbolTable
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun createEvaluationState(): JsEvaluationState {
|
||||||
|
val state = JsEvaluationState(ReentrantReadWriteLock(), ScriptEngineNashorn())
|
||||||
|
|
||||||
|
JsReplEvaluator().eval(state, createCompileResult(dependencyCode ?: error("Dependencies has to be compiled first")))
|
||||||
|
|
||||||
|
dependencyCode = null
|
||||||
|
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
Disposer.dispose(disposable)
|
Disposer.dispose(disposable)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ jvmTarget = "1.6"
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile(project(":kotlin-scripting-common"))
|
compile(project(":kotlin-scripting-common"))
|
||||||
compile(project(":compiler:cli-common"))
|
compileOnly(project(":compiler:backend.js"))
|
||||||
compile(project(":js:js.engines"))
|
compileOnly(project(":compiler:cli-common"))
|
||||||
compile(intellijCoreDep()) { includeJars("intellij-core") }
|
compileOnly(project(":js:js.engines"))
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
|||||||
+3
-4
@@ -11,9 +11,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock
|
|||||||
|
|
||||||
class JsReplEvaluator : ReplEvaluator {
|
class JsReplEvaluator : ReplEvaluator {
|
||||||
//TODO: support println()
|
//TODO: support println()
|
||||||
private val engine = ScriptEngineNashorn()
|
override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*> = JsEvaluationState(lock, ScriptEngineNashorn())
|
||||||
|
|
||||||
override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*> = JsState(lock)
|
|
||||||
|
|
||||||
override fun eval(
|
override fun eval(
|
||||||
state: IReplStageState<*>,
|
state: IReplStageState<*>,
|
||||||
@@ -22,7 +20,8 @@ class JsReplEvaluator : ReplEvaluator {
|
|||||||
invokeWrapper: InvokeWrapper?
|
invokeWrapper: InvokeWrapper?
|
||||||
): ReplEvalResult {
|
): ReplEvalResult {
|
||||||
return try {
|
return try {
|
||||||
val evalResult = engine.eval<Any?>(compileResult.data as String)
|
val evaluationState = state.asState(JsEvaluationState::class.java)
|
||||||
|
val evalResult = evaluationState.engine.eval<Any?>(compileResult.data as String)
|
||||||
ReplEvalResult.ValueResult("result", evalResult, "Any?")
|
ReplEvalResult.ValueResult("result", evalResult, "Any?")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
ReplEvalResult.Error.Runtime("Error while evaluating", e)
|
ReplEvalResult.Error.Runtime("Error while evaluating", e)
|
||||||
|
|||||||
@@ -6,7 +6,10 @@
|
|||||||
package org.jetbrains.kotlin.scripting.repl.js
|
package org.jetbrains.kotlin.scripting.repl.js
|
||||||
|
|
||||||
import org.jetbrains.kotlin.cli.common.repl.*
|
import org.jetbrains.kotlin.cli.common.repl.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||||
|
import org.jetbrains.kotlin.js.engine.ScriptEngine
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.script.experimental.api.CompiledScript
|
import kotlin.script.experimental.api.CompiledScript
|
||||||
@@ -14,7 +17,7 @@ import kotlin.script.experimental.api.ResultWithDiagnostics
|
|||||||
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
||||||
import kotlin.script.experimental.api.ScriptEvaluationConfiguration
|
import kotlin.script.experimental.api.ScriptEvaluationConfiguration
|
||||||
|
|
||||||
class JsState(override val lock: ReentrantReadWriteLock) : IReplStageState<ScriptDescriptor> {
|
abstract class JsState(override val lock: ReentrantReadWriteLock) : IReplStageState<ScriptDescriptor> {
|
||||||
override val history: IReplStageHistory<ScriptDescriptor>
|
override val history: IReplStageHistory<ScriptDescriptor>
|
||||||
get() = TODO("not implemented")
|
get() = TODO("not implemented")
|
||||||
|
|
||||||
@@ -23,7 +26,18 @@ class JsState(override val lock: ReentrantReadWriteLock) : IReplStageState<Scrip
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CompiledToJsScript(
|
abstract class JsCompilationState(
|
||||||
|
lock: ReentrantReadWriteLock,
|
||||||
|
val nameTables: NameTables,
|
||||||
|
val dependencies: List<ModuleDescriptor>) : JsState(lock)
|
||||||
|
|
||||||
|
class JsEvaluationState(lock: ReentrantReadWriteLock, val engine: ScriptEngine) : JsState(lock) {
|
||||||
|
override fun dispose() {
|
||||||
|
engine.release()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class JsCompiledScript(
|
||||||
val jsCode: String,
|
val jsCode: String,
|
||||||
override val compilationConfiguration: ScriptCompilationConfiguration
|
override val compilationConfiguration: ScriptCompilationConfiguration
|
||||||
) : CompiledScript<Any> {
|
) : CompiledScript<Any> {
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@ class JsScriptEvaluator : ScriptEvaluator {
|
|||||||
scriptEvaluationConfiguration: ScriptEvaluationConfiguration
|
scriptEvaluationConfiguration: ScriptEvaluationConfiguration
|
||||||
): ResultWithDiagnostics<EvaluationResult> {
|
): ResultWithDiagnostics<EvaluationResult> {
|
||||||
return try {
|
return try {
|
||||||
val evalResult = engine.eval<Any?>((compiledScript as CompiledToJsScript).jsCode)
|
val evalResult = engine.eval<Any?>((compiledScript as JsCompiledScript).jsCode)
|
||||||
ResultWithDiagnostics.Success(
|
ResultWithDiagnostics.Success(
|
||||||
EvaluationResult(
|
EvaluationResult(
|
||||||
ResultValue.Value(
|
ResultValue.Value(
|
||||||
|
|||||||
+3
-3
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
package kotlin.script.experimental.jvmhost
|
package kotlin.script.experimental.jvmhost
|
||||||
|
|
||||||
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptJvmCompilerProxy
|
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptCompilerProxy
|
||||||
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.ScriptJvmCompilerIsolated
|
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.ScriptJvmCompilerIsolated
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
@@ -16,12 +16,12 @@ import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
|||||||
|
|
||||||
open class JvmScriptCompiler(
|
open class JvmScriptCompiler(
|
||||||
baseHostConfiguration: ScriptingHostConfiguration = defaultJvmScriptingHostConfiguration,
|
baseHostConfiguration: ScriptingHostConfiguration = defaultJvmScriptingHostConfiguration,
|
||||||
compilerProxy: ScriptJvmCompilerProxy? = null
|
compilerProxy: ScriptCompilerProxy? = null
|
||||||
) : ScriptCompiler {
|
) : ScriptCompiler {
|
||||||
|
|
||||||
val hostConfiguration = baseHostConfiguration.withDefaultsFrom(defaultJvmScriptingHostConfiguration)
|
val hostConfiguration = baseHostConfiguration.withDefaultsFrom(defaultJvmScriptingHostConfiguration)
|
||||||
|
|
||||||
val compilerProxy: ScriptJvmCompilerProxy = compilerProxy ?: ScriptJvmCompilerIsolated(hostConfiguration)
|
val compilerProxy: ScriptCompilerProxy = compilerProxy ?: ScriptJvmCompilerIsolated(hostConfiguration)
|
||||||
|
|
||||||
override suspend operator fun invoke(
|
override suspend operator fun invoke(
|
||||||
script: SourceCode,
|
script: SourceCode,
|
||||||
|
|||||||
+4
-14
@@ -31,12 +31,7 @@ abstract class AbstractScriptEvaluationExtension : ScriptEvaluationExtension {
|
|||||||
): KotlinCoreEnvironment
|
): KotlinCoreEnvironment
|
||||||
|
|
||||||
abstract fun createScriptEvaluator(): ScriptEvaluator
|
abstract fun createScriptEvaluator(): ScriptEvaluator
|
||||||
|
abstract fun createScriptCompiler(environment: KotlinCoreEnvironment): ScriptCompilerProxy
|
||||||
abstract suspend fun compilerInvoke(
|
|
||||||
environment: KotlinCoreEnvironment,
|
|
||||||
script: SourceCode,
|
|
||||||
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
|
||||||
): ResultWithDiagnostics<CompiledScript<*>>
|
|
||||||
|
|
||||||
protected abstract fun ScriptEvaluationConfiguration.Builder.platformEvaluationConfiguration()
|
protected abstract fun ScriptEvaluationConfiguration.Builder.platformEvaluationConfiguration()
|
||||||
|
|
||||||
@@ -82,22 +77,17 @@ abstract class AbstractScriptEvaluationExtension : ScriptEvaluationExtension {
|
|||||||
|
|
||||||
}
|
}
|
||||||
val scriptCompilationConfiguration = definition.compilationConfiguration
|
val scriptCompilationConfiguration = definition.compilationConfiguration
|
||||||
|
val scriptCompiler = createScriptCompiler(environment)
|
||||||
val scriptEvaluator = createScriptEvaluator()
|
|
||||||
|
|
||||||
return runBlocking {
|
return runBlocking {
|
||||||
val compiledScript = compilerInvoke(
|
val compiledScript = scriptCompiler.compile(script, scriptCompilationConfiguration).valueOr {
|
||||||
environment,
|
|
||||||
script,
|
|
||||||
scriptCompilationConfiguration
|
|
||||||
).valueOr {
|
|
||||||
for (report in it.reports) {
|
for (report in it.reports) {
|
||||||
messageCollector.report(report.severity.toCompilerMessageSeverity(), report.render(withSeverity = false))
|
messageCollector.report(report.severity.toCompilerMessageSeverity(), report.render(withSeverity = false))
|
||||||
}
|
}
|
||||||
return@runBlocking ExitCode.COMPILATION_ERROR
|
return@runBlocking ExitCode.COMPILATION_ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
val evalResult = scriptEvaluator.invoke(compiledScript, evaluationConfiguration).valueOr {
|
val evalResult = createScriptEvaluator().invoke(compiledScript, evaluationConfiguration).valueOr {
|
||||||
for (report in it.reports) {
|
for (report in it.reports) {
|
||||||
messageCollector.report(report.severity.toCompilerMessageSeverity(), report.render(withSeverity = false))
|
messageCollector.report(report.severity.toCompilerMessageSeverity(), report.render(withSeverity = false))
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-33
@@ -6,22 +6,28 @@
|
|||||||
package org.jetbrains.kotlin.scripting.compiler.plugin
|
package org.jetbrains.kotlin.scripting.compiler.plugin
|
||||||
|
|
||||||
import com.intellij.core.JavaCoreProjectEnvironment
|
import com.intellij.core.JavaCoreProjectEnvironment
|
||||||
|
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
|
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
|
||||||
|
import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||||
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
|
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.JsScriptCompilerWithDependenciesProxy
|
||||||
|
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.withMessageCollector
|
||||||
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.platform
|
import org.jetbrains.kotlin.scripting.definitions.platform
|
||||||
import org.jetbrains.kotlin.scripting.repl.js.CompiledToJsScript
|
import org.jetbrains.kotlin.scripting.repl.js.*
|
||||||
import org.jetbrains.kotlin.scripting.repl.js.JsScriptCompiler
|
|
||||||
import org.jetbrains.kotlin.scripting.repl.js.JsScriptDependencyCompiler
|
|
||||||
import org.jetbrains.kotlin.scripting.repl.js.JsScriptEvaluator
|
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
import kotlin.script.experimental.jvm.JsDependency
|
import kotlin.script.experimental.jvm.JsDependency
|
||||||
|
|
||||||
|
// TODO: the code below has to be considered as temporary hack and removed ASAP.
|
||||||
|
// Actual ScriptCompilationConfiguration should be set up from CompilerConfiguration.
|
||||||
fun loadScriptConfiguration(configuration: CompilerConfiguration) {
|
fun loadScriptConfiguration(configuration: CompilerConfiguration) {
|
||||||
val scriptConfiguration = ScriptCompilationConfiguration {
|
val scriptConfiguration = ScriptCompilationConfiguration {
|
||||||
baseClass("kotlin.Any")
|
baseClass("kotlin.Any")
|
||||||
@@ -55,37 +61,13 @@ class JsScriptEvaluationExtension : AbstractScriptEvaluationExtension() {
|
|||||||
return JsScriptEvaluator()
|
return JsScriptEvaluator()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var environment: KotlinCoreEnvironment? = null
|
private var scriptCompilerProxy: ScriptCompilerProxy? = null
|
||||||
private var dependencyJsCode: String? = null
|
|
||||||
private val scriptCompiler: JsScriptCompiler by lazy {
|
override fun createScriptCompiler(environment: KotlinCoreEnvironment): ScriptCompilerProxy {
|
||||||
val env = environment ?: error("Expected environment is initialized prior to compiler instantiation")
|
return scriptCompilerProxy ?: JsScriptCompilerWithDependenciesProxy(environment).also { scriptCompilerProxy = it }
|
||||||
JsScriptCompiler(env).apply {
|
|
||||||
dependencyJsCode = JsScriptDependencyCompiler(env.configuration, nameTables, symbolTable).compile(dependencies)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun compilerInvoke(
|
override fun ScriptEvaluationConfiguration.Builder.platformEvaluationConfiguration() {}
|
||||||
environment: KotlinCoreEnvironment,
|
|
||||||
script: SourceCode,
|
|
||||||
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
|
||||||
): ResultWithDiagnostics<CompiledScript<*>> {
|
|
||||||
|
|
||||||
this.environment = environment
|
|
||||||
|
|
||||||
return scriptCompiler.invoke(script, scriptCompilationConfiguration).onSuccess {
|
|
||||||
val compiledResult = it as CompiledToJsScript
|
|
||||||
val actualResult = dependencyJsCode?.let { d ->
|
|
||||||
dependencyJsCode = null
|
|
||||||
CompiledToJsScript(d + "\n" + compiledResult.jsCode, compiledResult.compilationConfiguration)
|
|
||||||
} ?: compiledResult
|
|
||||||
|
|
||||||
ResultWithDiagnostics.Success(actualResult)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun ScriptEvaluationConfiguration.Builder.platformEvaluationConfiguration() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isAccepted(arguments: CommonCompilerArguments): Boolean {
|
override fun isAccepted(arguments: CommonCompilerArguments): Boolean {
|
||||||
return arguments is K2JSCompilerArguments
|
return arguments is K2JSCompilerArguments
|
||||||
|
|||||||
+2
-12
@@ -43,18 +43,8 @@ class JvmCliScriptEvaluationExtension : AbstractScriptEvaluationExtension() {
|
|||||||
return BasicJvmScriptEvaluator()
|
return BasicJvmScriptEvaluator()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var environment: KotlinCoreEnvironment? = null
|
override fun createScriptCompiler(environment: KotlinCoreEnvironment): ScriptCompilerProxy {
|
||||||
private val scriptCompiler: ScriptJvmCompilerFromEnvironment by lazy {
|
return ScriptJvmCompilerFromEnvironment(environment)
|
||||||
ScriptJvmCompilerFromEnvironment(environment!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun compilerInvoke(
|
|
||||||
environment: KotlinCoreEnvironment,
|
|
||||||
script: SourceCode,
|
|
||||||
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
|
||||||
): ResultWithDiagnostics<CompiledScript<*>> {
|
|
||||||
this.environment = environment
|
|
||||||
return scriptCompiler.compile(script, scriptCompilationConfiguration)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isAccepted(arguments: CommonCompilerArguments): Boolean =
|
override fun isAccepted(arguments: CommonCompilerArguments): Boolean =
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ import kotlin.script.experimental.api.ResultWithDiagnostics
|
|||||||
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
||||||
import kotlin.script.experimental.api.SourceCode
|
import kotlin.script.experimental.api.SourceCode
|
||||||
|
|
||||||
interface ScriptJvmCompilerProxy {
|
interface ScriptCompilerProxy {
|
||||||
fun compile(
|
fun compile(
|
||||||
script: SourceCode,
|
script: SourceCode,
|
||||||
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
||||||
+79
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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.scripting.compiler.plugin.impl
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace
|
||||||
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
|
import org.jetbrains.kotlin.context.ContextForNewModule
|
||||||
|
import org.jetbrains.kotlin.context.ProjectContext
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Severity
|
||||||
|
import org.jetbrains.kotlin.frontend.js.di.createTopDownAnalyzerForJs
|
||||||
|
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
||||||
|
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingTraceContext
|
||||||
|
import org.jetbrains.kotlin.resolve.TopDownAnalysisMode
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
|
||||||
|
|
||||||
|
abstract class AbstractJsScriptlikeCodeAnalyser(
|
||||||
|
private val environment: KotlinCoreEnvironment,
|
||||||
|
private val dependencies: List<ModuleDescriptor>
|
||||||
|
) {
|
||||||
|
|
||||||
|
protected class JsScriptAnalysisResult(
|
||||||
|
val moduleDescriptor: ModuleDescriptor,
|
||||||
|
private val scriptDescriptor: ClassDescriptorWithResolutionScopes?,
|
||||||
|
val bindingContext: BindingContext
|
||||||
|
) {
|
||||||
|
val isSuccess: Boolean get() = scriptDescriptor != null
|
||||||
|
val script: ClassDescriptorWithResolutionScopes get() = scriptDescriptor ?: error("Error occurred")
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun analysisImpl(psi: KtFile): JsScriptAnalysisResult {
|
||||||
|
val trace: BindingTraceContext = NoScopeRecordCliBindingTrace()
|
||||||
|
val project = environment.project
|
||||||
|
val builtIns: KotlinBuiltIns = dependencies.single { it.allDependencyModules.isEmpty() }.builtIns
|
||||||
|
val moduleContext = ContextForNewModule(
|
||||||
|
ProjectContext(project, "TopDownAnalyzer for JS Script"),
|
||||||
|
Name.special("<script>"),
|
||||||
|
builtIns,
|
||||||
|
platform = null
|
||||||
|
)
|
||||||
|
val languageVersionSettings = environment.configuration.languageVersionSettings
|
||||||
|
val lookupTracker = LookupTracker.DO_NOTHING
|
||||||
|
val expectActualTracker = ExpectActualTracker.DoNothing
|
||||||
|
val additionalPackages = emptyList<PackageFragmentProvider>()
|
||||||
|
val moduleDescriptor = moduleContext.module
|
||||||
|
|
||||||
|
moduleDescriptor.setDependencies(dependencies.map { it as ModuleDescriptorImpl } + moduleDescriptor)
|
||||||
|
|
||||||
|
val analyzer = createTopDownAnalyzerForJs(
|
||||||
|
moduleContext, trace,
|
||||||
|
FileBasedDeclarationProviderFactory(moduleContext.storageManager, listOf(psi)),
|
||||||
|
languageVersionSettings,
|
||||||
|
lookupTracker,
|
||||||
|
expectActualTracker,
|
||||||
|
additionalPackages
|
||||||
|
)
|
||||||
|
val analyzerContext = analyzer.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, listOf(psi))
|
||||||
|
|
||||||
|
val diagnostics = trace.bindingContext.diagnostics
|
||||||
|
val hasErrors = diagnostics.any { it.severity == Severity.ERROR }
|
||||||
|
val scriptDescriptor = analyzerContext.scripts[psi.script]
|
||||||
|
|
||||||
|
assert(scriptDescriptor != null || hasErrors) { "If no errors occurred script descriptor has to be existed" }
|
||||||
|
|
||||||
|
return JsScriptAnalysisResult(moduleDescriptor, scriptDescriptor, trace.bindingContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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.scripting.compiler.plugin.impl
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||||
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
|
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptCompilerProxy
|
||||||
|
import org.jetbrains.kotlin.scripting.repl.js.JsCompiledScript
|
||||||
|
import org.jetbrains.kotlin.scripting.repl.js.JsCoreScriptingCompiler
|
||||||
|
import org.jetbrains.kotlin.scripting.repl.js.JsScriptDependencyCompiler
|
||||||
|
import org.jetbrains.kotlin.scripting.repl.js.readLibrariesFromConfiguration
|
||||||
|
import kotlin.script.experimental.api.*
|
||||||
|
|
||||||
|
class JsScriptCompilerWithDependenciesProxy(private val environment: KotlinCoreEnvironment) : ScriptCompilerProxy {
|
||||||
|
private val nameTables = NameTables(emptyList())
|
||||||
|
private val symbolTable = SymbolTable()
|
||||||
|
private val dependencies: List<ModuleDescriptor> = readLibrariesFromConfiguration(environment.configuration)
|
||||||
|
private val compiler = JsCoreScriptingCompiler(environment, nameTables, symbolTable, dependencies)
|
||||||
|
private var scriptDependencyCompiler: JsScriptDependencyCompiler? =
|
||||||
|
JsScriptDependencyCompiler(environment.configuration, nameTables, symbolTable)
|
||||||
|
|
||||||
|
override fun compile(
|
||||||
|
script: SourceCode,
|
||||||
|
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
||||||
|
): ResultWithDiagnostics<CompiledScript<*>> {
|
||||||
|
val parentMessageCollector = environment.configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]
|
||||||
|
return withMessageCollector(script = script, parentMessageCollector = parentMessageCollector) { messageCollector ->
|
||||||
|
environment.configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
|
||||||
|
try {
|
||||||
|
val dependenciesCode = scriptDependencyCompiler?.let { scriptDependencyCompiler = null; it.compile(dependencies) } ?: ""
|
||||||
|
when (val compileResult = compiler.compile(org.jetbrains.kotlin.scripting.repl.js.makeReplCodeLine(0, script.text))) {
|
||||||
|
is ReplCompileResult.CompiledClasses -> {
|
||||||
|
val compileJsCode = compileResult.data as String
|
||||||
|
ResultWithDiagnostics.Success(
|
||||||
|
JsCompiledScript(dependenciesCode + "\n" + compileJsCode, scriptCompilationConfiguration)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is ReplCompileResult.Incomplete -> ResultWithDiagnostics.Failure(
|
||||||
|
ScriptDiagnostic("Incomplete code")
|
||||||
|
)
|
||||||
|
is ReplCompileResult.Error -> ResultWithDiagnostics.Failure(
|
||||||
|
ScriptDiagnostic(
|
||||||
|
message = compileResult.message,
|
||||||
|
severity = ScriptDiagnostic.Severity.ERROR
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (parentMessageCollector != null)
|
||||||
|
environment.configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, parentMessageCollector)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-3
@@ -19,7 +19,7 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
|
|||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
|
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
|
||||||
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptJvmCompilerProxy
|
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptCompilerProxy
|
||||||
import org.jetbrains.kotlin.scripting.compiler.plugin.dependencies.ScriptsCompilationDependencies
|
import org.jetbrains.kotlin.scripting.compiler.plugin.dependencies.ScriptsCompilationDependencies
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
@@ -30,7 +30,7 @@ import kotlin.script.experimental.jvm.compilationCache
|
|||||||
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
||||||
import kotlin.script.experimental.jvm.jvm
|
import kotlin.script.experimental.jvm.jvm
|
||||||
|
|
||||||
class ScriptJvmCompilerIsolated(val hostConfiguration: ScriptingHostConfiguration) : ScriptJvmCompilerProxy {
|
class ScriptJvmCompilerIsolated(val hostConfiguration: ScriptingHostConfiguration) : ScriptCompilerProxy {
|
||||||
|
|
||||||
override fun compile(
|
override fun compile(
|
||||||
script: SourceCode,
|
script: SourceCode,
|
||||||
@@ -50,7 +50,7 @@ class ScriptJvmCompilerIsolated(val hostConfiguration: ScriptingHostConfiguratio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ScriptJvmCompilerFromEnvironment(val environment: KotlinCoreEnvironment) : ScriptJvmCompilerProxy {
|
class ScriptJvmCompilerFromEnvironment(val environment: KotlinCoreEnvironment) : ScriptCompilerProxy {
|
||||||
|
|
||||||
override fun compile(
|
override fun compile(
|
||||||
script: SourceCode,
|
script: SourceCode,
|
||||||
|
|||||||
+22
-49
@@ -9,40 +9,36 @@ import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
|||||||
import org.jetbrains.kotlin.cli.common.environment.setIdeaIoUseFallback
|
import org.jetbrains.kotlin.cli.common.environment.setIdeaIoUseFallback
|
||||||
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
import org.jetbrains.kotlin.cli.common.repl.*
|
import org.jetbrains.kotlin.cli.common.repl.LineId
|
||||||
|
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
|
||||||
|
import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.ir.backend.js.*
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.generateJsCode
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.generateModuleFragment
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
|
||||||
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
|
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
|
||||||
import org.jetbrains.kotlin.ir.util.IrDeserializer
|
|
||||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||||
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
||||||
|
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzer
|
||||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||||
import kotlin.script.experimental.api.valueOr
|
import kotlin.script.experimental.api.valueOr
|
||||||
import kotlin.script.experimental.host.StringScriptSource
|
import kotlin.script.experimental.host.StringScriptSource
|
||||||
|
|
||||||
class DeserializerWithDependencies(val deserializer: IrDeserializer, val dependencies: List<IrModuleFragment>)
|
class JsCoreScriptingCompiler(
|
||||||
|
|
||||||
class CoreScriptingJsCompiler(
|
|
||||||
private val environment: KotlinCoreEnvironment,
|
private val environment: KotlinCoreEnvironment,
|
||||||
private val nameTables: NameTables,
|
private val nameTables: NameTables,
|
||||||
|
private val symbolTable: SymbolTable,
|
||||||
private val dependencyDescriptors: List<ModuleDescriptor>,
|
private val dependencyDescriptors: List<ModuleDescriptor>,
|
||||||
private val createDeserializer: (ModuleDescriptor, SymbolTable, IrBuiltIns) -> DeserializerWithDependencies? = { _, _, _ -> null }
|
private val replState: ReplCodeAnalyzer.ResettableAnalyzerState = ReplCodeAnalyzer.ResettableAnalyzerState()
|
||||||
) {
|
) {
|
||||||
private val analyzerEngine: JsReplCodeAnalyzer = JsReplCodeAnalyzer(environment.project, dependencyDescriptors)
|
|
||||||
private val symbolTable: SymbolTable = SymbolTable()
|
|
||||||
|
|
||||||
fun compile(codeLine: ReplCodeLine): ReplCompileResult {
|
fun compile(codeLine: ReplCodeLine): ReplCompileResult {
|
||||||
val snippet = codeLine.code
|
val snippet = codeLine.code
|
||||||
val snippetId = codeLine.no
|
val snippetId = codeLine.no
|
||||||
|
|
||||||
val messageCollector = environment.configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY] as MessageCollector
|
|
||||||
|
|
||||||
setIdeaIoUseFallback()
|
setIdeaIoUseFallback()
|
||||||
|
|
||||||
val sourceCode = StringScriptSource(snippet, "line-$snippetId.kts")
|
val sourceCode = StringScriptSource(snippet, "line-$snippetId.kts")
|
||||||
@@ -52,28 +48,20 @@ class CoreScriptingJsCompiler(
|
|||||||
environment.project
|
environment.project
|
||||||
).valueOr { return ReplCompileResult.Error(it.reports.joinToString { r -> r.message }) }
|
).valueOr { return ReplCompileResult.Error(it.reports.joinToString { r -> r.message }) }
|
||||||
|
|
||||||
analyzerEngine.analyzeReplLine(snippetKtFile, codeLine).also {
|
val messageCollector = environment.configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY] as MessageCollector
|
||||||
AnalyzerWithCompilerReport.reportDiagnostics(it, messageCollector)
|
val analyzerEngine = JsReplCodeAnalyzer(environment, dependencyDescriptors, replState)
|
||||||
|
val analysisResult = analyzerEngine.analyzeReplLine(snippetKtFile, codeLine).also {
|
||||||
|
AnalyzerWithCompilerReport.reportDiagnostics(it.bindingContext.diagnostics, messageCollector)
|
||||||
if (messageCollector.hasErrors()) return ReplCompileResult.Error("Error while analysis")
|
if (messageCollector.hasErrors()) return ReplCompileResult.Error("Error while analysis")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val module = analysisResult.moduleDescriptor
|
||||||
|
val bindingContext = analysisResult.bindingContext
|
||||||
|
|
||||||
val psi2ir = Psi2IrTranslator(environment.configuration.languageVersionSettings)
|
val psi2ir = Psi2IrTranslator(environment.configuration.languageVersionSettings)
|
||||||
val psi2irContext = psi2ir.createGeneratorContext(
|
val psi2irContext = psi2ir.createGeneratorContext(module, bindingContext, symbolTable)
|
||||||
analyzerEngine.context.module,
|
|
||||||
analyzerEngine.trace.bindingContext,
|
|
||||||
symbolTable
|
|
||||||
)
|
|
||||||
|
|
||||||
val deserializerWithDependencies = createDeserializer(psi2irContext.moduleDescriptor, symbolTable, psi2irContext.irBuiltIns)
|
|
||||||
|
|
||||||
val irModuleFragment = psi2irContext.generateModuleFragment(listOf(snippetKtFile), deserializerWithDependencies?.deserializer)
|
|
||||||
|
|
||||||
val deserializedFragments = deserializerWithDependencies?.dependencies ?: emptyList()
|
|
||||||
|
|
||||||
val irFiles = sortDependencies(deserializedFragments).flatMap { it.files } + irModuleFragment.files
|
|
||||||
irModuleFragment.files.clear()
|
|
||||||
irModuleFragment.files += irFiles
|
|
||||||
|
|
||||||
|
val irModuleFragment = psi2irContext.generateModuleFragment(listOf(snippetKtFile))
|
||||||
|
|
||||||
val context = JsIrBackendContext(
|
val context = JsIrBackendContext(
|
||||||
irModuleFragment.descriptor,
|
irModuleFragment.descriptor,
|
||||||
@@ -88,28 +76,13 @@ class CoreScriptingJsCompiler(
|
|||||||
ExternalDependenciesGenerator(
|
ExternalDependenciesGenerator(
|
||||||
irModuleFragment.descriptor,
|
irModuleFragment.descriptor,
|
||||||
psi2irContext.symbolTable,
|
psi2irContext.symbolTable,
|
||||||
psi2irContext.irBuiltIns,
|
psi2irContext.irBuiltIns
|
||||||
deserializer = deserializerWithDependencies?.deserializer
|
|
||||||
).generateUnboundSymbolsAsDependencies()
|
).generateUnboundSymbolsAsDependencies()
|
||||||
|
|
||||||
with(context.implicitDeclarationFile) {
|
|
||||||
if (!irModuleFragment.files.contains(this)) {
|
|
||||||
irModuleFragment.files += this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
context.implicitDeclarationFile.declarations.clear()
|
|
||||||
|
|
||||||
environment.configuration.put(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN)
|
environment.configuration.put(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN)
|
||||||
|
|
||||||
val code = compileForRepl(
|
val code = generateJsCode(context, irModuleFragment, nameTables)
|
||||||
context,
|
|
||||||
irModuleFragment,
|
|
||||||
nameTables
|
|
||||||
)
|
|
||||||
|
|
||||||
return createCompileResult(
|
return createCompileResult(LineId(codeLine), code)
|
||||||
LineId(codeLine),
|
|
||||||
code
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
-35
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2019 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.scripting.repl.js
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.cli.common.repl.*
|
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
|
||||||
|
|
||||||
class JsDebuggerCompiler(
|
|
||||||
environment: KotlinCoreEnvironment,
|
|
||||||
loadNames: NameTables
|
|
||||||
) : ReplCompiler {
|
|
||||||
// TODO: configure dependencies
|
|
||||||
private val compiler = CoreScriptingJsCompiler(
|
|
||||||
environment,
|
|
||||||
loadNames,
|
|
||||||
readLibrariesFromConfiguration(environment.configuration)
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*> {
|
|
||||||
return JsState(lock)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun check(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCheckResult {
|
|
||||||
return ReplCheckResult.Ok()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun compile(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCompileResult {
|
|
||||||
return compiler.compile(codeLine)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+15
-64
@@ -5,82 +5,33 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.scripting.repl.js
|
package org.jetbrains.kotlin.scripting.repl.js
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|
||||||
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
|
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
|
||||||
import org.jetbrains.kotlin.context.ContextForNewModule
|
|
||||||
import org.jetbrains.kotlin.context.MutableModuleContext
|
|
||||||
import org.jetbrains.kotlin.context.ProjectContext
|
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
|
||||||
import org.jetbrains.kotlin.diagnostics.Severity
|
|
||||||
import org.jetbrains.kotlin.frontend.js.di.createTopDownAnalyzerForJs
|
|
||||||
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
|
||||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.BindingTraceContext
|
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.AbstractJsScriptlikeCodeAnalyser
|
||||||
import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer
|
|
||||||
import org.jetbrains.kotlin.resolve.TopDownAnalysisMode
|
|
||||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
|
||||||
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
|
|
||||||
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzer
|
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzer
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptPriorities
|
import org.jetbrains.kotlin.scripting.definitions.ScriptPriorities
|
||||||
|
|
||||||
class JsReplCodeAnalyzer(private val project: Project, private val dependencies: List<ModuleDescriptor>) {
|
class JsReplCodeAnalyzer(
|
||||||
|
environment: KotlinCoreEnvironment,
|
||||||
private val replState = ReplCodeAnalyzer.ResettableAnalyzerState()
|
dependencies: List<ModuleDescriptor>,
|
||||||
val trace: BindingTraceContext = NoScopeRecordCliBindingTrace()
|
private val replState: ReplCodeAnalyzer.ResettableAnalyzerState
|
||||||
|
) : AbstractJsScriptlikeCodeAnalyser(environment, dependencies) {
|
||||||
private val builtIns: KotlinBuiltIns = dependencies.single { it.allDependencyModules.isEmpty() }.builtIns
|
|
||||||
lateinit var context: MutableModuleContext
|
|
||||||
private fun createTopDownAnalyzerJS(files: Collection<KtFile>): LazyTopDownAnalyzer {
|
|
||||||
context = ContextForNewModule(
|
|
||||||
ProjectContext(project, "TopDownAnalyzer for JS"),
|
|
||||||
Name.special("<script>"),
|
|
||||||
builtIns,
|
|
||||||
platform = null
|
|
||||||
)
|
|
||||||
|
|
||||||
val languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT
|
|
||||||
val lookupTracker = LookupTracker.DO_NOTHING
|
|
||||||
val expectActualTracker = ExpectActualTracker.DoNothing
|
|
||||||
val additionalPackages = mutableListOf<PackageFragmentProvider>()
|
|
||||||
|
|
||||||
context.module.setDependencies(dependencies.map { it as ModuleDescriptorImpl } + context.module)
|
|
||||||
|
|
||||||
return createTopDownAnalyzerForJs(
|
|
||||||
context, trace,
|
|
||||||
FileBasedDeclarationProviderFactory(context.storageManager, files),
|
|
||||||
languageVersionSettings,
|
|
||||||
lookupTracker,
|
|
||||||
expectActualTracker,
|
|
||||||
additionalPackages
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun analyzeReplLine(linePsi: KtFile, codeLine: ReplCodeLine): Diagnostics {
|
|
||||||
trace.clearDiagnostics()
|
|
||||||
|
|
||||||
|
fun analyzeReplLine(linePsi: KtFile, codeLine: ReplCodeLine): AnalysisResult {
|
||||||
linePsi.script!!.putUserData(ScriptPriorities.PRIORITY_KEY, codeLine.no)
|
linePsi.script!!.putUserData(ScriptPriorities.PRIORITY_KEY, codeLine.no)
|
||||||
|
|
||||||
replState.submitLine(linePsi, codeLine)
|
replState.submitLine(linePsi, codeLine)
|
||||||
|
|
||||||
val analyzer = createTopDownAnalyzerJS(listOf(linePsi))
|
val result = analysisImpl(linePsi)
|
||||||
val context = analyzer.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, listOf(linePsi))
|
|
||||||
|
|
||||||
val diagnostics = trace.bindingContext.diagnostics
|
return if (result.isSuccess) {
|
||||||
val hasErrors = diagnostics.any { it.severity == Severity.ERROR }
|
replState.lineSuccess(linePsi, codeLine, result.script)
|
||||||
|
AnalysisResult.success(result.bindingContext, result.moduleDescriptor)
|
||||||
if (hasErrors) {
|
|
||||||
replState.lineFailure(linePsi, codeLine)
|
|
||||||
} else {
|
} else {
|
||||||
val scriptDescriptor = context.scripts[linePsi.script]!!
|
replState.lineFailure(linePsi, codeLine)
|
||||||
replState.lineSuccess(linePsi, codeLine, scriptDescriptor)
|
AnalysisResult.compilationError(result.bindingContext)
|
||||||
}
|
}
|
||||||
return diagnostics
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-11
@@ -7,21 +7,22 @@ package org.jetbrains.kotlin.scripting.repl.js
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.cli.common.repl.*
|
import org.jetbrains.kotlin.cli.common.repl.*
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||||
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
|
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzer
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
|
|
||||||
class JsReplCompiler(
|
// Used to compile REPL code lines
|
||||||
environment: KotlinCoreEnvironment
|
class JsReplCompiler(private val environment: KotlinCoreEnvironment) : ReplCompiler {
|
||||||
) : ReplCompiler {
|
|
||||||
private val nameTables: NameTables = NameTables(emptyList())
|
|
||||||
private val dependencies: List<ModuleDescriptor> = readLibrariesFromConfiguration(environment.configuration)
|
|
||||||
|
|
||||||
val scriptDependencyBinary = ScriptDependencyCompiler(environment, nameTables).compile(dependencies).first
|
|
||||||
private val compiler = CoreScriptingJsCompiler(environment, nameTables, dependencies)
|
|
||||||
|
|
||||||
override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*> {
|
override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*> {
|
||||||
return JsState(lock)
|
return JsReplCompilationState(
|
||||||
|
lock,
|
||||||
|
NameTables(emptyList()),
|
||||||
|
readLibrariesFromConfiguration(environment.configuration),
|
||||||
|
ReplCodeAnalyzer.ResettableAnalyzerState(),
|
||||||
|
SymbolTable()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun check(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCheckResult {
|
override fun check(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCheckResult {
|
||||||
@@ -29,6 +30,13 @@ class JsReplCompiler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun compile(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCompileResult {
|
override fun compile(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCompileResult {
|
||||||
return compiler.compile(codeLine)
|
val compilationState = state.asState(JsReplCompilationState::class.java)
|
||||||
|
return JsCoreScriptingCompiler(
|
||||||
|
environment,
|
||||||
|
compilationState.nameTables,
|
||||||
|
compilationState.symbolTable,
|
||||||
|
compilationState.dependencies,
|
||||||
|
compilationState.replState
|
||||||
|
).compile(codeLine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
@@ -18,13 +18,16 @@ import org.jetbrains.kotlin.idea.KotlinLanguage
|
|||||||
import org.jetbrains.kotlin.ir.backend.js.loadKlib
|
import org.jetbrains.kotlin.ir.backend.js.loadKlib
|
||||||
import org.jetbrains.kotlin.ir.backend.js.getModuleDescriptorByLibrary
|
import org.jetbrains.kotlin.ir.backend.js.getModuleDescriptorByLibrary
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||||
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtScript
|
import org.jetbrains.kotlin.psi.KtScript
|
||||||
|
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzer
|
||||||
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptLightVirtualFile
|
import org.jetbrains.kotlin.scripting.resolve.ScriptLightVirtualFile
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
import kotlin.script.experimental.host.FileBasedScriptSource
|
import kotlin.script.experimental.host.FileBasedScriptSource
|
||||||
import kotlin.script.experimental.jvm.JsDependency
|
import kotlin.script.experimental.jvm.JsDependency
|
||||||
@@ -180,3 +183,12 @@ class DependencyLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class JsReplCompilationState(
|
||||||
|
lock: ReentrantReadWriteLock,
|
||||||
|
nameTables: NameTables,
|
||||||
|
dependencies: List<ModuleDescriptor>,
|
||||||
|
val replState: ReplCodeAnalyzer.ResettableAnalyzerState,
|
||||||
|
val symbolTable: SymbolTable
|
||||||
|
) : JsCompilationState(lock, nameTables, dependencies)
|
||||||
|
|
||||||
|
|||||||
-43
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2019 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.scripting.repl.js
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult.*
|
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
|
||||||
import kotlin.script.experimental.api.*
|
|
||||||
|
|
||||||
class JsScriptCompiler(
|
|
||||||
environment: KotlinCoreEnvironment
|
|
||||||
) : ScriptCompiler {
|
|
||||||
private val nameTables = NameTables(emptyList())
|
|
||||||
private val dependencies: List<ModuleDescriptor> = readLibrariesFromConfiguration(environment.configuration)
|
|
||||||
private val compiler = CoreScriptingJsCompiler(environment, nameTables, dependencies)
|
|
||||||
|
|
||||||
val scriptDependencyBinary = ScriptDependencyCompiler(environment, nameTables).compile(dependencies).first
|
|
||||||
|
|
||||||
override suspend fun invoke(
|
|
||||||
script: SourceCode,
|
|
||||||
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
|
||||||
): ResultWithDiagnostics<CompiledScript<*>> {
|
|
||||||
val compileResult = compiler.compile(makeReplCodeLine(0, script.text))
|
|
||||||
return when (compileResult) {
|
|
||||||
is CompiledClasses -> ResultWithDiagnostics.Success(
|
|
||||||
CompiledToJsScript(compileResult.data as String, scriptCompilationConfiguration)
|
|
||||||
)
|
|
||||||
is Incomplete -> ResultWithDiagnostics.Failure(
|
|
||||||
ScriptDiagnostic("Incomplete code")
|
|
||||||
)
|
|
||||||
is Error -> ResultWithDiagnostics.Failure(
|
|
||||||
ScriptDiagnostic(
|
|
||||||
message = compileResult.message,
|
|
||||||
severity = ScriptDiagnostic.Severity.ERROR
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+86
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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.scripting.repl.js
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
|
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.generateJsCode
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.emptyLoggingContext
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsMangler
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
|
||||||
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||||
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
|
|
||||||
|
// Transforms klib into js code in script-friendly way
|
||||||
|
class JsScriptDependencyCompiler(
|
||||||
|
private val configuration: CompilerConfiguration,
|
||||||
|
private val nameTables: NameTables,
|
||||||
|
private val symbolTable: SymbolTable
|
||||||
|
) {
|
||||||
|
fun compile(dependencies: List<ModuleDescriptor>): String {
|
||||||
|
val builtIns: KotlinBuiltIns = dependencies.single { it.allDependencyModules.isEmpty() }.builtIns
|
||||||
|
val languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT
|
||||||
|
val moduleName = Name.special("<script-dependencies>")
|
||||||
|
val storageManager = LockBasedStorageManager.NO_LOCKS
|
||||||
|
val moduleDescriptor = ModuleDescriptorImpl(moduleName, storageManager, builtIns, null).also {
|
||||||
|
it.setDependencies(dependencies.map { d -> d as ModuleDescriptorImpl } + it)
|
||||||
|
it.initialize(PackageFragmentProvider.Empty)
|
||||||
|
}
|
||||||
|
|
||||||
|
val typeTranslator = TypeTranslator(symbolTable, languageVersionSettings, moduleDescriptor.builtIns).also {
|
||||||
|
it.constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable)
|
||||||
|
}
|
||||||
|
|
||||||
|
val irBuiltIns = IrBuiltIns(builtIns, typeTranslator, symbolTable)
|
||||||
|
val jsLinker = JsIrLinker(moduleDescriptor, JsMangler, emptyLoggingContext, irBuiltIns, symbolTable)
|
||||||
|
|
||||||
|
val moduleFragment = IrModuleFragmentImpl(moduleDescriptor, irBuiltIns)
|
||||||
|
val irDependencies = dependencies.map { jsLinker.deserializeFullModule(it) }
|
||||||
|
|
||||||
|
ExternalDependenciesGenerator(
|
||||||
|
moduleDescriptor = moduleDescriptor,
|
||||||
|
symbolTable = symbolTable,
|
||||||
|
irBuiltIns = irBuiltIns,
|
||||||
|
deserializer = jsLinker
|
||||||
|
).generateUnboundSymbolsAsDependencies()
|
||||||
|
moduleFragment.patchDeclarationParents()
|
||||||
|
|
||||||
|
val backendContext = JsIrBackendContext(
|
||||||
|
moduleDescriptor,
|
||||||
|
irBuiltIns,
|
||||||
|
symbolTable,
|
||||||
|
moduleFragment,
|
||||||
|
emptySet(),
|
||||||
|
configuration,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
|
ExternalDependenciesGenerator(
|
||||||
|
moduleDescriptor = moduleDescriptor,
|
||||||
|
symbolTable = symbolTable,
|
||||||
|
irBuiltIns = irBuiltIns,
|
||||||
|
deserializer = jsLinker
|
||||||
|
).generateUnboundSymbolsAsDependencies()
|
||||||
|
moduleFragment.patchDeclarationParents()
|
||||||
|
|
||||||
|
moduleFragment.files += irDependencies.flatMap { it.files }
|
||||||
|
|
||||||
|
configuration.put(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN)
|
||||||
|
|
||||||
|
return generateJsCode(backendContext, moduleFragment, nameTables)
|
||||||
|
}
|
||||||
|
}
|
||||||
-41
@@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2019 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.scripting.repl.js
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult
|
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.emptyLoggingContext
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsMangler
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
|
||||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
|
||||||
|
|
||||||
class ScriptDependencyCompiler(
|
|
||||||
val environment: KotlinCoreEnvironment,
|
|
||||||
private val nameTables: NameTables = NameTables(emptyList())
|
|
||||||
) {
|
|
||||||
fun compile(dependencies: List<ModuleDescriptor>): Pair<String, NameTables> {
|
|
||||||
val compiler = CoreScriptingJsCompiler(
|
|
||||||
environment,
|
|
||||||
nameTables,
|
|
||||||
dependencies,
|
|
||||||
::createDeserializer
|
|
||||||
)
|
|
||||||
val compileResult = compiler.compile(makeReplCodeLine(0, ""))
|
|
||||||
return (compileResult as ReplCompileResult.CompiledClasses).data as String to nameTables
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createDeserializer(m: ModuleDescriptor, symbolTable: SymbolTable, irBuiltIns: IrBuiltIns): DeserializerWithDependencies {
|
|
||||||
val deserializer = JsIrLinker(m, JsMangler, emptyLoggingContext, irBuiltIns, symbolTable)
|
|
||||||
val deserializedModuleFragments = m.allDependencyModules.map {
|
|
||||||
deserializer.deserializeFullModule(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
return DeserializerWithDependencies(deserializer, deserializedModuleFragments)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user