diff --git a/pkl-gradle/gradle.lockfile b/pkl-gradle/gradle.lockfile index 4be37e7d..14afa279 100644 --- a/pkl-gradle/gradle.lockfile +++ b/pkl-gradle/gradle.lockfile @@ -16,10 +16,28 @@ com.github.ajalt.mordant:mordant-jvm:3.0.1=compileClasspath com.github.ajalt.mordant:mordant:3.0.1=compileClasspath com.github.ajalt.mordant:mordant:3.0.2=compileOnlyDependenciesMetadata 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 @@ -28,6 +46,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.jetbrains.kotlin:abi-tools-api:2.3.20=kotlinInternalAbiValidation org.jetbrains.kotlin:abi-tools:2.3.20=kotlinInternalAbiValidation org.jetbrains.kotlin:kotlin-build-tools-api:2.3.20=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath @@ -63,7 +83,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=compileClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinInternalAbiValidation,kotlinKlibCommonizerClasspath,swiftExportClasspathResolvable,testCompileClasspath,testRuntimeClasspath -org.jspecify:jspecify:1.0.0=compileClasspath,testCompileClasspath +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 @@ -73,4 +93,5 @@ org.junit.platform:junit-platform-launcher:6.0.3=testRuntimeClasspath 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 -empty=annotationProcessor,apiDependenciesMetadata,implementationDependenciesMetadata,intransitiveDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDefExtensions,runtimeClasspath,signatures,sourcesJar,testAnnotationProcessor,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testImplementationDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDefExtensions +org.pcollections:pcollections:4.0.1=annotationProcessor,testAnnotationProcessor +empty=apiDependenciesMetadata,implementationDependenciesMetadata,intransitiveDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDefExtensions,signatures,sourcesJar,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testImplementationDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDefExtensions diff --git a/pkl-gradle/pkl-gradle.gradle.kts b/pkl-gradle/pkl-gradle.gradle.kts index bea7fe30..c6b55f67 100644 --- a/pkl-gradle/pkl-gradle.gradle.kts +++ b/pkl-gradle/pkl-gradle.gradle.kts @@ -17,7 +17,7 @@ plugins { id("pklAllProjects") id("pklJavaLibrary") id("pklGradlePluginTest") - + id("pklJSpecify") `java-gradle-plugin` `maven-publish` id("pklPublishLibrary") diff --git a/pkl-gradle/src/main/java/org/pkl/gradle/PklPlugin.java b/pkl-gradle/src/main/java/org/pkl/gradle/PklPlugin.java index 619ab783..943bf2f3 100644 --- a/pkl-gradle/src/main/java/org/pkl/gradle/PklPlugin.java +++ b/pkl-gradle/src/main/java/org/pkl/gradle/PklPlugin.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. @@ -36,12 +36,11 @@ import org.gradle.api.tasks.TaskProvider; import org.gradle.language.base.plugins.LifecycleBasePlugin; import org.gradle.plugins.ide.idea.model.IdeaModel; import org.gradle.util.GradleVersion; +import org.jspecify.annotations.Nullable; import org.pkl.cli.CliEvaluatorOptions; import org.pkl.core.ImportGraph; import org.pkl.core.OutputFormat; import org.pkl.core.util.IoUtils; -import org.pkl.core.util.LateInit; -import org.pkl.core.util.Nullable; import org.pkl.gradle.spec.AnalyzeImportsSpec; import org.pkl.gradle.spec.BasePklSpec; import org.pkl.gradle.spec.CodeGenSpec; @@ -71,21 +70,26 @@ public class PklPlugin implements Plugin { private static final String MIN_GRADLE_VERSION = "8.2"; - @LateInit private Project project; + private @Nullable Project __project; @Override public void apply(Project project) { - this.project = project; + __project = project; if (GradleVersion.current().compareTo(GradleVersion.version(MIN_GRADLE_VERSION)) < 0) { throw new GradleException( String.format("Plugin `org.pkl` requires Gradle %s or higher.", MIN_GRADLE_VERSION)); } - var extension = project.getExtensions().create("pkl", PklExtension.class); + var extension = project().getExtensions().create("pkl", PklExtension.class); configureExtension(extension); } + private Project project() { + assert __project != null; + return __project; + } + private void configureExtension(PklExtension extension) { configureEvalTasks(extension.getEvaluators()); configureJavaCodeGenTasks(extension.getJavaCodeGenerators()); @@ -102,7 +106,7 @@ public class PklPlugin implements Plugin { spec -> { configureBaseSpec(spec); spec.getOutputPath() - .convention(project.getLayout().getBuildDirectory().dir("generated/pkl/packages")); + .convention(project().getLayout().getBuildDirectory().dir("generated/pkl/packages")); spec.getOverwrite().convention(false); var packageTask = createTask(ProjectPackageTask.class, spec); packageTask.configure( @@ -113,12 +117,12 @@ public class PklPlugin implements Plugin { task.getJunitReportsDir().set(spec.getJunitReportsDir()); task.getOverwrite().set(spec.getOverwrite()); }); - project + project() .getPluginManager() .withPlugin( "base", appliedPlugin -> - project + project() .getTasks() .named( LifecycleBasePlugin.BUILD_TASK_NAME, @@ -157,7 +161,7 @@ public class PklPlugin implements Plugin { configureBaseSpec(spec); spec.getOutputFile() .convention( - project + project() .getLayout() .getProjectDirectory() // %{moduleDir} is resolved relatively to the working directory, @@ -194,11 +198,12 @@ public class PklPlugin implements Plugin { // constructor parameters annotations by setting this property to `null`. spec.getParamsAnnotation() .set( - project.provider( - () -> - spec.getGenerateSpringBootConfig().get() - ? null - : "org.pkl.config.java.mapper.Named")); + project() + .provider( + () -> + spec.getGenerateSpringBootConfig().get() + ? null + : "org.pkl.config.java.mapper.Named")); createModulesTask(JavaCodeGenTask.class, spec) .configure( @@ -211,14 +216,15 @@ public class PklPlugin implements Plugin { }); }); - project.afterEvaluate( - prj -> - specs.all( - spec -> { - configureIdeaModule(spec); - configureCodeGenSpecSourceDirectories( - spec, "java", s -> Optional.of(s.getJava())); - })); + project() + .afterEvaluate( + prj -> + specs.all( + spec -> { + configureIdeaModule(spec); + configureCodeGenSpecSourceDirectories( + spec, "java", s -> Optional.of(s.getJava())); + })); } private void configureKotlinCodeGenTasks(NamedDomainObjectContainer specs) { @@ -237,14 +243,15 @@ public class PklPlugin implements Plugin { }); }); - project.afterEvaluate( - prj -> - specs.all( - spec -> { - configureIdeaModule(spec); - configureCodeGenSpecSourceDirectories( - spec, "kotlin", this::getKotlinSourceDirectorySet); - })); + project() + .afterEvaluate( + prj -> + specs.all( + spec -> { + configureIdeaModule(spec); + configureCodeGenSpecSourceDirectories( + spec, "kotlin", this::getKotlinSourceDirectorySet); + })); } private void configurePkldocTasks(NamedDomainObjectContainer specs) { @@ -254,7 +261,7 @@ public class PklPlugin implements Plugin { spec.getOutputDir() .convention( - project + project() .getLayout() .getBuildDirectory() .map(it -> it.dir("pkldoc").dir(spec.getName()))); @@ -284,12 +291,12 @@ public class PklPlugin implements Plugin { task.getOverwrite().set(spec.getOverwrite()); }); - project + project() .getPluginManager() .withPlugin( "base", appliedPlugin -> - project + project() .getTasks() .named( LifecycleBasePlugin.CHECK_TASK_NAME, @@ -306,7 +313,7 @@ public class PklPlugin implements Plugin { spec.getAllowedResources() .convention(List.of("env:", "prop:", "file:", "modulepath:", "https:", "package:")); - spec.getEvalRootDir().convention(project.getRootProject().getLayout().getProjectDirectory()); + spec.getEvalRootDir().convention(project().getRootProject().getLayout().getProjectDirectory()); // Defaulting to OS env vars is bad for reproducibility and cachability. // Hence, this spec defaults to empty env vars, which is consistent with other Gradle tasks @@ -326,18 +333,19 @@ public class PklPlugin implements Plugin { private void configureCodeGenSpec(CodeGenSpec spec) { spec.getOutputDir() .convention( - project + project() .getLayout() .getBuildDirectory() .map(it -> it.dir("generated").dir("pkl").dir(spec.getName()))); spec.getSourceSet() .convention( - project + project() .getProviders() .provider( () -> { - var sourceSets = project.getExtensions().findByType(SourceSetContainer.class); + var sourceSets = + project().getExtensions().findByType(SourceSetContainer.class); if (sourceSets == null) { return null; } @@ -371,7 +379,7 @@ public class PklPlugin implements Plugin { // Refer to configureCodeGenSpecSourceDirectories for logic which links the codegen task // to sourceSet.getResources().getSourceDirectories(). - var modulePath = project.files(); + var modulePath = project().files(); modulePath .from(getResourceSourceDirectoriesExceptSpecOutput(spec)) // This technically breaks the dependency on compile classpath builder tasks, @@ -411,14 +419,14 @@ public class PklPlugin implements Plugin { String languageName, Function> extractSourceDirectorySet) { - var task = project.getTasks().named(spec.getName(), CodeGenTask.class); + var task = project().getTasks().named(spec.getName(), CodeGenTask.class); var sourceSet = spec.getSourceSet().get(); extractSourceDirectorySet .apply(sourceSet) .ifPresentOrElse( dirSet -> dirSet.srcDir(task.flatMap(t -> t.getOutputDir().dir(languageName))), () -> - project + project() .getLogger() .debug( "Source directory set for language {} is not available, " @@ -431,12 +439,12 @@ public class PklPlugin implements Plugin { // Must be called from Project.afterEvaluate() only, because this method depends // on user-provided configuration not accessible with lazy configuration. private void configureIdeaModule(CodeGenSpec spec) { - project + project() .getPluginManager() .withPlugin( "idea", plugin -> { - var module = project.getExtensions().getByType(IdeaModel.class).getModule(); + var module = project().getExtensions().getByType(IdeaModel.class).getModule(); var outputDir = spec.getOutputDir().get().getAsFile(); module.getGeneratedSourceDirs().add(outputDir); if (spec.getSourceSet().get().getName().toLowerCase().contains("test")) { @@ -521,11 +529,11 @@ public class PklPlugin implements Plugin { private TaskProvider createAnalyzeImportsTask(ModulesSpec spec) { var outputFile = - project + project() .getLayout() .getBuildDirectory() .file("pkl-gradle/imports/" + spec.getName() + ".json"); - return project + return project() .getTasks() .register( spec.getName() + "GatherImports", @@ -567,7 +575,7 @@ public class PklPlugin implements Plugin { private TaskProvider createModulesTask( Class taskClass, ModulesSpec spec) { var analyzeImportsTask = createAnalyzeImportsTask(spec); - return project + return project() .getTasks() .register( spec.getName(), @@ -576,7 +584,7 @@ public class PklPlugin implements Plugin { } private TaskProvider createTask(Class taskClass, BasePklSpec spec) { - return project + return project() .getTasks() .register(spec.getName(), taskClass, task -> configureBaseTask(task, spec)); } diff --git a/pkl-gradle/src/main/java/org/pkl/gradle/package-info.java b/pkl-gradle/src/main/java/org/pkl/gradle/package-info.java index c181a60d..2ca7e1ca 100644 --- a/pkl-gradle/src/main/java/org/pkl/gradle/package-info.java +++ b/pkl-gradle/src/main/java/org/pkl/gradle/package-info.java @@ -1,4 +1,4 @@ -@NonnullByDefault +@NullMarked package org.pkl.gradle; -import org.pkl.core.util.NonnullByDefault; +import org.jspecify.annotations.NullMarked; diff --git a/pkl-gradle/src/main/java/org/pkl/gradle/spec/package-info.java b/pkl-gradle/src/main/java/org/pkl/gradle/spec/package-info.java index 3585dad3..60e80e61 100644 --- a/pkl-gradle/src/main/java/org/pkl/gradle/spec/package-info.java +++ b/pkl-gradle/src/main/java/org/pkl/gradle/spec/package-info.java @@ -1,4 +1,4 @@ -@NonnullByDefault +@NullMarked package org.pkl.gradle.spec; -import org.pkl.core.util.NonnullByDefault; +import org.jspecify.annotations.NullMarked; diff --git a/pkl-gradle/src/main/java/org/pkl/gradle/task/BasePklTask.java b/pkl-gradle/src/main/java/org/pkl/gradle/task/BasePklTask.java index f585ee10..a8d5fda0 100644 --- a/pkl-gradle/src/main/java/org/pkl/gradle/task/BasePklTask.java +++ b/pkl-gradle/src/main/java/org/pkl/gradle/task/BasePklTask.java @@ -28,6 +28,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import javax.inject.Inject; import org.gradle.api.DefaultTask; +import org.gradle.api.Transformer; import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.model.ObjectFactory; @@ -45,10 +46,9 @@ import org.gradle.api.tasks.Optional; import org.gradle.api.tasks.PathSensitive; import org.gradle.api.tasks.PathSensitivity; import org.gradle.api.tasks.TaskAction; +import org.jspecify.annotations.Nullable; import org.pkl.commons.cli.CliBaseOptions; import org.pkl.core.evaluatorSettings.Color; -import org.pkl.core.util.LateInit; -import org.pkl.core.util.Nullable; import org.pkl.gradle.utils.PluginUtils; @CacheableTask @@ -86,27 +86,21 @@ public abstract class BasePklTask extends DefaultTask { @Optional @PathSensitive(PathSensitivity.ABSOLUTE) public Provider getSettingsModuleFile() { + //noinspection RedundantCast return getParsedSettingsModule() + // NullAway needs this redundant cast .map( - it -> { - if (it instanceof File file) { - return file; - } - return null; - }); + (Transformer<@Nullable File, Object>) + object -> object instanceof File file ? file : null); } @Input @Optional public Provider getSettingsModuleUri() { + //noinspection RedundantCast return getParsedSettingsModule() - .map( - it -> { - if (it instanceof URI uri) { - return uri; - } - return null; - }); + // NullAway needs this redundant cast + .map((Transformer<@Nullable URI, Object>) object -> object instanceof URI uri ? uri : null); } // Exposed as a task input via evalRootDirPath, because we only need to depend @@ -180,13 +174,13 @@ public abstract class BasePklTask extends DefaultTask { protected abstract void doRunTask(); - @LateInit protected CliBaseOptions cachedOptions; + protected @Nullable CliBaseOptions __cachedOptions; // Must be called during task execution time only. @Internal protected CliBaseOptions getCliBaseOptions() { - if (cachedOptions == null) { - cachedOptions = + if (__cachedOptions == null) { + __cachedOptions = new CliBaseOptions( getSourceModulesAsUris(), patternsFromStrings(getAllowedModules().get()), @@ -215,7 +209,7 @@ public abstract class BasePklTask extends DefaultTask { null, getPowerAssertions().getOrElse(false)); } - return cachedOptions; + return __cachedOptions; } @Internal diff --git a/pkl-gradle/src/main/java/org/pkl/gradle/task/ModulesTask.java b/pkl-gradle/src/main/java/org/pkl/gradle/task/ModulesTask.java index a511b686..93bc23b7 100644 --- a/pkl-gradle/src/main/java/org/pkl/gradle/task/ModulesTask.java +++ b/pkl-gradle/src/main/java/org/pkl/gradle/task/ModulesTask.java @@ -145,8 +145,8 @@ public abstract class ModulesTask extends BasePklTask { @Internal @Override protected CliBaseOptions getCliBaseOptions() { - if (cachedOptions == null) { - cachedOptions = + if (__cachedOptions == null) { + __cachedOptions = new CliBaseOptions( getSourceModulesAsUris(), patternsFromStrings(getAllowedModules().get()), @@ -175,6 +175,6 @@ public abstract class ModulesTask extends BasePklTask { null, getPowerAssertions().getOrElse(false)); } - return cachedOptions; + return __cachedOptions; } } diff --git a/pkl-gradle/src/main/java/org/pkl/gradle/task/package-info.java b/pkl-gradle/src/main/java/org/pkl/gradle/task/package-info.java index 51aa344f..5ec528c1 100644 --- a/pkl-gradle/src/main/java/org/pkl/gradle/task/package-info.java +++ b/pkl-gradle/src/main/java/org/pkl/gradle/task/package-info.java @@ -1,4 +1,4 @@ -@NonnullByDefault +@NullMarked package org.pkl.gradle.task; -import org.pkl.core.util.NonnullByDefault; +import org.jspecify.annotations.NullMarked; diff --git a/pkl-gradle/src/main/java/org/pkl/gradle/utils/package-info.java b/pkl-gradle/src/main/java/org/pkl/gradle/utils/package-info.java index 83d5130a..2540f9d2 100644 --- a/pkl-gradle/src/main/java/org/pkl/gradle/utils/package-info.java +++ b/pkl-gradle/src/main/java/org/pkl/gradle/utils/package-info.java @@ -1,4 +1,4 @@ -@NonnullByDefault +@NullMarked package org.pkl.gradle.utils; -import org.pkl.core.util.NonnullByDefault; +import org.jspecify.annotations.NullMarked;