Skip to content

Commit 2e49a31

Browse files
authored
pkl-gradle: Migrate nullness to jSpecify (apple#1530)
1 parent b1a5d8c commit 2e49a31

9 files changed

Lines changed: 104 additions & 81 deletions

File tree

pkl-gradle/gradle.lockfile

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,28 @@ com.github.ajalt.mordant:mordant-jvm:3.0.1=compileClasspath
1616
com.github.ajalt.mordant:mordant:3.0.1=compileClasspath
1717
com.github.ajalt.mordant:mordant:3.0.2=compileOnlyDependenciesMetadata
1818
com.github.ben-manes.caffeine:caffeine:2.9.3=swiftExportClasspathResolvable
19+
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,testAnnotationProcessor
20+
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,testAnnotationProcessor
21+
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,testAnnotationProcessor
22+
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,testAnnotationProcessor
23+
com.google.auto:auto-common:1.2.2=annotationProcessor,testAnnotationProcessor
24+
com.google.errorprone:error_prone_annotation:2.48.0=annotationProcessor,testAnnotationProcessor
1925
com.google.errorprone:error_prone_annotations:2.28.0=swiftExportClasspathResolvable
20-
io.github.java-diff-utils:java-diff-utils:4.12=kotlinInternalAbiValidation
26+
com.google.errorprone:error_prone_annotations:2.48.0=annotationProcessor,testAnnotationProcessor
27+
com.google.errorprone:error_prone_check_api:2.48.0=annotationProcessor,testAnnotationProcessor
28+
com.google.errorprone:error_prone_core:2.48.0=annotationProcessor,testAnnotationProcessor
29+
com.google.googlejavaformat:google-java-format:1.34.1=annotationProcessor,testAnnotationProcessor
30+
com.google.guava:failureaccess:1.0.3=annotationProcessor,testAnnotationProcessor
31+
com.google.guava:guava:33.5.0-jre=annotationProcessor,testAnnotationProcessor
32+
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,testAnnotationProcessor
33+
com.google.j2objc:j2objc-annotations:3.1=annotationProcessor,testAnnotationProcessor
34+
com.google.protobuf:protobuf-java:4.33.2=annotationProcessor,testAnnotationProcessor
35+
com.uber.nullaway:nullaway:0.13.1=annotationProcessor,testAnnotationProcessor
36+
io.github.eisop:dataflow-errorprone:3.41.0-eisop1=annotationProcessor,testAnnotationProcessor
37+
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,kotlinInternalAbiValidation,testAnnotationProcessor
2138
io.opentelemetry:opentelemetry-api:1.41.0=swiftExportClasspathResolvable
2239
io.opentelemetry:opentelemetry-context:1.41.0=swiftExportClasspathResolvable
40+
javax.inject:javax.inject:1=annotationProcessor,testAnnotationProcessor
2341
net.bytebuddy:byte-buddy:1.18.3=testCompileClasspath,testRuntimeClasspath
2442
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
2543
org.assertj:assertj-core:3.27.7=testCompileClasspath,testRuntimeClasspath
@@ -28,6 +46,8 @@ org.bouncycastle:bcpkix-jdk18on:1.80=kotlinBouncyCastleConfiguration
2846
org.bouncycastle:bcprov-jdk18on:1.80=kotlinBouncyCastleConfiguration
2947
org.bouncycastle:bcutil-jdk18on:1.80=kotlinBouncyCastleConfiguration
3048
org.checkerframework:checker-qual:3.43.0=swiftExportClasspathResolvable
49+
org.checkerframework:checker-qual:3.53.0=annotationProcessor,testAnnotationProcessor
50+
org.checkerframework:dataflow-nullaway:3.53.0=annotationProcessor,testAnnotationProcessor
3151
org.jetbrains.kotlin:abi-tools-api:2.3.20=kotlinInternalAbiValidation
3252
org.jetbrains.kotlin:abi-tools:2.3.20=kotlinInternalAbiValidation
3353
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
6383
org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.3=swiftExportClasspathResolvable
6484
org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3=swiftExportClasspathResolvable
6585
org.jetbrains:annotations:13.0=compileClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinInternalAbiValidation,kotlinKlibCommonizerClasspath,swiftExportClasspathResolvable,testCompileClasspath,testRuntimeClasspath
66-
org.jspecify:jspecify:1.0.0=compileClasspath,testCompileClasspath
86+
org.jspecify:jspecify:1.0.0=annotationProcessor,compileClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
6787
org.junit.jupiter:junit-jupiter-api:6.0.3=testCompileClasspath,testRuntimeClasspath
6888
org.junit.jupiter:junit-jupiter-engine:6.0.3=testCompileClasspath,testRuntimeClasspath
6989
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
7393
org.junit:junit-bom:6.0.3=testCompileClasspath,testRuntimeClasspath
7494
org.msgpack:msgpack-core:0.9.11=testRuntimeClasspath
7595
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
76-
empty=annotationProcessor,apiDependenciesMetadata,implementationDependenciesMetadata,intransitiveDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDefExtensions,runtimeClasspath,signatures,sourcesJar,testAnnotationProcessor,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testImplementationDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDefExtensions
96+
org.pcollections:pcollections:4.0.1=annotationProcessor,testAnnotationProcessor
97+
empty=apiDependenciesMetadata,implementationDependenciesMetadata,intransitiveDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDefExtensions,signatures,sourcesJar,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testImplementationDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDefExtensions

pkl-gradle/pkl-gradle.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ plugins {
1717
id("pklAllProjects")
1818
id("pklJavaLibrary")
1919
id("pklGradlePluginTest")
20-
20+
id("pklJSpecify")
2121
`java-gradle-plugin`
2222
`maven-publish`
2323
id("pklPublishLibrary")

pkl-gradle/src/main/java/org/pkl/gradle/PklPlugin.java

Lines changed: 55 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
2+
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -36,12 +36,11 @@
3636
import org.gradle.language.base.plugins.LifecycleBasePlugin;
3737
import org.gradle.plugins.ide.idea.model.IdeaModel;
3838
import org.gradle.util.GradleVersion;
39+
import org.jspecify.annotations.Nullable;
3940
import org.pkl.cli.CliEvaluatorOptions;
4041
import org.pkl.core.ImportGraph;
4142
import org.pkl.core.OutputFormat;
4243
import org.pkl.core.util.IoUtils;
43-
import org.pkl.core.util.LateInit;
44-
import org.pkl.core.util.Nullable;
4544
import org.pkl.gradle.spec.AnalyzeImportsSpec;
4645
import org.pkl.gradle.spec.BasePklSpec;
4746
import org.pkl.gradle.spec.CodeGenSpec;
@@ -71,21 +70,26 @@ public class PklPlugin implements Plugin<Project> {
7170

7271
private static final String MIN_GRADLE_VERSION = "8.2";
7372

74-
@LateInit private Project project;
73+
private @Nullable Project __project;
7574

7675
@Override
7776
public void apply(Project project) {
78-
this.project = project;
77+
__project = project;
7978

8079
if (GradleVersion.current().compareTo(GradleVersion.version(MIN_GRADLE_VERSION)) < 0) {
8180
throw new GradleException(
8281
String.format("Plugin `org.pkl` requires Gradle %s or higher.", MIN_GRADLE_VERSION));
8382
}
8483

85-
var extension = project.getExtensions().create("pkl", PklExtension.class);
84+
var extension = project().getExtensions().create("pkl", PklExtension.class);
8685
configureExtension(extension);
8786
}
8887

88+
private Project project() {
89+
assert __project != null;
90+
return __project;
91+
}
92+
8993
private void configureExtension(PklExtension extension) {
9094
configureEvalTasks(extension.getEvaluators());
9195
configureJavaCodeGenTasks(extension.getJavaCodeGenerators());
@@ -102,7 +106,7 @@ private void configureProjectPackageTasks(NamedDomainObjectContainer<ProjectPack
102106
spec -> {
103107
configureBaseSpec(spec);
104108
spec.getOutputPath()
105-
.convention(project.getLayout().getBuildDirectory().dir("generated/pkl/packages"));
109+
.convention(project().getLayout().getBuildDirectory().dir("generated/pkl/packages"));
106110
spec.getOverwrite().convention(false);
107111
var packageTask = createTask(ProjectPackageTask.class, spec);
108112
packageTask.configure(
@@ -113,12 +117,12 @@ private void configureProjectPackageTasks(NamedDomainObjectContainer<ProjectPack
113117
task.getJunitReportsDir().set(spec.getJunitReportsDir());
114118
task.getOverwrite().set(spec.getOverwrite());
115119
});
116-
project
120+
project()
117121
.getPluginManager()
118122
.withPlugin(
119123
"base",
120124
appliedPlugin ->
121-
project
125+
project()
122126
.getTasks()
123127
.named(
124128
LifecycleBasePlugin.BUILD_TASK_NAME,
@@ -157,7 +161,7 @@ private void configureEvalTasks(NamedDomainObjectContainer<EvalSpec> specs) {
157161
configureBaseSpec(spec);
158162
spec.getOutputFile()
159163
.convention(
160-
project
164+
project()
161165
.getLayout()
162166
.getProjectDirectory()
163167
// %{moduleDir} is resolved relatively to the working directory,
@@ -194,11 +198,12 @@ private void configureJavaCodeGenTasks(NamedDomainObjectContainer<JavaCodeGenSpe
194198
// constructor parameters annotations by setting this property to `null`.
195199
spec.getParamsAnnotation()
196200
.set(
197-
project.provider(
198-
() ->
199-
spec.getGenerateSpringBootConfig().get()
200-
? null
201-
: "org.pkl.config.java.mapper.Named"));
201+
project()
202+
.provider(
203+
() ->
204+
spec.getGenerateSpringBootConfig().get()
205+
? null
206+
: "org.pkl.config.java.mapper.Named"));
202207

203208
createModulesTask(JavaCodeGenTask.class, spec)
204209
.configure(
@@ -211,14 +216,15 @@ private void configureJavaCodeGenTasks(NamedDomainObjectContainer<JavaCodeGenSpe
211216
});
212217
});
213218

214-
project.afterEvaluate(
215-
prj ->
216-
specs.all(
217-
spec -> {
218-
configureIdeaModule(spec);
219-
configureCodeGenSpecSourceDirectories(
220-
spec, "java", s -> Optional.of(s.getJava()));
221-
}));
219+
project()
220+
.afterEvaluate(
221+
prj ->
222+
specs.all(
223+
spec -> {
224+
configureIdeaModule(spec);
225+
configureCodeGenSpecSourceDirectories(
226+
spec, "java", s -> Optional.of(s.getJava()));
227+
}));
222228
}
223229

224230
private void configureKotlinCodeGenTasks(NamedDomainObjectContainer<KotlinCodeGenSpec> specs) {
@@ -237,14 +243,15 @@ private void configureKotlinCodeGenTasks(NamedDomainObjectContainer<KotlinCodeGe
237243
});
238244
});
239245

240-
project.afterEvaluate(
241-
prj ->
242-
specs.all(
243-
spec -> {
244-
configureIdeaModule(spec);
245-
configureCodeGenSpecSourceDirectories(
246-
spec, "kotlin", this::getKotlinSourceDirectorySet);
247-
}));
246+
project()
247+
.afterEvaluate(
248+
prj ->
249+
specs.all(
250+
spec -> {
251+
configureIdeaModule(spec);
252+
configureCodeGenSpecSourceDirectories(
253+
spec, "kotlin", this::getKotlinSourceDirectorySet);
254+
}));
248255
}
249256

250257
private void configurePkldocTasks(NamedDomainObjectContainer<PkldocSpec> specs) {
@@ -254,7 +261,7 @@ private void configurePkldocTasks(NamedDomainObjectContainer<PkldocSpec> specs)
254261

255262
spec.getOutputDir()
256263
.convention(
257-
project
264+
project()
258265
.getLayout()
259266
.getBuildDirectory()
260267
.map(it -> it.dir("pkldoc").dir(spec.getName())));
@@ -284,12 +291,12 @@ private void configureTestTasks(NamedDomainObjectContainer<TestSpec> specs) {
284291
task.getOverwrite().set(spec.getOverwrite());
285292
});
286293

287-
project
294+
project()
288295
.getPluginManager()
289296
.withPlugin(
290297
"base",
291298
appliedPlugin ->
292-
project
299+
project()
293300
.getTasks()
294301
.named(
295302
LifecycleBasePlugin.CHECK_TASK_NAME,
@@ -306,7 +313,7 @@ private void configureBaseSpec(BasePklSpec spec) {
306313
spec.getAllowedResources()
307314
.convention(List.of("env:", "prop:", "file:", "modulepath:", "https:", "package:"));
308315

309-
spec.getEvalRootDir().convention(project.getRootProject().getLayout().getProjectDirectory());
316+
spec.getEvalRootDir().convention(project().getRootProject().getLayout().getProjectDirectory());
310317

311318
// Defaulting to OS env vars is bad for reproducibility and cachability.
312319
// Hence, this spec defaults to empty env vars, which is consistent with other Gradle tasks
@@ -326,18 +333,19 @@ private void configureBaseSpec(BasePklSpec spec) {
326333
private void configureCodeGenSpec(CodeGenSpec spec) {
327334
spec.getOutputDir()
328335
.convention(
329-
project
336+
project()
330337
.getLayout()
331338
.getBuildDirectory()
332339
.map(it -> it.dir("generated").dir("pkl").dir(spec.getName())));
333340

334341
spec.getSourceSet()
335342
.convention(
336-
project
343+
project()
337344
.getProviders()
338345
.provider(
339346
() -> {
340-
var sourceSets = project.getExtensions().findByType(SourceSetContainer.class);
347+
var sourceSets =
348+
project().getExtensions().findByType(SourceSetContainer.class);
341349
if (sourceSets == null) {
342350
return null;
343351
}
@@ -371,7 +379,7 @@ private void configureCodeGenSpecModulePath(CodeGenSpec spec) {
371379
// Refer to configureCodeGenSpecSourceDirectories for logic which links the codegen task
372380
// to sourceSet.getResources().getSourceDirectories().
373381

374-
var modulePath = project.files();
382+
var modulePath = project().files();
375383
modulePath
376384
.from(getResourceSourceDirectoriesExceptSpecOutput(spec))
377385
// This technically breaks the dependency on compile classpath builder tasks,
@@ -411,14 +419,14 @@ private void configureCodeGenSpecSourceDirectories(
411419
String languageName,
412420
Function<? super SourceSet, ? extends Optional<SourceDirectorySet>>
413421
extractSourceDirectorySet) {
414-
var task = project.getTasks().named(spec.getName(), CodeGenTask.class);
422+
var task = project().getTasks().named(spec.getName(), CodeGenTask.class);
415423
var sourceSet = spec.getSourceSet().get();
416424
extractSourceDirectorySet
417425
.apply(sourceSet)
418426
.ifPresentOrElse(
419427
dirSet -> dirSet.srcDir(task.flatMap(t -> t.getOutputDir().dir(languageName))),
420428
() ->
421-
project
429+
project()
422430
.getLogger()
423431
.debug(
424432
"Source directory set for language {} is not available, "
@@ -431,12 +439,12 @@ private void configureCodeGenSpecSourceDirectories(
431439
// Must be called from Project.afterEvaluate() only, because this method depends
432440
// on user-provided configuration not accessible with lazy configuration.
433441
private void configureIdeaModule(CodeGenSpec spec) {
434-
project
442+
project()
435443
.getPluginManager()
436444
.withPlugin(
437445
"idea",
438446
plugin -> {
439-
var module = project.getExtensions().getByType(IdeaModel.class).getModule();
447+
var module = project().getExtensions().getByType(IdeaModel.class).getModule();
440448
var outputDir = spec.getOutputDir().get().getAsFile();
441449
module.getGeneratedSourceDirs().add(outputDir);
442450
if (spec.getSourceSet().get().getName().toLowerCase().contains("test")) {
@@ -521,11 +529,11 @@ private <T extends ModulesTask, S extends ModulesSpec> void configureModulesTask
521529

522530
private TaskProvider<AnalyzeImportsTask> createAnalyzeImportsTask(ModulesSpec spec) {
523531
var outputFile =
524-
project
532+
project()
525533
.getLayout()
526534
.getBuildDirectory()
527535
.file("pkl-gradle/imports/" + spec.getName() + ".json");
528-
return project
536+
return project()
529537
.getTasks()
530538
.register(
531539
spec.getName() + "GatherImports",
@@ -567,7 +575,7 @@ private TaskProvider<AnalyzeImportsTask> createAnalyzeImportsTask(ModulesSpec sp
567575
private <T extends ModulesTask> TaskProvider<T> createModulesTask(
568576
Class<T> taskClass, ModulesSpec spec) {
569577
var analyzeImportsTask = createAnalyzeImportsTask(spec);
570-
return project
578+
return project()
571579
.getTasks()
572580
.register(
573581
spec.getName(),
@@ -576,7 +584,7 @@ private <T extends ModulesTask> TaskProvider<T> createModulesTask(
576584
}
577585

578586
private <T extends BasePklTask> TaskProvider<T> createTask(Class<T> taskClass, BasePklSpec spec) {
579-
return project
587+
return project()
580588
.getTasks()
581589
.register(spec.getName(), taskClass, task -> configureBaseTask(task, spec));
582590
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@NonnullByDefault
1+
@NullMarked
22
package org.pkl.gradle;
33

4-
import org.pkl.core.util.NonnullByDefault;
4+
import org.jspecify.annotations.NullMarked;
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@NonnullByDefault
1+
@NullMarked
22
package org.pkl.gradle.spec;
33

4-
import org.pkl.core.util.NonnullByDefault;
4+
import org.jspecify.annotations.NullMarked;

0 commit comments

Comments
 (0)