Add colours to Pkl errors in Cli output

To make error messages from Pkl eval easier to read, this change uses
the Jansi library to colour the output, making it quicker and easier to
scan error messages and understand what's happened.

The Jansi library also detects if the CLI output is a terminal capable
of handling colours, and will automatically strip out escape codes if
the output won't support them (e.g. piping the output somewhere else).
This commit is contained in:
Thomas Purchas
2024-06-26 23:15:05 +01:00
committed by Philip K.F. Hölzenspies
parent 49aaf288cc
commit 0d7b95d3ff
27 changed files with 93 additions and 28 deletions
+1
View File
@@ -8,6 +8,7 @@ net.sf.jopt-simple:jopt-simple:5.0.4=jmh,jmhCompileClasspath,jmhImplementationDe
org.apache.commons:commons-math3:3.6.1=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath org.apache.commons:commons-math3:3.6.1=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.fusesource.jansi:jansi:2.4.1=jmh,jmhRuntimeClasspath
org.graalvm.compiler:compiler:23.0.2=graal org.graalvm.compiler:compiler:23.0.2=graal
org.graalvm.sdk:graal-sdk:23.0.2=graal,jmh,jmhRuntimeClasspath,truffle org.graalvm.sdk:graal-sdk:23.0.2=graal,jmh,jmhRuntimeClasspath,truffle
org.graalvm.truffle:truffle-api:23.0.2=graal,jmh,jmhRuntimeClasspath,truffle org.graalvm.truffle:truffle-api:23.0.2=graal,jmh,jmhRuntimeClasspath,truffle
@@ -24,6 +24,9 @@ tasks.withType<Test>().configureEach {
// enable checking of stdlib return types // enable checking of stdlib return types
systemProperty("org.pkl.testMode", "true") systemProperty("org.pkl.testMode", "true")
// Disable colour output in tests
systemProperty("org.fusesource.jansi.Ansi.disable", "true")
reports.named("html") { reports.named("html") {
enabled = true enabled = true
} }
+1
View File
@@ -7,6 +7,7 @@ net.bytebuddy:byte-buddy:1.14.16=testCompileClasspath,testImplementationDependen
net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.fusesource.jansi:jansi:2.4.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.sdk:graal-sdk:23.0.2=testRuntimeClasspath org.graalvm.sdk:graal-sdk:23.0.2=testRuntimeClasspath
org.graalvm.truffle:truffle-api:23.0.2=testRuntimeClasspath org.graalvm.truffle:truffle-api:23.0.2=testRuntimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
+1 -1
View File
@@ -101,4 +101,4 @@ org.xmlunit:xmlunit-core:2.10.0=testCompileClasspath,testImplementationDependenc
org.xmlunit:xmlunit-legacy:2.10.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.xmlunit:xmlunit-legacy:2.10.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.xmlunit:xmlunit-placeholders:2.10.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.xmlunit:xmlunit-placeholders:2.10.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.yaml:snakeyaml:2.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.yaml:snakeyaml:2.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
empty=annotationProcessor,archives,compile,intransitiveDependenciesMetadata,javaExecutable,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,runtime,runtimeOnlyDependenciesMetadata,shadow,signatures,sourcesJar,stagedAlpineLinuxAmd64Executable,stagedLinuxAarch64Executable,stagedLinuxAmd64Executable,stagedMacAarch64Executable,stagedMacAmd64Executable,testAnnotationProcessor,testApiDependenciesMetadata,testCompile,testCompileOnly,testCompileOnlyDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDef,testKotlinScriptDefExtensions,testRuntime empty=annotationProcessor,archives,compile,intransitiveDependenciesMetadata,javaExecutable,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,runtime,runtimeOnlyDependenciesMetadata,shadow,signatures,sourcesJar,stagedAlpineLinuxAmd64Executable,stagedLinuxAarch64Executable,stagedLinuxAmd64Executable,stagedMacAarch64Executable,stagedMacAmd64Executable,stagedWindowsAmd64Executable,testAnnotationProcessor,testApiDependenciesMetadata,testCompile,testCompileOnly,testCompileOnlyDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDef,testKotlinScriptDefExtensions,testRuntime
+2 -1
View File
@@ -176,7 +176,8 @@ fun Exec.configureExecutable(
// that the "initialize everything at build time" *CLI* option is likely here to stay // that the "initialize everything at build time" *CLI* option is likely here to stay
add("--initialize-at-build-time=") add("--initialize-at-build-time=")
// needed for messagepack-java (see https://github.com/msgpack/msgpack-java/issues/600) // needed for messagepack-java (see https://github.com/msgpack/msgpack-java/issues/600)
add("--initialize-at-run-time=org.msgpack.core.buffer.DirectBufferAccess") // needed for jansi (see https://github.com/fusesource/jansi/issues/199#issuecomment-1252268229)
add("--initialize-at-run-time=org.msgpack.core.buffer.DirectBufferAccess,org.fusesource.jansi.internal")
add("--no-fallback") add("--no-fallback")
add("-H:IncludeResources=org/pkl/core/stdlib/.*\\.pkl") add("-H:IncludeResources=org/pkl/core/stdlib/.*\\.pkl")
add("-H:IncludeResources=org/jline/utils/.*") add("-H:IncludeResources=org/jline/utils/.*")
@@ -89,6 +89,7 @@ constructor(
} catch (ex: Exception) { } catch (ex: Exception) {
errWriter.appendLine("Error evaluating module ${moduleUri.path}:") errWriter.appendLine("Error evaluating module ${moduleUri.path}:")
errWriter.write(ex.message ?: "") errWriter.write(ex.message ?: "")
errWriter.write(ex.stackTraceToString())
if (moduleUri != sources.last()) { if (moduleUri != sources.last()) {
errWriter.appendLine() errWriter.appendLine()
} }
+1
View File
@@ -10,6 +10,7 @@ net.bytebuddy:byte-buddy:1.14.16=testCompileClasspath,testImplementationDependen
net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.fusesource.jansi:jansi:2.4.1=runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.sdk:graal-sdk:23.0.2=default,runtimeClasspath,testRuntimeClasspath org.graalvm.sdk:graal-sdk:23.0.2=default,runtimeClasspath,testRuntimeClasspath
org.graalvm.truffle:truffle-api:23.0.2=default,runtimeClasspath,testRuntimeClasspath org.graalvm.truffle:truffle-api:23.0.2=default,runtimeClasspath,testRuntimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
+1
View File
@@ -10,6 +10,7 @@ net.bytebuddy:byte-buddy:1.14.16=testCompileClasspath,testImplementationDependen
net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath,testRuntimeClasspath net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath,testRuntimeClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.fusesource.jansi:jansi:2.4.1=runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.sdk:graal-sdk:23.0.2=default,runtimeClasspath,testRuntimeClasspath org.graalvm.sdk:graal-sdk:23.0.2=default,runtimeClasspath,testRuntimeClasspath
org.graalvm.truffle:truffle-api:23.0.2=default,runtimeClasspath,testRuntimeClasspath org.graalvm.truffle:truffle-api:23.0.2=default,runtimeClasspath,testRuntimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
+1
View File
@@ -8,6 +8,7 @@ net.bytebuddy:byte-buddy:1.14.16=testCompileClasspath,testImplementationDependen
net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.fusesource.jansi:jansi:2.4.1=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.sdk:graal-sdk:23.0.2=default,runtimeClasspath,testRuntimeClasspath org.graalvm.sdk:graal-sdk:23.0.2=default,runtimeClasspath,testRuntimeClasspath
org.graalvm.truffle:truffle-api:23.0.2=default,runtimeClasspath,testRuntimeClasspath org.graalvm.truffle:truffle-api:23.0.2=default,runtimeClasspath,testRuntimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
+1 -1
View File
@@ -11,7 +11,7 @@ dependencies {
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk8") exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk8")
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-common") exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-common")
} }
implementation(libs.jansi)
implementation(projects.pklCommons) implementation(projects.pklCommons)
testImplementation(projects.pklCommonsTest) testImplementation(projects.pklCommonsTest)
} }
@@ -17,6 +17,7 @@ package org.pkl.commons.cli
import java.io.PrintStream import java.io.PrintStream
import kotlin.system.exitProcess import kotlin.system.exitProcess
import org.fusesource.jansi.AnsiConsole
/** Building block for CLIs. Intended to be called from a `main` method. */ /** Building block for CLIs. Intended to be called from a `main` method. */
fun cliMain(block: () -> Unit) { fun cliMain(block: () -> Unit) {
@@ -27,6 +28,9 @@ fun cliMain(block: () -> Unit) {
if (!message.endsWith('\n')) stream.println() if (!message.endsWith('\n')) stream.println()
} }
// Setup AnsiConsole. This will automatically strip escape codes if
// the target shell doesn't appear to support them.
AnsiConsole.systemInstall()
// Force `native-image` to use system proxies (which does not happen with `-D`). // Force `native-image` to use system proxies (which does not happen with `-D`).
System.setProperty("java.net.useSystemProxies", "true") System.setProperty("java.net.useSystemProxies", "true")
try { try {
+1
View File
@@ -7,6 +7,7 @@ net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.apiguardian:apiguardian-api:1.1.2=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.apiguardian:apiguardian-api:1.1.2=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.24.2=default org.assertj:assertj-core:3.24.2=default
org.assertj:assertj-core:3.26.0=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.assertj:assertj-core:3.26.0=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.fusesource.jansi:jansi:2.4.1=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
@@ -11,6 +11,7 @@ dependencies {
api(libs.junitApi) api(libs.junitApi)
api(libs.junitEngine) api(libs.junitEngine)
api(libs.junitParams) api(libs.junitParams)
api(libs.jansi)
api(projects.pklCommons) // for convenience api(projects.pklCommons) // for convenience
implementation(libs.assertj) implementation(libs.assertj)
} }
+1
View File
@@ -12,6 +12,7 @@ net.bytebuddy:byte-buddy:1.14.16=testCompileClasspath,testImplementationDependen
net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.fusesource.jansi:jansi:2.4.1=pklCodegenJava,runtimeClasspath,testRuntimeClasspath
org.graalvm.sdk:graal-sdk:23.0.2=default,pklCodegenJava,runtimeClasspath,testRuntimeClasspath org.graalvm.sdk:graal-sdk:23.0.2=default,pklCodegenJava,runtimeClasspath,testRuntimeClasspath
org.graalvm.truffle:truffle-api:23.0.2=default,pklCodegenJava,runtimeClasspath,testRuntimeClasspath org.graalvm.truffle:truffle-api:23.0.2=default,pklCodegenJava,runtimeClasspath,testRuntimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
+1
View File
@@ -11,6 +11,7 @@ net.bytebuddy:byte-buddy:1.14.16=testCompileClasspath,testImplementationDependen
net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.fusesource.jansi:jansi:2.4.1=pklCodegenKotlin,pklConfigJava,runtimeClasspath,testRuntimeClasspath
org.graalvm.sdk:graal-sdk:23.0.2=default,pklCodegenKotlin,pklConfigJava,runtimeClasspath,testRuntimeClasspath org.graalvm.sdk:graal-sdk:23.0.2=default,pklCodegenKotlin,pklConfigJava,runtimeClasspath,testRuntimeClasspath
org.graalvm.truffle:truffle-api:23.0.2=default,pklCodegenKotlin,pklConfigJava,runtimeClasspath,testRuntimeClasspath org.graalvm.truffle:truffle-api:23.0.2=default,pklCodegenKotlin,pklConfigJava,runtimeClasspath,testRuntimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
+1
View File
@@ -13,6 +13,7 @@ org.antlr:ST4:4.3=antlr
org.antlr:antlr-runtime:3.5.2=antlr org.antlr:antlr-runtime:3.5.2=antlr
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.fusesource.jansi:jansi:2.4.1=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.sdk:graal-sdk:23.0.2=compileClasspath,default,generatorCompileClasspath,generatorImplementationDependenciesMetadata,generatorRuntimeClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.graalvm.sdk:graal-sdk:23.0.2=compileClasspath,default,generatorCompileClasspath,generatorImplementationDependenciesMetadata,generatorRuntimeClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.truffle:truffle-api:23.0.2=compileClasspath,default,generatorCompileClasspath,generatorImplementationDependenciesMetadata,generatorRuntimeClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.graalvm.truffle:truffle-api:23.0.2=compileClasspath,default,generatorCompileClasspath,generatorImplementationDependenciesMetadata,generatorRuntimeClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.truffle:truffle-dsl-processor:23.0.2=annotationProcessor org.graalvm.truffle:truffle-dsl-processor:23.0.2=annotationProcessor
+2
View File
@@ -57,6 +57,8 @@ dependencies {
implementation(libs.snakeYaml) implementation(libs.snakeYaml)
implementation(libs.jansi)
testImplementation(projects.pklCommonsTest) testImplementation(projects.pklCommonsTest)
add("generatorImplementation", libs.javaPoet) add("generatorImplementation", libs.javaPoet)
@@ -15,15 +15,23 @@
*/ */
package org.pkl.core.runtime; package org.pkl.core.runtime;
import static org.fusesource.jansi.Ansi.ansi;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Function; import java.util.function.Function;
import org.fusesource.jansi.Ansi;
import org.fusesource.jansi.Ansi.Color;
import org.pkl.core.StackFrame; import org.pkl.core.StackFrame;
import org.pkl.core.util.Nullable; import org.pkl.core.util.Nullable;
public final class StackTraceRenderer { public final class StackTraceRenderer {
private final Function<StackFrame, StackFrame> frameTransformer; private final Function<StackFrame, StackFrame> frameTransformer;
private static final Ansi.Color frameColor = Color.YELLOW;
private static final Ansi.Color lineNumColor = Color.BLUE;
private static final Ansi.Color repetitionColor = Color.MAGENTA;
public StackTraceRenderer(Function<StackFrame, StackFrame> frameTransformer) { public StackTraceRenderer(Function<StackFrame, StackFrame> frameTransformer) {
this.frameTransformer = frameTransformer; this.frameTransformer = frameTransformer;
} }
@@ -40,6 +48,7 @@ public final class StackTraceRenderer {
StringBuilder builder, StringBuilder builder,
String leftMargin, String leftMargin,
boolean isFirstElement) { boolean isFirstElement) {
var out = ansi(builder);
for (var frame : frames) { for (var frame : frames) {
if (frame instanceof StackFrameLoop loop) { if (frame instanceof StackFrameLoop loop) {
// ensure a cycle of length 1 doesn't get rendered as a loop // ensure a cycle of length 1 doesn't get rendered as a loop
@@ -47,20 +56,28 @@ public final class StackTraceRenderer {
doRender(loop.frames, null, builder, leftMargin, isFirstElement); doRender(loop.frames, null, builder, leftMargin, isFirstElement);
} else { } else {
if (!isFirstElement) { if (!isFirstElement) {
builder.append(leftMargin).append("\n"); out.fgBright(frameColor).a(leftMargin).reset().a("\n");
} }
builder.append(leftMargin).append("┌─ ").append(loop.count).append(" repetitions of:\n"); out.fgBright(frameColor)
.a(leftMargin)
.a("┌─ ")
.reset()
.bold()
.fg(repetitionColor)
.a(Integer.toString(loop.count))
.reset()
.a(" repetitions of:\n");
var newLeftMargin = leftMargin + ""; var newLeftMargin = leftMargin + "";
doRender(loop.frames, null, builder, newLeftMargin, isFirstElement); doRender(loop.frames, null, builder, newLeftMargin, isFirstElement);
if (isFirstElement) { if (isFirstElement) {
renderHint(hint, builder, newLeftMargin); renderHint(hint, builder, newLeftMargin);
isFirstElement = false; isFirstElement = false;
} }
builder.append(leftMargin).append("└─\n"); out.fgBright(frameColor).a(leftMargin).a("└─").reset().a("\n");
} }
} else { } else {
if (!isFirstElement) { if (!isFirstElement) {
builder.append(leftMargin).append('\n'); out.fgBright(frameColor).a(leftMargin).reset().a('\n');
} }
renderFrame((StackFrame) frame, builder, leftMargin); renderFrame((StackFrame) frame, builder, leftMargin);
} }
@@ -80,14 +97,16 @@ public final class StackTraceRenderer {
private void renderHint(@Nullable String hint, StringBuilder builder, String leftMargin) { private void renderHint(@Nullable String hint, StringBuilder builder, String leftMargin) {
if (hint == null || hint.isEmpty()) return; if (hint == null || hint.isEmpty()) return;
var out = ansi(builder);
builder.append('\n'); out.a('\n');
builder.append(leftMargin); out.fgBright(frameColor).a(leftMargin);
builder.append(hint); out.fgBright(frameColor).bold().a(hint).reset();
builder.append('\n'); out.a('\n');
} }
private void renderSourceLine(StackFrame frame, StringBuilder builder, String leftMargin) { private void renderSourceLine(StackFrame frame, StringBuilder builder, String leftMargin) {
var out = ansi(builder);
var originalSourceLine = frame.getSourceLines().get(0); var originalSourceLine = frame.getSourceLines().get(0);
var leadingWhitespace = VmUtils.countLeadingWhitespace(originalSourceLine); var leadingWhitespace = VmUtils.countLeadingWhitespace(originalSourceLine);
var sourceLine = originalSourceLine.strip(); var sourceLine = originalSourceLine.strip();
@@ -98,27 +117,36 @@ public final class StackTraceRenderer {
: sourceLine.length(); : sourceLine.length();
var prefix = frame.getStartLine() + " | "; var prefix = frame.getStartLine() + " | ";
builder.append(leftMargin).append(prefix).append(sourceLine).append('\n'); out.fgBright(frameColor)
builder.append(leftMargin); .a(leftMargin)
.fgBright(lineNumColor)
.a(prefix)
.reset()
.a(sourceLine)
.a('\n');
out.fgBright(frameColor).a(leftMargin).reset();
//noinspection StringRepeatCanBeUsed //noinspection StringRepeatCanBeUsed
for (int i = 1; i < prefix.length() + startColumn; i++) { for (int i = 1; i < prefix.length() + startColumn; i++) {
builder.append(' '); out.append(' ');
} }
out.fgRed();
//noinspection StringRepeatCanBeUsed //noinspection StringRepeatCanBeUsed
for (int i = startColumn; i <= endColumn; i++) { for (int i = startColumn; i <= endColumn; i++) {
builder.append('^'); out.a('^');
} }
builder.append('\n'); out.reset().a('\n');
} }
private void renderSourceLocation(StackFrame frame, StringBuilder builder, String leftMargin) { private void renderSourceLocation(StackFrame frame, StringBuilder builder, String leftMargin) {
builder.append(leftMargin).append("at "); var out = ansi(builder);
out.fgBright(frameColor).a(leftMargin).reset().a("at ");
if (frame.getMemberName() != null) { if (frame.getMemberName() != null) {
builder.append(frame.getMemberName()); out.a(frame.getMemberName());
} else { } else {
builder.append("<unknown>"); out.a("<unknown>");
} }
builder.append(" (").append(frame.getModuleUri()).append(')').append('\n'); out.a(" (").a(frame.getModuleUri()).a(')').a('\n');
} }
/** /**
@@ -15,10 +15,14 @@
*/ */
package org.pkl.core.runtime; package org.pkl.core.runtime;
import static org.fusesource.jansi.Ansi.ansi;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import org.fusesource.jansi.Ansi;
import org.fusesource.jansi.Ansi.Color;
import org.pkl.core.Release; import org.pkl.core.Release;
import org.pkl.core.util.ErrorMessages; import org.pkl.core.util.ErrorMessages;
import org.pkl.core.util.Nullable; import org.pkl.core.util.Nullable;
@@ -27,6 +31,8 @@ import org.pkl.core.util.StringBuilderWriter;
public final class VmExceptionRenderer { public final class VmExceptionRenderer {
private final @Nullable StackTraceRenderer stackTraceRenderer; private final @Nullable StackTraceRenderer stackTraceRenderer;
private static final Ansi.Color errorColor = Color.RED;
/** /**
* Constructs an error renderer with the given stack trace renderer. If stack trace renderer is * Constructs an error renderer with the given stack trace renderer. If stack trace renderer is
* {@code null}, stack traces will not be included in error output. * {@code null}, stack traces will not be included in error output.
@@ -73,7 +79,8 @@ public final class VmExceptionRenderer {
} }
private void renderException(VmException exception, StringBuilder builder) { private void renderException(VmException exception, StringBuilder builder) {
var header = "–– Pkl Error ––"; var out = ansi(builder);
out.fg(errorColor).a("–– Pkl Error ––").reset();
String message; String message;
var hint = exception.getHint(); var hint = exception.getHint();
@@ -94,7 +101,7 @@ public final class VmExceptionRenderer {
message = exception.getMessage(); message = exception.getMessage();
} }
builder.append(header).append('\n').append(message).append('\n'); out.a('\n').fgBright(errorColor).a(message).reset().a('\n');
// include cause's message unless it's the same as this exception's message // include cause's message unless it's the same as this exception's message
if (exception.getCause() != null) { if (exception.getCause() != null) {
@@ -3,7 +3,6 @@ package org.pkl.core
import org.pkl.commons.createTempFile import org.pkl.commons.createTempFile
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir import org.junit.jupiter.api.io.TempDir
import org.pkl.commons.writeString import org.pkl.commons.writeString
@@ -11,7 +10,6 @@ import org.pkl.core.ModuleSource.*
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.createFile import kotlin.io.path.createFile
import kotlin.io.path.name
class EvaluateTestsTest { class EvaluateTestsTest {
@@ -149,8 +149,9 @@ class ProjectTest {
.setModuleCacheDir(null) .setModuleCacheDir(null)
.setHttpClient(httpClient) .setHttpClient(httpClient)
.build() .build()
assertThatCode { evaluator.evaluate(ModuleSource.path(projectDir.resolve("bug.pkl"))) } assertThatCode {
.hasMessageStartingWith(""" evaluator.evaluate(ModuleSource.path(projectDir.resolve("bug.pkl")))
}.hasMessageStartingWith("""
–– Pkl Error –– –– Pkl Error ––
Cannot download package `package://localhost:0/fruit@1.0.5` because the computed checksum for package metadata does not match the expected checksum. Cannot download package `package://localhost:0/fruit@1.0.5` because the computed checksum for package metadata does not match the expected checksum.
+1
View File
@@ -40,6 +40,7 @@ org.commonmark:commonmark:0.21.0=default
org.commonmark:commonmark:0.22.0=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.commonmark:commonmark:0.22.0=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.eclipse.jetty:jetty-util-ajax:9.4.18.v20190429=validator org.eclipse.jetty:jetty-util-ajax:9.4.18.v20190429=validator
org.eclipse.jetty:jetty-util:9.4.18.v20190429=validator org.eclipse.jetty:jetty-util:9.4.18.v20190429=validator
org.fusesource.jansi:jansi:2.4.1=testCompileClasspath,testRuntimeClasspath
org.graalvm.js:js:23.0.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.graalvm.js:js:23.0.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.regex:regex:23.0.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.graalvm.regex:regex:23.0.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.sdk:graal-sdk:23.0.2=default,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.graalvm.sdk:graal-sdk:23.0.2=default,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
+1
View File
@@ -6,6 +6,7 @@ net.bytebuddy:byte-buddy:1.14.16=testCompileClasspath,testImplementationDependen
net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.fusesource.jansi:jansi:2.4.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.sdk:graal-sdk:23.0.2=testRuntimeClasspath org.graalvm.sdk:graal-sdk:23.0.2=testRuntimeClasspath
org.graalvm.truffle:truffle-api:23.0.2=testRuntimeClasspath org.graalvm.truffle:truffle-api:23.0.2=testRuntimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
+1
View File
@@ -7,6 +7,7 @@ net.bytebuddy:byte-buddy:1.14.16=testCompileClasspath,testImplementationDependen
net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.fusesource.jansi:jansi:2.4.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
+6
View File
@@ -74,6 +74,12 @@ gradlePluginTests {
skippedGradleVersions = listOf() skippedGradleVersions = listOf()
} }
tasks.withType<Test>().configureEach {
// Disable colour output in tests
// Need additional disablement here because of how Jansi is packaged in the plugin
systemProperty("org.pkl.thirdparty.jansiAnsi.disable", "true")
}
signing { signing {
publishing.publications.withType(MavenPublication::class.java).configureEach { publishing.publications.withType(MavenPublication::class.java).configureEach {
if (name != "library") { if (name != "library") {
+1
View File
@@ -6,6 +6,7 @@ net.bytebuddy:byte-buddy:1.14.16=testCompileClasspath,testImplementationDependen
net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.fusesource.jansi:jansi:2.4.1=testCompileClasspath,testRuntimeClasspath
org.graalvm.sdk:graal-sdk:23.0.2=compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.graalvm.sdk:graal-sdk:23.0.2=compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.graalvm.truffle:truffle-api:23.0.2=compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.graalvm.truffle:truffle-api:23.0.2=compileClasspath,default,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath