Skip to content

Commit 3db2dde

Browse files
Copilotdondonz
andcommitted
Update JSpecify annotation prompt with effectiveness improvements
Co-authored-by: dondonz <13839920+dondonz@users.noreply.github.com>
1 parent c02fa4e commit 3db2dde

File tree

1 file changed

+68
-1
lines changed

1 file changed

+68
-1
lines changed

.claude/commands/jspecify-annotate.md

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ Note that JSpecify is already used in this repository so it's already imported.
44

55
If you see a builder static class, you can label it `@NullUnmarked` and not need to do anymore for this static class in terms of annotations.
66

7+
## Batch Size and Prioritization
8+
9+
Annotate approximately 10 classes per batch for optimal context management. Start with interface/simple classes first, then tackle complex classes with builders. This helps identify patterns early.
10+
11+
## Exploration Phase
12+
13+
Before annotating, use `grep` to search for how each class is instantiated (e.g., `grep -r "new Comment"`) to understand which parameters can be null. Check constructor calls, method returns, and field assignments to inform your nullability decisions.
14+
715
Analyze this Java class and add JSpecify annotations based on:
816
1. Set the class to be `@NullMarked`
917
2. Remove all the redundant `@NonNull` annotations that IntelliJ added
@@ -14,14 +22,73 @@ Analyze this Java class and add JSpecify annotations based on:
1422

1523
IntelliJ's infer nullity code analysis isn't comprehensive so feel free to make corrections.
1624

25+
## Pattern Examples
26+
27+
Here are concrete examples of common annotation patterns:
28+
29+
**Interface:**
30+
```java
31+
@PublicApi
32+
@NullMarked
33+
public interface MyInterface {
34+
// Methods inherit @NullMarked context
35+
}
36+
```
37+
38+
**Class with nullable field:**
39+
```java
40+
@PublicApi
41+
@NullMarked
42+
public class Comment {
43+
private final String content;
44+
private final @Nullable SourceLocation sourceLocation;
45+
46+
public Comment(String content, @Nullable SourceLocation sourceLocation) {
47+
this.content = content;
48+
this.sourceLocation = sourceLocation;
49+
}
50+
51+
public @Nullable SourceLocation getSourceLocation() {
52+
return sourceLocation;
53+
}
54+
}
55+
```
56+
57+
**Class with nullable return type:**
58+
```java
59+
@PublicApi
60+
@NullMarked
61+
public class Container {
62+
public @Nullable Node getChildOrNull(String key) {
63+
// May return null
64+
return children.get(key);
65+
}
66+
}
67+
```
68+
69+
**Builder with @NullUnmarked:**
70+
```java
71+
@PublicApi
72+
@NullMarked
73+
public class MyClass {
74+
@NullUnmarked
75+
public static class Builder {
76+
// No further annotations needed in builder
77+
}
78+
}
79+
```
80+
1781
## GraphQL Specification Compliance
1882
This is a GraphQL implementation. When determining nullability, consult the GraphQL specification (https://spec.graphql.org/draft/) for the relevant concept. Key principles:
1983

2084
The spec defines which elements are required (non-null) vs optional (nullable). Look for keywords like "MUST" to indicate when an element is required, and conditional words such as "IF" to indicate when an element is optional.
2185

2286
If a class implements or represents a GraphQL specification concept, prioritize the spec's nullability requirements over what IntelliJ inferred.
2387

24-
## How to validate
88+
## Validation Strategy
89+
90+
Run `./gradlew compileJava` after every 3-5 classes annotated, not just at the end. This catches issues early and makes debugging easier.
91+
2592
Finally, please check all this works by running the NullAway compile check.
2693

2794
If you find NullAway errors, try and make the smallest possible change to fix them. If you must, you can use assertNotNull. Make sure to include a message as well.

0 commit comments

Comments
 (0)