[JS REPL] Extract JS script/repl parts into separate module
- don't load js evaluation plugin in CLI compiler
This commit is contained in:
@@ -11,14 +11,11 @@ dependencies {
|
||||
compileOnly(project(":compiler:psi"))
|
||||
compileOnly(project(":compiler:plugin-api"))
|
||||
compileOnly(project(":compiler:cli"))
|
||||
compileOnly(project(":compiler:backend.js"))
|
||||
compileOnly(project(":core:descriptors.runtime"))
|
||||
compileOnly(project(":compiler:ir.tree.impl"))
|
||||
compileOnly(project(":compiler:backend.jvm.entrypoint"))
|
||||
compileOnly(project(":kotlin-reflect-api"))
|
||||
api(project(":kotlin-scripting-common"))
|
||||
api(project(":kotlin-scripting-js"))
|
||||
api(project(":kotlin-util-klib"))
|
||||
api(project(":kotlin-scripting-jvm"))
|
||||
api(project(":kotlin-scripting-compiler-impl"))
|
||||
api(kotlinStdlib())
|
||||
@@ -30,7 +27,6 @@ dependencies {
|
||||
testApi(project(":compiler:cli"))
|
||||
testApi(project(":compiler:cli-common"))
|
||||
testApi(project(":compiler:frontend.java"))
|
||||
testApi(project(":compiler:backend.js"))
|
||||
testApi(projectTests(":compiler:tests-common"))
|
||||
testApi(commonDependency("junit:junit"))
|
||||
|
||||
|
||||
-68
@@ -1,68 +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.compiler.plugin
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.JsScriptCompilerWithDependenciesProxy
|
||||
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||
import org.jetbrains.kotlin.scripting.definitions.platform
|
||||
import org.jetbrains.kotlin.scripting.repl.js.JsScriptEvaluator
|
||||
import kotlin.script.experimental.api.*
|
||||
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||
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) {
|
||||
val scriptConfiguration = ScriptCompilationConfiguration {
|
||||
baseClass("kotlin.Any")
|
||||
dependencies.append(JsDependency("libraries/stdlib/js-ir/build/classes/kotlin/js/main/"))
|
||||
platform.put("JS")
|
||||
}
|
||||
configuration.add(
|
||||
ScriptingConfigurationKeys.SCRIPT_DEFINITIONS,
|
||||
ScriptDefinition.FromConfigurations(ScriptingHostConfiguration(), scriptConfiguration, null)
|
||||
)
|
||||
}
|
||||
|
||||
class JsScriptEvaluationExtension : AbstractScriptEvaluationExtension() {
|
||||
|
||||
override fun setupScriptConfiguration(configuration: CompilerConfiguration) {
|
||||
loadScriptConfiguration(configuration)
|
||||
}
|
||||
|
||||
override fun createEnvironment(
|
||||
projectEnvironment: KotlinCoreEnvironment.ProjectEnvironment,
|
||||
configuration: CompilerConfiguration
|
||||
): KotlinCoreEnvironment {
|
||||
return KotlinCoreEnvironment.createForProduction(
|
||||
projectEnvironment,
|
||||
configuration,
|
||||
EnvironmentConfigFiles.JS_CONFIG_FILES
|
||||
)
|
||||
}
|
||||
|
||||
override fun createScriptEvaluator(): ScriptEvaluator {
|
||||
return JsScriptEvaluator()
|
||||
}
|
||||
|
||||
private var scriptCompilerProxy: ScriptCompilerProxy? = null
|
||||
|
||||
override fun createScriptCompiler(environment: KotlinCoreEnvironment): ScriptCompilerProxy {
|
||||
return scriptCompilerProxy ?: JsScriptCompilerWithDependenciesProxy(environment).also { scriptCompilerProxy = it }
|
||||
}
|
||||
|
||||
override fun ScriptEvaluationConfiguration.Builder.platformEvaluationConfiguration() {}
|
||||
|
||||
override fun isAccepted(arguments: CommonCompilerArguments): Boolean {
|
||||
return arguments is K2JSCompilerArguments
|
||||
}
|
||||
}
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* 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.scripting.compiler.plugin.impl
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor
|
||||
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.lower.serialization.ir.JsManglerDesc
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
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(), mappedNames = mutableMapOf())
|
||||
private val symbolTable = SymbolTable(IdSignatureDescriptor(JsManglerDesc), IrFactoryImpl)
|
||||
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(ScriptDiagnostic.incompleteCode, "Incomplete code")
|
||||
)
|
||||
is ReplCompileResult.Error -> ResultWithDiagnostics.Failure(
|
||||
ScriptDiagnostic(
|
||||
ScriptDiagnostic.unspecifiedError,
|
||||
message = compileResult.message,
|
||||
severity = ScriptDiagnostic.Severity.ERROR
|
||||
)
|
||||
)
|
||||
}
|
||||
} finally {
|
||||
if (parentMessageCollector != null)
|
||||
environment.configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, parentMessageCollector)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
||||
import org.jetbrains.kotlin.scripting.extensions.ScriptExtraImportsProviderExtension
|
||||
import org.jetbrains.kotlin.scripting.extensions.ScriptingResolveExtension
|
||||
import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import java.net.URLClassLoader
|
||||
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||
@@ -51,7 +52,6 @@ class ScriptingCompilerConfigurationComponentRegistrar : ComponentRegistrar {
|
||||
CompilerConfigurationExtension.registerExtension(project, ScriptingCompilerConfigurationExtension(project, hostConfiguration))
|
||||
CollectAdditionalSourcesExtension.registerExtension(project, ScriptingCollectAdditionalSourcesExtension(project))
|
||||
ScriptEvaluationExtension.registerExtensionIfRequired(project, JvmCliScriptEvaluationExtension())
|
||||
ScriptEvaluationExtension.registerExtensionIfRequired(project, JsScriptEvaluationExtension())
|
||||
ShellExtension.registerExtensionIfRequired(project, JvmCliReplShellExtension())
|
||||
ReplFactoryExtension.registerExtensionIfRequired(project, JvmStandardReplFactoryExtension())
|
||||
|
||||
|
||||
-115
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* 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.scripting.repl.js
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.common.environment.setIdeaIoUseFallback
|
||||
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
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.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.generateJsCode
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrScript
|
||||
import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol
|
||||
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
|
||||
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
|
||||
import org.jetbrains.kotlin.psi2ir.generators.generateTypicalIrProviderList
|
||||
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzerBase
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
import kotlin.script.experimental.api.valueOr
|
||||
import kotlin.script.experimental.host.StringScriptSource
|
||||
|
||||
class JsCoreScriptingCompiler(
|
||||
private val environment: KotlinCoreEnvironment,
|
||||
private val nameTables: NameTables,
|
||||
private val symbolTable: SymbolTable,
|
||||
private val dependencyDescriptors: List<ModuleDescriptor>,
|
||||
private val replCompilerState: JsReplCompilerState? = null
|
||||
) {
|
||||
fun compile(codeLine: ReplCodeLine): ReplCompileResult {
|
||||
val snippet = codeLine.code
|
||||
val snippetId = codeLine.no
|
||||
|
||||
setIdeaIoUseFallback()
|
||||
|
||||
val sourceCode = StringScriptSource(snippet, "line-$snippetId.kts")
|
||||
val snippetKtFile = getScriptKtFile(
|
||||
sourceCode,
|
||||
snippet,
|
||||
environment.project
|
||||
).valueOr { return ReplCompileResult.Error(it.reports.joinToString { r -> r.message }) }
|
||||
|
||||
val messageCollector = environment.configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY] as MessageCollector
|
||||
|
||||
val analyzerState = replCompilerState?.analyzerState ?: ReplCodeAnalyzerBase.ResettableAnalyzerState()
|
||||
|
||||
val analyzerEngine = JsReplCodeAnalyzer(environment, dependencyDescriptors, analyzerState)
|
||||
val analysisResult = analyzerEngine.analyzeReplLine(snippetKtFile, codeLine).also {
|
||||
AnalyzerWithCompilerReport.reportDiagnostics(it.bindingContext.diagnostics, messageCollector)
|
||||
if (messageCollector.hasErrors()) return ReplCompileResult.Error("Error while analysis")
|
||||
}
|
||||
|
||||
val files = listOf(snippetKtFile)
|
||||
val (bindingContext, module) = analysisResult
|
||||
val psi2ir = Psi2IrTranslator(environment.configuration.languageVersionSettings, Psi2IrConfiguration())
|
||||
|
||||
val generatorExtensions =
|
||||
if (replCompilerState == null) GeneratorExtensions()
|
||||
else object : GeneratorExtensions() {
|
||||
override fun getPreviousScripts() = replCompilerState.history.map { it.item.scriptSymbol }
|
||||
}
|
||||
|
||||
val psi2irContext = psi2ir.createGeneratorContext(module, bindingContext, symbolTable, generatorExtensions)
|
||||
val providers = generateTypicalIrProviderList(module, psi2irContext.irBuiltIns, psi2irContext.symbolTable)
|
||||
val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files, providers, emptyList(), null) // TODO: deserializer
|
||||
|
||||
val context = JsIrBackendContext(
|
||||
irModuleFragment.descriptor,
|
||||
psi2irContext.irBuiltIns,
|
||||
psi2irContext.symbolTable,
|
||||
irModuleFragment,
|
||||
emptySet(),
|
||||
environment.configuration,
|
||||
true
|
||||
)
|
||||
|
||||
ExternalDependenciesGenerator(
|
||||
psi2irContext.symbolTable,
|
||||
generateTypicalIrProviderList(
|
||||
irModuleFragment.descriptor,
|
||||
psi2irContext.irBuiltIns,
|
||||
psi2irContext.symbolTable
|
||||
)
|
||||
).generateUnboundSymbolsAsDependencies()
|
||||
|
||||
environment.configuration.put(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN)
|
||||
|
||||
val code = generateJsCode(context, irModuleFragment, nameTables)
|
||||
|
||||
updateHistory(codeLine, irModuleFragment)
|
||||
|
||||
return createCompileResult(LineId(codeLine.no, 0, codeLine.hashCode()), code)
|
||||
}
|
||||
|
||||
private fun updateHistory(codeLine: ReplCodeLine, irModuleFragment: IrModuleFragment) {
|
||||
if (replCompilerState != null) {
|
||||
val lineId = LineId(codeLine.no, 0, codeLine.code.hashCode())
|
||||
val scriptSymbol = irModuleFragment.files.single().declarations.single { it is IrScript }.symbol as IrScriptSymbol
|
||||
replCompilerState.history.push(lineId, JsReplCompilationHistoryItem(scriptSymbol))
|
||||
}
|
||||
}
|
||||
}
|
||||
-38
@@ -1,38 +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.analyzer.AnalysisResult
|
||||
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.AbstractJsScriptlikeCodeAnalyser
|
||||
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzerBase
|
||||
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.toSourceCode
|
||||
import org.jetbrains.kotlin.scripting.definitions.ScriptPriorities
|
||||
|
||||
class JsReplCodeAnalyzer(
|
||||
environment: KotlinCoreEnvironment,
|
||||
dependencies: List<ModuleDescriptor>,
|
||||
private val replState: ReplCodeAnalyzerBase.ResettableAnalyzerState
|
||||
) : AbstractJsScriptlikeCodeAnalyser(environment, dependencies) {
|
||||
|
||||
fun analyzeReplLine(linePsi: KtFile, codeLine: ReplCodeLine): AnalysisResult {
|
||||
linePsi.script!!.putUserData(ScriptPriorities.PRIORITY_KEY, codeLine.no)
|
||||
replState.submitLine(linePsi)
|
||||
|
||||
val result = analysisImpl(linePsi)
|
||||
|
||||
return if (result.isSuccess) {
|
||||
replState.lineSuccess(linePsi, codeLine.toSourceCode(), result.script)
|
||||
AnalysisResult.success(result.bindingContext, result.moduleDescriptor)
|
||||
} else {
|
||||
replState.lineFailure(linePsi)
|
||||
AnalysisResult.compilationError(result.bindingContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* 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.scripting.repl.js
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor
|
||||
import org.jetbrains.kotlin.cli.common.repl.*
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzerBase
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
|
||||
// Used to compile REPL code lines
|
||||
class JsReplCompiler(private val environment: KotlinCoreEnvironment) : ReplCompiler {
|
||||
|
||||
override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*> {
|
||||
return JsReplCompilerState(
|
||||
lock,
|
||||
NameTables(emptyList(), mappedNames = mutableMapOf()),
|
||||
readLibrariesFromConfiguration(environment.configuration),
|
||||
ReplCodeAnalyzerBase.ResettableAnalyzerState(),
|
||||
SymbolTable(IdSignatureDescriptor(JsManglerDesc), IrFactoryImpl)
|
||||
)
|
||||
}
|
||||
|
||||
override fun check(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCheckResult {
|
||||
return ReplCheckResult.Ok()
|
||||
}
|
||||
|
||||
override fun compile(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCompileResult {
|
||||
val compilationState = state.asState(JsReplCompilerState::class.java)
|
||||
return JsCoreScriptingCompiler(
|
||||
environment,
|
||||
compilationState.nameTables,
|
||||
compilationState.symbolTable,
|
||||
compilationState.dependencies,
|
||||
compilationState
|
||||
).compile(codeLine)
|
||||
}
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* 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.scripting.repl.js
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.repl.BasicReplStageHistory
|
||||
import org.jetbrains.kotlin.cli.common.repl.IReplStageState
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||
import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzerBase
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
|
||||
class JsReplCompilationHistoryItem(
|
||||
val scriptSymbol: IrScriptSymbol
|
||||
)
|
||||
|
||||
class JsReplCompilerStageHistory(lock: ReentrantReadWriteLock) : BasicReplStageHistory<JsReplCompilationHistoryItem>(lock)
|
||||
|
||||
// NOTE: the state management machinery is reduced in this implementation, since it is unused at the moment in the JS REPL (see JvmReplCompilerState for complete implementation, if needed)
|
||||
class JsReplCompilerState(
|
||||
override val lock: ReentrantReadWriteLock,
|
||||
val nameTables: NameTables,
|
||||
val dependencies: List<ModuleDescriptor>,
|
||||
val analyzerState: ReplCodeAnalyzerBase.ResettableAnalyzerState,
|
||||
val symbolTable: SymbolTable
|
||||
) : IReplStageState<JsReplCompilationHistoryItem> {
|
||||
|
||||
override val history = JsReplCompilerStageHistory(lock)
|
||||
|
||||
override val currentGeneration: Int get() = (history as BasicReplStageHistory<*>).currentGeneration.get()
|
||||
}
|
||||
-215
@@ -1,215 +0,0 @@
|
||||
/*
|
||||
* 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.scripting.repl.js
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiFileFactory
|
||||
import com.intellij.psi.impl.PsiFileFactoryImpl
|
||||
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.GroupingMessageCollector
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
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.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.ir.backend.js.getModuleDescriptorByLibrary
|
||||
import org.jetbrains.kotlin.ir.backend.js.jsResolveLibraries
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||
import org.jetbrains.kotlin.library.resolver.TopologicalLibraryOrder
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtScript
|
||||
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||
import org.jetbrains.kotlin.scripting.resolve.ScriptLightVirtualFile
|
||||
import org.jetbrains.kotlin.util.Logger
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import java.io.BufferedReader
|
||||
import java.io.FileOutputStream
|
||||
import java.io.FileReader
|
||||
import java.io.InputStreamReader
|
||||
import java.nio.charset.Charset
|
||||
import kotlin.script.experimental.api.*
|
||||
import kotlin.script.experimental.host.FileBasedScriptSource
|
||||
import kotlin.script.experimental.jvm.JsDependency
|
||||
|
||||
fun getScriptKtFile(
|
||||
script: SourceCode,
|
||||
scriptText: String,
|
||||
project: Project
|
||||
): ResultWithDiagnostics<KtFile> {
|
||||
val psiFileFactory: PsiFileFactoryImpl = PsiFileFactory.getInstance(project) as PsiFileFactoryImpl
|
||||
val virtualFile = ScriptLightVirtualFile(
|
||||
script.name!!,
|
||||
(script as? FileBasedScriptSource)?.file?.path,
|
||||
scriptText
|
||||
)
|
||||
val ktFile = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile?
|
||||
return when {
|
||||
ktFile == null -> ResultWithDiagnostics.Failure(
|
||||
ScriptDiagnostic(
|
||||
ScriptDiagnostic.unspecifiedError,
|
||||
message = "Cannot create PSI",
|
||||
severity = ScriptDiagnostic.Severity.ERROR
|
||||
)
|
||||
)
|
||||
ktFile.declarations.firstIsInstanceOrNull<KtScript>() == null -> ResultWithDiagnostics.Failure(
|
||||
ScriptDiagnostic(
|
||||
ScriptDiagnostic.unspecifiedError,
|
||||
message = "There is not Script",
|
||||
severity = ScriptDiagnostic.Severity.ERROR
|
||||
)
|
||||
)
|
||||
else -> ktFile.asSuccess()
|
||||
}
|
||||
}
|
||||
|
||||
fun makeReplCodeLine(no: Int, code: String): ReplCodeLine = ReplCodeLine(no, 0, code)
|
||||
|
||||
//TODO: remove and use collector from kotlin-scripting-compiler
|
||||
class ReplMessageCollector : MessageCollector {
|
||||
private var hasErrors = false
|
||||
private var messages = mutableListOf<Pair<CompilerMessageSeverity, String>>()
|
||||
|
||||
override fun clear() {
|
||||
hasErrors = false
|
||||
messages.clear()
|
||||
}
|
||||
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) {
|
||||
if (severity == CompilerMessageSeverity.ERROR) hasErrors = true
|
||||
messages.add(Pair(severity, message))
|
||||
}
|
||||
|
||||
override fun hasErrors(): Boolean {
|
||||
return hasErrors
|
||||
}
|
||||
|
||||
fun hasNotErrors(): Boolean {
|
||||
return !hasErrors
|
||||
}
|
||||
|
||||
fun getMessage(): String {
|
||||
val resultMessage = StringBuilder("Found ${messages.size} problems:\n")
|
||||
for (m in messages) {
|
||||
resultMessage.append(m.first.toString() + " : " + m.second + "\n")
|
||||
}
|
||||
return resultMessage.toString()
|
||||
}
|
||||
}
|
||||
|
||||
fun readLibrariesFromConfiguration(configuration: CompilerConfiguration): List<ModuleDescriptor> {
|
||||
// TODO: Reimplement this code once we get proper klib dependency resolver
|
||||
val scriptConfig = configuration[ScriptingConfigurationKeys.SCRIPT_DEFINITIONS]!!
|
||||
val scriptCompilationConfig = scriptConfig.find { (it).platform == "JS" }!!.compilationConfiguration
|
||||
val scriptDependencies = scriptCompilationConfig[ScriptCompilationConfiguration.dependencies]!!
|
||||
val descriptorMap = mutableMapOf<String, ModuleDescriptorImpl>()
|
||||
val libraries = scriptDependencies.map { (it as JsDependency).path }
|
||||
val resolvedLibraries = jsResolveLibraries(
|
||||
libraries,
|
||||
emptyList(),
|
||||
object : Logger {
|
||||
private val collector = configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY] ?: MessageCollector.NONE
|
||||
override fun warning(message: String) = collector.report(CompilerMessageSeverity.STRONG_WARNING, message)
|
||||
override fun error(message: String) = collector.report(CompilerMessageSeverity.ERROR, message)
|
||||
override fun log(message: String) = collector.report(CompilerMessageSeverity.LOGGING, message)
|
||||
override fun fatal(message: String): Nothing {
|
||||
collector.report(CompilerMessageSeverity.ERROR, message)
|
||||
(collector as? GroupingMessageCollector)?.flush()
|
||||
kotlin.error(message)
|
||||
}
|
||||
}
|
||||
)
|
||||
return resolvedLibraries.getFullList(TopologicalLibraryOrder)
|
||||
.map { descriptorMap.getOrPut(it.libraryName) { getModuleDescriptorByLibrary(it, descriptorMap) } }
|
||||
}
|
||||
|
||||
fun createCompileResult(code: String) = createCompileResult(LineId(0, 0, 0), code)
|
||||
|
||||
fun createCompileResult(lineId: LineId, code: String): ReplCompileResult.CompiledClasses {
|
||||
return ReplCompileResult.CompiledClasses(
|
||||
lineId,
|
||||
emptyList(),
|
||||
"",
|
||||
emptyList(),
|
||||
false,
|
||||
emptyList(),
|
||||
"Any?",
|
||||
code
|
||||
)
|
||||
}
|
||||
|
||||
class DependencyLoader {
|
||||
// TODO: this should be taken from CompilerConfiguration
|
||||
private val commonPath = "libraries/stdlib/js-ir/build/classes/kotlin/js/main/"
|
||||
private val mappedNamesPath = "$commonPath/mappedNames.txt"
|
||||
private val scriptDependencyBinaryPath = "$commonPath/scriptDependencyBinary.js"
|
||||
|
||||
fun saveNames(nameTables: NameTables, path: String = mappedNamesPath) {
|
||||
writeDataByPath(writeNames(nameTables), path)
|
||||
}
|
||||
|
||||
fun loadNames(path: String = mappedNamesPath): NameTables {
|
||||
return readNames(readDataByPath(path))
|
||||
}
|
||||
|
||||
fun saveScriptDependencyBinary(stdlibCompiledResult: String, path: String = scriptDependencyBinaryPath) {
|
||||
writeDataByPath(writeScriptDependencyBinary(stdlibCompiledResult), path)
|
||||
}
|
||||
|
||||
fun loadScriptDependencyBinary(path: String = scriptDependencyBinaryPath): String {
|
||||
return readScriptDependencyBinary(readDataByPath(path))
|
||||
}
|
||||
|
||||
|
||||
fun writeNames(nameTables: NameTables): ByteArray {
|
||||
val result = StringBuilder()
|
||||
for (entry in nameTables.mappedNames.orEmpty()) {
|
||||
result.append("${entry.key} ${entry.value}" + System.lineSeparator())
|
||||
}
|
||||
return result.toString().toByteArray(Charset.defaultCharset())
|
||||
}
|
||||
|
||||
fun readNames(data: ByteArray): NameTables {
|
||||
val mappedNames = mutableMapOf<String, String>()
|
||||
val reserved = mutableSetOf<String>()
|
||||
|
||||
BufferedReader(InputStreamReader(data.inputStream())).use { reader ->
|
||||
for (line in reader.readLines()) {
|
||||
val (key, value) = line.split(" ")
|
||||
mappedNames[key] = value
|
||||
reserved += value
|
||||
}
|
||||
}
|
||||
|
||||
return NameTables(emptyList(), mappedNames = mappedNames, reservedForGlobal = reserved)
|
||||
}
|
||||
|
||||
fun writeScriptDependencyBinary(stdlibCompiledResult: String): ByteArray {
|
||||
return stdlibCompiledResult.toByteArray(Charset.defaultCharset())
|
||||
}
|
||||
|
||||
fun readScriptDependencyBinary(data: ByteArray): String {
|
||||
return data.toString(Charset.defaultCharset())
|
||||
}
|
||||
|
||||
fun readDataByPath(path: String): ByteArray {
|
||||
FileReader(path).use { reader ->
|
||||
val stdlibCompiledResult = reader.readText()
|
||||
return stdlibCompiledResult.toByteArray(Charset.defaultCharset())
|
||||
}
|
||||
}
|
||||
|
||||
fun writeDataByPath(data: ByteArray, path: String) {
|
||||
FileOutputStream(path).use {
|
||||
it.write(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-84
@@ -1,84 +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.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.descriptors.konan.kotlinLibrary
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.generateJsCode
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltInsOverDescriptors
|
||||
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
|
||||
import org.jetbrains.kotlin.ir.util.IrMessageLogger
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi2ir.generators.TypeTranslatorImpl
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
|
||||
// Transforms klib into js code in script-friendly way
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
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 messageLogger = configuration[IrMessageLogger.IR_MESSAGE_LOGGER] ?: IrMessageLogger.None
|
||||
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 = TypeTranslatorImpl(symbolTable, languageVersionSettings, moduleDescriptor)
|
||||
val irBuiltIns = IrBuiltInsOverDescriptors(builtIns, typeTranslator, symbolTable)
|
||||
val jsLinker = JsIrLinker(null, messageLogger, irBuiltIns, symbolTable, null)
|
||||
|
||||
val irDependencies = dependencies.map { jsLinker.deserializeFullModule(it, it.kotlinLibrary) }
|
||||
val moduleFragment = irDependencies.last()
|
||||
val irProviders = listOf(jsLinker)
|
||||
|
||||
jsLinker.init(null, emptyList())
|
||||
|
||||
ExternalDependenciesGenerator(symbolTable, irProviders)
|
||||
.generateUnboundSymbolsAsDependencies()
|
||||
moduleFragment.patchDeclarationParents()
|
||||
|
||||
val backendContext = JsIrBackendContext(
|
||||
moduleDescriptor,
|
||||
irBuiltIns,
|
||||
symbolTable,
|
||||
moduleFragment,
|
||||
emptySet(),
|
||||
configuration,
|
||||
true
|
||||
)
|
||||
|
||||
ExternalDependenciesGenerator(symbolTable, irProviders)
|
||||
.generateUnboundSymbolsAsDependencies()
|
||||
moduleFragment.patchDeclarationParents()
|
||||
jsLinker.postProcess()
|
||||
|
||||
moduleFragment.files += irDependencies.filter { it !== moduleFragment }.flatMap { it.files }
|
||||
|
||||
configuration.put(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN)
|
||||
|
||||
return generateJsCode(backendContext, moduleFragment, nameTables)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user