From 10c08bab6cf178a6767767cf6eb570ae0c80b686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89amonn=20McManus?= Date: Mon, 14 Sep 2026 17:45:44 +0000 Subject: [PATCH 1/2] Add JSpecify annotations to the API. --- build.gradle | 2 ++ java/com/google/re2j/Matcher.java | 8 ++++++-- java/com/google/re2j/Pattern.java | 5 ++++- java/com/google/re2j/PatternSyntaxException.java | 3 +++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 662642c0..01089d77 100644 --- a/build.gradle +++ b/build.gradle @@ -85,6 +85,8 @@ dependencies { errorproneJavac 'com.google.errorprone:javac:9+181-r4173-1' errorprone 'com.google.errorprone:error_prone_core:2.10.0' + compileOnly 'org.jspecify:jspecify:1.0.1' + testCompile 'junit:junit:4.12' testCompile 'com.google.gwt:gwt-dev:2.9.0' testCompile 'com.google.gwt:gwt-user:2.9.0' diff --git a/java/com/google/re2j/Matcher.java b/java/com/google/re2j/Matcher.java index 678186d0..119440b1 100644 --- a/java/com/google/re2j/Matcher.java +++ b/java/com/google/re2j/Matcher.java @@ -9,6 +9,8 @@ import com.google.re2j.MatcherInput.Encoding; import java.io.UnsupportedEncodingException; import java.util.Map; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; /** * A stateful iterator that interprets a regex {@code Pattern} on a specific input. Its interface @@ -38,6 +40,7 @@ * * @author rsc@google.com (Russ Cox) */ +@NullMarked public final class Matcher { // The pattern being matched. private final Pattern pattern; @@ -53,6 +56,7 @@ public final class Matcher { // The number of instructions in the pattern. private final int numberOfInstructions; + @SuppressWarnings("nullness:initialization.field.uninitialized") private MatcherInput matcherInput; // The input length in UTF16 codes. @@ -242,7 +246,7 @@ public String group() { * @throws IllegalStateException if there is no match * @throws IndexOutOfBoundsException if {@code group < 0} or {@code group > groupCount()} */ - public String group(int group) { + public @Nullable String group(int group) { int start = start(group); int end = end(group); if (start < 0 && end < 0) { @@ -258,7 +262,7 @@ public String group(int group) { * @param group the group name * @throws IllegalArgumentException if no group with that name exists */ - public String group(String group) { + public @Nullable String group(String group) { Integer g = namedGroups.get(group); if (g == null) { throw new IllegalArgumentException("group '" + group + "' not found"); diff --git a/java/com/google/re2j/Pattern.java b/java/com/google/re2j/Pattern.java index dfe1bf18..130f7c65 100644 --- a/java/com/google/re2j/Pattern.java +++ b/java/com/google/re2j/Pattern.java @@ -11,6 +11,8 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; /** * A compiled representation of an RE2 regular expression, mimicking the @@ -27,6 +29,7 @@ * * @author rsc@google.com (Russ Cox) */ +@NullMarked public final class Pattern implements Serializable { /** Flag: case insensitive matching. */ public static final int CASE_INSENSITIVE = 1; @@ -339,7 +342,7 @@ Object readResolve() { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) { return true; } diff --git a/java/com/google/re2j/PatternSyntaxException.java b/java/com/google/re2j/PatternSyntaxException.java index 17101df3..f92e45e9 100644 --- a/java/com/google/re2j/PatternSyntaxException.java +++ b/java/com/google/re2j/PatternSyntaxException.java @@ -6,11 +6,14 @@ */ package com.google.re2j; +import org.jspecify.annotations.NullMarked; + /** * An exception thrown by the parser if the pattern was invalid. * * Following {@code java.util.regex.PatternSyntaxException}, this is an unchecked exception. */ +@NullMarked public class PatternSyntaxException extends RuntimeException { private final String error; // the nature of the error From 293d6e3ac129166ecea9fd6a14a997051ee76303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89amonn=20McManus?= Date: Mon, 14 Sep 2026 18:14:52 +0000 Subject: [PATCH 2/2] Change Gradle scope for JSpecify to `implementation`. This is needed for GWTTest to pass. It does its own compilation, and that requires JSpecify to be on the classpath of the test. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 01089d77..73173367 100644 --- a/build.gradle +++ b/build.gradle @@ -85,7 +85,7 @@ dependencies { errorproneJavac 'com.google.errorprone:javac:9+181-r4173-1' errorprone 'com.google.errorprone:error_prone_core:2.10.0' - compileOnly 'org.jspecify:jspecify:1.0.1' + implementation 'org.jspecify:jspecify:1.0.1' testCompile 'junit:junit:4.12' testCompile 'com.google.gwt:gwt-dev:2.9.0'