[JS BE] Drop JS scripting support

JS scripting uses the old IR to JS transformer.
 The new IR to JS transformer can not be used for
 JS scripting out of the box. Patching the new transformer for
 JS scripting is potentially dangerous and requires a lot of effort.
 Dropping JS scripting and the old IR to JS transformer allows to
 refactor and simplify JS BE codebase.
This commit is contained in:
Alexander Korepanov
2022-11-03 14:26:11 +01:00
committed by Space Team
parent d75bbc49e7
commit d5e9e87538
41 changed files with 14 additions and 1860 deletions
-1
View File
@@ -708,7 +708,6 @@ tasks {
register("scriptingTest") {
dependsOn("scriptingJvmTest")
dependsOn(":kotlin-scripting-js-test:test")
}
register("compilerTest") {
@@ -349,6 +349,15 @@ class K2JSCompilerArguments : CommonCompilerArguments() {
var legacyDeprecatedNoWarn: Boolean by FreezableVar(false)
override fun configureAnalysisFlags(collector: MessageCollector, languageVersion: LanguageVersion): MutableMap<AnalysisFlag<*>, Any> {
// TODO: 'enableJsScripting' is used in intellij tests
// Drop it after removing the usage from the intellij repository:
// https://github.com/JetBrains/intellij-community/blob/master/plugins/kotlin/gradle/gradle-java/tests/test/org/jetbrains/kotlin/gradle/CompilerArgumentsCachingTest.kt#L329
if (enableJsScripting) {
collector.report(
CompilerMessageSeverity.WARNING, "'-Xenable-js-scripting' is deprecated and will be removed in a future release"
)
}
return super.configureAnalysisFlags(collector, languageVersion).also {
it[allowFullyQualifiedNameInKClass] = wasm && wasmKClassFqn //Only enabled WASM BE supports this flag
}
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants
import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants.RUNTIME_DIAGNOSTIC_EXCEPTION
import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants.RUNTIME_DIAGNOSTIC_LOG
import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot
import org.jetbrains.kotlin.cli.common.extensions.ScriptEvaluationExtension
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
@@ -158,29 +157,9 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val pluginLoadResult = loadPlugins(paths, arguments, configuration)
if (pluginLoadResult != OK) return pluginLoadResult
//TODO: add to configuration everything that may come in handy at script compiler and use it there
if (arguments.script) {
if (!arguments.enableJsScripting) {
@Suppress("SpellCheckingInspection")
messageCollector.report(ERROR, "Script for K/JS should be enabled explicitly, see -Xenable-js-scripting")
return COMPILATION_ERROR
}
configuration.put(CommonConfigurationKeys.MODULE_NAME, "repl.kts")
val environment = KotlinCoreEnvironment.getOrCreateApplicationEnvironmentForProduction(rootDisposable, configuration)
val projectEnv = KotlinCoreEnvironment.ProjectEnvironment(rootDisposable, environment, configuration)
projectEnv.registerExtensionsFromPlugins(configuration)
val scriptingEvaluators = ScriptEvaluationExtension.getInstances(projectEnv.project)
val scriptingEvaluator = scriptingEvaluators.find { it.isAccepted(arguments) }
if (scriptingEvaluator == null) {
messageCollector.report(ERROR, "Unable to evaluate script, no scripting plugin loaded")
return COMPILATION_ERROR
}
return scriptingEvaluator.eval(arguments, configuration, projectEnv)
messageCollector.report(ERROR, "K/JS does not support Kotlin script (*.kts) files")
return COMPILATION_ERROR
}
if (arguments.freeArgs.isEmpty() && !(incrementalCompilationIsEnabledForJs(arguments))) {
@@ -1 +0,0 @@
/* ERROR: unsupported element type: IrScriptImpl */
@@ -1,10 +0,0 @@
fun test() {
val x = intArrayOf(1, 2, 3)
x[1] = 0
}
fun foo() = 1
fun test2() {
intArrayOf(1, 2, 3)[foo()] = 1
}
@@ -1,33 +0,0 @@
FILE fqName:<root> fileName:/arrayAssignment.kts
SCRIPT
FUN name:test visibility:public modality:FINAL <> ($this:<root>.ArrayAssignment) returnType:kotlin.Unit
$this: VALUE_PARAMETER name:<this> type:<root>.ArrayAssignment
BLOCK_BODY
VAR name:x type:kotlin.IntArray [val]
CALL 'public final fun intArrayOf (vararg elements: kotlin.Int): kotlin.IntArray declared in kotlin' type=kotlin.IntArray origin=null
elements: VARARG type=kotlin.IntArray varargElementType=kotlin.Int
CONST Int type=kotlin.Int value=1
CONST Int type=kotlin.Int value=2
CONST Int type=kotlin.Int value=3
CALL 'public final fun set (index: kotlin.Int, value: kotlin.Int): kotlin.Unit [operator] declared in kotlin.IntArray' type=kotlin.Unit origin=EQ
$this: GET_VAR 'val x: kotlin.IntArray [val] declared in <root>.ArrayAssignment.test' type=kotlin.IntArray origin=null
index: CONST Int type=kotlin.Int value=1
value: CONST Int type=kotlin.Int value=0
FUN name:foo visibility:public modality:FINAL <> ($this:<root>.ArrayAssignment) returnType:kotlin.Int
$this: VALUE_PARAMETER name:<this> type:<root>.ArrayAssignment
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun foo (): kotlin.Int declared in <root>.ArrayAssignment'
CONST Int type=kotlin.Int value=1
FUN name:test2 visibility:public modality:FINAL <> ($this:<root>.ArrayAssignment) returnType:kotlin.Unit
$this: VALUE_PARAMETER name:<this> type:<root>.ArrayAssignment
BLOCK_BODY
CALL 'public final fun set (index: kotlin.Int, value: kotlin.Int): kotlin.Unit [operator] declared in kotlin.IntArray' type=kotlin.Unit origin=EQ
$this: CALL 'public final fun intArrayOf (vararg elements: kotlin.Int): kotlin.IntArray declared in kotlin' type=kotlin.IntArray origin=null
elements: VARARG type=kotlin.IntArray varargElementType=kotlin.Int
CONST Int type=kotlin.Int value=1
CONST Int type=kotlin.Int value=2
CONST Int type=kotlin.Int value=3
index: CALL 'public final fun foo (): kotlin.Int declared in <root>.ArrayAssignment' type=kotlin.Int origin=null
$this: GET_VAR '<this>: <root>.ArrayAssignment declared in <root>.ArrayAssignment.test2' type=<root>.ArrayAssignment origin=null
value: CONST Int type=kotlin.Int value=1
VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.ArrayAssignment
-1
View File
@@ -1 +0,0 @@
/* ERROR: unsupported element type: IrScriptImpl */
-13
View File
@@ -1,13 +0,0 @@
fun <T> test1(i: Int, j: T) {}
fun test2(i: Int = 0, j: String = "") {}
fun test3(vararg args: String) {}
fun String.textExt1(i: Int, j: String) {}
class Host {
fun String.testMembetExt1(i: Int, j: String) {}
fun <T> String.testMembetExt2(i: Int, j: T) {}
}
-60
View File
@@ -1,60 +0,0 @@
FILE fqName:<root> fileName:/fun.kts
SCRIPT
FUN name:test1 visibility:public modality:FINAL <T> ($this:<root>.Fun, i:kotlin.Int, j:T of <root>.Fun.test1) returnType:kotlin.Unit
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] reified:false
$this: VALUE_PARAMETER name:<this> type:<root>.Fun
VALUE_PARAMETER name:i index:0 type:kotlin.Int
VALUE_PARAMETER name:j index:1 type:T of <root>.Fun.test1
BLOCK_BODY
FUN name:test2 visibility:public modality:FINAL <> ($this:<root>.Fun, i:kotlin.Int, j:kotlin.String) returnType:kotlin.Unit
$this: VALUE_PARAMETER name:<this> type:<root>.Fun
VALUE_PARAMETER name:i index:0 type:kotlin.Int
EXPRESSION_BODY
CONST Int type=kotlin.Int value=0
VALUE_PARAMETER name:j index:1 type:kotlin.String
EXPRESSION_BODY
CONST String type=kotlin.String value=""
BLOCK_BODY
FUN name:test3 visibility:public modality:FINAL <> ($this:<root>.Fun, args:kotlin.Array<out kotlin.String>) returnType:kotlin.Unit
$this: VALUE_PARAMETER name:<this> type:<root>.Fun
VALUE_PARAMETER name:args index:0 type:kotlin.Array<out kotlin.String> varargElementType:kotlin.String [vararg]
BLOCK_BODY
FUN name:textExt1 visibility:public modality:FINAL <> ($this:<root>.Fun, $receiver:kotlin.String, i:kotlin.Int, j:kotlin.String) returnType:kotlin.Unit
$this: VALUE_PARAMETER name:<this> type:<root>.Fun
$receiver: VALUE_PARAMETER name:<this> type:kotlin.String
VALUE_PARAMETER name:i index:0 type:kotlin.Int
VALUE_PARAMETER name:j index:1 type:kotlin.String
BLOCK_BODY
CLASS CLASS name:Host modality:FINAL visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.Fun.Host
CONSTRUCTOR visibility:public <> () returnType:<root>.Fun.Host [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Host modality:FINAL visibility:public superTypes:[kotlin.Any]'
FUN name:testMembetExt1 visibility:public modality:FINAL <> ($this:<root>.Fun.Host, $receiver:kotlin.String, i:kotlin.Int, j:kotlin.String) returnType:kotlin.Unit
$this: VALUE_PARAMETER name:<this> type:<root>.Fun.Host
$receiver: VALUE_PARAMETER name:<this> type:kotlin.String
VALUE_PARAMETER name:i index:0 type:kotlin.Int
VALUE_PARAMETER name:j index:1 type:kotlin.String
BLOCK_BODY
FUN name:testMembetExt2 visibility:public modality:FINAL <T> ($this:<root>.Fun.Host, $receiver:kotlin.String, i:kotlin.Int, j:T of <root>.Fun.Host.testMembetExt2) returnType:kotlin.Unit
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] reified:false
$this: VALUE_PARAMETER name:<this> type:<root>.Fun.Host
$receiver: VALUE_PARAMETER name:<this> type:kotlin.String
VALUE_PARAMETER name:i index:0 type:kotlin.Int
VALUE_PARAMETER name:j index:1 type:T of <root>.Fun.Host.testMembetExt2
BLOCK_BODY
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.Fun
@@ -1 +0,0 @@
/* ERROR: unsupported element type: IrScriptImpl */
-21
View File
@@ -1,21 +0,0 @@
class Ref(var value: Int)
interface IHost {
fun String.extLength() = length
}
fun test1(x: String?) = x?.length
fun test2(x: String?) = x?.hashCode()
fun test3(x: String?, y: Any?) = x?.equals(y)
fun test4(x: Ref?) {
x?.value = 0
}
fun IHost.test5(s: String?) = s?.extLength()
fun Int.foo() = 239
fun box() {
42?.foo()
}
-183
View File
@@ -1,183 +0,0 @@
FILE fqName:<root> fileName:/safeCalls.kts
SCRIPT
CLASS CLASS name:Ref modality:FINAL visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.SafeCalls.Ref
CONSTRUCTOR visibility:public <> (value:kotlin.Int) returnType:<root>.SafeCalls.Ref [primary]
VALUE_PARAMETER name:value index:0 type:kotlin.Int
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Ref modality:FINAL visibility:public superTypes:[kotlin.Any]'
PROPERTY name:value visibility:public modality:FINAL [var]
FIELD PROPERTY_BACKING_FIELD name:value type:kotlin.Int visibility:private
EXPRESSION_BODY
GET_VAR 'value: kotlin.Int declared in <root>.SafeCalls.Ref.<init>' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-value> visibility:public modality:FINAL <> ($this:<root>.SafeCalls.Ref) returnType:kotlin.Int
correspondingProperty: PROPERTY name:value visibility:public modality:FINAL [var]
$this: VALUE_PARAMETER name:<this> type:<root>.SafeCalls.Ref
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-value> (): kotlin.Int declared in <root>.SafeCalls.Ref'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:kotlin.Int visibility:private' type=kotlin.Int origin=null
receiver: GET_VAR '<this>: <root>.SafeCalls.Ref declared in <root>.SafeCalls.Ref.<get-value>' type=<root>.SafeCalls.Ref origin=null
FUN DEFAULT_PROPERTY_ACCESSOR name:<set-value> visibility:public modality:FINAL <> ($this:<root>.SafeCalls.Ref, <set-?>:kotlin.Int) returnType:kotlin.Unit
correspondingProperty: PROPERTY name:value visibility:public modality:FINAL [var]
$this: VALUE_PARAMETER name:<this> type:<root>.SafeCalls.Ref
VALUE_PARAMETER name:<set-?> index:0 type:kotlin.Int
BLOCK_BODY
SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:kotlin.Int visibility:private' type=kotlin.Unit origin=null
receiver: GET_VAR '<this>: <root>.SafeCalls.Ref declared in <root>.SafeCalls.Ref.<set-value>' type=<root>.SafeCalls.Ref origin=null
value: GET_VAR '<set-?>: kotlin.Int declared in <root>.SafeCalls.Ref.<set-value>' type=kotlin.Int origin=null
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
CLASS INTERFACE name:IHost modality:ABSTRACT visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.SafeCalls.IHost
FUN name:extLength visibility:public modality:OPEN <> ($this:<root>.SafeCalls.IHost, $receiver:kotlin.String) returnType:kotlin.Int
$this: VALUE_PARAMETER name:<this> type:<root>.SafeCalls.IHost
$receiver: VALUE_PARAMETER name:<this> type:kotlin.String
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun extLength (): kotlin.Int declared in <root>.SafeCalls.IHost'
CALL 'public open fun <get-length> (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=GET_PROPERTY
$this: GET_VAR '<this>: kotlin.String declared in <root>.SafeCalls.IHost.extLength' type=kotlin.String origin=null
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN name:test1 visibility:public modality:FINAL <> ($this:<root>.SafeCalls, x:kotlin.String?) returnType:kotlin.Int?
$this: VALUE_PARAMETER name:<this> type:<root>.SafeCalls
VALUE_PARAMETER name:x index:0 type:kotlin.String?
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test1 (x: kotlin.String?): kotlin.Int? declared in <root>.SafeCalls'
BLOCK type=kotlin.Int? origin=SAFE_CALL
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.String? [val]
GET_VAR 'x: kotlin.String? declared in <root>.SafeCalls.test1' type=kotlin.String? origin=null
WHEN type=kotlin.Int? origin=null
BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp_0: kotlin.String? [val] declared in <root>.SafeCalls.test1' type=kotlin.String? origin=null
arg1: CONST Null type=kotlin.Nothing? value=null
then: CONST Null type=kotlin.Nothing? value=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CALL 'public open fun <get-length> (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=GET_PROPERTY
$this: GET_VAR 'val tmp_0: kotlin.String? [val] declared in <root>.SafeCalls.test1' type=kotlin.String? origin=null
FUN name:test2 visibility:public modality:FINAL <> ($this:<root>.SafeCalls, x:kotlin.String?) returnType:kotlin.Int?
$this: VALUE_PARAMETER name:<this> type:<root>.SafeCalls
VALUE_PARAMETER name:x index:0 type:kotlin.String?
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test2 (x: kotlin.String?): kotlin.Int? declared in <root>.SafeCalls'
BLOCK type=kotlin.Int? origin=SAFE_CALL
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.String? [val]
GET_VAR 'x: kotlin.String? declared in <root>.SafeCalls.test2' type=kotlin.String? origin=null
WHEN type=kotlin.Int? origin=null
BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp_1: kotlin.String? [val] declared in <root>.SafeCalls.test2' type=kotlin.String? origin=null
arg1: CONST Null type=kotlin.Nothing? value=null
then: CONST Null type=kotlin.Nothing? value=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CALL 'public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.String' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_1: kotlin.String? [val] declared in <root>.SafeCalls.test2' type=kotlin.String? origin=null
FUN name:test3 visibility:public modality:FINAL <> ($this:<root>.SafeCalls, x:kotlin.String?, y:kotlin.Any?) returnType:kotlin.Boolean?
$this: VALUE_PARAMETER name:<this> type:<root>.SafeCalls
VALUE_PARAMETER name:x index:0 type:kotlin.String?
VALUE_PARAMETER name:y index:1 type:kotlin.Any?
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test3 (x: kotlin.String?, y: kotlin.Any?): kotlin.Boolean? declared in <root>.SafeCalls'
BLOCK type=kotlin.Boolean? origin=SAFE_CALL
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.String? [val]
GET_VAR 'x: kotlin.String? declared in <root>.SafeCalls.test3' type=kotlin.String? origin=null
WHEN type=kotlin.Boolean? origin=null
BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp_2: kotlin.String? [val] declared in <root>.SafeCalls.test3' type=kotlin.String? origin=null
arg1: CONST Null type=kotlin.Nothing? value=null
then: CONST Null type=kotlin.Nothing? value=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.String' type=kotlin.Boolean origin=null
$this: GET_VAR 'val tmp_2: kotlin.String? [val] declared in <root>.SafeCalls.test3' type=kotlin.String? origin=null
other: GET_VAR 'y: kotlin.Any? declared in <root>.SafeCalls.test3' type=kotlin.Any? origin=null
FUN name:test4 visibility:public modality:FINAL <> ($this:<root>.SafeCalls, x:<root>.SafeCalls.Ref?) returnType:kotlin.Unit
$this: VALUE_PARAMETER name:<this> type:<root>.SafeCalls
VALUE_PARAMETER name:x index:0 type:<root>.SafeCalls.Ref?
BLOCK_BODY
BLOCK type=kotlin.Unit origin=SAFE_CALL
VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:<root>.SafeCalls.Ref? [val]
GET_VAR 'x: <root>.SafeCalls.Ref? declared in <root>.SafeCalls.test4' type=<root>.SafeCalls.Ref? origin=null
WHEN type=kotlin.Unit origin=null
BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp_3: <root>.SafeCalls.Ref? [val] declared in <root>.SafeCalls.test4' type=<root>.SafeCalls.Ref? origin=null
arg1: CONST Null type=kotlin.Nothing? value=null
then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
CONST Null type=kotlin.Nothing? value=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CALL 'public final fun <set-value> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>.SafeCalls.Ref' type=kotlin.Unit origin=EQ
$this: GET_VAR 'val tmp_3: <root>.SafeCalls.Ref? [val] declared in <root>.SafeCalls.test4' type=<root>.SafeCalls.Ref? origin=null
<set-?>: CONST Int type=kotlin.Int value=0
FUN name:test5 visibility:public modality:FINAL <> ($this:<root>.SafeCalls, $receiver:<root>.SafeCalls.IHost, s:kotlin.String?) returnType:kotlin.Int?
$this: VALUE_PARAMETER name:<this> type:<root>.SafeCalls
$receiver: VALUE_PARAMETER name:<this> type:<root>.SafeCalls.IHost
VALUE_PARAMETER name:s index:0 type:kotlin.String?
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test5 (s: kotlin.String?): kotlin.Int? declared in <root>.SafeCalls'
BLOCK type=kotlin.Int? origin=SAFE_CALL
VAR IR_TEMPORARY_VARIABLE name:tmp_4 type:kotlin.String? [val]
GET_VAR 's: kotlin.String? declared in <root>.SafeCalls.test5' type=kotlin.String? origin=null
WHEN type=kotlin.Int? origin=null
BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp_4: kotlin.String? [val] declared in <root>.SafeCalls.test5' type=kotlin.String? origin=null
arg1: CONST Null type=kotlin.Nothing? value=null
then: CONST Null type=kotlin.Nothing? value=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CALL 'public open fun extLength (): kotlin.Int declared in <root>.SafeCalls.IHost' type=kotlin.Int origin=null
$this: GET_VAR '<this>: <root>.SafeCalls.IHost declared in <root>.SafeCalls.test5' type=<root>.SafeCalls.IHost origin=null
$receiver: GET_VAR 'val tmp_4: kotlin.String? [val] declared in <root>.SafeCalls.test5' type=kotlin.String? origin=null
FUN name:foo visibility:public modality:FINAL <> ($this:<root>.SafeCalls, $receiver:kotlin.Int) returnType:kotlin.Int
$this: VALUE_PARAMETER name:<this> type:<root>.SafeCalls
$receiver: VALUE_PARAMETER name:<this> type:kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun foo (): kotlin.Int declared in <root>.SafeCalls'
CONST Int type=kotlin.Int value=239
FUN name:box visibility:public modality:FINAL <> ($this:<root>.SafeCalls) returnType:kotlin.Unit
$this: VALUE_PARAMETER name:<this> type:<root>.SafeCalls
BLOCK_BODY
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
BLOCK type=kotlin.Int? origin=SAFE_CALL
VAR IR_TEMPORARY_VARIABLE name:tmp_5 type:kotlin.Int [val]
CONST Int type=kotlin.Int value=42
WHEN type=kotlin.Int? origin=null
BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp_5: kotlin.Int [val] declared in <root>.SafeCalls.box' type=kotlin.Int origin=null
arg1: CONST Null type=kotlin.Nothing? value=null
then: CONST Null type=kotlin.Nothing? value=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CALL 'public final fun foo (): kotlin.Int declared in <root>.SafeCalls' type=kotlin.Int origin=null
$this: GET_VAR '<this>: <root>.SafeCalls declared in <root>.SafeCalls.box' type=<root>.SafeCalls origin=null
$receiver: GET_VAR 'val tmp_5: kotlin.Int [val] declared in <root>.SafeCalls.box' type=kotlin.Int origin=null
VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.SafeCalls
-1
View File
@@ -7,7 +7,6 @@ plugins {
dependencies {
testApi(kotlinStdlib("jdk8"))
testApi(project(":kotlin-scripting-compiler"))
testApi(project(":kotlin-scripting-compiler-js"))
testApi(project(":core:descriptors"))
testApi(project(":core:descriptors.jvm"))
testApi(project(":core:deserialization"))
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi2ir.generators.DeclarationStubGeneratorImpl
import org.jetbrains.kotlin.scripting.js.loadScriptConfiguration
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
import org.jetbrains.kotlin.test.util.JUnit4Assertions
@@ -88,7 +87,6 @@ abstract class AbstractIrTextTestCase : AbstractIrGeneratorTestCase() {
override fun configureTestSpecific(configuration: CompilerConfiguration, testFiles: List<TestFile>) {
if (testFiles.any { it.name.endsWith(".kts") }) {
loadScriptConfiguration(configuration)
loadPluginsForTests(configuration)
}
}
@@ -187,32 +187,4 @@ public class IrJsTextTestCaseGenerated extends AbstractIrJsTextTestCase {
runTest("compiler/testData/ir/irJsText/native/nativeNativeKotlin.kt");
}
}
@TestMetadata("compiler/testData/ir/irJsText/scripting")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Scripting extends AbstractIrJsTextTestCase {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInScripting() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/irJsText/scripting"), Pattern.compile("^(.+)\\.kt(s)?$"), null, true);
}
@TestMetadata("arrayAssignment.kts")
public void testArrayAssignment() throws Exception {
runTest("compiler/testData/ir/irJsText/scripting/arrayAssignment.kts");
}
@TestMetadata("fun.kts")
public void testFun() throws Exception {
runTest("compiler/testData/ir/irJsText/scripting/fun.kts");
}
@TestMetadata("safeCalls.kts")
public void testSafeCalls() throws Exception {
runTest("compiler/testData/ir/irJsText/scripting/safeCalls.kts");
}
}
}
@@ -188,17 +188,4 @@ public class KlibJsTextTestCaseGenerated extends AbstractKlibJsTextTestCase {
runTest("compiler/testData/ir/irJsText/native/nativeNativeKotlin.kt");
}
}
@TestMetadata("compiler/testData/ir/irJsText/scripting")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Scripting extends AbstractKlibJsTextTestCase {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInScripting() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/irJsText/scripting"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
}
}
@@ -71,8 +71,6 @@ object PathUtil {
const val KOTLIN_SCRIPTING_COMMON_JAR = "$KOTLIN_SCRIPTING_COMMON_NAME.jar"
const val KOTLIN_SCRIPTING_JVM_NAME = "kotlin-scripting-jvm"
const val KOTLIN_SCRIPTING_JVM_JAR = "$KOTLIN_SCRIPTING_JVM_NAME.jar"
const val KOTLIN_SCRIPTING_JS_NAME = "kotlin-scripting-js"
const val KOTLIN_SCRIPTING_JS_JAR = "$KOTLIN_SCRIPTING_JS_NAME.jar"
const val KOTLIN_DAEMON_NAME = "kotlin-daemon"
const val KOTLIN_DAEMON_JAR = "$KOTLIN_SCRIPTING_JVM_NAME.jar"
const val KOTLIN_SCRIPTING_COMPILER_PLUGIN_NAME = "kotlin-scripting-compiler"
@@ -89,7 +87,7 @@ object PathUtil {
KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMPILER_IMPL_JAR,
KOTLINX_COROUTINES_CORE_JAR,
KOTLIN_SCRIPTING_COMMON_JAR, KOTLIN_SCRIPTING_JVM_JAR,
KOTLIN_SCRIPTING_JS_JAR, JS_ENGINES_JAR
JS_ENGINES_JAR
)
const val KOTLIN_TEST_NAME = "kotlin-test"
@@ -230,7 +230,6 @@ class CompilerArgumentsContentProspectorTest {
K2JSCompilerArguments::typedArrays,
K2JSCompilerArguments::friendModulesDisabled,
K2JSCompilerArguments::metadataOnly,
K2JSCompilerArguments::enableJsScripting,
K2JSCompilerArguments::fakeOverrideValidator,
K2JSCompilerArguments::wasm
)
@@ -277,4 +276,4 @@ class CompilerArgumentsContentProspectorTest {
)
}
}
}
}
@@ -198,14 +198,4 @@ public class Fir2IrJsTextTestGenerated extends AbstractFir2IrJsTextTest {
runTest("compiler/testData/ir/irJsText/native/nativeNativeKotlin.kt");
}
}
@Nested
@TestMetadata("compiler/testData/ir/irJsText/scripting")
@TestDataPath("$PROJECT_ROOT")
public class Scripting {
@Test
public void testAllFilesPresentInScripting() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/irJsText/scripting"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
}
}
@@ -1,35 +0,0 @@
plugins {
kotlin("jvm")
}
val embeddableTestRuntime by configurations.creating
dependencies {
testApi(commonDependency("junit"))
testApi(project(":kotlin-scripting-js"))
testApi(project(":compiler:plugin-api"))
testApi(project(":kotlin-scripting-compiler-js"))
testApi(project(":compiler:cli"))
testApi(project(":compiler:backend.js"))
testApi(project(":compiler:ir.tree"))
testApi(project(":js:js.engines"))
testApi(intellijCore())
testRuntimeOnly(commonDependency("org.jetbrains.intellij.deps.fastutil:intellij-deps-fastutil"))
testRuntimeOnly(commonDependency("org.jetbrains.intellij.deps:jdom"))
testRuntimeOnly(commonDependency("org.jetbrains.intellij.deps:trove4j"))
}
optInToExperimentalCompilerApi()
sourceSets {
"main" {}
"test" { projectDefault() }
}
projectTest(parallel = true) {
dependsOn(":kotlin-stdlib-js-ir:compileKotlinJs")
systemProperty("kotlin.js.full.stdlib.path", "libraries/stdlib/js-ir/build/classes/kotlin/js/main")
workingDir = rootDir
}
@@ -1,85 +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.
*/
@file:Suppress("DEPRECATION")
package org.jetbrains.kotlin.scripting.repl.js.test
import com.intellij.openapi.util.Disposer
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult
import org.jetbrains.kotlin.cli.common.repl.ReplEvalResult
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigurationComponentRegistrar
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.js.JsReplCompiler
import org.jetbrains.kotlin.scripting.js.JsReplCompilerState
import org.jetbrains.kotlin.scripting.js.ReplMessageCollector
import org.jetbrains.kotlin.scripting.repl.js.*
import java.io.Closeable
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.baseClass
import kotlin.script.experimental.api.dependencies
import kotlin.script.experimental.host.ScriptingHostConfiguration
import kotlin.script.experimental.jvm.JsDependency
abstract class AbstractJsReplTest : Closeable {
protected lateinit var compilerState: JsReplCompilerState
protected lateinit var evaluationState: JsEvaluationState
protected abstract fun createCompilationState(): JsReplCompilerState
protected abstract fun createEvaluationState(): JsEvaluationState
fun compile(codeLine: ReplCodeLine): ReplCompileResult {
return JsReplCompiler(environment).compile(compilerState, codeLine)
}
fun evaluate(compileResult: ReplCompileResult.CompiledClasses): ReplEvalResult {
return JsReplEvaluator().eval(evaluationState, compileResult)
}
fun reset() {
collector.clear()
compilerState = createCompilationState()
evaluationState = createEvaluationState()
}
private val collector: MessageCollector = ReplMessageCollector()
protected val disposable = Disposer.newDisposable()
protected val environment = KotlinCoreEnvironment.createForProduction(
disposable, loadConfiguration(), EnvironmentConfigFiles.JS_CONFIG_FILES
)
private var snippetId: Int = 1 //index 0 for klib
fun newSnippetId(): Int = snippetId++
private fun loadConfiguration(): CompilerConfiguration {
val configuration = CompilerConfiguration()
configuration.add(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS, ScriptingCompilerConfigurationComponentRegistrar())
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, collector)
configuration.put(CommonConfigurationKeys.MODULE_NAME, "repl.kts")
configuration.put(JSConfigurationKeys.GENERATE_POLYFILLS, true)
val stdlibPath = System.getProperty("kotlin.js.full.stdlib.path")
val scriptConfiguration = ScriptCompilationConfiguration {
baseClass("kotlin.Any")
dependencies.append(JsDependency(stdlibPath))
platform.put("JS")
}
configuration.add(
ScriptingConfigurationKeys.SCRIPT_DEFINITIONS,
ScriptDefinition.FromConfigurations(ScriptingHostConfiguration(), scriptConfiguration, null)
)
return configuration
}
}
@@ -1,53 +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.test
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor
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.js.engine.ScriptEngineNashorn
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzerBase
import org.jetbrains.kotlin.scripting.js.*
import org.jetbrains.kotlin.scripting.repl.js.JsEvaluationState
import org.jetbrains.kotlin.scripting.repl.js.JsReplEvaluator
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() {
private val dependencyLoader = DependencyLoader()
private val dependencies = readLibrariesFromConfiguration(environment.configuration)
init {
val nameTable = NameTables(emptyList(), mappedNames = mutableMapOf())
val compiler = JsScriptDependencyCompiler(environment.configuration, nameTable, createSymbolTable())
val runtimeBinary = compiler.compile(dependencies)
dependencyLoader.saveScriptDependencyBinary(runtimeBinary)
dependencyLoader.saveNames(nameTable)
}
override fun createCompilationState(): JsReplCompilerState {
val replState = ReplCodeAnalyzerBase.ResettableAnalyzerState()
return JsReplCompilerState(ReentrantReadWriteLock(), dependencyLoader.loadNames(), dependencies, replState, createSymbolTable())
}
private fun createSymbolTable(): SymbolTable =
SymbolTable(IdSignatureDescriptor(JsManglerDesc), IrFactoryImpl)
override fun createEvaluationState(): JsEvaluationState {
val state = JsEvaluationState(ReentrantReadWriteLock(), ScriptEngineNashorn())
JsReplEvaluator().eval(state, createCompileResult(dependencyLoader.loadScriptDependencyBinary()))
return state
}
override fun close() {
//do nothing
}
}
@@ -1,56 +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.test
import com.intellij.openapi.util.Disposer
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor
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.js.engine.ScriptEngineNashorn
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzerBase
import org.jetbrains.kotlin.scripting.js.JsReplCompilerState
import org.jetbrains.kotlin.scripting.js.JsScriptDependencyCompiler
import org.jetbrains.kotlin.scripting.js.createCompileResult
import org.jetbrains.kotlin.scripting.js.readLibrariesFromConfiguration
import org.jetbrains.kotlin.scripting.repl.js.*
import java.util.concurrent.locks.ReentrantReadWriteLock
class JsReplTestAgainstKlib : AbstractJsReplTest() {
private var dependencyCode: String? = null
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 JsReplCompilerState(
ReentrantReadWriteLock(),
nameTables,
dependencies,
ReplCodeAnalyzerBase.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() {
Disposer.dispose(disposable)
}
}
@@ -1,287 +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.test
import junit.framework.TestCase
import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult
import org.junit.Assert
import org.junit.Test
import org.jetbrains.kotlin.cli.common.repl.ReplEvalResult
import org.jetbrains.kotlin.scripting.js.makeReplCodeLine
abstract class AbstractReplTestRunner : TestCase() {
abstract fun getTester(): AbstractJsReplTest
@Test
fun testIndependentLines() {
val lines = listOf(
"var x = 38",
"var y = 99",
"4 + 1"
)
Assert.assertEquals(5, compileAndEval(lines))
}
@Test
fun testDependentLines() {
val lines = listOf(
"var x = 7",
"var y = 32",
"x + y"
)
Assert.assertEquals(39, compileAndEval(lines))
}
@Test
fun testFunctionCall() {
val lines = listOf(
"var x = 2",
"var y = 3",
"fun foo(x: Int, unused: Int) = x + y",
"foo(x, x) * foo(y, y)"
)
Assert.assertEquals(30, compileAndEval(lines))
}
@Test
fun testList() {
val lines = listOf(
"var a = 4",
"var b = 6",
"listOf(a, 5, b).last()"
)
Assert.assertEquals(6, compileAndEval(lines))
}
@Test
fun testMatchingNames() {
val lines = listOf(
"fun foo(i: Int) = i + 2",
"fun foo(s: String) = s",
"class C {fun foo(s: String) = s + s}",
"foo(\"x\") + foo(2) + C().foo(\"class\")"
)
Assert.assertEquals("x4classclass", compileAndEval(lines))
}
@Test
fun testInline() {
val lines = listOf(
"inline fun foo(i : Int) = if (i % 2 == 0) {} else i",
"""
fun box(): String {
val a = foo(1)
if (a != 1) return "fail1: ${'$'}a"
val b = foo(2)
if (b != Unit) return "fail2: ${'$'}b"
return "OK"
}
""",
"box()"
)
Assert.assertEquals("OK", compileAndEval(lines))
}
@Test
fun testAnonymous() {
val lines = listOf(
"""
inline fun foo(f: () -> String): () -> String {
val result = f()
return { result }
}
""",
"fun bar(f: () -> String) = foo(f)()",
"fun box(): String = bar { \"OK\" }",
"box()"
)
Assert.assertEquals("OK", compileAndEval(lines))
}
@Test
fun testNoneLocalReturn() {
val lines = listOf(
"""
inline fun f(ignored: () -> Any): Any {
return ignored()
}
""",
"""
fun test(): String {
f { return "OK" };
return "error"
}
""",
"test()"
)
Assert.assertEquals("OK", compileAndEval(lines))
}
/* Ignore annotation doesn't work, so comment it
@Ignore("we use Object.assign inside type checks and nashorn does not support it")
@Test
fun testInstanceOf() {
val lines = listOf(
"""
val list = listOf(1, 2, 3)
val f: Boolean = list is List<Int>
""",
"val s = list is List<Int>",
"f.toString() + s.toString()"
)
Assert.assertEquals("truetrue", compileAndEval(lines))
}
*/
@Test
fun testScopes() {
val lines = listOf(
"""
fun foo(): Int {
var t = 2 * 2
class A(val value: Int = 5) {
fun bar(): Int {
class B(val value: Int = 4) {
fun baz(): Int = value
}
var q = B().baz()
var w = 1
return q + w
}
}
return A().bar() * 2
}
foo()
"""
)
Assert.assertEquals(10, compileAndEval(lines))
}
@Test
fun testEvaluateFunctionName() {
val lines = listOf(
"fun evaluateScript() = 5",
"fun foo(i: Int) = i + evaluateScript()",
"foo(5)"
)
Assert.assertEquals(10, compileAndEval(lines))
}
@Test
fun testMemberDeclarations() {
val lines = listOf(
"""
val a = listOf(1, 2, 3, 4, 5)
val str = "" + kotlin.math.PI
str + a.subList(2, 3).toString() + a.lastIndexOf(4)
"""
)
Assert.assertEquals("3.141592653589793[3]3", compileAndEval(lines))
}
@Test
fun testInitializeScriptFunction() {
val lines = listOf(
"""
var result = ""
class Class(val x: Int = 10)
result += Class().x
fun function() = "#$@"
result += function()
val field = 123456
result += field
val sq: (x: Int) -> Int = { x -> x * x }
result += "_" + sq(9)
result += if (sq(5) % 2 == 0) {
class I(val x: Int = 100)
I().x
} else {
class I(val x: String = "goo")
I().x
}
result
"""
)
Assert.assertEquals("10#$@123456_81goo", compileAndEval(lines))
}
@Test
fun testFunctionReference() {
val lines = listOf(
"""
fun foo(k: String) = "O" + k
val f = ::foo
f("K")
"""
)
Assert.assertEquals("OK", compileAndEval(lines))
}
@Test
fun testPropertyReference() {
val lines = listOf(
"""
var r = ""
val o = "O"
val ro = ::o
r += ro.get()
r += ro()
var k = "k"
var rk = ::k
r += rk.get()
rk.set("y")
r += rk()
r
"""
)
Assert.assertEquals("OOky", compileAndEval(lines))
}
private fun compileAndEval(lines: List<String>): Any? {
var result: Any? = null
getTester().use { tester ->
tester.reset()
lines.forEach { line ->
val compileResult = tester.compile(makeReplCodeLine(tester.newSnippetId(), line))
if (compileResult !is ReplCompileResult.CompiledClasses) return compileResult.toString()
val evalResult = tester.evaluate(compileResult)
when (evalResult) {
is ReplEvalResult.Error.Runtime -> return evalResult.cause.toString()
!is ReplEvalResult.ValueResult -> return evalResult.toString()
else -> result = evalResult.value
}
}
}
return result
}
}
class ReplTestRunnerAgainstKLib : AbstractReplTestRunner() {
override fun getTester(): AbstractJsReplTest = JsReplTestAgainstKlib()
}
class ReplTestRunnerAgainstBinaries : AbstractReplTestRunner() {
override fun getTester(): AbstractJsReplTest = tester
companion object {
private val tester = JsReplTestAgainstBinaries()
}
}
-21
View File
@@ -1,21 +0,0 @@
plugins {
kotlin("jvm")
id("jps-compatible")
}
dependencies {
api(project(":kotlin-scripting-common"))
compileOnly(project(":compiler:backend.js"))
compileOnly(project(":compiler:cli-common"))
compileOnly(project(":js:js.engines"))
}
sourceSets {
"main" { projectDefault() }
"test" { }
}
publish()
standardPublicJars()
@@ -1,30 +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.repl.*
import org.jetbrains.kotlin.js.engine.ScriptEngineNashorn
import java.util.concurrent.locks.ReentrantReadWriteLock
class JsReplEvaluator : ReplEvaluator {
//TODO: support println()
override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*> = JsEvaluationState(lock, ScriptEngineNashorn())
override fun eval(
state: IReplStageState<*>,
compileResult: ReplCompileResult.CompiledClasses,
scriptArgs: ScriptArgsWithTypes?,
invokeWrapper: InvokeWrapper?
): ReplEvalResult {
return try {
val evaluationState = state.asState(JsEvaluationState::class.java)
val evalResult = evaluationState.engine.evalWithTypedResult<Any?>(compileResult.data as String)
ReplEvalResult.ValueResult("result", evalResult, "Any?")
} catch (e: Exception) {
ReplEvalResult.Error.Runtime("Error while evaluating", e)
}
}
}
@@ -1,38 +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.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
import kotlin.script.experimental.api.CompiledScript
import kotlin.script.experimental.api.ResultWithDiagnostics
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.ScriptEvaluationConfiguration
// 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")
}
class JsCompiledScript(
val jsCode: String,
override val compilationConfiguration: ScriptCompilationConfiguration
) : CompiledScript {
override suspend fun getClass(scriptEvaluationConfiguration: ScriptEvaluationConfiguration?): ResultWithDiagnostics<KClass<*>> {
throw IllegalStateException("Class is not available for JS implementation")
}
}
@@ -1,44 +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.js.engine.ScriptEngineNashorn
import kotlin.script.experimental.api.*
class JsScriptEvaluator : ScriptEvaluator {
//TODO: support println()
private val engine = ScriptEngineNashorn()
override suspend fun invoke(
compiledScript: CompiledScript,
scriptEvaluationConfiguration: ScriptEvaluationConfiguration
): ResultWithDiagnostics<EvaluationResult> {
return try {
val evalResult = engine.evalWithTypedResult<Any?>((compiledScript as JsCompiledScript).jsCode)
ResultWithDiagnostics.Success(
EvaluationResult(
ResultValue.Value(
name = "result",
value = evalResult,
type = "Any?",
scriptClass = null,
scriptInstance = null
),
scriptEvaluationConfiguration
)
)
} catch (e: Exception) {
ResultWithDiagnostics.Failure(
ScriptDiagnostic(
ScriptDiagnostic.unspecifiedError,
message = e.localizedMessage,
severity = ScriptDiagnostic.Severity.ERROR,
exception = e
)
)
}
}
}
@@ -86,11 +86,6 @@
<artifactId>kotlin-scripting-compiler</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>kotlin-scripting-js</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>kotlin-scripting-jvm</artifactId>
@@ -154,4 +149,4 @@
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
</project>
@@ -1,32 +0,0 @@
description = "Kotlin Scripting Compiler JS Plugin"
plugins {
kotlin("jvm")
id("jps-compatible")
}
dependencies {
compileOnly(project(":compiler:frontend"))
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"))
api(project(":kotlin-scripting-common"))
api(project(":kotlin-scripting-js"))
api(project(":kotlin-util-klib"))
api(project(":kotlin-scripting-compiler"))
api(kotlinStdlib())
compileOnly(intellijCore())
}
sourceSets {
"main" { projectDefault() }
}
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>> {
kotlinOptions {
freeCompilerArgs = freeCompilerArgs - "-progressive" + "-Xskip-metadata-version-check"
}
}
@@ -1,87 +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.js
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.EnumWhenTracker
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.InlineConstTracker
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.CompilerEnvironment
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 inlineConstTracker = InlineConstTracker.DoNothing
val enumWhenTracker = EnumWhenTracker.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,
inlineConstTracker,
enumWhenTracker,
additionalPackages,
CompilerEnvironment,
)
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)
}
}
@@ -1,127 +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.js
import org.jetbrains.kotlin.backend.common.serialization.DescriptorByIdSignatureFinderImpl
import org.jetbrains.kotlin.backend.common.serialization.linkerissues.checkNoUnboundSymbols
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.lower.serialization.ir.JsManglerDesc
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, renderInternalDiagnosticName = false)
if (messageCollector.hasErrors()) return ReplCompileResult.Error("Error while analysis")
}
val files = listOf(snippetKtFile)
val (bindingContext, module) = analysisResult
val psi2ir = Psi2IrTranslator(
environment.configuration.languageVersionSettings,
Psi2IrConfiguration(),
environment.configuration::checkNoUnboundSymbols
)
val generatorExtensions =
if (replCompilerState == null) GeneratorExtensions()
else object : GeneratorExtensions() {
override fun getPreviousScripts() = replCompilerState.history.map { it.item.scriptSymbol }
override val lowerScriptToClass: Boolean = false
}
val psi2irContext = psi2ir.createGeneratorContext(module, bindingContext, symbolTable, generatorExtensions)
val providers = generateTypicalIrProviderList(
module, psi2irContext.irBuiltIns, psi2irContext.symbolTable, DescriptorByIdSignatureFinderImpl(module, JsManglerDesc)
)
val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files, providers, emptyList(), null) // TODO: deserializer
val context = JsIrBackendContext(
irModuleFragment.descriptor,
psi2irContext.irBuiltIns,
psi2irContext.symbolTable,
irModuleFragment,
additionalExportedDeclarationNames = emptySet(),
keep = emptySet(),
environment.configuration,
true
)
ExternalDependenciesGenerator(
psi2irContext.symbolTable,
generateTypicalIrProviderList(
irModuleFragment.descriptor,
psi2irContext.irBuiltIns,
psi2irContext.symbolTable,
DescriptorByIdSignatureFinderImpl(irModuleFragment.descriptor, JsManglerDesc)
)
).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))
}
}
}
@@ -1,37 +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.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.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)
}
}
}
@@ -1,45 +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.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)
}
}
@@ -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.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,215 +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.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)
}
}
}
@@ -1,82 +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.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.util.*
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi2ir.descriptors.IrBuiltInsOverDescriptors
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
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, partialLinkageEnabled = false, 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,
additionalExportedDeclarationNames = emptySet(),
keep = 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)
}
}
@@ -1,69 +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.js
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.AbstractScriptEvaluationExtension
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptCompilerProxy
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
}
}
@@ -1,63 +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.js
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.compiler.plugin.impl.withMessageCollector
import org.jetbrains.kotlin.scripting.repl.js.JsCompiledScript
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(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
View File
@@ -99,7 +99,6 @@ val distLibraryProjects = listOfNotNull(
":kotlin-scripting-compiler",
":kotlin-scripting-compiler-impl",
":kotlin-scripting-jvm",
":kotlin-scripting-js",
":js:js.engines",
":kotlin-test:kotlin-test-junit",
":kotlin-test:kotlin-test-junit5",
-6
View File
@@ -275,15 +275,12 @@ include ":kotlin-imports-dumper-compiler-plugin",
":examples:kotlin-jsr223-daemon-local-eval-example",
":kotlin-annotations-jvm",
":kotlin-scripting-common",
':kotlin-scripting-js',
':kotlin-scripting-js-test',
":kotlin-scripting-jvm",
":kotlin-scripting-jvm-host-unshaded",
":kotlin-scripting-jvm-host-test",
":kotlin-scripting-jvm-host",
":kotlin-scripting-intellij",
":kotlin-scripting-compiler",
":kotlin-scripting-compiler-js",
":kotlin-scripting-compiler-embeddable",
":kotlin-scripting-compiler-impl",
":kotlin-scripting-compiler-impl-embeddable",
@@ -784,8 +781,6 @@ project(':examples:kotlin-jsr223-local-example').projectDir = "$rootDir/librarie
project(':examples:kotlin-jsr223-daemon-local-eval-example').projectDir = "$rootDir/libraries/examples/kotlin-jsr223-daemon-local-eval-example" as File
project(':kotlin-annotations-jvm').projectDir = "$rootDir/libraries/tools/kotlin-annotations-jvm" as File
project(':kotlin-scripting-common').projectDir = "$rootDir/libraries/scripting/common" as File
project(':kotlin-scripting-js').projectDir = "$rootDir/libraries/scripting/js" as File
project(':kotlin-scripting-js-test').projectDir = "$rootDir/libraries/scripting/js-test" as File
project(':kotlin-scripting-jvm').projectDir = "$rootDir/libraries/scripting/jvm" as File
project(':kotlin-scripting-jvm-host-unshaded').projectDir = "$rootDir/libraries/scripting/jvm-host" as File
project(':kotlin-scripting-jvm-host-test').projectDir = "$rootDir/libraries/scripting/jvm-host-test" as File
@@ -798,7 +793,6 @@ project(':kotlin-scripting-jsr223-test').projectDir = "$rootDir/libraries/script
project(':kotlin-scripting-jsr223').projectDir = "$rootDir/libraries/scripting/jsr223-embeddable" as File
project(':kotlin-scripting-intellij').projectDir = "$rootDir/libraries/scripting/intellij" as File
project(':kotlin-scripting-compiler').projectDir = "$rootDir/plugins/scripting/scripting-compiler" as File
project(':kotlin-scripting-compiler-js').projectDir = "$rootDir/plugins/scripting/scripting-compiler-js" as File
project(':kotlin-scripting-compiler-embeddable').projectDir = "$rootDir/plugins/scripting/scripting-compiler-embeddable" as File
project(':kotlin-scripting-compiler-impl').projectDir = "$rootDir/plugins/scripting/scripting-compiler-impl" as File
project(':kotlin-scripting-compiler-impl-embeddable').projectDir = "$rootDir/plugins/scripting/scripting-compiler-impl-embeddable" as File