Skip to content

Commit 0c5bc4a

Browse files
committed
Use JSpecify's @nullable, and no other nullness annotation
jsr305's javax.annotation.Nullable gives way to org.jspecify.annotations.Nullable, and the jsr305 dependency to jspecify 1.0.1, the version Guava already brings. Obs's @CheckReturnValue, the other jsr305 annotation in use, is now Error Prone's. JetBrains' @NotNull goes from the IntelliJ plugin: what is not @nullable is non-null, and NullAway checks it. The plugin does not instrument its code, so the annotations added no runtime checks either. JSpecify's @nullable is a type-use annotation. Where it stood above an @OverRide it now follows it, next to the return type it annotates. CLAUDE.md names the annotation and where it goes on nested and array types.
1 parent 3e19dc8 commit 0c5bc4a

23 files changed

Lines changed: 38 additions & 43 deletions

‎CLAUDE.md‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ Building and testing: the README's "Building and testing locally" section. Gradl
88
- **Collections.** Plain `java.util` types. `List.of`, `List.copyOf`, `Map.of` and `Stream.toList()` give
99
unmodifiable collections, so new code does not need Guava's `ImmutableList` or `ImmutableMap`; use them only
1010
where an existing API already hands one over.
11-
- **Nullability.** One annotation, `javax.annotation.Nullable` (jsr305), the one the code uses; do not add another
12-
`Nullable`.
11+
- **Nullability.** One annotation, JSpecify's `org.jspecify.annotations.Nullable`; do not add another `Nullable`,
12+
nor a `NotNull` or `NonNull`: what is not `@Nullable` is non-null, and NullAway checks it. It is a type-use
13+
annotation, so on a nested type it goes before the simple name (`Input.@Nullable Token`), and on an array before
14+
the brackets (`String @Nullable []`).
1315
- **Local variables.** `var` wherever the initializer gives the type unchanged, in `for` loops too. Not where it
1416
would box a primitive (`for (var n : List<Integer>)`), and not without an initializer that has a type of its own
1517
(a lambda, `null`).

‎gradle/libs.versions.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jackson-datatype-jdk8 = { module = "com.fasterxml.jackson.datatype:jackson-datat
3939
jackson-module-parameterNames = { module = "com.fasterxml.jackson.module:jackson-module-parameter-names", version = "2.22.4" }
4040
jmh-core = { module = "org.openjdk.jmh:jmh-core", version = "1.37" }
4141
jmh-generator-annprocess = { module = "org.openjdk.jmh:jmh-generator-annprocess", version = "1.37" }
42-
jsr305 = { module = "com.google.code.findbugs:jsr305", version = "3.0.2" }
42+
jspecify = { module = "org.jspecify:jspecify", version = "1.0.1" }
4343
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version = "6.1.3" }
4444
junit-jupiter-migrationsupport = { module = "org.junit.jupiter:junit-jupiter-migrationsupport", version = "6.1.3" }
4545
junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher", version = "6.1.3" }

‎open-java-format-eclipse-plugin/build.gradle‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ dependencies {
2828
compileOnly libs.eclipse.text
2929

3030
implementation project(':open-java-format')
31-
implementation libs.jsr305
31+
implementation libs.jspecify
3232
}
3333

3434
// The dependencies embedded in the plugin jar. Named once, so the manifest can list exactly what

‎open-java-format-eclipse-plugin/src/main/java/com/palantir/javaformat/java/PalantirJavaFormatter.java‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,30 @@
1919
import com.palantir.javaformat.java.SnippetFormatter.SnippetKind;
2020
import java.util.ArrayList;
2121
import java.util.List;
22-
import javax.annotation.Nullable;
2322
import org.eclipse.jdt.core.dom.ASTParser;
2423
import org.eclipse.jdt.core.formatter.CodeFormatter;
2524
import org.eclipse.jface.text.IRegion;
2625
import org.eclipse.jface.text.Region;
2726
import org.eclipse.text.edits.MultiTextEdit;
2827
import org.eclipse.text.edits.ReplaceEdit;
2928
import org.eclipse.text.edits.TextEdit;
29+
import org.jspecify.annotations.Nullable;
3030

