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:
+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