diff --git a/pkl-executor/gradle.lockfile b/pkl-executor/gradle.lockfile index fb250002..d1f0e016 100644 --- a/pkl-executor/gradle.lockfile +++ b/pkl-executor/gradle.lockfile @@ -2,10 +2,28 @@ # Manual edits can break the build and are not advised. # This file is expected to be part of source control. com.github.ben-manes.caffeine:caffeine:2.9.3=swiftExportClasspathResolvable +com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,testAnnotationProcessor +com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,testAnnotationProcessor +com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,testAnnotationProcessor +com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,testAnnotationProcessor +com.google.auto:auto-common:1.2.2=annotationProcessor,testAnnotationProcessor +com.google.errorprone:error_prone_annotation:2.48.0=annotationProcessor,testAnnotationProcessor com.google.errorprone:error_prone_annotations:2.28.0=swiftExportClasspathResolvable -io.github.java-diff-utils:java-diff-utils:4.12=kotlinInternalAbiValidation +com.google.errorprone:error_prone_annotations:2.48.0=annotationProcessor,testAnnotationProcessor +com.google.errorprone:error_prone_check_api:2.48.0=annotationProcessor,testAnnotationProcessor +com.google.errorprone:error_prone_core:2.48.0=annotationProcessor,testAnnotationProcessor +com.google.googlejavaformat:google-java-format:1.34.1=annotationProcessor,testAnnotationProcessor +com.google.guava:failureaccess:1.0.3=annotationProcessor,testAnnotationProcessor +com.google.guava:guava:33.5.0-jre=annotationProcessor,testAnnotationProcessor +com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,testAnnotationProcessor +com.google.j2objc:j2objc-annotations:3.1=annotationProcessor,testAnnotationProcessor +com.google.protobuf:protobuf-java:4.33.2=annotationProcessor,testAnnotationProcessor +com.uber.nullaway:nullaway:0.13.1=annotationProcessor,testAnnotationProcessor +io.github.eisop:dataflow-errorprone:3.41.0-eisop1=annotationProcessor,testAnnotationProcessor +io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,kotlinInternalAbiValidation,testAnnotationProcessor io.opentelemetry:opentelemetry-api:1.41.0=swiftExportClasspathResolvable io.opentelemetry:opentelemetry-context:1.41.0=swiftExportClasspathResolvable +javax.inject:javax.inject:1=annotationProcessor,testAnnotationProcessor net.bytebuddy:byte-buddy:1.18.3=testCompileClasspath,testRuntimeClasspath org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath org.assertj:assertj-core:3.27.7=testCompileClasspath,testRuntimeClasspath @@ -14,6 +32,8 @@ org.bouncycastle:bcpkix-jdk18on:1.80=kotlinBouncyCastleConfiguration org.bouncycastle:bcprov-jdk18on:1.80=kotlinBouncyCastleConfiguration org.bouncycastle:bcutil-jdk18on:1.80=kotlinBouncyCastleConfiguration org.checkerframework:checker-qual:3.43.0=swiftExportClasspathResolvable +org.checkerframework:checker-qual:3.53.0=annotationProcessor,testAnnotationProcessor +org.checkerframework:dataflow-nullaway:3.53.0=annotationProcessor,testAnnotationProcessor org.graalvm.polyglot:polyglot:25.0.1=testRuntimeClasspath org.graalvm.sdk:collections:25.0.1=testRuntimeClasspath org.graalvm.sdk:graal-sdk:25.0.1=testRuntimeClasspath @@ -53,7 +73,7 @@ org.jetbrains.kotlinx:kotlinx-serialization-bom:1.7.3=swiftExportClasspathResolv org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.3=swiftExportClasspathResolvable org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3=swiftExportClasspathResolvable org.jetbrains:annotations:13.0=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinInternalAbiValidation,kotlinKlibCommonizerClasspath,swiftExportClasspathResolvable,testCompileClasspath,testRuntimeClasspath -org.jspecify:jspecify:1.0.0=testCompileClasspath,testRuntimeClasspath +org.jspecify:jspecify:1.0.0=annotationProcessor,compileClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath org.junit.jupiter:junit-jupiter-api:6.0.3=testCompileClasspath,testRuntimeClasspath org.junit.jupiter:junit-jupiter-engine:6.0.3=testCompileClasspath,testRuntimeClasspath org.junit.jupiter:junit-jupiter-params:6.0.3=testCompileClasspath,testRuntimeClasspath @@ -64,8 +84,9 @@ org.junit:junit-bom:6.0.3=testCompileClasspath,testRuntimeClasspath org.msgpack:msgpack-core:0.9.11=testRuntimeClasspath org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath org.organicdesign:Paguro:3.10.3=testRuntimeClasspath +org.pcollections:pcollections:4.0.1=annotationProcessor,testAnnotationProcessor org.pkl-lang:pkl-config-java-all:0.25.0=pklHistoricalDistributions org.slf4j:slf4j-api:2.0.17=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.slf4j:slf4j-simple:2.0.17=testCompileClasspath,testRuntimeClasspath org.snakeyaml:snakeyaml-engine:2.10=testRuntimeClasspath -empty=annotationProcessor,apiDependenciesMetadata,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,intransitiveDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDefExtensions,pklDistributionCurrent,signatures,sourcesJar,testAnnotationProcessor,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testImplementationDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDefExtensions +empty=apiDependenciesMetadata,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,intransitiveDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDefExtensions,pklDistributionCurrent,signatures,sourcesJar,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testImplementationDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDefExtensions diff --git a/pkl-executor/pkl-executor.gradle.kts b/pkl-executor/pkl-executor.gradle.kts index ba47f1a6..232b58ae 100644 --- a/pkl-executor/pkl-executor.gradle.kts +++ b/pkl-executor/pkl-executor.gradle.kts @@ -20,6 +20,7 @@ plugins { id("pklAllProjects") id("pklJavaLibrary") id("pklPublishLibrary") + id("pklJSpecify") } val pklDistributionCurrent: Configuration by configurations.creating @@ -31,7 +32,7 @@ val pklHistoricalDistributions: Configuration by configurations.creating // (Pkl distributions used by EmbeddedExecutor are isolated via class loaders.) dependencies { pklDistributionCurrent(project(":pkl-config-java", "fatJar")) - @Suppress("UnstableApiUsage") pklHistoricalDistributions(libs.pklConfigJavaAll025) + pklHistoricalDistributions(libs.pklConfigJavaAll025) implementation(libs.slf4jApi) diff --git a/pkl-executor/src/main/java/org/pkl/executor/EmbeddedExecutor.java b/pkl-executor/src/main/java/org/pkl/executor/EmbeddedExecutor.java index e7d67f88..059eda4f 100644 --- a/pkl-executor/src/main/java/org/pkl/executor/EmbeddedExecutor.java +++ b/pkl-executor/src/main/java/org/pkl/executor/EmbeddedExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import java.nio.file.Path; import java.util.*; import java.util.regex.Pattern; import java.util.stream.Collectors; +import org.jspecify.annotations.Nullable; import org.pkl.executor.spi.v1.ExecutorSpi; import org.pkl.executor.spi.v1.ExecutorSpiException; import org.slf4j.Logger; @@ -60,8 +61,7 @@ final class EmbeddedExecutor implements Executor { Version requestedVersion = null; PklDistribution distribution = null; - String output = null; - RuntimeException exception = null; + String output; try { if (!Files.isRegularFile(modulePath)) { @@ -76,29 +76,33 @@ final class EmbeddedExecutor implements Executor { // (but not any modules imported by it) and only requires parsing (but not evaluating) the // module. requestedVersion = detectRequestedPklVersion(modulePath, options); - //noinspection resource distribution = findCompatibleDistribution(modulePath, requestedVersion, options); output = distribution.evaluatePath(modulePath, options); } catch (RuntimeException e) { - exception = e; + // Could log exception, but this would violate "don't log and throw", + // and Pkl stack trace might contain semi-sensitive information. + logFinished(modulePath, false, requestedVersion, distribution, startTime, System.nanoTime()); + throw e; } - var endTime = System.nanoTime(); + logFinished(modulePath, true, requestedVersion, distribution, startTime, System.nanoTime()); + return output; + } - // Could log exception, but this would violate "don't log and throw", - // and Pkl stack trace might contain semi-sensitive information. + private static void logFinished( + Path modulePath, + boolean success, + @Nullable Version requestedVersion, + @Nullable PklDistribution distribution, + long startTime, + long endTime) { logger.info( "Finished evaluating Pkl module. modulePath={} outcome={} requestedVersion={} selectedVersion={} elapsedMillis={}", modulePath, - exception == null ? "success" : "failure", + success, requestedVersion == null ? "n/a" : requestedVersion.toString(), distribution == null ? "n/a" : distribution.getVersion().toString(), (endTime - startTime) / 1_000_000); - - if (exception != null) throw exception; - - assert output != null; - return output; } private Version detectRequestedPklVersion(Path modulePath, ExecutorOptions options) { @@ -126,7 +130,7 @@ final class EmbeddedExecutor implements Executor { toDisplayPath(modulePath, options), availableVersions)); } - /* @Nullable */ static Version extractMinPklVersion(String sourceText) { + static @Nullable Version extractMinPklVersion(String sourceText) { var matcher = MODULE_INFO_PATTERN.matcher(sourceText); return matcher.find() ? Version.parse(matcher.group(1)) : null; } @@ -177,7 +181,7 @@ final class EmbeddedExecutor implements Executor { private static final class PklDistribution implements AutoCloseable { final URLClassLoader pklDistributionClassLoader; - final /* @Nullable */ ExecutorSpi executorSpi; + final ExecutorSpi executorSpi; final Version version; /** diff --git a/pkl-executor/src/main/java/org/pkl/executor/ExecutorException.java b/pkl-executor/src/main/java/org/pkl/executor/ExecutorException.java index 5a50f078..c77317fe 100644 --- a/pkl-executor/src/main/java/org/pkl/executor/ExecutorException.java +++ b/pkl-executor/src/main/java/org/pkl/executor/ExecutorException.java @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,24 +16,26 @@ package org.pkl.executor; import java.util.Objects; +import org.jspecify.annotations.Nullable; /** * Indicates an {@link Executor} error. {@link #getMessage()} returns a user-facing error message. */ public final class ExecutorException extends RuntimeException { - private final String pklVersion; + private final @Nullable String pklVersion; public ExecutorException(String message) { super(message); pklVersion = null; } - public ExecutorException(String message, Throwable cause) { + public ExecutorException(@Nullable String message, @Nullable Throwable cause) { super(message, cause); pklVersion = null; } - public ExecutorException(String message, Throwable cause, String version) { + public ExecutorException( + @Nullable String message, @Nullable Throwable cause, @Nullable String version) { super(message, cause); pklVersion = Objects.requireNonNull(version); } @@ -43,12 +45,12 @@ public final class ExecutorException extends RuntimeException { * *
Returns {@code null} if this exception does not originate from an underlying Pkl evaluator.
*/
- public String getPklVersion() {
+ public @Nullable String getPklVersion() {
return pklVersion;
}
@Override
- public String getMessage() {
+ public @Nullable String getMessage() {
var message = super.getMessage();
if (pklVersion == null) {
return message;
diff --git a/pkl-executor/src/main/java/org/pkl/executor/ExecutorOptions.java b/pkl-executor/src/main/java/org/pkl/executor/ExecutorOptions.java
index 27c92f9e..e81960aa 100644
--- a/pkl-executor/src/main/java/org/pkl/executor/ExecutorOptions.java
+++ b/pkl-executor/src/main/java/org/pkl/executor/ExecutorOptions.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
+ * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import org.jspecify.annotations.Nullable;
import org.pkl.executor.spi.v1.ExecutorSpiOptions;
import org.pkl.executor.spi.v1.ExecutorSpiOptions2;
import org.pkl.executor.spi.v1.ExecutorSpiOptions3;
@@ -41,15 +42,15 @@ public final class ExecutorOptions {
private final List Unlike the CLI, this option only sets project dependencies. It does not set evaluator
* settings.
*/
- public /* @Nullable */ Path getProjectDir() {
+ public @Nullable Path getProjectDir() {
return projectDir;
}
@@ -407,11 +408,10 @@ public final class ExecutorOptions {
}
@Override
- public boolean equals(/* @Nullable */ Object obj) {
+ public boolean equals(@Nullable Object obj) {
if (this == obj) return true;
- if (obj.getClass() != ExecutorOptions.class) return false;
+ if (!(obj instanceof ExecutorOptions other)) return false;
- var other = (ExecutorOptions) obj;
return allowedModules.equals(other.allowedModules)
&& allowedResources.equals(other.allowedResources)
&& environmentVariables.equals(other.environmentVariables)
diff --git a/pkl-executor/src/main/java/org/pkl/executor/Version.java b/pkl-executor/src/main/java/org/pkl/executor/Version.java
index 2f2d8a28..02a0ab65 100644
--- a/pkl-executor/src/main/java/org/pkl/executor/Version.java
+++ b/pkl-executor/src/main/java/org/pkl/executor/Version.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
+ * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ package org.pkl.executor;
import java.util.*;
import java.util.regex.Pattern;
+import org.jspecify.annotations.Nullable;
/**
* A semantic version.
@@ -54,19 +55,15 @@ final class Version implements Comparable Returns {@code null} if the given string could not be parsed as a semantic version number or
* is too large to fit into a {@link Version}.
*/
- public static /*@Nullable*/ Version parseOrNull(String version) {
+ public static @Nullable Version parseOrNull(String version) {
var matcher = VERSION.matcher(version);
if (!matcher.matches()) return null;
@@ -151,22 +148,22 @@ final class Version implements Comparable