3131
/** Runs the Palantir Java formatter on the given code. */
3232
public class PalantirJavaFormatter extends CodeFormatter {
3333

3434
private static final int INDENTATION_SIZE = 4;
3535

36-
@Nullable
3736
@Override
37+
@Nullable
3838
public TextEdit format(
3939
int kind, String source, int offset, int length, int indentationLevel, String _lineSeparator) {
4040
IRegion[] regions = new IRegion[] {new Region(offset, length)};
4141
return formatInternal(kind, source, regions, indentationLevel);
4242
}
4343

44-
@Nullable
4544
@Override
45+
@Nullable
4646
public TextEdit format(int kind, String source, IRegion[] regions, int indentationLevel, String _lineSeparator) {
4747
return formatInternal(kind, source, regions, indentationLevel);
4848
}

‎open-java-format-idea-plugin/build.gradle‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ dependencies {
8181
testImplementation libs.assertj
8282
testImplementation libs.junit.jupiter
8383
testImplementation libs.junit.platform.launcher
84-
implementation libs.jsr305
84+
implementation libs.jspecify
8585
}
8686

8787
intellijPlatform {

‎open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/EmbeddedNativeImage.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
import java.util.concurrent.atomic.AtomicBoolean;
4444
import java.util.concurrent.atomic.AtomicReference;
4545
import java.util.regex.Pattern;
46-
import javax.annotation.Nullable;
46+
import org.jspecify.annotations.Nullable;
4747

4848
/**
4949
* The native binary the plugin downloads for the IDE's platform, one for the whole IDE. It is kept in the IDE's system

‎open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/InitialConfigurationStartupActivity.java‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,10 @@
1818

1919
import com.intellij.openapi.project.Project;
2020
import com.intellij.openapi.startup.StartupActivity;
21-
import org.jetbrains.annotations.NotNull;
2221

2322
public final class InitialConfigurationStartupActivity implements StartupActivity.DumbAware {
2423
@Override
25-
public void runActivity(@NotNull Project project) {
24+
public void runActivity(Project project) {
2625
PalantirJavaFormatSettings settings = PalantirJavaFormatSettings.getInstance(project);
2726
if (settings.isUninitialized()) {
2827
settings.setEnabled(false);

‎open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/NativeImageNoticeStartupActivity.java‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@
2222
import com.intellij.openapi.startup.StartupActivity;
2323
import com.palantir.javaformat.intellij.EmbeddedNativeImage.Status;
2424
import java.util.Optional;
25-
import javax.annotation.Nullable;
26-
import org.jetbrains.annotations.NotNull;
25+
import org.jspecify.annotations.Nullable;
2726

2827
/**
2928
* Tells the user, as the IDE does about outdated spelling dictionaries, when the embedded native binary is older than
@@ -41,7 +40,7 @@ record Missing() implements Notice {}
4140
}
4241

4342
@Override
44-
public void runActivity(@NotNull Project project) {
43+
public void runActivity(Project project) {
4544
var embedded = EmbeddedNativeImage.getInstance();
4645
embedded.removeStale();
4746

‎open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/PalantirJavaFormatConfigurable.java‎

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
import java.nio.file.InvalidPathException;
4242
import java.nio.file.Path;
4343
import java.util.Optional;
44-
import javax.annotation.Nullable;
4544
import javax.swing.Box;
4645
import javax.swing.JCheckBox;
4746
import javax.swing.JComponent;
@@ -50,7 +49,7 @@
5049
import javax.swing.JTextArea;
5150
import javax.swing.event.DocumentEvent;
5251
import org.jetbrains.annotations.Nls;
53-
import org.jetbrains.annotations.NotNull;
52+
import org.jspecify.annotations.Nullable;
5453

5554
class PalantirJavaFormatConfigurable extends BaseConfigurable implements SearchableConfigurable {
5655

@@ -130,14 +129,13 @@ protected void textChanged(DocumentEvent event) {
130129
.getPanel();
131130
}
132131

133-
@NotNull
134132
@Override
135133
public String getId() {
136134
return "open-java-format.settings";
137135
}
138136

139-
@Nullable
140137
@Override
138+
@Nullable
141139
public Runnable enableSearch(String option) {
142140
return null;
143141
}
@@ -148,14 +146,14 @@ public String getDisplayName() {
148146
return "open-java-format Settings";
149147
}
150148

151-
@Nullable
152149
@Override
150+
@Nullable
153151
public String getHelpTopic() {
154152
return null;
155153
}
156154

157-
@Nullable
158155
@Override
156+
@Nullable
159157
public JComponent createComponent() {
160158
if (uiDisposable == null) {
161159
uiDisposable = Disposer.newDisposable("open-java-format settings page");

‎open-java-format-idea-plugin/src/main/java/com/palantir/javaformat/intellij/PalantirJavaFormatFormattingService.java‎

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,8 @@
3333
import com.palantir.javaformat.java.FormatterException;
3434
import com.palantir.javaformat.java.FormatterService;
3535
import com.palantir.javaformat.java.Replacement;
36-
import org.jetbrains.annotations.NotNull;
36+
import org.jspecify.annotations.Nullable;
3737

38-
import javax.annotation.Nullable;
3938
import java.util.ArrayList;
4039
import java.util.Collection;
4140
import java.util.List;
@@ -57,7 +56,7 @@ class PalantirJavaFormatFormattingService extends AsyncDocumentFormattingService
5756
private PluginDescriptor pluginDescriptor;
5857

5958
@Override
60-
public void setPluginDescriptor(@NotNull PluginDescriptor pluginDescriptor) {
59+
public void setPluginDescriptor(PluginDescriptor pluginDescriptor) {
6160
this.pluginDescriptor = pluginDescriptor;
6261
}
6362

@@ -66,7 +65,7 @@ Optional<PluginDescriptor> getPluginDescriptor() {
6665
}
6766

6867
@Override
69-
protected FormattingTask createFormattingTask(@NotNull AsyncFormattingRequest request) {
68+
protected FormattingTask createFormattingTask(AsyncFormattingRequest request) {
7069
Project project = request.getContext().getProject();
7170
// The marketplace verifier reports this class as experimental, and newer IDEs also deprecate it. It stays:
7271
// its replacement, com.intellij.ide.trustedProjects.TrustedProjects, is @ApiStatus.Internal — a worse thing
@@ -84,22 +83,22 @@ protected FormattingTask createFormattingTask(@NotNull AsyncFormattingRequest re
8483
}
8584

8685
@Override
87-
protected @NotNull String getNotificationGroupId() {
86+
protected String getNotificationGroupId() {
8887
return Notifications.PARSING_ERROR_NOTIFICATION_GROUP;
8988
}
9089

9190
@Override
92-
protected @NotNull @NlsSafe String getName() {
91+
protected @NlsSafe String getName() {
9392
return "open-java-format";
9493
}
9594

9695
@Override
97-
public @NotNull Set<Feature> getFeatures() {
96+
public Set<Feature> getFeatures() {
9897
return Set.of(Feature.FORMAT_FRAGMENTS);
9998
}
10099

101100
@Override
102-
public boolean canFormat(@NotNull PsiFile file) {
101+
public boolean canFormat(PsiFile file) {
103102
return JavaFileType.INSTANCE.equals(file.getFileType())
104103
&& PalantirJavaFormatSettings.getInstance(file.getProject()).isEnabled();
105104
}

0 commit comments

Comments
 (0)