Extend GeneratorExtensions with previous script, implemt it for JS REPL
also refactor JS REPL for better compatibility with the generic REPL/scripting infrastructure
This commit is contained in:
+3
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall
|
||||
import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol
|
||||
import org.jetbrains.kotlin.ir.util.StubGeneratorExtensions
|
||||
import org.jetbrains.kotlin.psi.KtPureClassOrObject
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
@@ -39,4 +40,6 @@ open class GeneratorExtensions : StubGeneratorExtensions() {
|
||||
|
||||
open val shouldPreventDeprecatedIntegerValueTypeLiteralConversion: Boolean
|
||||
get() = false
|
||||
|
||||
open fun getPreviousScripts(): List<IrScriptSymbol> = emptyList()
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class ScriptGenerator(declarationGenerator: DeclarationGenerator) : DeclarationG
|
||||
fun generateScriptDeclaration(ktScript: KtScript): IrDeclaration? {
|
||||
val descriptor = getOrFail(BindingContext.DECLARATION_TO_DESCRIPTOR, ktScript) as ScriptDescriptor
|
||||
|
||||
val existedScripts = context.symbolTable.listExistedScripts()
|
||||
val previousScripts = context.extensions.getPreviousScripts()
|
||||
|
||||
return context.symbolTable.declareScript(descriptor).buildWithScope { irScript ->
|
||||
|
||||
@@ -54,7 +54,7 @@ class ScriptGenerator(declarationGenerator: DeclarationGenerator) : DeclarationG
|
||||
|
||||
// TODO: since script could reference instances of previous one their receivers have to be enlisted in its scope
|
||||
// Remove this code once script is no longer represented by Class
|
||||
existedScripts.forEach {
|
||||
previousScripts.forEach {
|
||||
if (it.owner != irScript && it.descriptor !in importedScripts) {
|
||||
context.symbolTable.introduceValueParameter(it.owner.thisReceiver)
|
||||
}
|
||||
@@ -117,7 +117,7 @@ class ScriptGenerator(declarationGenerator: DeclarationGenerator) : DeclarationG
|
||||
valueParameter to irProperty.symbol
|
||||
}
|
||||
|
||||
irScript.earlierScripts = existedScripts
|
||||
irScript.earlierScripts = previousScripts
|
||||
|
||||
for (d in ktScript.declarations) {
|
||||
when (d) {
|
||||
|
||||
+4
-4
@@ -29,14 +29,14 @@ import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||
import kotlin.script.experimental.jvm.JsDependency
|
||||
|
||||
abstract class AbstractJsReplTest : Closeable {
|
||||
protected lateinit var compilationState: JsReplCompilationState
|
||||
protected lateinit var compilerState: JsReplCompilerState
|
||||
protected lateinit var evaluationState: JsEvaluationState
|
||||
|
||||
protected abstract fun createCompilationState(): JsReplCompilationState
|
||||
protected abstract fun createCompilationState(): JsReplCompilerState
|
||||
protected abstract fun createEvaluationState(): JsEvaluationState
|
||||
|
||||
fun compile(codeLine: ReplCodeLine): ReplCompileResult {
|
||||
return JsReplCompiler(environment).compile(compilationState, codeLine)
|
||||
return JsReplCompiler(environment).compile(compilerState, codeLine)
|
||||
}
|
||||
|
||||
fun evaluate(compileResult: ReplCompileResult.CompiledClasses): ReplEvalResult {
|
||||
@@ -45,7 +45,7 @@ abstract class AbstractJsReplTest : Closeable {
|
||||
|
||||
fun reset() {
|
||||
collector.clear()
|
||||
compilationState = createCompilationState()
|
||||
compilerState = createCompilationState()
|
||||
evaluationState = createEvaluationState()
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -31,9 +31,9 @@ class JsReplTestAgainstBinaries : AbstractJsReplTest() {
|
||||
dependencyLoader.saveNames(nameTable)
|
||||
}
|
||||
|
||||
override fun createCompilationState(): JsReplCompilationState {
|
||||
override fun createCompilationState(): JsReplCompilerState {
|
||||
val replState = ReplCodeAnalyzerBase.ResettableAnalyzerState()
|
||||
return JsReplCompilationState(ReentrantReadWriteLock(), dependencyLoader.loadNames(), dependencies, replState, createSymbolTable())
|
||||
return JsReplCompilerState(ReentrantReadWriteLock(), dependencyLoader.loadNames(), dependencies, replState, createSymbolTable())
|
||||
}
|
||||
|
||||
private fun createSymbolTable(): SymbolTable =
|
||||
|
||||
+2
-2
@@ -20,14 +20,14 @@ class JsReplTestAgainstKlib : AbstractJsReplTest() {
|
||||
|
||||
private var dependencyCode: String? = null
|
||||
|
||||
override fun createCompilationState(): JsReplCompilationState {
|
||||
override fun createCompilationState(): JsReplCompilerState {
|
||||
val nameTables = NameTables(emptyList(), mappedNames = mutableMapOf())
|
||||
val symbolTable = SymbolTable(IdSignatureDescriptor(JsManglerDesc), IrFactoryImpl)
|
||||
val dependencyCompiler = JsScriptDependencyCompiler(environment.configuration, nameTables, symbolTable)
|
||||
val dependencies = readLibrariesFromConfiguration(environment.configuration)
|
||||
dependencyCode = dependencyCompiler.compile(dependencies)
|
||||
|
||||
return JsReplCompilationState(
|
||||
return JsReplCompilerState(
|
||||
ReentrantReadWriteLock(),
|
||||
nameTables,
|
||||
dependencies,
|
||||
|
||||
@@ -5,10 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.scripting.repl.js
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.repl.*
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||
import org.jetbrains.kotlin.cli.common.repl.IReplStageHistory
|
||||
import org.jetbrains.kotlin.cli.common.repl.IReplStageState
|
||||
import org.jetbrains.kotlin.js.engine.ScriptEngineWithTypedResult
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
import kotlin.reflect.KClass
|
||||
@@ -17,24 +15,17 @@ import kotlin.script.experimental.api.ResultWithDiagnostics
|
||||
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
||||
import kotlin.script.experimental.api.ScriptEvaluationConfiguration
|
||||
|
||||
abstract class JsState(override val lock: ReentrantReadWriteLock) : IReplStageState<ScriptDescriptor> {
|
||||
override val history: IReplStageHistory<ScriptDescriptor>
|
||||
// NOTE: the state management machinery is not implemented here, since it is unused at the moment in the JS REPL (see JvmReplEvaluatorState for complete implementation, if needed)
|
||||
class JsEvaluationState(override val lock: ReentrantReadWriteLock, val engine: ScriptEngineWithTypedResult) : IReplStageState<Nothing> {
|
||||
override fun dispose() {
|
||||
engine.reset()
|
||||
}
|
||||
|
||||
override val history: IReplStageHistory<Nothing>
|
||||
get() = TODO("not implemented")
|
||||
|
||||
override val currentGeneration: Int
|
||||
get() = TODO("not implemented")
|
||||
|
||||
}
|
||||
|
||||
abstract class JsCompilationState(
|
||||
lock: ReentrantReadWriteLock,
|
||||
val nameTables: NameTables,
|
||||
val dependencies: List<ModuleDescriptor>) : JsState(lock)
|
||||
|
||||
class JsEvaluationState(lock: ReentrantReadWriteLock, val engine: ScriptEngineWithTypedResult) : JsState(lock) {
|
||||
override fun dispose() {
|
||||
engine.reset()
|
||||
}
|
||||
}
|
||||
|
||||
class JsCompiledScript(
|
||||
|
||||
+27
-3
@@ -18,13 +18,17 @@ 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.descriptors.IrFunctionFactory
|
||||
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.generateTypicalIrProviderList
|
||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
|
||||
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzerBase
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
import kotlin.script.experimental.api.valueOr
|
||||
@@ -35,7 +39,7 @@ class JsCoreScriptingCompiler(
|
||||
private val nameTables: NameTables,
|
||||
private val symbolTable: SymbolTable,
|
||||
private val dependencyDescriptors: List<ModuleDescriptor>,
|
||||
private val replState: ReplCodeAnalyzerBase.ResettableAnalyzerState = ReplCodeAnalyzerBase.ResettableAnalyzerState()
|
||||
private val replCompilerState: JsReplCompilerState? = null
|
||||
) {
|
||||
fun compile(codeLine: ReplCodeLine): ReplCompileResult {
|
||||
val snippet = codeLine.code
|
||||
@@ -51,7 +55,10 @@ class JsCoreScriptingCompiler(
|
||||
).valueOr { return ReplCompileResult.Error(it.reports.joinToString { r -> r.message }) }
|
||||
|
||||
val messageCollector = environment.configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY] as MessageCollector
|
||||
val analyzerEngine = JsReplCodeAnalyzer(environment, dependencyDescriptors, replState)
|
||||
|
||||
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")
|
||||
@@ -60,7 +67,14 @@ class JsCoreScriptingCompiler(
|
||||
val files = listOf(snippetKtFile)
|
||||
val (bindingContext, module) = analysisResult
|
||||
val psi2ir = Psi2IrTranslator(environment.configuration.languageVersionSettings, Psi2IrConfiguration())
|
||||
val psi2irContext = psi2ir.createGeneratorContext(module, bindingContext, symbolTable)
|
||||
|
||||
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
|
||||
|
||||
@@ -91,6 +105,16 @@ class JsCoreScriptingCompiler(
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -19,7 +19,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
class JsReplCompiler(private val environment: KotlinCoreEnvironment) : ReplCompiler {
|
||||
|
||||
override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*> {
|
||||
return JsReplCompilationState(
|
||||
return JsReplCompilerState(
|
||||
lock,
|
||||
NameTables(emptyList(), mappedNames = mutableMapOf()),
|
||||
readLibrariesFromConfiguration(environment.configuration),
|
||||
@@ -33,13 +33,13 @@ class JsReplCompiler(private val environment: KotlinCoreEnvironment) : ReplCompi
|
||||
}
|
||||
|
||||
override fun compile(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCompileResult {
|
||||
val compilationState = state.asState(JsReplCompilationState::class.java)
|
||||
val compilationState = state.asState(JsReplCompilerState::class.java)
|
||||
return JsCoreScriptingCompiler(
|
||||
environment,
|
||||
compilationState.nameTables,
|
||||
compilationState.symbolTable,
|
||||
compilationState.dependencies,
|
||||
compilationState.replState
|
||||
compilationState
|
||||
).compile(codeLine)
|
||||
}
|
||||
}
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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()
|
||||
}
|
||||
+1
-12
@@ -9,8 +9,8 @@ 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.CompilerMessageSourceLocation
|
||||
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
|
||||
@@ -23,11 +23,9 @@ 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.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.library.resolver.TopologicalLibraryOrder
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtScript
|
||||
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzerBase
|
||||
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||
import org.jetbrains.kotlin.scripting.resolve.ScriptLightVirtualFile
|
||||
import org.jetbrains.kotlin.util.Logger
|
||||
@@ -37,7 +35,6 @@ import java.io.FileOutputStream
|
||||
import java.io.FileReader
|
||||
import java.io.InputStreamReader
|
||||
import java.nio.charset.Charset
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
import kotlin.script.experimental.api.*
|
||||
import kotlin.script.experimental.host.FileBasedScriptSource
|
||||
import kotlin.script.experimental.jvm.JsDependency
|
||||
@@ -216,11 +213,3 @@ class DependencyLoader {
|
||||
}
|
||||
}
|
||||
|
||||
class JsReplCompilationState(
|
||||
lock: ReentrantReadWriteLock,
|
||||
nameTables: NameTables,
|
||||
dependencies: List<ModuleDescriptor>,
|
||||
val replState: ReplCodeAnalyzerBase.ResettableAnalyzerState,
|
||||
val symbolTable: SymbolTable
|
||||
) : JsCompilationState(lock, nameTables, dependencies)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user