mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 06:01:37 +03:00
Run unit tests with truffle-compiler (#8467)
This commit is contained in:
parent
b2a1cd55d2
commit
21d164ec3e
461
build.sbt
461
build.sbt
@ -12,9 +12,14 @@ import src.main.scala.licenses.{
|
|||||||
DistributionDescription,
|
DistributionDescription,
|
||||||
SBTDistributionComponent
|
SBTDistributionComponent
|
||||||
}
|
}
|
||||||
import com.sandinh.javamodule.moduleinfo.JpmsModule
|
import sbt.librarymanagement.DependencyFilter
|
||||||
|
|
||||||
|
// This import is unnecessary, but bit adds a proper code completion features
|
||||||
|
// to IntelliJ.
|
||||||
|
import JPMSPlugin.autoImport.*
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import scala.collection.mutable.ListBuffer
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// === Global Configuration ===================================================
|
// === Global Configuration ===================================================
|
||||||
@ -295,8 +300,6 @@ lazy val enso = (project in file("."))
|
|||||||
`runtime-instrument-id-execution`,
|
`runtime-instrument-id-execution`,
|
||||||
`runtime-instrument-repl-debugger`,
|
`runtime-instrument-repl-debugger`,
|
||||||
`runtime-instrument-runtime-server`,
|
`runtime-instrument-runtime-server`,
|
||||||
`runtime-with-instruments`,
|
|
||||||
`runtime-with-polyglot`,
|
|
||||||
`runtime-version-manager`,
|
`runtime-version-manager`,
|
||||||
`runtime-version-manager-test`,
|
`runtime-version-manager-test`,
|
||||||
editions,
|
editions,
|
||||||
@ -519,6 +522,8 @@ lazy val componentModulesPaths =
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lazy val compileModuleInfo = taskKey[Unit]("Compiles `module-info.java`")
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// === Internal Libraries =====================================================
|
// === Internal Libraries =====================================================
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@ -879,6 +884,7 @@ lazy val `refactoring-utils` = project
|
|||||||
.dependsOn(testkit % Test)
|
.dependsOn(testkit % Test)
|
||||||
|
|
||||||
lazy val `project-manager` = (project in file("lib/scala/project-manager"))
|
lazy val `project-manager` = (project in file("lib/scala/project-manager"))
|
||||||
|
.enablePlugins(JPMSPlugin)
|
||||||
.settings(
|
.settings(
|
||||||
(Compile / mainClass) := Some("org.enso.projectmanager.boot.ProjectManager")
|
(Compile / mainClass) := Some("org.enso.projectmanager.boot.ProjectManager")
|
||||||
)
|
)
|
||||||
@ -907,6 +913,8 @@ lazy val `project-manager` = (project in file("lib/scala/project-manager"))
|
|||||||
"org.typelevel" %% "kind-projector" % kindProjectorVersion cross CrossVersion.full
|
"org.typelevel" %% "kind-projector" % kindProjectorVersion cross CrossVersion.full
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
/** Fat jar assembly settings
|
||||||
|
*/
|
||||||
.settings(
|
.settings(
|
||||||
assembly / assemblyJarName := "project-manager.jar",
|
assembly / assemblyJarName := "project-manager.jar",
|
||||||
assembly / test := {},
|
assembly / test := {},
|
||||||
@ -934,26 +942,42 @@ lazy val `project-manager` = (project in file("lib/scala/project-manager"))
|
|||||||
case "application.conf" => MergeStrategy.concat
|
case "application.conf" => MergeStrategy.concat
|
||||||
case "reference.conf" => MergeStrategy.concat
|
case "reference.conf" => MergeStrategy.concat
|
||||||
case _ => MergeStrategy.first
|
case _ => MergeStrategy.first
|
||||||
|
}
|
||||||
|
)
|
||||||
|
/** JPMS related settings for tests
|
||||||
|
*/
|
||||||
|
.settings(
|
||||||
|
Test / fork := true,
|
||||||
|
// These dependencies are here so that we can use them in `--module-path` later on.
|
||||||
|
libraryDependencies ++= {
|
||||||
|
val necessaryModules =
|
||||||
|
GraalVM.modules.map(_.withConfigurations(Some(Test.name))) ++
|
||||||
|
GraalVM.langsPkgs.map(_.withConfigurations(Some(Test.name)))
|
||||||
|
necessaryModules
|
||||||
},
|
},
|
||||||
Test / javaOptions ++=
|
Test / addModules := Seq(
|
||||||
Seq(
|
(`runtime-fat-jar` / javaModuleName).value
|
||||||
"-Dpolyglot.engine.WarnInterpreterOnly=false",
|
),
|
||||||
"-Dpolyglotimpl.DisableClassPathIsolation=true",
|
Test / modulePath := {
|
||||||
s"-Dconfig.file=${sourceDirectory.value}/test/resources/application.conf",
|
val updateReport = (Test / update).value
|
||||||
"-Dslf4j.provider=ch.qos.logback.classic.spi.LogbackServiceProvider"
|
val requiredModIds =
|
||||||
),
|
GraalVM.modules ++ GraalVM.langsPkgs ++ logbackPkg ++ Seq(
|
||||||
// Append enso language on the class-path
|
"org.slf4j" % "slf4j-api" % slf4jVersion
|
||||||
Test / unmanagedClasspath :=
|
)
|
||||||
(LocalProject(
|
val requiredMods = JPMSUtils.filterModulesFromUpdate(
|
||||||
"runtime-with-instruments"
|
updateReport,
|
||||||
) / Compile / fullClasspath).value,
|
requiredModIds,
|
||||||
// In project-manager tests, we test installing projects and for that, we need
|
streams.value.log,
|
||||||
// to launch engine-runner properly. For that, we need all the JARs that we
|
shouldContainAll = true
|
||||||
// normally use in engine distribution. That is why there is dependency on
|
)
|
||||||
// `buildEngineDistributionNoIndex`.
|
val runtimeMod =
|
||||||
(Test / test) := (Test / test)
|
(`runtime-fat-jar` / Compile / productDirectories).value.head
|
||||||
.dependsOn(buildEngineDistributionNoIndex)
|
|
||||||
.value,
|
requiredMods ++ Seq(runtimeMod)
|
||||||
|
},
|
||||||
|
Test / javaOptions ++= testLogProviderOptions
|
||||||
|
)
|
||||||
|
.settings(
|
||||||
rebuildNativeImage := NativeImage
|
rebuildNativeImage := NativeImage
|
||||||
.buildNativeImage(
|
.buildNativeImage(
|
||||||
"project-manager",
|
"project-manager",
|
||||||
@ -1201,7 +1225,7 @@ lazy val `polyglot-api` = project
|
|||||||
// Append enso language on the class-path
|
// Append enso language on the class-path
|
||||||
Test / unmanagedClasspath :=
|
Test / unmanagedClasspath :=
|
||||||
(LocalProject(
|
(LocalProject(
|
||||||
"runtime-with-instruments"
|
"runtime-fat-jar"
|
||||||
) / Compile / fullClasspath).value,
|
) / Compile / fullClasspath).value,
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
"org.graalvm.sdk" % "polyglot-tck" % graalMavenPackagesVersion % "provided",
|
"org.graalvm.sdk" % "polyglot-tck" % graalMavenPackagesVersion % "provided",
|
||||||
@ -1220,6 +1244,7 @@ lazy val `polyglot-api` = project
|
|||||||
.dependsOn(testkit % Test)
|
.dependsOn(testkit % Test)
|
||||||
|
|
||||||
lazy val `language-server` = (project in file("engine/language-server"))
|
lazy val `language-server` = (project in file("engine/language-server"))
|
||||||
|
.enablePlugins(JPMSPlugin)
|
||||||
.settings(
|
.settings(
|
||||||
commands += WithDebugCommand.withDebug,
|
commands += WithDebugCommand.withDebug,
|
||||||
frgaalJavaCompilerSetting,
|
frgaalJavaCompilerSetting,
|
||||||
@ -1237,7 +1262,11 @@ lazy val `language-server` = (project in file("engine/language-server"))
|
|||||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
|
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
|
||||||
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test,
|
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test,
|
||||||
"org.graalvm.sdk" % "polyglot-tck" % graalMavenPackagesVersion % "provided",
|
"org.graalvm.sdk" % "polyglot-tck" % graalMavenPackagesVersion % "provided",
|
||||||
"org.eclipse.jgit" % "org.eclipse.jgit" % jgitVersion
|
"org.eclipse.jgit" % "org.eclipse.jgit" % jgitVersion,
|
||||||
|
"org.bouncycastle" % "bcutil-jdk18on" % "1.76" % Test,
|
||||||
|
"org.bouncycastle" % "bcpkix-jdk18on" % "1.76" % Test,
|
||||||
|
"org.bouncycastle" % "bcprov-jdk18on" % "1.76" % Test,
|
||||||
|
"org.apache.tika" % "tika-core" % tikaVersion % Test
|
||||||
),
|
),
|
||||||
Test / testOptions += Tests
|
Test / testOptions += Tests
|
||||||
.Argument(TestFrameworks.ScalaCheck, "-minSuccessfulTests", "1000"),
|
.Argument(TestFrameworks.ScalaCheck, "-minSuccessfulTests", "1000"),
|
||||||
@ -1256,17 +1285,93 @@ lazy val `language-server` = (project in file("engine/language-server"))
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
.settings(
|
.settings(
|
||||||
// These settings are needed by language-server tests that create a runtime context.
|
|
||||||
Test / fork := true,
|
Test / fork := true,
|
||||||
Test / javaOptions ++= testLogProviderOptions ++ Seq(
|
// These dependencies are here so that we can use them in `--module-path` later on.
|
||||||
"-Dpolyglot.engine.WarnInterpreterOnly=false",
|
libraryDependencies ++= {
|
||||||
"-Dpolyglotimpl.DisableClassPathIsolation=true"
|
val necessaryModules =
|
||||||
|
GraalVM.modules.map(_.withConfigurations(Some(Test.name))) ++
|
||||||
|
GraalVM.langsPkgs.map(_.withConfigurations(Some(Test.name)))
|
||||||
|
necessaryModules
|
||||||
|
},
|
||||||
|
Test / addModules := Seq(
|
||||||
|
(`runtime-fat-jar` / javaModuleName).value
|
||||||
),
|
),
|
||||||
// Append enso language on the class-path
|
Test / modulePath := {
|
||||||
Test / unmanagedClasspath :=
|
val updateReport = (Test / update).value
|
||||||
(LocalProject(
|
// org.bouncycastle is a module required by `org.enso.runtime` module.
|
||||||
"runtime-with-instruments"
|
val requiredModIds =
|
||||||
) / Compile / fullClasspath).value,
|
GraalVM.modules ++ GraalVM.langsPkgs ++ logbackPkg ++ Seq(
|
||||||
|
"org.slf4j" % "slf4j-api" % slf4jVersion,
|
||||||
|
"org.bouncycastle" % "bcutil-jdk18on" % "1.76",
|
||||||
|
"org.bouncycastle" % "bcpkix-jdk18on" % "1.76",
|
||||||
|
"org.bouncycastle" % "bcprov-jdk18on" % "1.76"
|
||||||
|
)
|
||||||
|
val requiredMods = JPMSUtils.filterModulesFromUpdate(
|
||||||
|
updateReport,
|
||||||
|
requiredModIds,
|
||||||
|
streams.value.log,
|
||||||
|
shouldContainAll = true
|
||||||
|
)
|
||||||
|
val runtimeMod =
|
||||||
|
(`runtime-fat-jar` / Compile / productDirectories).value.head
|
||||||
|
requiredMods ++ Seq(runtimeMod)
|
||||||
|
},
|
||||||
|
Test / javaOptions ++= testLogProviderOptions,
|
||||||
|
Test / patchModules := {
|
||||||
|
|
||||||
|
/** All these modules will be in --patch-module cmdline option to java, which means that
|
||||||
|
* for the JVM, it will appear that all the classes contained in these sbt projects are contained
|
||||||
|
* in the `org.enso.runtime` module. In this way, we do not have to assembly the `runtime.jar`
|
||||||
|
* fat jar.
|
||||||
|
*/
|
||||||
|
val modulesToPatchIntoRuntime: Seq[File] =
|
||||||
|
(LocalProject(
|
||||||
|
"runtime-instrument-common"
|
||||||
|
) / Compile / productDirectories).value ++
|
||||||
|
(LocalProject(
|
||||||
|
"runtime-instrument-id-execution"
|
||||||
|
) / Compile / productDirectories).value ++
|
||||||
|
(LocalProject(
|
||||||
|
"runtime-instrument-repl-debugger"
|
||||||
|
) / Compile / productDirectories).value ++
|
||||||
|
(LocalProject(
|
||||||
|
"runtime-instrument-runtime-server"
|
||||||
|
) / Compile / productDirectories).value ++
|
||||||
|
(LocalProject(
|
||||||
|
"runtime-language-epb"
|
||||||
|
) / Compile / productDirectories).value ++
|
||||||
|
(LocalProject(
|
||||||
|
"runtime-compiler"
|
||||||
|
) / Compile / productDirectories).value ++
|
||||||
|
(LocalProject("runtime-parser") / Compile / productDirectories).value ++
|
||||||
|
(LocalProject(
|
||||||
|
"interpreter-dsl"
|
||||||
|
) / Compile / productDirectories).value ++
|
||||||
|
// We have to patch the `runtime` project as well, as it contains BuiltinTypes.metadata in
|
||||||
|
// runtime/target/classes/META-INF directory
|
||||||
|
(LocalProject("runtime") / Compile / productDirectories).value ++
|
||||||
|
(LocalProject(
|
||||||
|
"syntax-rust-definition"
|
||||||
|
) / Compile / productDirectories).value
|
||||||
|
val extraModsToPatch = JPMSUtils.filterModulesFromUpdate(
|
||||||
|
(Test / update).value,
|
||||||
|
Seq(
|
||||||
|
"org.apache.tika" % "tika-core" % tikaVersion
|
||||||
|
),
|
||||||
|
streams.value.log,
|
||||||
|
shouldContainAll = true
|
||||||
|
)
|
||||||
|
Map(
|
||||||
|
(`runtime-fat-jar` / javaModuleName).value -> (modulesToPatchIntoRuntime ++ extraModsToPatch)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
Test / addReads := {
|
||||||
|
Map(
|
||||||
|
(`runtime-fat-jar` / javaModuleName).value -> Seq("ALL-UNNAMED")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.settings(
|
||||||
Test / compile := (Test / compile)
|
Test / compile := (Test / compile)
|
||||||
.dependsOn(LocalProject("enso") / updateLibraryManifests)
|
.dependsOn(LocalProject("enso") / updateLibraryManifests)
|
||||||
.value,
|
.value,
|
||||||
@ -1388,8 +1493,37 @@ lazy val `runtime-language-epb` =
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/** `runtime-test-instruments` project contains Truffle instruments that are used solely for testing.
|
||||||
|
* It is compiled into an explicit Java module. Note that this project cannot have compile-time dependency on `runtime`
|
||||||
|
* project, so if you need access to classes from `runtime`, you need to use reflection.
|
||||||
|
*/
|
||||||
|
lazy val `runtime-test-instruments` =
|
||||||
|
(project in file("engine/runtime-test-instruments"))
|
||||||
|
.enablePlugins(JPMSPlugin)
|
||||||
|
.settings(
|
||||||
|
inConfig(Compile)(truffleRunOptionsSettings),
|
||||||
|
truffleDslSuppressWarnsSetting,
|
||||||
|
instrumentationSettings,
|
||||||
|
javaModuleName := "org.enso.runtime.test",
|
||||||
|
modulePath := {
|
||||||
|
JPMSUtils.filterModulesFromUpdate(
|
||||||
|
update.value,
|
||||||
|
GraalVM.modules ++ Seq(
|
||||||
|
"org.netbeans.api" % "org-openide-util-lookup" % netbeansApiVersion
|
||||||
|
),
|
||||||
|
streams.value.log,
|
||||||
|
shouldContainAll = true
|
||||||
|
)
|
||||||
|
},
|
||||||
|
libraryDependencies ++= GraalVM.modules,
|
||||||
|
libraryDependencies ++= Seq(
|
||||||
|
"org.netbeans.api" % "org-openide-util-lookup" % netbeansApiVersion % "provided"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
lazy val runtime = (project in file("engine/runtime"))
|
lazy val runtime = (project in file("engine/runtime"))
|
||||||
.configs(Benchmark)
|
.configs(Benchmark)
|
||||||
|
.enablePlugins(JPMSPlugin)
|
||||||
.settings(
|
.settings(
|
||||||
frgaalJavaCompilerSetting,
|
frgaalJavaCompilerSetting,
|
||||||
truffleDslSuppressWarnsSetting,
|
truffleDslSuppressWarnsSetting,
|
||||||
@ -1426,7 +1560,8 @@ lazy val runtime = (project in file("engine/runtime"))
|
|||||||
"junit" % "junit" % junitVersion % Test,
|
"junit" % "junit" % junitVersion % Test,
|
||||||
"com.github.sbt" % "junit-interface" % junitIfVersion % Test,
|
"com.github.sbt" % "junit-interface" % junitIfVersion % Test,
|
||||||
"org.hamcrest" % "hamcrest-all" % hamcrestVersion % Test,
|
"org.hamcrest" % "hamcrest-all" % hamcrestVersion % Test,
|
||||||
"org.slf4j" % "slf4j-nop" % slf4jVersion % Benchmark
|
"org.slf4j" % "slf4j-nop" % slf4jVersion % Benchmark,
|
||||||
|
"org.slf4j" % "slf4j-api" % slf4jVersion % Test
|
||||||
),
|
),
|
||||||
// Add all GraalVM packages with Runtime scope - we don't need them for compilation,
|
// Add all GraalVM packages with Runtime scope - we don't need them for compilation,
|
||||||
// just provide them at runtime (in module-path).
|
// just provide them at runtime (in module-path).
|
||||||
@ -1438,10 +1573,87 @@ lazy val runtime = (project in file("engine/runtime"))
|
|||||||
val tools =
|
val tools =
|
||||||
GraalVM.toolsPkgs.map(_.withConfigurations(Some(Runtime.name)))
|
GraalVM.toolsPkgs.map(_.withConfigurations(Some(Runtime.name)))
|
||||||
necessaryModules ++ langs ++ tools
|
necessaryModules ++ langs ++ tools
|
||||||
},
|
}
|
||||||
Test / javaOptions ++= testLogProviderOptions ++ Seq(
|
)
|
||||||
"-Dpolyglotimpl.DisableClassPathIsolation=true"
|
.settings(
|
||||||
|
Test / unmanagedClasspath := (LocalProject(
|
||||||
|
"runtime-fat-jar"
|
||||||
|
) / Compile / exportedProducts).value,
|
||||||
|
Test / addModules := Seq(
|
||||||
|
(`runtime-test-instruments` / javaModuleName).value,
|
||||||
|
(`runtime-fat-jar` / javaModuleName).value
|
||||||
),
|
),
|
||||||
|
Test / modulePath := {
|
||||||
|
val updateReport = (Test / update).value
|
||||||
|
val requiredModIds =
|
||||||
|
GraalVM.modules ++ GraalVM.langsPkgs ++ GraalVM.insightPkgs ++ logbackPkg ++ Seq(
|
||||||
|
"org.slf4j" % "slf4j-api" % slf4jVersion,
|
||||||
|
"org.netbeans.api" % "org-openide-util-lookup" % netbeansApiVersion
|
||||||
|
)
|
||||||
|
val requiredMods = JPMSUtils.filterModulesFromUpdate(
|
||||||
|
updateReport,
|
||||||
|
requiredModIds,
|
||||||
|
streams.value.log,
|
||||||
|
shouldContainAll = true
|
||||||
|
)
|
||||||
|
val runtimeTestInstrumentsMod =
|
||||||
|
(`runtime-test-instruments` / Compile / exportedProducts).value.head.data
|
||||||
|
val runtimeMod =
|
||||||
|
(`runtime-fat-jar` / Compile / exportedProducts).value.head.data
|
||||||
|
requiredMods ++
|
||||||
|
Seq(runtimeTestInstrumentsMod) ++
|
||||||
|
Seq(runtimeMod)
|
||||||
|
},
|
||||||
|
Test / patchModules := {
|
||||||
|
|
||||||
|
/** All these modules will be in --patch-module cmdline option to java, which means that
|
||||||
|
* for the JVM, it will appear that all the classes contained in these sbt projects are contained
|
||||||
|
* in the `org.enso.runtime` module. In this way, we do not have to assembly the `runtime.jar`
|
||||||
|
* fat jar.
|
||||||
|
*/
|
||||||
|
val modulesToPatchIntoRuntime: Seq[File] =
|
||||||
|
(LocalProject(
|
||||||
|
"runtime-instrument-common"
|
||||||
|
) / Compile / productDirectories).value ++
|
||||||
|
(LocalProject(
|
||||||
|
"runtime-instrument-id-execution"
|
||||||
|
) / Compile / productDirectories).value ++
|
||||||
|
(LocalProject(
|
||||||
|
"runtime-instrument-repl-debugger"
|
||||||
|
) / Compile / productDirectories).value ++
|
||||||
|
(LocalProject(
|
||||||
|
"runtime-instrument-runtime-server"
|
||||||
|
) / Compile / productDirectories).value ++
|
||||||
|
(LocalProject(
|
||||||
|
"runtime-language-epb"
|
||||||
|
) / Compile / productDirectories).value ++
|
||||||
|
(LocalProject(
|
||||||
|
"runtime-compiler"
|
||||||
|
) / Compile / productDirectories).value ++
|
||||||
|
(LocalProject("refactoring-utils") / Compile / productDirectories).value
|
||||||
|
// Patch test-classes into the runtime module. This is standard way to deal with the
|
||||||
|
// split package problem in unit tests. For example, Maven's surefire plugin does this.
|
||||||
|
val testClassesDir = (Test / productDirectories).value.head
|
||||||
|
Map(
|
||||||
|
(`runtime-fat-jar` / javaModuleName).value -> (modulesToPatchIntoRuntime ++ Seq(
|
||||||
|
testClassesDir
|
||||||
|
))
|
||||||
|
)
|
||||||
|
},
|
||||||
|
Test / addReads := {
|
||||||
|
val runtimeModName = (`runtime-fat-jar` / javaModuleName).value
|
||||||
|
val testInstrumentsModName =
|
||||||
|
(`runtime-test-instruments` / javaModuleName).value
|
||||||
|
Map(
|
||||||
|
// We patched the test-classes into the runtime module. These classes access some stuff from
|
||||||
|
// unnamed module. Thus, let's add ALL-UNNAMED.
|
||||||
|
runtimeModName -> Seq("ALL-UNNAMED", testInstrumentsModName),
|
||||||
|
testInstrumentsModName -> Seq(runtimeModName)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
Test / javaOptions ++= testLogProviderOptions
|
||||||
|
)
|
||||||
|
.settings(
|
||||||
Test / fork := true,
|
Test / fork := true,
|
||||||
Test / envVars ++= distributionEnvironmentOverrides ++ Map(
|
Test / envVars ++= distributionEnvironmentOverrides ++ Map(
|
||||||
"ENSO_TEST_DISABLE_IR_CACHE" -> "false"
|
"ENSO_TEST_DISABLE_IR_CACHE" -> "false"
|
||||||
@ -1479,7 +1691,7 @@ lazy val runtime = (project in file("engine/runtime"))
|
|||||||
// runtime.jar fat jar needs to be assembled as it is used in the
|
// runtime.jar fat jar needs to be assembled as it is used in the
|
||||||
// benchmarks. This dependency is here so that `runtime/bench` works
|
// benchmarks. This dependency is here so that `runtime/bench` works
|
||||||
// after clean build.
|
// after clean build.
|
||||||
LocalProject("runtime-with-instruments") / assembly
|
LocalProject("runtime-fat-jar") / assembly
|
||||||
)
|
)
|
||||||
.value,
|
.value,
|
||||||
benchOnly := Def.inputTaskDyn {
|
benchOnly := Def.inputTaskDyn {
|
||||||
@ -1519,6 +1731,7 @@ lazy val runtime = (project in file("engine/runtime"))
|
|||||||
.dependsOn(`connected-lock-manager`)
|
.dependsOn(`connected-lock-manager`)
|
||||||
.dependsOn(testkit % Test)
|
.dependsOn(testkit % Test)
|
||||||
.dependsOn(`logging-service-logback` % "test->test")
|
.dependsOn(`logging-service-logback` % "test->test")
|
||||||
|
.dependsOn(`runtime-test-instruments` % "test->compile")
|
||||||
|
|
||||||
lazy val `runtime-parser` =
|
lazy val `runtime-parser` =
|
||||||
(project in file("engine/runtime-parser"))
|
(project in file("engine/runtime-parser"))
|
||||||
@ -1583,7 +1796,9 @@ lazy val `runtime-instrument-common` =
|
|||||||
)
|
)
|
||||||
.dependsOn(`refactoring-utils`)
|
.dependsOn(`refactoring-utils`)
|
||||||
.dependsOn(
|
.dependsOn(
|
||||||
runtime % "compile->compile;test->test;runtime->runtime;bench->bench"
|
LocalProject(
|
||||||
|
"runtime"
|
||||||
|
) % "compile->compile;test->test;runtime->runtime;bench->bench"
|
||||||
)
|
)
|
||||||
|
|
||||||
lazy val `runtime-instrument-id-execution` =
|
lazy val `runtime-instrument-id-execution` =
|
||||||
@ -1593,7 +1808,7 @@ lazy val `runtime-instrument-id-execution` =
|
|||||||
inConfig(Compile)(truffleRunOptionsSettings),
|
inConfig(Compile)(truffleRunOptionsSettings),
|
||||||
instrumentationSettings
|
instrumentationSettings
|
||||||
)
|
)
|
||||||
.dependsOn(runtime)
|
.dependsOn(LocalProject("runtime"))
|
||||||
.dependsOn(`runtime-instrument-common`)
|
.dependsOn(`runtime-instrument-common`)
|
||||||
|
|
||||||
lazy val `runtime-instrument-repl-debugger` =
|
lazy val `runtime-instrument-repl-debugger` =
|
||||||
@ -1602,7 +1817,7 @@ lazy val `runtime-instrument-repl-debugger` =
|
|||||||
inConfig(Compile)(truffleRunOptionsSettings),
|
inConfig(Compile)(truffleRunOptionsSettings),
|
||||||
instrumentationSettings
|
instrumentationSettings
|
||||||
)
|
)
|
||||||
.dependsOn(runtime)
|
.dependsOn(LocalProject("runtime"))
|
||||||
.dependsOn(`runtime-instrument-common`)
|
.dependsOn(`runtime-instrument-common`)
|
||||||
|
|
||||||
lazy val `runtime-instrument-runtime-server` =
|
lazy val `runtime-instrument-runtime-server` =
|
||||||
@ -1611,65 +1826,64 @@ lazy val `runtime-instrument-runtime-server` =
|
|||||||
inConfig(Compile)(truffleRunOptionsSettings),
|
inConfig(Compile)(truffleRunOptionsSettings),
|
||||||
instrumentationSettings
|
instrumentationSettings
|
||||||
)
|
)
|
||||||
.dependsOn(runtime)
|
.dependsOn(LocalProject("runtime"))
|
||||||
.dependsOn(`runtime-instrument-common`)
|
.dependsOn(`runtime-instrument-common`)
|
||||||
|
|
||||||
lazy val `runtime-with-instruments` =
|
/** A "meta" project that exists solely to provide logic for assembling the `runtime.jar` fat Jar.
|
||||||
(project in file("engine/runtime-with-instruments"))
|
* We do not want to put this task into any other existing project, as it internally copies some
|
||||||
.configs(Benchmark)
|
* classes from other projects into the `classes` directory, therefore, pollutes the build.
|
||||||
|
* There is only one Java source in this project - `module-info.java`. During the assembling of the
|
||||||
|
* fat jar, all the classes from the dependent projects are copied into the `classes` directory of
|
||||||
|
* this project and then, a custom task is invoked to compile the `module-info.java`.
|
||||||
|
*/
|
||||||
|
lazy val `runtime-fat-jar` =
|
||||||
|
(project in file("engine/runtime-fat-jar"))
|
||||||
|
.enablePlugins(JPMSPlugin)
|
||||||
.settings(
|
.settings(
|
||||||
frgaalJavaCompilerSetting,
|
Compile / compileModuleInfo := {
|
||||||
inConfig(Compile)(truffleRunOptionsSettings),
|
JPMSUtils.compileModuleInfo(
|
||||||
commands += WithDebugCommand.withDebug,
|
copyDepsFilter = ScopeFilter(
|
||||||
Test / javaOptions ++= testLogProviderOptions ++ Seq(
|
inProjects(
|
||||||
"-Dpolyglotimpl.DisableClassPathIsolation=true"
|
LocalProject("runtime"),
|
||||||
),
|
LocalProject("runtime-language-epb"),
|
||||||
Test / fork := true,
|
LocalProject("runtime-instrument-common"),
|
||||||
Test / envVars ++= distributionEnvironmentOverrides ++ Map(
|
LocalProject("runtime-instrument-id-execution"),
|
||||||
"ENSO_TEST_DISABLE_IR_CACHE" -> "false"
|
LocalProject("runtime-instrument-repl-debugger"),
|
||||||
),
|
LocalProject("runtime-instrument-runtime-server")
|
||||||
libraryDependencies ++= Seq(
|
),
|
||||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
|
inConfigurations(Compile)
|
||||||
"org.graalvm.truffle" % "truffle-api" % graalMavenPackagesVersion % Test,
|
),
|
||||||
"org.graalvm.truffle" % "truffle-dsl-processor" % graalMavenPackagesVersion % Test,
|
modulePath = JPMSUtils.componentModules
|
||||||
"org.slf4j" % "slf4j-nop" % slf4jVersion % Benchmark
|
)
|
||||||
),
|
}
|
||||||
// Add all GraalVM packages with Runtime scope - we don't need them for compilation,
|
.dependsOn(Compile / compile)
|
||||||
// just provide them at runtime (in module-path).
|
.value,
|
||||||
libraryDependencies ++= {
|
|
||||||
val necessaryModules =
|
|
||||||
GraalVM.modules.map(_.withConfigurations(Some(Runtime.name)))
|
|
||||||
val langs =
|
|
||||||
GraalVM.langsPkgs.map(_.withConfigurations(Some(Runtime.name)))
|
|
||||||
necessaryModules ++ langs
|
|
||||||
},
|
|
||||||
// Note [Unmanaged Classpath]
|
|
||||||
Test / unmanagedClasspath += (baseDirectory.value / ".." / ".." / "app" / "gui" / "view" / "graph-editor" / "src" / "builtin" / "visualization" / "native" / "inc"),
|
|
||||||
// Filter module-info.java from the compilation
|
// Filter module-info.java from the compilation
|
||||||
excludeFilter := excludeFilter.value || "module-info.java",
|
excludeFilter := excludeFilter.value || "module-info.java",
|
||||||
moduleInfos := Seq(
|
javaModuleName := "org.enso.runtime",
|
||||||
JpmsModule("org.enso.runtime")
|
compileOrder := CompileOrder.JavaThenScala
|
||||||
)
|
)
|
||||||
|
/** The following libraryDependencies are provided in Runtime scope.
|
||||||
|
* Later, we will collect them into --module-path option.
|
||||||
|
* We don't collect them in Compile scope as it does not even make sense
|
||||||
|
* to run `compile` task in this project.
|
||||||
|
*/
|
||||||
|
.settings(
|
||||||
|
libraryDependencies ++= {
|
||||||
|
val graalMods =
|
||||||
|
GraalVM.modules.map(_.withConfigurations(Some(Runtime.name)))
|
||||||
|
val langMods =
|
||||||
|
GraalVM.langsPkgs.map(_.withConfigurations(Some(Runtime.name)))
|
||||||
|
val logbackMods =
|
||||||
|
logbackPkg.map(_.withConfigurations(Some(Runtime.name)))
|
||||||
|
graalMods ++ langMods ++ logbackMods
|
||||||
|
}
|
||||||
)
|
)
|
||||||
/** Assembling Uber Jar */
|
/** Assembling Uber Jar */
|
||||||
.settings(
|
.settings(
|
||||||
assembly := assembly
|
assembly := assembly
|
||||||
.dependsOn(
|
.dependsOn(Compile / compile)
|
||||||
JPMSUtils.compileModuleInfo(
|
.dependsOn(Compile / compileModuleInfo)
|
||||||
copyDepsFilter = ScopeFilter(
|
|
||||||
inProjects(
|
|
||||||
LocalProject("runtime"),
|
|
||||||
LocalProject("runtime-language-epb"),
|
|
||||||
LocalProject("runtime-instrument-common"),
|
|
||||||
LocalProject("runtime-instrument-id-execution"),
|
|
||||||
LocalProject("runtime-instrument-repl-debugger"),
|
|
||||||
LocalProject("runtime-instrument-runtime-server")
|
|
||||||
),
|
|
||||||
inConfigurations(Compile)
|
|
||||||
),
|
|
||||||
modulePath = JPMSUtils.componentModules
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.value,
|
.value,
|
||||||
assembly / assemblyJarName := "runtime.jar",
|
assembly / assemblyJarName := "runtime.jar",
|
||||||
assembly / test := {},
|
assembly / test := {},
|
||||||
@ -1704,61 +1918,12 @@ lazy val `runtime-with-instruments` =
|
|||||||
case _ => MergeStrategy.first
|
case _ => MergeStrategy.first
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
/** Benchmark settings */
|
|
||||||
.settings(
|
|
||||||
inConfig(Benchmark)(Defaults.testSettings),
|
|
||||||
Benchmark / javacOptions --= Seq(
|
|
||||||
"-source",
|
|
||||||
frgaalSourceLevel,
|
|
||||||
"--enable-preview"
|
|
||||||
),
|
|
||||||
(Benchmark / javaOptions) :=
|
|
||||||
(LocalProject("std-benchmarks") / Benchmark / run / javaOptions).value
|
|
||||||
)
|
|
||||||
.dependsOn(runtime % "compile->compile;test->test;runtime->runtime")
|
|
||||||
.dependsOn(`runtime-instrument-common`)
|
.dependsOn(`runtime-instrument-common`)
|
||||||
.dependsOn(`runtime-instrument-id-execution`)
|
.dependsOn(`runtime-instrument-id-execution`)
|
||||||
.dependsOn(`runtime-instrument-repl-debugger`)
|
.dependsOn(`runtime-instrument-repl-debugger`)
|
||||||
.dependsOn(`runtime-instrument-runtime-server`)
|
.dependsOn(`runtime-instrument-runtime-server`)
|
||||||
.dependsOn(`runtime-language-epb`)
|
.dependsOn(`runtime-language-epb`)
|
||||||
.dependsOn(`logging-service-logback` % "test->test")
|
.dependsOn(LocalProject("runtime"))
|
||||||
|
|
||||||
/* runtime-with-polyglot
|
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
* Unlike `runtime`, this project includes the truffle language JARs on the
|
|
||||||
* class-path.
|
|
||||||
*/
|
|
||||||
|
|
||||||
lazy val `runtime-with-polyglot` =
|
|
||||||
(project in file("engine/runtime-with-polyglot"))
|
|
||||||
.configs(Benchmark)
|
|
||||||
.settings(
|
|
||||||
frgaalJavaCompilerSetting,
|
|
||||||
inConfig(Compile)(truffleRunOptionsSettings),
|
|
||||||
inConfig(Benchmark)(Defaults.testSettings),
|
|
||||||
commands += WithDebugCommand.withDebug,
|
|
||||||
Benchmark / javacOptions --= Seq(
|
|
||||||
"-source",
|
|
||||||
frgaalSourceLevel,
|
|
||||||
"--enable-preview"
|
|
||||||
),
|
|
||||||
Test / javaOptions ++= testLogProviderOptions ++ Seq(
|
|
||||||
"-Dpolyglotimpl.DisableClassPathIsolation=true"
|
|
||||||
),
|
|
||||||
Test / fork := true,
|
|
||||||
Test / envVars ++= distributionEnvironmentOverrides ++ Map(
|
|
||||||
"ENSO_TEST_DISABLE_IR_CACHE" -> "false"
|
|
||||||
),
|
|
||||||
libraryDependencies ++= GraalVM.langsPkgs ++ Seq(
|
|
||||||
"org.graalvm.polyglot" % "polyglot" % graalMavenPackagesVersion % "provided",
|
|
||||||
"org.graalvm.tools" % "insight-tool" % graalMavenPackagesVersion % "provided",
|
|
||||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test
|
|
||||||
),
|
|
||||||
(Benchmark / javaOptions) :=
|
|
||||||
(LocalProject("std-benchmarks") / Benchmark / run / javaOptions).value
|
|
||||||
)
|
|
||||||
.dependsOn(runtime % "compile->compile;test->test;runtime->runtime")
|
|
||||||
.dependsOn(`runtime-with-instruments`)
|
|
||||||
|
|
||||||
/* Note [Unmanaged Classpath]
|
/* Note [Unmanaged Classpath]
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -1833,7 +1998,7 @@ lazy val `engine-runner` = project
|
|||||||
)
|
)
|
||||||
.settings(
|
.settings(
|
||||||
assembly := assembly
|
assembly := assembly
|
||||||
.dependsOn(`runtime-with-instruments` / assembly)
|
.dependsOn(`runtime-fat-jar` / assembly)
|
||||||
.value,
|
.value,
|
||||||
rebuildNativeImage :=
|
rebuildNativeImage :=
|
||||||
NativeImage
|
NativeImage
|
||||||
@ -2016,7 +2181,7 @@ lazy val `bench-processor` = (project in file("lib/scala/bench-processor"))
|
|||||||
),
|
),
|
||||||
// Append enso language on the class-path
|
// Append enso language on the class-path
|
||||||
(Test / unmanagedClasspath) :=
|
(Test / unmanagedClasspath) :=
|
||||||
(LocalProject("runtime-with-instruments") / Compile / fullClasspath).value
|
(LocalProject("runtime-fat-jar") / Compile / fullClasspath).value
|
||||||
)
|
)
|
||||||
.dependsOn(`polyglot-api`)
|
.dependsOn(`polyglot-api`)
|
||||||
.dependsOn(runtime)
|
.dependsOn(runtime)
|
||||||
@ -2055,11 +2220,11 @@ lazy val `std-benchmarks` = (project in file("std-bits/benchmarks"))
|
|||||||
(Benchmark / parallelExecution) := false,
|
(Benchmark / parallelExecution) := false,
|
||||||
(Benchmark / run / fork) := true,
|
(Benchmark / run / fork) := true,
|
||||||
(Benchmark / run / connectInput) := true,
|
(Benchmark / run / connectInput) := true,
|
||||||
// This ensures that the full class-path of runtime-with-instruments is put on
|
// This ensures that the full class-path of runtime-fat-jar is put on
|
||||||
// class-path of the Java compiler (and thus the benchmark annotation processor).
|
// class-path of the Java compiler (and thus the benchmark annotation processor).
|
||||||
(Benchmark / compile / unmanagedClasspath) ++=
|
(Benchmark / compile / unmanagedClasspath) ++=
|
||||||
(LocalProject(
|
(LocalProject(
|
||||||
"runtime-with-instruments"
|
"runtime-fat-jar"
|
||||||
) / Compile / fullClasspath).value,
|
) / Compile / fullClasspath).value,
|
||||||
(Benchmark / compile / javacOptions) ++= Seq(
|
(Benchmark / compile / javacOptions) ++= Seq(
|
||||||
"-s",
|
"-s",
|
||||||
@ -2083,13 +2248,13 @@ lazy val `std-benchmarks` = (project in file("std-bits/benchmarks"))
|
|||||||
.map(_.data.getAbsolutePath)
|
.map(_.data.getAbsolutePath)
|
||||||
val runtimeJar =
|
val runtimeJar =
|
||||||
(LocalProject(
|
(LocalProject(
|
||||||
"runtime-with-instruments"
|
"runtime-fat-jar"
|
||||||
) / assembly / assemblyOutputPath).value.getAbsolutePath
|
) / assembly / assemblyOutputPath).value.getAbsolutePath
|
||||||
val allModulePaths = requiredModulesPaths ++ Seq(runtimeJar)
|
val allModulePaths = requiredModulesPaths ++ Seq(runtimeJar)
|
||||||
val runtimeModuleName =
|
val runtimeModuleName =
|
||||||
(LocalProject(
|
(LocalProject(
|
||||||
"runtime-with-instruments"
|
"runtime-fat-jar"
|
||||||
) / moduleInfos).value.head.moduleName
|
) / javaModuleName).value
|
||||||
Seq(
|
Seq(
|
||||||
// To enable logging in benchmarks, add ch.qos.logback module on the modulePath
|
// To enable logging in benchmarks, add ch.qos.logback module on the modulePath
|
||||||
"-Dslf4j.provider=org.slf4j.nop.NOPServiceProvider",
|
"-Dslf4j.provider=org.slf4j.nop.NOPServiceProvider",
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
module org.enso.runtime.test {
|
||||||
|
requires org.graalvm.truffle;
|
||||||
|
requires org.openide.util.lookup.RELEASE180;
|
||||||
|
|
||||||
|
exports org.enso.interpreter.test.instruments;
|
||||||
|
exports org.enso.interpreter.test.instruments.service;
|
||||||
|
|
||||||
|
provides com.oracle.truffle.api.instrumentation.provider.TruffleInstrumentProvider with
|
||||||
|
org.enso.interpreter.test.instruments.CodeIdsTestInstrumentProvider,
|
||||||
|
org.enso.interpreter.test.instruments.CodeLocationsTestInstrumentProvider,
|
||||||
|
org.enso.interpreter.test.instruments.NodeCountingTestInstrumentProvider;
|
||||||
|
}
|
@ -1,13 +1,14 @@
|
|||||||
package org.enso.interpreter.test;
|
package org.enso.interpreter.test.instruments;
|
||||||
|
|
||||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
import com.oracle.truffle.api.instrumentation.*;
|
import com.oracle.truffle.api.instrumentation.*;
|
||||||
import com.oracle.truffle.api.nodes.Node;
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import org.enso.interpreter.node.ExpressionNode;
|
import org.enso.interpreter.test.instruments.service.RuntimeTestService;
|
||||||
import org.enso.interpreter.runtime.control.TailCallException;
|
import org.openide.util.Lookup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A debug instrument used to test code locations.
|
* A debug instrument used to test code locations.
|
||||||
@ -20,8 +21,13 @@ import org.enso.interpreter.runtime.control.TailCallException;
|
|||||||
services = CodeIdsTestInstrument.class)
|
services = CodeIdsTestInstrument.class)
|
||||||
public class CodeIdsTestInstrument extends TruffleInstrument {
|
public class CodeIdsTestInstrument extends TruffleInstrument {
|
||||||
public static final String INSTRUMENT_ID = "ids-test";
|
public static final String INSTRUMENT_ID = "ids-test";
|
||||||
|
private static final RuntimeTestService runtimeTestService;
|
||||||
private Env env;
|
private Env env;
|
||||||
|
|
||||||
|
static {
|
||||||
|
runtimeTestService = Lookup.getDefault().lookup(RuntimeTestService.class);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the instrument. Substitute for a constructor, called by the Truffle framework.
|
* Initializes the instrument. Substitute for a constructor, called by the Truffle framework.
|
||||||
*
|
*
|
||||||
@ -94,7 +100,6 @@ public class CodeIdsTestInstrument extends TruffleInstrument {
|
|||||||
/**
|
/**
|
||||||
* Checks if the node to be executed is the node this listener was created to observe.
|
* Checks if the node to be executed is the node this listener was created to observe.
|
||||||
*
|
*
|
||||||
* @param context current execution context
|
|
||||||
* @param frame current execution frame
|
* @param frame current execution frame
|
||||||
* @param result the result of executing the node
|
* @param result the result of executing the node
|
||||||
*/
|
*/
|
||||||
@ -104,11 +109,11 @@ public class CodeIdsTestInstrument extends TruffleInstrument {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Node node = context.getInstrumentedNode();
|
Node node = context.getInstrumentedNode();
|
||||||
if (!(node instanceof ExpressionNode)) {
|
if (!runtimeTestService.isExpressionNode(node)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nodes.put(this, result);
|
nodes.put(this, result);
|
||||||
UUID id = ((ExpressionNode) node).getId();
|
UUID id = runtimeTestService.getNodeID(node);
|
||||||
if (id == null || !id.equals(expectedId)) {
|
if (id == null || !id.equals(expectedId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -120,19 +125,18 @@ public class CodeIdsTestInstrument extends TruffleInstrument {
|
|||||||
/**
|
/**
|
||||||
* Checks if the specified was called, if its execution triggered TCO.
|
* Checks if the specified was called, if its execution triggered TCO.
|
||||||
*
|
*
|
||||||
* @param context current execution context.
|
|
||||||
* @param frame current execution frame.
|
* @param frame current execution frame.
|
||||||
* @param exception the exception thrown from this node's execution.
|
* @param exception the exception thrown from this node's execution.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onReturnExceptional(VirtualFrame frame, Throwable exception) {
|
public void onReturnExceptional(VirtualFrame frame, Throwable exception) {
|
||||||
if (!(exception instanceof TailCallException)) {
|
if (!runtimeTestService.isTailCallException(exception)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!(context.getInstrumentedNode() instanceof ExpressionNode)) {
|
if (!runtimeTestService.isExpressionNode(context.getInstrumentedNode())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UUID id = ((ExpressionNode) context.getInstrumentedNode()).getId();
|
UUID id = runtimeTestService.getNodeID(context.getInstrumentedNode());
|
||||||
if (expectedResult == null) {
|
if (expectedResult == null) {
|
||||||
successful = true;
|
successful = true;
|
||||||
}
|
}
|
||||||
@ -142,8 +146,9 @@ public class CodeIdsTestInstrument extends TruffleInstrument {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.append(context.getInstrumentedNode().getClass().getSimpleName());
|
sb.append(context.getInstrumentedNode().getClass().getSimpleName());
|
||||||
if (context.getInstrumentedNode() instanceof ExpressionNode expr) {
|
if (runtimeTestService.isExpressionNode(context.getInstrumentedNode())) {
|
||||||
sb.append("@").append(expr.getId());
|
UUID id = runtimeTestService.getNodeID(context.getInstrumentedNode());
|
||||||
|
sb.append("@").append(id);
|
||||||
}
|
}
|
||||||
sb.append(" ");
|
sb.append(" ");
|
||||||
sb.append(context.getInstrumentedSourceSection());
|
sb.append(context.getInstrumentedSourceSection());
|
@ -1,4 +1,4 @@
|
|||||||
package org.enso.interpreter.test;
|
package org.enso.interpreter.test.instruments;
|
||||||
|
|
||||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
import com.oracle.truffle.api.instrumentation.EventBinding;
|
import com.oracle.truffle.api.instrumentation.EventBinding;
|
@ -1,6 +1,4 @@
|
|||||||
package org.enso.interpreter.test;
|
package org.enso.interpreter.test.instruments;
|
||||||
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
import com.oracle.truffle.api.instrumentation.EventContext;
|
import com.oracle.truffle.api.instrumentation.EventContext;
|
||||||
@ -9,18 +7,17 @@ import com.oracle.truffle.api.instrumentation.ExecutionEventNodeFactory;
|
|||||||
import com.oracle.truffle.api.instrumentation.SourceSectionFilter;
|
import com.oracle.truffle.api.instrumentation.SourceSectionFilter;
|
||||||
import com.oracle.truffle.api.instrumentation.TruffleInstrument;
|
import com.oracle.truffle.api.instrumentation.TruffleInstrument;
|
||||||
import com.oracle.truffle.api.nodes.Node;
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
import com.oracle.truffle.api.nodes.RootNode;
|
|
||||||
import com.oracle.truffle.api.source.SourceSection;
|
import com.oracle.truffle.api.source.SourceSection;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import org.enso.interpreter.node.MethodRootNode;
|
import org.enso.interpreter.test.instruments.service.FunctionCallInfo;
|
||||||
import org.enso.interpreter.node.callable.FunctionCallInstrumentationNode;
|
import org.enso.interpreter.test.instruments.service.RuntimeTestService;
|
||||||
import org.enso.pkg.QualifiedName;
|
import org.openide.util.Lookup;
|
||||||
|
|
||||||
/** Testing instrument to control newly created nodes. */
|
/** Testing instrument to control newly created nodes. */
|
||||||
@TruffleInstrument.Registration(
|
@TruffleInstrument.Registration(
|
||||||
@ -28,12 +25,17 @@ import org.enso.pkg.QualifiedName;
|
|||||||
services = NodeCountingTestInstrument.class)
|
services = NodeCountingTestInstrument.class)
|
||||||
public class NodeCountingTestInstrument extends TruffleInstrument {
|
public class NodeCountingTestInstrument extends TruffleInstrument {
|
||||||
public static final String INSTRUMENT_ID = "node-count-test";
|
public static final String INSTRUMENT_ID = "node-count-test";
|
||||||
|
private static final RuntimeTestService runtimeTestService;
|
||||||
private final Map<Node, Node> all = new ConcurrentHashMap<>();
|
private final Map<Node, Node> all = new ConcurrentHashMap<>();
|
||||||
private Map<Class, List<Node>> counter = new ConcurrentHashMap<>();
|
private Map<Class, List<Node>> counter = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final Map<UUID, FunctionCallInfo> calls = new ConcurrentHashMap<>();
|
private final Map<UUID, FunctionCallInfo> calls = new ConcurrentHashMap<>();
|
||||||
private Env env;
|
private Env env;
|
||||||
|
|
||||||
|
static {
|
||||||
|
runtimeTestService = Lookup.getDefault().lookup(RuntimeTestService.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Env env) {
|
protected void onCreate(Env env) {
|
||||||
env.registerService(this);
|
env.registerService(this);
|
||||||
@ -75,10 +77,10 @@ public class NodeCountingTestInstrument extends TruffleInstrument {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (value < min) {
|
if (value < min) {
|
||||||
fail(dump.apply(msg + ". Minimal size should be " + min + ", but was: " + value + " in"));
|
throw new AssertionError(dump.apply(msg + ". Minimal size should be " + min + ", but was: " + value + " in"));
|
||||||
}
|
}
|
||||||
if (value > max) {
|
if (value > max) {
|
||||||
fail(dump.apply(msg + ". Maximal size should be " + max + ", but was: " + value + " in"));
|
throw new AssertionError(dump.apply(msg + ". Maximal size should be " + max + ", but was: " + value + " in"));
|
||||||
}
|
}
|
||||||
counter = new ConcurrentHashMap<>();
|
counter = new ConcurrentHashMap<>();
|
||||||
return prev;
|
return prev;
|
||||||
@ -120,73 +122,16 @@ public class NodeCountingTestInstrument extends TruffleInstrument {
|
|||||||
|
|
||||||
public void onReturnValue(VirtualFrame frame, Object result) {
|
public void onReturnValue(VirtualFrame frame, Object result) {
|
||||||
Node node = context.getInstrumentedNode();
|
Node node = context.getInstrumentedNode();
|
||||||
if (node instanceof FunctionCallInstrumentationNode instrumentableNode
|
|
||||||
&& result instanceof FunctionCallInstrumentationNode.FunctionCall functionCall) {
|
if (runtimeTestService.isFunctionCallInstrumentationNode(node)
|
||||||
onFunctionReturn(instrumentableNode, functionCall);
|
&& runtimeTestService.isFunctionCall(result)) {
|
||||||
|
UUID nodeId = runtimeTestService.getNodeID(node);
|
||||||
|
if (nodeId != null) {
|
||||||
|
var funcCallInfo = runtimeTestService.extractFunctionCallInfo(result);
|
||||||
|
calls.put(nodeId, funcCallInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void onFunctionReturn(
|
|
||||||
FunctionCallInstrumentationNode node, FunctionCallInstrumentationNode.FunctionCall result) {
|
|
||||||
if (node.getId() != null) {
|
|
||||||
calls.put(node.getId(), new FunctionCallInfo(result));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class FunctionCallInfo {
|
|
||||||
|
|
||||||
private final QualifiedName moduleName;
|
|
||||||
private final QualifiedName typeName;
|
|
||||||
private final String functionName;
|
|
||||||
|
|
||||||
public FunctionCallInfo(FunctionCallInstrumentationNode.FunctionCall call) {
|
|
||||||
RootNode rootNode = call.getFunction().getCallTarget().getRootNode();
|
|
||||||
if (rootNode instanceof MethodRootNode methodNode) {
|
|
||||||
moduleName = methodNode.getModuleScope().getModule().getName();
|
|
||||||
typeName = methodNode.getType().getQualifiedName();
|
|
||||||
functionName = methodNode.getMethodName();
|
|
||||||
} else {
|
|
||||||
moduleName = null;
|
|
||||||
typeName = null;
|
|
||||||
functionName = rootNode.getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
FunctionCallInfo that = (FunctionCallInfo) o;
|
|
||||||
return Objects.equals(moduleName, that.moduleName)
|
|
||||||
&& Objects.equals(typeName, that.typeName)
|
|
||||||
&& Objects.equals(functionName, that.functionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(moduleName, typeName, functionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return moduleName + "::" + typeName + "::" + functionName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public QualifiedName getModuleName() {
|
|
||||||
return moduleName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public QualifiedName getTypeName() {
|
|
||||||
return typeName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFunctionName() {
|
|
||||||
return functionName;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package org.enso.interpreter.test.instruments.service;
|
||||||
|
|
||||||
|
public record FunctionCallInfo(
|
||||||
|
String moduleName,
|
||||||
|
String typeName,
|
||||||
|
String functionName
|
||||||
|
) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return moduleName + "::" + typeName + "::" + functionName;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package org.enso.interpreter.test.instruments.service;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import com.oracle.truffle.api.nodes.RootNode;
|
||||||
|
import java.util.UUID;
|
||||||
|
import org.enso.interpreter.test.instruments.service.FunctionCallInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A service that provides information from the `runtime` project to the instruments in this project
|
||||||
|
* (`runtime-test-instruments`). Note that this project cannot have a compile time dependency on
|
||||||
|
* `runtime`, thus, we need to use a service provider mechanism.
|
||||||
|
*/
|
||||||
|
public interface RuntimeTestService {
|
||||||
|
UUID getNodeID(Node node);
|
||||||
|
boolean isExpressionNode(Object node);
|
||||||
|
boolean isTailCallException(Object obj);
|
||||||
|
boolean isFunctionCallInstrumentationNode(Object node);
|
||||||
|
boolean isFunctionCall(Object obj);
|
||||||
|
FunctionCallInfo extractFunctionCallInfo(Object functionCall);
|
||||||
|
}
|
@ -1,77 +0,0 @@
|
|||||||
package org.enso.interpreter.test.instrument;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import org.enso.interpreter.test.MockLogHandler;
|
|
||||||
import org.enso.polyglot.MethodNames;
|
|
||||||
import org.enso.polyglot.RuntimeOptions;
|
|
||||||
import org.graalvm.polyglot.Context;
|
|
||||||
import org.graalvm.polyglot.Source;
|
|
||||||
import org.graalvm.polyglot.io.IOAccess;
|
|
||||||
import org.junit.AfterClass;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class VerifyLanguageAvailabilityTest {
|
|
||||||
private static Context ctx;
|
|
||||||
private static MockLogHandler handler;
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
public static void initEnsoContext() {
|
|
||||||
handler = new MockLogHandler();
|
|
||||||
ctx =
|
|
||||||
Context.newBuilder()
|
|
||||||
.allowExperimentalOptions(true)
|
|
||||||
.allowIO(IOAccess.ALL)
|
|
||||||
.option(RuntimeOptions.PREINITIALIZE, "js")
|
|
||||||
.option(
|
|
||||||
RuntimeOptions.LANGUAGE_HOME_OVERRIDE,
|
|
||||||
Paths.get("../../distribution/component").toFile().getAbsolutePath())
|
|
||||||
.option(RuntimeOptions.LOG_LEVEL, Level.FINE.getName())
|
|
||||||
.logHandler(handler)
|
|
||||||
.allowAllAccess(true)
|
|
||||||
.build();
|
|
||||||
assertNotNull("Enso language is supported", ctx.getEngine().getLanguages().get("enso"));
|
|
||||||
var fourtyTwo =
|
|
||||||
ctx.eval("enso", "mul x y = x * y").invokeMember("eval_expression", "mul").execute(6, 7);
|
|
||||||
assertEquals(42, fourtyTwo.asInt());
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void closeEnsoContext() throws Exception {
|
|
||||||
ctx.close();
|
|
||||||
|
|
||||||
var args =
|
|
||||||
handler.assertMessage("epb.org.enso.interpreter.epb.EpbContext", "Parsing foreign script");
|
|
||||||
assertEquals("js", args[0]);
|
|
||||||
assertEquals("mul.mul", args[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void javaScriptIsPresent() throws Exception {
|
|
||||||
var js = ctx.getEngine().getLanguages().get("js");
|
|
||||||
assertNotNull("JavaScript is available", js);
|
|
||||||
var src =
|
|
||||||
Source.newBuilder(
|
|
||||||
"enso",
|
|
||||||
"""
|
|
||||||
foreign js mul a b = \"\"\"
|
|
||||||
return a * b
|
|
||||||
|
|
||||||
run = mul 6 7
|
|
||||||
""",
|
|
||||||
"mul.enso")
|
|
||||||
.build();
|
|
||||||
var fourtyTwo = ctx.eval(src).invokeMember(MethodNames.Module.EVAL_EXPRESSION, "run");
|
|
||||||
assertEquals(42, fourtyTwo.asInt());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void ensoIsPresent() {
|
|
||||||
var enso = ctx.getEngine().getLanguages().get("enso");
|
|
||||||
assertNotNull("Enso is available", enso);
|
|
||||||
}
|
|
||||||
}
|
|
@ -85,36 +85,6 @@ public class BigNumberTest extends TestBase {
|
|||||||
return powers;
|
return powers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void averageOfMixedArrayOverDouble() throws Exception {
|
|
||||||
boolean assertsOn = false;
|
|
||||||
assert assertsOn = true;
|
|
||||||
if (assertsOn) {
|
|
||||||
// skip this test when asserts are on
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var code =
|
|
||||||
"""
|
|
||||||
from Standard.Base.Data.Vector import Vector
|
|
||||||
polyglot java import org.enso.example.TestClass
|
|
||||||
|
|
||||||
powers n =
|
|
||||||
go x v b = if x > n then b.to_vector else
|
|
||||||
b.append v
|
|
||||||
@Tail_Call go x+1 v*2 b
|
|
||||||
go 1 1 Vector.new_builder
|
|
||||||
|
|
||||||
avg n = TestClass.doubleArrayAverage (powers n)
|
|
||||||
""";
|
|
||||||
var fn = evalCode(code, "avg");
|
|
||||||
var avg = fn.execute(200);
|
|
||||||
|
|
||||||
assertTrue("Got a number back " + avg, avg.isNumber());
|
|
||||||
assertFalse("It's not a long", avg.fitsInLong());
|
|
||||||
assertTrue("It's a double", avg.fitsInDouble());
|
|
||||||
assertEquals("It is big enough", Math.pow(2, 200) / 200, avg.asDouble(), 300);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void averageOfMixedArrayOverNumber() throws Exception {
|
public void averageOfMixedArrayOverNumber() throws Exception {
|
||||||
var code =
|
var code =
|
||||||
|
@ -42,7 +42,6 @@ import org.graalvm.polyglot.io.IOAccess;
|
|||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class DebuggingEnsoTest {
|
public class DebuggingEnsoTest {
|
||||||
@ -58,7 +57,7 @@ public class DebuggingEnsoTest {
|
|||||||
.option(
|
.option(
|
||||||
RuntimeOptions.LANGUAGE_HOME_OVERRIDE,
|
RuntimeOptions.LANGUAGE_HOME_OVERRIDE,
|
||||||
Paths.get("../../distribution/component").toFile().getAbsolutePath())
|
Paths.get("../../distribution/component").toFile().getAbsolutePath())
|
||||||
.option(RuntimeOptions.LOG_LEVEL, Level.FINEST.getName())
|
.option(RuntimeOptions.LOG_LEVEL, Level.WARNING.getName())
|
||||||
.logHandler(System.err)
|
.logHandler(System.err)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@ -504,9 +503,7 @@ public class DebuggingEnsoTest {
|
|||||||
bar 42 # 6
|
bar 42 # 6
|
||||||
end = 0 # 7
|
end = 0 # 7
|
||||||
""");
|
""");
|
||||||
// Steps into line 2 - declaration of the method, which is fine.
|
List<Integer> expectedLineNumbers = List.of(5, 6, 7);
|
||||||
// (5, 6, 7) would be better.
|
|
||||||
List<Integer> expectedLineNumbers = List.of(5, 6, 2, 7);
|
|
||||||
Queue<SuspendedCallback> steps = createStepOverEvents(expectedLineNumbers.size());
|
Queue<SuspendedCallback> steps = createStepOverEvents(expectedLineNumbers.size());
|
||||||
testStepping(src, "foo", new Object[] {0}, steps, expectedLineNumbers);
|
testStepping(src, "foo", new Object[] {0}, steps, expectedLineNumbers);
|
||||||
}
|
}
|
||||||
@ -514,12 +511,7 @@ public class DebuggingEnsoTest {
|
|||||||
/**
|
/**
|
||||||
* Use some methods from Vector in stdlib. Stepping over methods from different modules might be
|
* Use some methods from Vector in stdlib. Stepping over methods from different modules might be
|
||||||
* problematic.
|
* problematic.
|
||||||
*
|
|
||||||
* <p>TODO[pm] This test is ignored, because the current behavior of step over is that it first
|
|
||||||
* steps into the declaration (name) of the method that is being stepped over and then steps back.
|
|
||||||
* So there would be weird line numbers from std lib.
|
|
||||||
*/
|
*/
|
||||||
@Ignore
|
|
||||||
@Test
|
@Test
|
||||||
public void testSteppingOverUseStdLib() {
|
public void testSteppingOverUseStdLib() {
|
||||||
Source src =
|
Source src =
|
||||||
@ -562,7 +554,7 @@ public class DebuggingEnsoTest {
|
|||||||
bar 42 # 4
|
bar 42 # 4
|
||||||
end = 0 # 5
|
end = 0 # 5
|
||||||
""");
|
""");
|
||||||
List<Integer> expectedLineNumbers = List.of(3, 4, 2, 1, 5);
|
List<Integer> expectedLineNumbers = List.of(3, 4, 2, 1, 2, 4, 5);
|
||||||
Queue<SuspendedCallback> steps =
|
Queue<SuspendedCallback> steps =
|
||||||
new ArrayDeque<>(
|
new ArrayDeque<>(
|
||||||
Collections.nCopies(expectedLineNumbers.size(), (event) -> event.prepareStepInto(1)));
|
Collections.nCopies(expectedLineNumbers.size(), (event) -> event.prepareStepInto(1)));
|
||||||
@ -581,7 +573,7 @@ public class DebuggingEnsoTest {
|
|||||||
bar (baz x) # 4
|
bar (baz x) # 4
|
||||||
end = 0 # 5
|
end = 0 # 5
|
||||||
""");
|
""");
|
||||||
List<Integer> expectedLineNumbers = List.of(3, 4, 1, 2, 5);
|
List<Integer> expectedLineNumbers = List.of(3, 4, 1, 4, 2, 4, 5);
|
||||||
Queue<SuspendedCallback> steps =
|
Queue<SuspendedCallback> steps =
|
||||||
new ArrayDeque<>(
|
new ArrayDeque<>(
|
||||||
Collections.nCopies(expectedLineNumbers.size(), (event) -> event.prepareStepInto(1)));
|
Collections.nCopies(expectedLineNumbers.size(), (event) -> event.prepareStepInto(1)));
|
||||||
|
@ -47,6 +47,7 @@ public class MetaIsATest extends TestBase {
|
|||||||
public static void disposeCtx() {
|
public static void disposeCtx() {
|
||||||
if (generator != null) {
|
if (generator != null) {
|
||||||
generator.dispose();
|
generator.dispose();
|
||||||
|
generator = null;
|
||||||
}
|
}
|
||||||
ctx.close();
|
ctx.close();
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ public class MetaObjectTest extends TestBase {
|
|||||||
public static void disposeCtx() {
|
public static void disposeCtx() {
|
||||||
if (generator != null) {
|
if (generator != null) {
|
||||||
generator.dispose();
|
generator.dispose();
|
||||||
|
generator = null;
|
||||||
}
|
}
|
||||||
ctx.close();
|
ctx.close();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
package org.enso.interpreter.test;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import com.oracle.truffle.api.nodes.RootNode;
|
||||||
|
import java.util.UUID;
|
||||||
|
import org.enso.interpreter.node.ExpressionNode;
|
||||||
|
import org.enso.interpreter.node.MethodRootNode;
|
||||||
|
import org.enso.interpreter.node.callable.FunctionCallInstrumentationNode;
|
||||||
|
import org.enso.interpreter.node.callable.FunctionCallInstrumentationNode.FunctionCall;
|
||||||
|
import org.enso.interpreter.runtime.control.TailCallException;
|
||||||
|
import org.enso.interpreter.test.instruments.service.FunctionCallInfo;
|
||||||
|
import org.enso.interpreter.test.instruments.service.RuntimeTestService;
|
||||||
|
import org.openide.util.lookup.ServiceProvider;
|
||||||
|
|
||||||
|
@ServiceProvider(service = RuntimeTestService.class)
|
||||||
|
public class RuntimeTestServiceImpl implements RuntimeTestService {
|
||||||
|
@Override
|
||||||
|
public UUID getNodeID(Node node) {
|
||||||
|
if (node instanceof ExpressionNode exprNode) {
|
||||||
|
return exprNode.getId();
|
||||||
|
} else if (node instanceof FunctionCallInstrumentationNode funcNode) {
|
||||||
|
return funcNode.getId();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isExpressionNode(Object node) {
|
||||||
|
return node instanceof ExpressionNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTailCallException(Object obj) {
|
||||||
|
return obj instanceof TailCallException;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFunctionCallInstrumentationNode(Object node) {
|
||||||
|
return node instanceof FunctionCallInstrumentationNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFunctionCall(Object obj) {
|
||||||
|
return obj instanceof FunctionCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FunctionCallInfo extractFunctionCallInfo(Object functionCallObj) {
|
||||||
|
if (functionCallObj instanceof FunctionCall functionCall) {
|
||||||
|
RootNode rootNode = functionCall.getFunction().getCallTarget().getRootNode();
|
||||||
|
if (rootNode instanceof MethodRootNode methodNode) {
|
||||||
|
String moduleName = methodNode.getModuleScope().getModule().getName().toString();
|
||||||
|
String typeName = methodNode.getType().getQualifiedName().toString();
|
||||||
|
String functionName = methodNode.getMethodName();
|
||||||
|
return new FunctionCallInfo(moduleName, typeName, functionName);
|
||||||
|
} else {
|
||||||
|
return new FunctionCallInfo(null, null, rootNode.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,7 @@ import java.util.logging.Level;
|
|||||||
import org.enso.interpreter.node.ClosureRootNode;
|
import org.enso.interpreter.node.ClosureRootNode;
|
||||||
import org.enso.interpreter.runtime.tag.AvoidIdInstrumentationTag;
|
import org.enso.interpreter.runtime.tag.AvoidIdInstrumentationTag;
|
||||||
import org.enso.interpreter.runtime.tag.IdentifiedTag;
|
import org.enso.interpreter.runtime.tag.IdentifiedTag;
|
||||||
import org.enso.interpreter.test.NodeCountingTestInstrument;
|
import org.enso.interpreter.test.instruments.NodeCountingTestInstrument;
|
||||||
import org.enso.polyglot.RuntimeOptions;
|
import org.enso.polyglot.RuntimeOptions;
|
||||||
import org.graalvm.polyglot.Context;
|
import org.graalvm.polyglot.Context;
|
||||||
import org.graalvm.polyglot.Language;
|
import org.graalvm.polyglot.Language;
|
@ -14,8 +14,8 @@ import org.enso.compiler.core.ir.Literal;
|
|||||||
import org.enso.interpreter.node.expression.literal.LiteralNode;
|
import org.enso.interpreter.node.expression.literal.LiteralNode;
|
||||||
import org.enso.interpreter.runtime.type.ConstantsGen;
|
import org.enso.interpreter.runtime.type.ConstantsGen;
|
||||||
import org.enso.interpreter.test.Metadata;
|
import org.enso.interpreter.test.Metadata;
|
||||||
import org.enso.interpreter.test.NodeCountingTestInstrument;
|
|
||||||
import org.enso.interpreter.test.instrument.RuntimeServerTest.TestContext;
|
import org.enso.interpreter.test.instrument.RuntimeServerTest.TestContext;
|
||||||
|
import org.enso.interpreter.test.instruments.NodeCountingTestInstrument;
|
||||||
import org.enso.polyglot.runtime.Runtime$Api$CreateContextRequest;
|
import org.enso.polyglot.runtime.Runtime$Api$CreateContextRequest;
|
||||||
import org.enso.polyglot.runtime.Runtime$Api$CreateContextResponse;
|
import org.enso.polyglot.runtime.Runtime$Api$CreateContextResponse;
|
||||||
import org.enso.polyglot.runtime.Runtime$Api$EditFileNotification;
|
import org.enso.polyglot.runtime.Runtime$Api$EditFileNotification;
|
||||||
@ -35,6 +35,7 @@ import org.enso.polyglot.runtime.Runtime$Api$StackItem$ExplicitCall;
|
|||||||
import org.enso.polyglot.runtime.Runtime$Api$StackItem$LocalCall;
|
import org.enso.polyglot.runtime.Runtime$Api$StackItem$LocalCall;
|
||||||
import org.enso.text.editing.model;
|
import org.enso.text.editing.model;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import scala.Option;
|
import scala.Option;
|
||||||
@ -77,7 +78,7 @@ public class IncrementalUpdatesTest {
|
|||||||
var m = context.languageContext().findModule(MODULE_NAME).orElse(null);
|
var m = context.languageContext().findModule(MODULE_NAME).orElse(null);
|
||||||
assertNotNull("Module found", m);
|
assertNotNull("Module found", m);
|
||||||
var numbers = m.getIr().preorder().filter((v1) -> v1 instanceof Literal.Number);
|
var numbers = m.getIr().preorder().filter((v1) -> v1 instanceof Literal.Number);
|
||||||
assertEquals("One number found: " + numbers, 1, numbers.size());
|
Assert.assertEquals("One number found: " + numbers, 1, numbers.size());
|
||||||
if (numbers.head() instanceof Literal.Number n) {
|
if (numbers.head() instanceof Literal.Number n) {
|
||||||
assertEquals("updated to 5", "5", n.value());
|
assertEquals("updated to 5", "5", n.value());
|
||||||
}
|
}
|
||||||
@ -100,10 +101,10 @@ public class IncrementalUpdatesTest {
|
|||||||
sendUpdatesWhenFunctionBodyIsChangedBySettingValue(
|
sendUpdatesWhenFunctionBodyIsChangedBySettingValue(
|
||||||
"4", ConstantsGen.INTEGER, "4", "1000", "1000", LiteralNode.class);
|
"4", ConstantsGen.INTEGER, "4", "1000", "1000", LiteralNode.class);
|
||||||
sendExpressionValue("1000", "333");
|
sendExpressionValue("1000", "333");
|
||||||
assertEquals(List.newBuilder().addOne("333"), context.consumeOut());
|
Assert.assertEquals(List.newBuilder().addOne("333"), context.consumeOut());
|
||||||
nodeCountingInstrument.assertNewNodes("No execution on 333, no nodes yet", 0, 0);
|
nodeCountingInstrument.assertNewNodes("No execution on 333, no nodes yet", 0, 0);
|
||||||
sendExpressionValue("333", "22");
|
sendExpressionValue("333", "22");
|
||||||
assertEquals(List.newBuilder().addOne("22"), context.consumeOut());
|
Assert.assertEquals(List.newBuilder().addOne("22"), context.consumeOut());
|
||||||
nodeCountingInstrument.assertNewNodes("No execution on 22, no nodes yet", 0, 0);
|
nodeCountingInstrument.assertNewNodes("No execution on 22, no nodes yet", 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +128,7 @@ public class IncrementalUpdatesTest {
|
|||||||
assertTrue(
|
assertTrue(
|
||||||
"Execution succeeds: " + result,
|
"Execution succeeds: " + result,
|
||||||
result.head().payload() instanceof Runtime$Api$ExecutionComplete);
|
result.head().payload() instanceof Runtime$Api$ExecutionComplete);
|
||||||
assertEquals(
|
Assert.assertEquals(
|
||||||
"Error is printed as a result",
|
"Error is printed as a result",
|
||||||
List.newBuilder().addOne("(Error: Uninitialized value)"),
|
List.newBuilder().addOne("(Error: Uninitialized value)"),
|
||||||
context.consumeOut());
|
context.consumeOut());
|
||||||
@ -273,7 +274,7 @@ public class IncrementalUpdatesTest {
|
|||||||
Vector$.MODULE$.empty())),
|
Vector$.MODULE$.empty())),
|
||||||
TestMessages.update(contextId, mainRes, ConstantsGen.NOTHING),
|
TestMessages.update(contextId, mainRes, ConstantsGen.NOTHING),
|
||||||
context.executionComplete(contextId));
|
context.executionComplete(contextId));
|
||||||
assertEquals(List.newBuilder().addOne(originalOutput), context.consumeOut());
|
Assert.assertEquals(List.newBuilder().addOne(originalOutput), context.consumeOut());
|
||||||
|
|
||||||
var allNodesAfterException =
|
var allNodesAfterException =
|
||||||
nodeCountingInstrument.assertNewNodes("Execution creates some nodes", 20, 35);
|
nodeCountingInstrument.assertNewNodes("Execution creates some nodes", 20, 35);
|
||||||
@ -290,7 +291,7 @@ public class IncrementalUpdatesTest {
|
|||||||
TestMessages.update(contextId, fooX, exprType),
|
TestMessages.update(contextId, fooX, exprType),
|
||||||
TestMessages.update(contextId, fooRes, exprType),
|
TestMessages.update(contextId, fooRes, exprType),
|
||||||
context.executionComplete(contextId));
|
context.executionComplete(contextId));
|
||||||
assertEquals(List.newBuilder().addOne(originalOutput), context.consumeOut());
|
Assert.assertEquals(List.newBuilder().addOne(originalOutput), context.consumeOut());
|
||||||
|
|
||||||
nodeCountingInstrument.assertNewNodes("No new nodes created", 0, 0);
|
nodeCountingInstrument.assertNewNodes("No new nodes created", 0, 0);
|
||||||
var literalNode = findLiteralNode(truffleNodeType, allNodesAfterException);
|
var literalNode = findLiteralNode(truffleNodeType, allNodesAfterException);
|
||||||
@ -302,7 +303,7 @@ public class IncrementalUpdatesTest {
|
|||||||
var executionCompleteEvents = sendEdit.apply(originalText, newText);
|
var executionCompleteEvents = sendEdit.apply(originalText, newText);
|
||||||
if (executionOutput != null) {
|
if (executionOutput != null) {
|
||||||
assertSameElements(executionCompleteEvents, context.executionComplete(contextId));
|
assertSameElements(executionCompleteEvents, context.executionComplete(contextId));
|
||||||
assertEquals(List.newBuilder().addOne(executionOutput), context.consumeOut());
|
Assert.assertEquals(List.newBuilder().addOne(executionOutput), context.consumeOut());
|
||||||
nodeCountingInstrument.assertNewNodes("No new nodes created", 0, 0);
|
nodeCountingInstrument.assertNewNodes("No new nodes created", 0, 0);
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
@ -1,6 +1,7 @@
|
|||||||
package org.enso.interpreter.test.instrument;
|
package org.enso.interpreter.test.instrument;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import com.oracle.truffle.api.instrumentation.SourceSectionFilter;
|
import com.oracle.truffle.api.instrumentation.SourceSectionFilter;
|
||||||
import com.oracle.truffle.api.instrumentation.StandardTags;
|
import com.oracle.truffle.api.instrumentation.StandardTags;
|
||||||
@ -10,7 +11,7 @@ import java.util.logging.Level;
|
|||||||
import org.enso.interpreter.runtime.tag.AvoidIdInstrumentationTag;
|
import org.enso.interpreter.runtime.tag.AvoidIdInstrumentationTag;
|
||||||
import org.enso.interpreter.runtime.tag.IdentifiedTag;
|
import org.enso.interpreter.runtime.tag.IdentifiedTag;
|
||||||
import org.enso.interpreter.test.Metadata;
|
import org.enso.interpreter.test.Metadata;
|
||||||
import org.enso.interpreter.test.NodeCountingTestInstrument;
|
import org.enso.interpreter.test.instruments.NodeCountingTestInstrument;
|
||||||
import org.enso.polyglot.RuntimeOptions;
|
import org.enso.polyglot.RuntimeOptions;
|
||||||
import org.graalvm.polyglot.Context;
|
import org.graalvm.polyglot.Context;
|
||||||
import org.graalvm.polyglot.Language;
|
import org.graalvm.polyglot.Language;
|
||||||
@ -92,9 +93,9 @@ public class WarningInstrumentationTest {
|
|||||||
var calls = instrument.registeredCalls();
|
var calls = instrument.registeredCalls();
|
||||||
|
|
||||||
assertEquals(calls.keySet().size(), 3);
|
assertEquals(calls.keySet().size(), 3);
|
||||||
assertEquals(calls.get(idOp1).getFunctionName(), "new");
|
assertEquals(calls.get(idOp1).functionName(), "new");
|
||||||
assertEquals(calls.get(idOp2).getFunctionName(), "attach");
|
assertEquals(calls.get(idOp2).functionName(), "attach");
|
||||||
assertEquals(calls.get(idOp3).getTypeName().item(), "Table");
|
assertTrue(calls.get(idOp3).typeName().contains("Table"));
|
||||||
assertEquals(calls.get(idOp3).getFunctionName(), "get");
|
assertEquals(calls.get(idOp3).functionName(), "get");
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,8 +1,12 @@
|
|||||||
package org.enso.interpreter.test
|
package org.enso.interpreter.test
|
||||||
|
|
||||||
import com.oracle.truffle.api.instrumentation.EventBinding
|
import com.oracle.truffle.api.instrumentation.EventBinding
|
||||||
import org.enso.interpreter.test.CodeIdsTestInstrument.IdEventListener
|
import org.enso.interpreter.test.instruments.CodeIdsTestInstrument.IdEventListener
|
||||||
import org.enso.interpreter.test.CodeLocationsTestInstrument.LocationsEventListener
|
import org.enso.interpreter.test.instruments.{
|
||||||
|
CodeIdsTestInstrument,
|
||||||
|
CodeLocationsTestInstrument
|
||||||
|
}
|
||||||
|
import org.enso.interpreter.test.instruments.CodeLocationsTestInstrument.LocationsEventListener
|
||||||
import org.enso.polyglot.debugger.{
|
import org.enso.polyglot.debugger.{
|
||||||
DebugServerInfo,
|
DebugServerInfo,
|
||||||
DebuggerSessionManagerEndpoint,
|
DebuggerSessionManagerEndpoint,
|
||||||
|
@ -2,9 +2,9 @@ package org.enso.interpreter.test.instrument
|
|||||||
|
|
||||||
import org.enso.polyglot.{LanguageInfo, RuntimeOptions}
|
import org.enso.polyglot.{LanguageInfo, RuntimeOptions}
|
||||||
import org.graalvm.polyglot.{Context, PolyglotException}
|
import org.graalvm.polyglot.{Context, PolyglotException}
|
||||||
import org.scalatest.{BeforeAndAfterEach, Suite}
|
|
||||||
import org.scalatest.matchers.should.Matchers
|
import org.scalatest.matchers.should.Matchers
|
||||||
import org.scalatest.wordspec.AnyWordSpec
|
import org.scalatest.wordspec.AnyWordSpec
|
||||||
|
import org.scalatest.{BeforeAndAfterEach, Suite}
|
||||||
|
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
@ -44,7 +44,6 @@ class RuntimeProjectContextTest
|
|||||||
.toFile
|
.toFile
|
||||||
.getAbsolutePath
|
.getAbsolutePath
|
||||||
)
|
)
|
||||||
.option("engine.WarnInterpreterOnly", "false")
|
|
||||||
.option(RuntimeOptions.EDITION_OVERRIDE, "0.0.0-dev")
|
.option(RuntimeOptions.EDITION_OVERRIDE, "0.0.0-dev")
|
||||||
.option(RuntimeOptions.LOG_LEVEL, Level.WARNING.getName)
|
.option(RuntimeOptions.LOG_LEVEL, Level.WARNING.getName)
|
||||||
.logHandler(System.err)
|
.logHandler(System.err)
|
@ -5,9 +5,9 @@ import org.enso.interpreter.runtime.`type`.ConstantsGen
|
|||||||
import org.enso.interpreter.test.Metadata
|
import org.enso.interpreter.test.Metadata
|
||||||
import org.enso.polyglot._
|
import org.enso.polyglot._
|
||||||
import org.enso.polyglot.runtime.Runtime.Api
|
import org.enso.polyglot.runtime.Runtime.Api
|
||||||
import org.enso.text.{ContentBasedVersioning, Sha3_224VersionCalculator}
|
|
||||||
import org.enso.text.editing.model
|
import org.enso.text.editing.model
|
||||||
import org.enso.text.editing.model.TextEdit
|
import org.enso.text.editing.model.TextEdit
|
||||||
|
import org.enso.text.{ContentBasedVersioning, Sha3_224VersionCalculator}
|
||||||
import org.graalvm.polyglot.Context
|
import org.graalvm.polyglot.Context
|
||||||
import org.scalatest.BeforeAndAfterEach
|
import org.scalatest.BeforeAndAfterEach
|
||||||
import org.scalatest.flatspec.AnyFlatSpec
|
import org.scalatest.flatspec.AnyFlatSpec
|
@ -1,7 +1,8 @@
|
|||||||
package org.enso.interpreter.test.instrument
|
package org.enso.interpreter.test.instrument
|
||||||
|
|
||||||
import org.enso.interpreter.runtime.`type`.{Constants, ConstantsGen, Types}
|
import org.apache.commons.io.output.TeeOutputStream
|
||||||
import org.enso.interpreter.runtime.EnsoContext
|
import org.enso.interpreter.runtime.EnsoContext
|
||||||
|
import org.enso.interpreter.runtime.`type`.{Constants, ConstantsGen, Types}
|
||||||
import org.enso.interpreter.test.Metadata
|
import org.enso.interpreter.test.Metadata
|
||||||
import org.enso.polyglot._
|
import org.enso.polyglot._
|
||||||
import org.enso.polyglot.data.TypeGraph
|
import org.enso.polyglot.data.TypeGraph
|
||||||
@ -16,7 +17,6 @@ import org.scalatest.matchers.should.Matchers
|
|||||||
import java.io.{ByteArrayOutputStream, File}
|
import java.io.{ByteArrayOutputStream, File}
|
||||||
import java.nio.file.{Files, Paths}
|
import java.nio.file.{Files, Paths}
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import org.apache.commons.io.output.TeeOutputStream
|
|
||||||
|
|
||||||
@scala.annotation.nowarn("msg=multiarg infix syntax")
|
@scala.annotation.nowarn("msg=multiarg infix syntax")
|
||||||
class RuntimeServerTest
|
class RuntimeServerTest
|
@ -83,7 +83,11 @@ object GraalVM {
|
|||||||
"org.graalvm.tools" % "dap-tool" % version
|
"org.graalvm.tools" % "dap-tool" % version
|
||||||
)
|
)
|
||||||
|
|
||||||
val toolsPkgs = chromeInspectorPkgs ++ debugAdapterProtocolPkgs
|
val insightPkgs = Seq(
|
||||||
|
"org.graalvm.tools" % "insight-tool" % version
|
||||||
|
)
|
||||||
|
|
||||||
|
val toolsPkgs = chromeInspectorPkgs ++ debugAdapterProtocolPkgs ++ insightPkgs
|
||||||
|
|
||||||
val langsPkgs = jsPkgs ++ pythonPkgs
|
val langsPkgs = jsPkgs ++ pythonPkgs
|
||||||
|
|
||||||
|
182
project/JPMSPlugin.scala
Normal file
182
project/JPMSPlugin.scala
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
import sbt.*
|
||||||
|
import sbt.Keys.*
|
||||||
|
import sbt.internal.inc.{CompileOutput, PlainVirtualFile}
|
||||||
|
import sbt.util.CacheStore
|
||||||
|
import sbtassembly.Assembly.{Dependency, JarEntry, Project}
|
||||||
|
import sbtassembly.{CustomMergeStrategy, MergeStrategy}
|
||||||
|
import xsbti.compile.IncToolOptionsUtil
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/** An automatic plugin that handles everything related to JPMS modules. One needs to explicitly
|
||||||
|
* enable this plugin in a project with `.enablePlugins(JPMSPlugin)`. The keys and tasks provided by this plugin
|
||||||
|
* corresponds to the module-related options of `javac` and `java` commands.
|
||||||
|
*
|
||||||
|
* This plugin injects all the module-specific options to `javaOptions`, based on
|
||||||
|
* the settings of this plugin.
|
||||||
|
*
|
||||||
|
* If this plugin is enabled, and no settings/tasks from this plugin are used, then the plugin will
|
||||||
|
* not inject anything into `javaOptions` or `javacOptions`.
|
||||||
|
*/
|
||||||
|
object JPMSPlugin extends AutoPlugin {
|
||||||
|
object autoImport {
|
||||||
|
val javaModuleName =
|
||||||
|
settingKey[String]("The name of the Java (JPMS) module")
|
||||||
|
val addModules = settingKey[Seq[String]](
|
||||||
|
"Module names that will be added to --add-modules option"
|
||||||
|
)
|
||||||
|
val modulePath = taskKey[Seq[File]](
|
||||||
|
"Directories (Jar archives or expanded Jar archives) that will be put into " +
|
||||||
|
"--module-path option"
|
||||||
|
)
|
||||||
|
val patchModules = taskKey[Map[String, Seq[File]]](
|
||||||
|
"""
|
||||||
|
|A map of module names to directories (Jar archives or expanded Jar archives) that will be
|
||||||
|
|put into --patch-module option.
|
||||||
|
|""".stripMargin
|
||||||
|
)
|
||||||
|
val addExports = taskKey[Map[String, Seq[String]]](
|
||||||
|
"""
|
||||||
|
|A map of module names to packages that will be put into --add-exports option.
|
||||||
|
|The format of `--add-exports` option is `module/package=target-module(,target-module)*`
|
||||||
|
|The key in the map is `module/package` and the value is a sequence of target modules
|
||||||
|
|""".stripMargin
|
||||||
|
)
|
||||||
|
val addReads = taskKey[Map[String, Seq[String]]](
|
||||||
|
"""
|
||||||
|
|A map of module names to modules that will be put into --add-reads option.
|
||||||
|
|When a module A reads a module B, it means that it "depends" on it - it has the same
|
||||||
|
|effect as if module A would have `requires B` in its module-info.java file.
|
||||||
|
|""".stripMargin
|
||||||
|
)
|
||||||
|
val compileModuleInfo = taskKey[Unit]("Compile module-info.java")
|
||||||
|
val modulePathTestOptions_ = taskKey[Seq[String]](
|
||||||
|
"Assembles options for the JVM for running tests with all the required modules. " +
|
||||||
|
"Including truffle-compiler and org.enso.runtime modules and all their dependencies."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
import autoImport.*
|
||||||
|
|
||||||
|
override lazy val projectSettings: Seq[Setting[_]] = Seq(
|
||||||
|
addModules := Seq.empty,
|
||||||
|
modulePath := Seq.empty,
|
||||||
|
patchModules := Map.empty,
|
||||||
|
addExports := Map.empty,
|
||||||
|
addReads := Map.empty,
|
||||||
|
compileModuleInfo := {},
|
||||||
|
// javacOptions only inject --module-path and --add-modules, not the rest of the
|
||||||
|
// options.
|
||||||
|
Compile / javacOptions ++= {
|
||||||
|
constructOptions(
|
||||||
|
streams.value.log,
|
||||||
|
modulePath = (Compile / modulePath).value,
|
||||||
|
addModules = (Compile / addModules).value
|
||||||
|
)
|
||||||
|
},
|
||||||
|
Compile / javaOptions ++= {
|
||||||
|
constructOptions(
|
||||||
|
streams.value.log,
|
||||||
|
(Compile / modulePath).value,
|
||||||
|
(Compile / addModules).value,
|
||||||
|
(Compile / patchModules).value,
|
||||||
|
(Compile / addExports).value,
|
||||||
|
(Compile / addReads).value
|
||||||
|
)
|
||||||
|
},
|
||||||
|
Test / javacOptions ++= {
|
||||||
|
constructOptions(
|
||||||
|
streams.value.log,
|
||||||
|
modulePath = (Test / modulePath).value,
|
||||||
|
addModules = (Test / addModules).value
|
||||||
|
)
|
||||||
|
},
|
||||||
|
Test / javaOptions ++= {
|
||||||
|
constructOptions(
|
||||||
|
streams.value.log,
|
||||||
|
(Test / modulePath).value,
|
||||||
|
(Test / addModules).value,
|
||||||
|
(Test / patchModules).value,
|
||||||
|
(Test / addExports).value,
|
||||||
|
(Test / addReads).value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def constructOptions(
|
||||||
|
log: Logger,
|
||||||
|
modulePath: Seq[File],
|
||||||
|
addModules: Seq[String] = Seq.empty,
|
||||||
|
patchModules: Map[String, Seq[File]] = Map.empty,
|
||||||
|
addExports: Map[String, Seq[String]] = Map.empty,
|
||||||
|
addReads: Map[String, Seq[String]] = Map.empty
|
||||||
|
): Seq[String] = {
|
||||||
|
val patchOpts: Seq[String] = patchModules.flatMap {
|
||||||
|
case (moduleName, dirsToPatch) =>
|
||||||
|
ensureDirectoriesExist(dirsToPatch, log)
|
||||||
|
val patchStr = dirsToPatch
|
||||||
|
.map(_.getAbsolutePath)
|
||||||
|
.mkString(File.pathSeparator)
|
||||||
|
Seq(
|
||||||
|
"--patch-module",
|
||||||
|
s"$moduleName=$patchStr"
|
||||||
|
)
|
||||||
|
}.toSeq
|
||||||
|
|
||||||
|
ensureDirectoriesExist(modulePath, log)
|
||||||
|
|
||||||
|
val addExportsOpts: Seq[String] = addExports.flatMap {
|
||||||
|
case (modPkgName, targetModules) =>
|
||||||
|
if (!modPkgName.contains("/")) {
|
||||||
|
log.error(s"JPMSPlugin: Invalid module/package name: $modPkgName")
|
||||||
|
}
|
||||||
|
Seq(
|
||||||
|
"--add-exports",
|
||||||
|
modPkgName + "=" + targetModules.mkString(",")
|
||||||
|
)
|
||||||
|
}.toSeq
|
||||||
|
|
||||||
|
val modulePathOpts = if (modulePath.isEmpty) {
|
||||||
|
Seq.empty
|
||||||
|
} else {
|
||||||
|
Seq(
|
||||||
|
"--module-path",
|
||||||
|
modulePath.map(_.getAbsolutePath).mkString(File.pathSeparator)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val addModsOpts = if (addModules.isEmpty) {
|
||||||
|
Seq.empty
|
||||||
|
} else {
|
||||||
|
Seq(
|
||||||
|
"--add-modules",
|
||||||
|
addModules.mkString(",")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val addReadsOpts = addReads.flatMap { case (modName, targetModules) =>
|
||||||
|
Seq(
|
||||||
|
"--add-reads",
|
||||||
|
modName + "=" + targetModules.mkString(",")
|
||||||
|
)
|
||||||
|
}.toSeq
|
||||||
|
|
||||||
|
modulePathOpts ++ addModsOpts ++ patchOpts ++ addExportsOpts ++ addReadsOpts
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Java does not mandate that the directories specified in the module path or
|
||||||
|
* in --patch-module exist, but it is usefull to report at least warnings.
|
||||||
|
* @param dirs
|
||||||
|
* @param log
|
||||||
|
*/
|
||||||
|
private def ensureDirectoriesExist(
|
||||||
|
dirs: Seq[File],
|
||||||
|
log: Logger
|
||||||
|
): Unit = {
|
||||||
|
dirs.foreach { dir =>
|
||||||
|
if (!dir.exists()) {
|
||||||
|
log.warn(s"JPMSPlugin: Directory $dir does not exist.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,21 +1,22 @@
|
|||||||
|
import JPMSPlugin.autoImport.javaModuleName
|
||||||
import sbt.*
|
import sbt.*
|
||||||
import sbt.Keys.*
|
import sbt.Keys.*
|
||||||
import sbtassembly.Assembly.{Dependency, JarEntry, Library, Project}
|
|
||||||
import sbtassembly.MergeStrategy
|
|
||||||
|
|
||||||
import java.io.{File, FilenameFilter}
|
|
||||||
import sbtassembly.CustomMergeStrategy
|
|
||||||
import xsbti.compile.IncToolOptionsUtil
|
|
||||||
import sbt.internal.inc.{CompileOutput, PlainVirtualFile}
|
import sbt.internal.inc.{CompileOutput, PlainVirtualFile}
|
||||||
|
import sbt.util.CacheStore
|
||||||
|
import sbtassembly.Assembly.{Dependency, JarEntry, Project}
|
||||||
|
import sbtassembly.{CustomMergeStrategy, MergeStrategy}
|
||||||
|
import xsbti.compile.IncToolOptionsUtil
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
import java.nio.file.attribute.BasicFileAttributes
|
import java.nio.file.attribute.BasicFileAttributes
|
||||||
import java.nio.file.{
|
import java.nio.file.{
|
||||||
|
FileVisitOption,
|
||||||
FileVisitResult,
|
FileVisitResult,
|
||||||
FileVisitor,
|
|
||||||
Files,
|
Files,
|
||||||
Path,
|
Path,
|
||||||
SimpleFileVisitor
|
SimpleFileVisitor
|
||||||
}
|
}
|
||||||
|
import scala.collection.mutable
|
||||||
|
|
||||||
/** Collection of utility methods dealing with JPMS modules.
|
/** Collection of utility methods dealing with JPMS modules.
|
||||||
* The motivation comes from the update of GraalVM to
|
* The motivation comes from the update of GraalVM to
|
||||||
@ -40,8 +41,9 @@ object JPMSUtils {
|
|||||||
)
|
)
|
||||||
|
|
||||||
/** Filters modules by their IDs from the given classpath.
|
/** Filters modules by their IDs from the given classpath.
|
||||||
* @param cp The classpath to filter
|
*
|
||||||
* @param modules These modules are looked for in the class path, can be duplicated.
|
* @param cp The classpath to filter
|
||||||
|
* @param modules These modules are looked for in the class path, can be duplicated.
|
||||||
* @param shouldContainAll If true, the method will throw an exception if not all modules were found
|
* @param shouldContainAll If true, the method will throw an exception if not all modules were found
|
||||||
* in the classpath.
|
* in the classpath.
|
||||||
* @return The classpath with only the provided modules searched by their IDs.
|
* @return The classpath with only the provided modules searched by their IDs.
|
||||||
@ -76,6 +78,43 @@ object JPMSUtils {
|
|||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Filters all the requested modules from the given [[UpdateReport]].
|
||||||
|
*
|
||||||
|
* @param updateReport The update report to filter. This is the result of `update.value`.
|
||||||
|
* @param modules The modules to filter from the update report. Can be duplicated.
|
||||||
|
* @param log The logger to use for logging.
|
||||||
|
* @param shouldContainAll If true, the method will log an error if not all modules were found.
|
||||||
|
* @return The list of files (Jar archives, directories, etc.) that were found in the update report.
|
||||||
|
*/
|
||||||
|
def filterModulesFromUpdate(
|
||||||
|
updateReport: UpdateReport,
|
||||||
|
modules: Seq[ModuleID],
|
||||||
|
log: sbt.util.Logger,
|
||||||
|
shouldContainAll: Boolean = false
|
||||||
|
): Seq[File] = {
|
||||||
|
val distinctModules = modules.distinct
|
||||||
|
|
||||||
|
def shouldFilterModule(module: ModuleID): Boolean = {
|
||||||
|
distinctModules.exists(m =>
|
||||||
|
m.organization == module.organization &&
|
||||||
|
m.name == module.name &&
|
||||||
|
m.revision == module.revision
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val foundFiles = updateReport.select(
|
||||||
|
module = shouldFilterModule
|
||||||
|
)
|
||||||
|
if (shouldContainAll) {
|
||||||
|
if (foundFiles.size < distinctModules.size) {
|
||||||
|
log.error("Not all modules from update were found")
|
||||||
|
log.error(s"Returned (${foundFiles.size}): $foundFiles")
|
||||||
|
log.error(s"Expected: (${distinctModules.size}): $distinctModules")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foundFiles
|
||||||
|
}
|
||||||
|
|
||||||
def filterTruffleAndGraalArtifacts(
|
def filterTruffleAndGraalArtifacts(
|
||||||
classPath: Def.Classpath
|
classPath: Def.Classpath
|
||||||
): Def.Classpath = {
|
): Def.Classpath = {
|
||||||
@ -130,17 +169,23 @@ object JPMSUtils {
|
|||||||
* Note that sbt is not able to correctly handle `module-info.java` files when
|
* Note that sbt is not able to correctly handle `module-info.java` files when
|
||||||
* compilation order is defined to mixed order.
|
* compilation order is defined to mixed order.
|
||||||
*
|
*
|
||||||
|
* Compilation of `module-info.java` is skipped iff none of all the classes from all the dependencies
|
||||||
|
* changed and if the `module-info.java` itself have not changed.
|
||||||
|
*
|
||||||
* @param copyDepsFilter The filter of scopes of the projects from which the class files are first
|
* @param copyDepsFilter The filter of scopes of the projects from which the class files are first
|
||||||
* copied into the `target` directory before `module-info.java` is compiled.
|
* copied into the `target` directory before `module-info.java` is compiled.
|
||||||
* @param modulePath IDs of dependencies that should be put on the module path. The modules
|
* @param modulePath IDs of dependencies that should be put on the module path. The modules
|
||||||
* put into `modulePath` are filtered away from class-path, so that module-path
|
* put into `modulePath` are filtered away from class-path, so that module-path
|
||||||
* and class-path passed to the `javac` are exclusive.
|
* and class-path passed to the `javac` are exclusive.
|
||||||
|
* @param modulePathExtra More directories that should be added on `--module-path`. This parameter is of
|
||||||
|
* type [[File]], because this is how inter project dependencies are gathered.
|
||||||
*
|
*
|
||||||
* @see https://users.scala-lang.org/t/scala-jdk-11-and-jpms/6102/19
|
* @see https://users.scala-lang.org/t/scala-jdk-11-and-jpms/6102/19
|
||||||
*/
|
*/
|
||||||
def compileModuleInfo(
|
def compileModuleInfo(
|
||||||
copyDepsFilter: ScopeFilter,
|
copyDepsFilter: ScopeFilter,
|
||||||
modulePath: Seq[ModuleID] = Seq()
|
modulePath: Seq[ModuleID] = Seq(),
|
||||||
|
modulePathExtra: Seq[File] = Seq()
|
||||||
): Def.Initialize[Task[Unit]] =
|
): Def.Initialize[Task[Unit]] =
|
||||||
Def
|
Def
|
||||||
.task {
|
.task {
|
||||||
@ -153,79 +198,153 @@ object JPMSUtils {
|
|||||||
// copied to.
|
// copied to.
|
||||||
val outputPath: Path = output.getSingleOutputAsPath
|
val outputPath: Path = output.getSingleOutputAsPath
|
||||||
.get()
|
.get()
|
||||||
|
// Class directories of all the dependencies.
|
||||||
|
val sourceProducts =
|
||||||
|
productDirectories.all(copyDepsFilter).value.flatten
|
||||||
|
|
||||||
/** Copy classes into the target directory from all the dependencies */
|
val moduleName = javaModuleName.value
|
||||||
log.debug(s"Copying classes to $output")
|
val cacheStore = streams.value.cacheStoreFactory
|
||||||
val sourceProducts = products.all(copyDepsFilter).value.flatten
|
val repoRootDir = (LocalProject("enso") / baseDirectory).value
|
||||||
|
var someDepChanged = false
|
||||||
if (!(outputPath.toFile.exists())) {
|
sourceProducts.foreach(sourceProduct => {
|
||||||
Files.createDirectory(outputPath)
|
if (!sourceProduct.exists()) {
|
||||||
}
|
log.error(s"Source product ${sourceProduct} does not exist")
|
||||||
|
log.error(
|
||||||
val outputLangProvider =
|
"This means that the Compile/compile task was probably not run in " +
|
||||||
outputPath / "META-INF" / "services" / "com.oracle.truffle.api.provider.TruffleLanguageProvider"
|
"the corresponding project"
|
||||||
sourceProducts.foreach { sourceProduct =>
|
|
||||||
log.debug(s"Copying ${sourceProduct} to ${output}")
|
|
||||||
val sourceLangProvider =
|
|
||||||
sourceProduct / "META-INF" / "services" / "com.oracle.truffle.api.provider.TruffleLanguageProvider"
|
|
||||||
if (
|
|
||||||
outputLangProvider.toFile.exists() && sourceLangProvider.exists()
|
|
||||||
) {
|
|
||||||
log.debug(
|
|
||||||
s"Merging ${sourceLangProvider} into ${outputLangProvider}"
|
|
||||||
)
|
)
|
||||||
val sourceLines = IO.readLines(sourceLangProvider)
|
log.error("Run Compile/compile before this task")
|
||||||
val destLines = IO.readLines(outputLangProvider.toFile)
|
}
|
||||||
val outLines = (sourceLines ++ destLines).distinct
|
val relPath = repoRootDir.toPath.relativize(sourceProduct.toPath)
|
||||||
IO.writeLines(outputLangProvider.toFile, outLines)
|
val cache = cacheStore.make("cache-" + relPath.toString)
|
||||||
|
val depChanged = copyClasses(sourceProduct, output, cache, log)
|
||||||
|
if (depChanged) {
|
||||||
|
someDepChanged = true
|
||||||
}
|
}
|
||||||
// Copy the rest of the directory - don't override META-INF.
|
|
||||||
IO.copyDirectory(
|
|
||||||
sourceProduct,
|
|
||||||
outputPath.toFile,
|
|
||||||
CopyOptions(
|
|
||||||
overwrite = false,
|
|
||||||
preserveLastModified = true,
|
|
||||||
preserveExecutable = true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.info("Compiling module-info.java with javac")
|
|
||||||
val baseJavacOpts = (Compile / javacOptions).value
|
|
||||||
val fullCp = (Compile / fullClasspath).value
|
|
||||||
val (mp, cp) = fullCp.partition(file => {
|
|
||||||
val moduleID =
|
|
||||||
file.metadata.get(AttributeKey[ModuleID]("moduleID")).get
|
|
||||||
modulePath.exists(mod => {
|
|
||||||
mod.organization == moduleID.organization &&
|
|
||||||
mod.name == moduleID.name &&
|
|
||||||
mod.revision == moduleID.revision
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
val allOpts = baseJavacOpts ++ Seq(
|
val baseJavacOpts = (Compile / javacOptions).value
|
||||||
"--class-path",
|
val fullCp = (Compile / fullClasspath).value
|
||||||
cp.map(_.data.getAbsolutePath).mkString(File.pathSeparator),
|
|
||||||
"--module-path",
|
|
||||||
mp.map(_.data.getAbsolutePath).mkString(File.pathSeparator),
|
|
||||||
"-d",
|
|
||||||
outputPath.toAbsolutePath().toString()
|
|
||||||
)
|
|
||||||
val javaCompiler =
|
val javaCompiler =
|
||||||
(Compile / compile / compilers).value.javaTools.javac()
|
(Compile / compile / compilers).value.javaTools.javac()
|
||||||
val succ = javaCompiler.run(
|
|
||||||
Array(PlainVirtualFile(moduleInfo.toPath)),
|
// Skip module-info.java compilation if the source have not changed
|
||||||
allOpts.toArray,
|
// Force the compilation if some class file from one of the dependencies changed,
|
||||||
output,
|
// just to be sure that we don't cause any weird compilation errors.
|
||||||
incToolOpts,
|
val moduleInfoCache = cacheStore.make("cache-module-info-" + moduleName)
|
||||||
reporter,
|
Tracked.diffInputs(moduleInfoCache, FileInfo.lastModified)(
|
||||||
log
|
Set(moduleInfo)
|
||||||
)
|
) { changeReport =>
|
||||||
if (!succ) {
|
if (
|
||||||
sys.error(s"Compilation of ${moduleInfo} failed")
|
someDepChanged || changeReport.modified.nonEmpty || changeReport.added.nonEmpty
|
||||||
|
) {
|
||||||
|
log.info(s"Compiling $moduleInfo with javac")
|
||||||
|
val (mp, cp) = fullCp.partition(file => {
|
||||||
|
val moduleID =
|
||||||
|
file.metadata.get(AttributeKey[ModuleID]("moduleID")).get
|
||||||
|
modulePath.exists(mod => {
|
||||||
|
mod.organization == moduleID.organization &&
|
||||||
|
mod.name == moduleID.name &&
|
||||||
|
mod.revision == moduleID.revision
|
||||||
|
})
|
||||||
|
})
|
||||||
|
val allDirsOnMp = mp.map(_.data) ++ modulePathExtra
|
||||||
|
|
||||||
|
val allOpts = baseJavacOpts ++ Seq(
|
||||||
|
"--class-path",
|
||||||
|
cp.map(_.data.getAbsolutePath).mkString(File.pathSeparator),
|
||||||
|
"--module-path",
|
||||||
|
allDirsOnMp.map(_.getAbsolutePath).mkString(File.pathSeparator),
|
||||||
|
"-d",
|
||||||
|
outputPath.toAbsolutePath.toString
|
||||||
|
)
|
||||||
|
log.debug(s"javac options: $allOpts")
|
||||||
|
|
||||||
|
val succ = javaCompiler.run(
|
||||||
|
Array(PlainVirtualFile(moduleInfo.toPath)),
|
||||||
|
allOpts.toArray,
|
||||||
|
output,
|
||||||
|
incToolOpts,
|
||||||
|
reporter,
|
||||||
|
log
|
||||||
|
)
|
||||||
|
if (!succ) {
|
||||||
|
log.error(s"Compilation of ${moduleInfo} failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.dependsOn(Compile / compile)
|
|
||||||
|
|
||||||
|
/** Copies all classes from all the dependencies `classes` directories into the target directory.
|
||||||
|
* @param sourceClassesDir Directory from where the classes will be copied.
|
||||||
|
* @param output Target directory where all the classes from all the dependencies
|
||||||
|
* will be copied to.
|
||||||
|
* @param log
|
||||||
|
* @return True iff some of the dependencies changed, i.e., if there is a modified class file, or
|
||||||
|
* some class file was added, or removed
|
||||||
|
*/
|
||||||
|
private def copyClasses(
|
||||||
|
sourceClassesDir: File,
|
||||||
|
output: xsbti.compile.Output,
|
||||||
|
cache: CacheStore,
|
||||||
|
log: Logger
|
||||||
|
): Boolean = {
|
||||||
|
require(sourceClassesDir.isDirectory)
|
||||||
|
val outputPath: Path = output.getSingleOutputAsPath.get()
|
||||||
|
val outputDir = outputPath.toFile
|
||||||
|
val filesToCopy = mutable.HashSet.empty[File]
|
||||||
|
val fileVisitor = new SimpleFileVisitor[Path] {
|
||||||
|
override def visitFile(
|
||||||
|
path: Path,
|
||||||
|
attrs: BasicFileAttributes
|
||||||
|
): FileVisitResult = {
|
||||||
|
if (!path.toFile.isDirectory) {
|
||||||
|
filesToCopy.add(path.toFile)
|
||||||
|
}
|
||||||
|
FileVisitResult.CONTINUE
|
||||||
|
}
|
||||||
|
|
||||||
|
override def preVisitDirectory(
|
||||||
|
dir: Path,
|
||||||
|
attrs: BasicFileAttributes
|
||||||
|
): FileVisitResult = {
|
||||||
|
// We do not care about files in META-INF directory. Everything should be described
|
||||||
|
// in the `module-info.java`.
|
||||||
|
if (dir.getFileName.toString == "META-INF") {
|
||||||
|
FileVisitResult.SKIP_SUBTREE
|
||||||
|
} else {
|
||||||
|
FileVisitResult.CONTINUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Files.walkFileTree(sourceClassesDir.toPath, fileVisitor)
|
||||||
|
if (!outputDir.exists()) {
|
||||||
|
IO.createDirectory(outputDir)
|
||||||
|
}
|
||||||
|
var someDependencyChanged = false
|
||||||
|
Tracked.diffInputs(cache, FileInfo.lastModified)(filesToCopy.toSet) {
|
||||||
|
changeReport =>
|
||||||
|
for (f <- changeReport.removed) {
|
||||||
|
val relPath = sourceClassesDir.toPath.relativize(f.toPath)
|
||||||
|
val dest = outputDir.toPath.resolve(relPath)
|
||||||
|
IO.delete(dest.toFile)
|
||||||
|
someDependencyChanged = true
|
||||||
|
}
|
||||||
|
for (f <- changeReport.modified -- changeReport.removed) {
|
||||||
|
val relPath = sourceClassesDir.toPath.relativize(f.toPath)
|
||||||
|
val dest = outputDir.toPath.resolve(relPath)
|
||||||
|
IO.copyFile(f, dest.toFile)
|
||||||
|
someDependencyChanged = true
|
||||||
|
}
|
||||||
|
for (f <- changeReport.unmodified) {
|
||||||
|
val relPath = sourceClassesDir.toPath.relativize(f.toPath)
|
||||||
|
val dest = outputDir.toPath.resolve(relPath)
|
||||||
|
if (!dest.toFile.exists()) {
|
||||||
|
IO.copyFile(f, dest.toFile)
|
||||||
|
someDependencyChanged = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
someDependencyChanged
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,11 +61,13 @@ object WithDebugCommand {
|
|||||||
val (debugFlags, prefixedRunArgs) = args.span(_ != argSeparator)
|
val (debugFlags, prefixedRunArgs) = args.span(_ != argSeparator)
|
||||||
val runArgs = " " + prefixedRunArgs.drop(1).mkString(" ")
|
val runArgs = " " + prefixedRunArgs.drop(1).mkString(" ")
|
||||||
|
|
||||||
val taskKey =
|
val taskKeyOpt =
|
||||||
if (debugFlags.contains(benchOnlyCommandName)) BenchTasks.benchOnly
|
if (debugFlags.contains(benchOnlyCommandName))
|
||||||
else if (debugFlags.contains(runCommandName)) Compile / Keys.run
|
Some(BenchTasks.benchOnly)
|
||||||
else if (debugFlags.contains(testOnlyCommandName)) Test / Keys.testOnly
|
else if (debugFlags.contains(runCommandName)) Some(Compile / Keys.run)
|
||||||
else throw new IllegalArgumentException("Invalid command name.")
|
else if (debugFlags.contains(testOnlyCommandName))
|
||||||
|
Some(Test / Keys.testOnly)
|
||||||
|
else None
|
||||||
|
|
||||||
val dumpGraphsOpts =
|
val dumpGraphsOpts =
|
||||||
if (debugFlags.contains(dumpGraphsOption)) truffleDumpGraphsOptions
|
if (debugFlags.contains(dumpGraphsOption)) truffleDumpGraphsOptions
|
||||||
@ -90,14 +92,22 @@ object WithDebugCommand {
|
|||||||
debuggerOpts
|
debuggerOpts
|
||||||
).flatten
|
).flatten
|
||||||
|
|
||||||
val extracted = Project.extract(state)
|
taskKeyOpt match {
|
||||||
val withJavaOpts = extracted.appendWithoutSession(
|
case None =>
|
||||||
Seq(Compile / Keys.javaOptions ++= javaOpts),
|
state.log.error(
|
||||||
state
|
s"Invalid command name. Expected one of $benchOnlyCommandName, $runCommandName, or $testOnlyCommandName"
|
||||||
)
|
)
|
||||||
Project
|
state.fail
|
||||||
.extract(withJavaOpts)
|
case Some(taskKey) =>
|
||||||
.runInputTask(taskKey, runArgs, withJavaOpts)
|
val extracted = Project.extract(state)
|
||||||
state
|
val withJavaOpts = extracted.appendWithoutSession(
|
||||||
|
Seq(Compile / Keys.javaOptions ++= javaOpts),
|
||||||
|
state
|
||||||
|
)
|
||||||
|
Project
|
||||||
|
.extract(withJavaOpts)
|
||||||
|
.runInputTask(taskKey, runArgs, withJavaOpts)
|
||||||
|
state
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
addSbtPlugin("com.sandinh" % "sbt-java-module-info" % "0.4.0")
|
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.1.3")
|
||||||
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.1.3")
|
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.6")
|
||||||
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.6")
|
addSbtPlugin("com.github.sbt" % "sbt-license-report" % "1.5.0")
|
||||||
addSbtPlugin("com.github.sbt" % "sbt-license-report" % "1.5.0")
|
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0")
|
||||||
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0")
|
addSbtPlugin("com.simplytyped" % "sbt-antlr4" % "0.8.3")
|
||||||
addSbtPlugin("com.simplytyped" % "sbt-antlr4" % "0.8.3")
|
|
||||||
|
|
||||||
libraryDependencies += "io.circe" %% "circe-yaml" % "0.14.2"
|
libraryDependencies += "io.circe" %% "circe-yaml" % "0.14.2"
|
||||||
libraryDependencies += "commons-io" % "commons-io" % "2.12.0"
|
libraryDependencies += "commons-io" % "commons-io" % "2.12.0"
|
||||||
|
Loading…
Reference in New Issue
Block a user