Skip to content

Commit

Permalink
Migrate Nullability assertions to jspecify (#2048)
Browse files Browse the repository at this point in the history
Away from jsr305

With the goal of having a nullability assertion annotation that supports Java modules, so we can release the next version of jsoup.

Annotation options appear limited and does not support @​WillClose, but rest appears OK.

Fixes #2028
Fixes #1992
  • Loading branch information
jhy authored Nov 10, 2023
1 parent de0c3ad commit d11450c
Show file tree
Hide file tree
Showing 42 changed files with 81 additions and 94 deletions.
12 changes: 6 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@
<instructions>
<Bundle-DocURL>https://jsoup.org/</Bundle-DocURL>
<Export-Package>org.jsoup.*</Export-Package>
<Import-Package>javax.annotation;version=!;resolution:=optional,javax.annotation.meta;version=!;resolution:=optional,*</Import-Package>
<Import-Package>org.jspecify.annotations;version=!;resolution:=optional,*</Import-Package>
</instructions>
</configuration>
</plugin>
Expand Down Expand Up @@ -232,7 +232,7 @@
<breakBuildOnBinaryIncompatibleModifications>true</breakBuildOnBinaryIncompatibleModifications>
<breakBuildOnSourceIncompatibleModifications>true</breakBuildOnSourceIncompatibleModifications>
<excludes>
<exclude>@java.lang.Deprecated</exclude>
<!-- <exclude>@java.lang.Deprecated</exclude> -->
</excludes>
<overrideCompatibilityChangeParameters>
<!-- allows new default and move to default methods. compatible as long as existing binaries aren't making calls via reflection. if so, they need to catch errors anyway. -->
Expand Down Expand Up @@ -415,10 +415,10 @@
</dependency>

<dependency>
<!-- javax.annotations.nonnull, with Apache 2 (not GPL) license. Build time only. -->
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
<!-- org.jspecify.annotations.nonnull, with Apache 2 license. Build time only. -->
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
<version>0.3.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jsoup/Connection.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import org.jsoup.helper.RequestAuthenticator;
import org.jsoup.nodes.Document;
import org.jsoup.parser.Parser;
import org.jspecify.annotations.Nullable;

import javax.annotation.Nullable;
import javax.net.ssl.SSLSocketFactory;
import java.io.BufferedInputStream;
import java.io.IOException;
Expand Down
6 changes: 2 additions & 4 deletions src/main/java/org/jsoup/Jsoup.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
import org.jsoup.parser.Parser;
import org.jsoup.safety.Cleaner;
import org.jsoup.safety.Safelist;

import javax.annotation.Nullable;
import javax.annotation.WillClose;
import org.jspecify.annotations.Nullable;

import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -196,7 +194,7 @@ public static Document parse(File file, @Nullable String charsetName, String bas
@throws IOException if the file could not be found, or read, or if the charsetName is invalid.
*/
public static Document parse(@WillClose InputStream in, @Nullable String charsetName, String baseUri) throws IOException {
public static Document parse(InputStream in, @Nullable String charsetName, String baseUri) throws IOException {
return DataUtil.load(in, charsetName, baseUri);
}

Expand Down
3 changes: 2 additions & 1 deletion src/main/java/org/jsoup/helper/AuthenticationHandler.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.jsoup.helper;

import javax.annotation.Nullable;
import org.jspecify.annotations.Nullable;

import java.lang.reflect.Constructor;
import java.net.Authenticator;
import java.net.HttpURLConnection;
Expand Down
10 changes: 4 additions & 6 deletions src/main/java/org/jsoup/helper/DataUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@
import org.jsoup.nodes.XmlDeclaration;
import org.jsoup.parser.Parser;
import org.jsoup.select.Elements;

import javax.annotation.Nullable;
import javax.annotation.WillClose;
import org.jspecify.annotations.Nullable;

import java.io.BufferedReader;
import java.io.CharArrayReader;
Expand Down Expand Up @@ -105,7 +103,7 @@ public static Document load(File file, @Nullable String charsetName, String base
* @return Document
* @throws IOException on IO error
*/
public static Document load(@WillClose InputStream in, @Nullable String charsetName, String baseUri) throws IOException {
public static Document load(InputStream in, @Nullable String charsetName, String baseUri) throws IOException {
return parseInputStream(in, charsetName, baseUri, Parser.htmlParser());
}

Expand All @@ -118,7 +116,7 @@ public static Document load(@WillClose InputStream in, @Nullable String charsetN
* @return Document
* @throws IOException on IO error
*/
public static Document load(@WillClose InputStream in, @Nullable String charsetName, String baseUri, Parser parser) throws IOException {
public static Document load(InputStream in, @Nullable String charsetName, String baseUri, Parser parser) throws IOException {
return parseInputStream(in, charsetName, baseUri, parser);
}

Expand All @@ -136,7 +134,7 @@ static void crossStreams(final InputStream in, final OutputStream out) throws IO
}
}

static Document parseInputStream(@Nullable @WillClose InputStream input, @Nullable String charsetName, String baseUri, Parser parser) throws IOException {
static Document parseInputStream(@Nullable InputStream input, @Nullable String charsetName, String baseUri, Parser parser) throws IOException {
if (input == null) // empty body
return new Document(baseUri);
input = ConstrainableInputStream.wrap(input, bufferSize, 0);
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/org/jsoup/helper/HttpConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
import org.jsoup.nodes.Document;
import org.jsoup.parser.Parser;
import org.jsoup.parser.TokenQueue;
import org.jspecify.annotations.Nullable;

import javax.annotation.Nullable;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
import java.io.BufferedInputStream;
Expand Down Expand Up @@ -111,7 +111,7 @@ private static String encodeMimeName(String val) {
}

private HttpConnection.Request req;
private @Nullable Connection.Response res;
private Connection.@Nullable Response res;

@Override
public Connection newRequest() {
Expand Down Expand Up @@ -539,7 +539,7 @@ private List<String> getHeadersCaseInsensitive(String name) {
return Collections.emptyList();
}

private @Nullable Map.Entry<String, List<String>> scanHeaders(String name) {
private Map.@Nullable Entry<String, List<String>> scanHeaders(String name) {
String lc = lowerCase(name);
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
if (lowerCase(entry.getKey()).equals(lc))
Expand Down Expand Up @@ -1061,7 +1061,7 @@ private void safeClose() {
}

// set up url, method, header, cookies
private Response(HttpURLConnection conn, HttpConnection.Request request, @Nullable HttpConnection.Response previousResponse) throws IOException {
private Response(HttpURLConnection conn, HttpConnection.Request request, HttpConnection.@Nullable Response previousResponse) throws IOException {
this.conn = conn;
this.req = request;
method = Method.valueOf(conn.getRequestMethod());
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jsoup/helper/RequestAuthenticator.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.jsoup.helper;

import org.jsoup.Connection;
import org.jspecify.annotations.Nullable;

import javax.annotation.Nullable;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.URL;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jsoup/helper/UrlBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import org.jsoup.Connection;
import org.jsoup.internal.StringUtil;
import org.jspecify.annotations.Nullable;

import javax.annotation.Nullable;
import java.io.UnsupportedEncodingException;
import java.net.IDN;
import java.net.MalformedURLException;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jsoup/helper/Validate.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.jsoup.helper;

import javax.annotation.Nullable;
import org.jspecify.annotations.Nullable;

/**
* Validators to check that method arguments meet expectations.
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/jsoup/helper/W3CDom.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.jspecify.annotations.Nullable;

import javax.annotation.Nullable;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
Expand Down Expand Up @@ -353,7 +353,7 @@ protected static class W3CBuilder implements NodeVisitor {
private final Stack<HashMap<String, String>> namespacesStack = new Stack<>(); // stack of namespaces, prefix => urn
private Node dest;
private Syntax syntax = Syntax.xml; // the syntax (to coerce attributes to). From the input doc if available.
@Nullable private final org.jsoup.nodes.Element contextElement;
/*@Nullable*/ private final org.jsoup.nodes.Element contextElement; // todo - unsure why this can't be marked nullable?

public W3CBuilder(Document doc) {
this.doc = doc;
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/jsoup/helper/package-info.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
Package containing classes supporting the core jsoup code.
*/
@NonnullByDefault
@NullMarked
package org.jsoup.helper;

import org.jsoup.internal.NonnullByDefault;
import org.jspecify.annotations.NullMarked;
12 changes: 5 additions & 7 deletions src/main/java/org/jsoup/internal/FieldsAreNonnullByDefault.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
package org.jsoup.internal;

import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
import org.jspecify.annotations.NullMarked;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
Indicates that fields types are not nullable, unless otherwise specified by @Nullable.
@see javax.annotation.ParametersAreNonnullByDefault
@deprecated Previously indicated that fields types are not nullable, unless otherwise specified by @Nullable.
*/
@Deprecated
@Documented
@Nonnull
@TypeQualifierDefault(ElementType.FIELD)
@NullMarked
@Retention(value = RetentionPolicy.CLASS)
public @interface FieldsAreNonnullByDefault {
}
12 changes: 5 additions & 7 deletions src/main/java/org/jsoup/internal/NonnullByDefault.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
package org.jsoup.internal;

import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
import org.jspecify.annotations.NullMarked;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
Indicates that all components (methods, returns, fields) are not nullable, unless otherwise specified by @Nullable.
@see javax.annotation.ParametersAreNonnullByDefault
@deprecated Previously indicated that all components (methods, returns, fields) are not nullable, unless otherwise specified by @Nullable.
*/
@Deprecated
@Documented
@Nonnull
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
@NullMarked
@Retention(value = RetentionPolicy.CLASS)
public @interface NonnullByDefault {
}
12 changes: 5 additions & 7 deletions src/main/java/org/jsoup/internal/ReturnsAreNonnullByDefault.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
package org.jsoup.internal;

import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
import org.jspecify.annotations.NullMarked;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
Indicates return types are not nullable, unless otherwise specified by @Nullable.
@see javax.annotation.ParametersAreNonnullByDefault
@deprecated Previously indicated that return types are not nullable, unless otherwise specified by @Nullable.
*/
@Deprecated
@Documented
@Nonnull
@TypeQualifierDefault(ElementType.METHOD)
@NullMarked
@Retention(value = RetentionPolicy.RUNTIME)
public @interface ReturnsAreNonnullByDefault {
}
2 changes: 1 addition & 1 deletion src/main/java/org/jsoup/internal/StringUtil.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.jsoup.internal;

import org.jsoup.helper.Validate;
import org.jspecify.annotations.Nullable;

import javax.annotation.Nullable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/org/jsoup/internal/package-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@
* Util methods used by Jsoup. Please don't depend on the APIs implemented here as the contents may change without
* notice.
*/
@NullMarked
package org.jsoup.internal;

import org.jspecify.annotations.NullMarked;
2 changes: 1 addition & 1 deletion src/main/java/org/jsoup/nodes/Attribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import org.jsoup.internal.Normalizer;
import org.jsoup.internal.StringUtil;
import org.jsoup.nodes.Document.OutputSettings.Syntax;
import org.jspecify.annotations.Nullable;

import javax.annotation.Nullable;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jsoup/nodes/Attributes.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import org.jsoup.helper.Validate;
import org.jsoup.internal.StringUtil;
import org.jsoup.parser.ParseSettings;
import org.jspecify.annotations.Nullable;

import javax.annotation.Nullable;
import java.io.IOException;
import java.util.AbstractMap;
import java.util.AbstractSet;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jsoup/nodes/Comment.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import org.jsoup.parser.ParseSettings;
import org.jsoup.parser.Parser;
import org.jspecify.annotations.Nullable;

import javax.annotation.Nullable;
import java.io.IOException;

/**
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jsoup/nodes/Document.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
import org.jsoup.select.Elements;
import org.jsoup.select.Evaluator;
import org.jsoup.select.Selector;
import org.jspecify.annotations.Nullable;

import javax.annotation.Nullable;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.List;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jsoup/nodes/Element.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
import org.jsoup.select.NodeVisitor;
import org.jsoup.select.QueryParser;
import org.jsoup.select.Selector;
import org.jspecify.annotations.Nullable;

import javax.annotation.Nullable;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jsoup/nodes/Entities.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import org.jsoup.nodes.Document.OutputSettings;
import org.jsoup.parser.CharacterReader;
import org.jsoup.parser.Parser;
import org.jspecify.annotations.Nullable;

import javax.annotation.Nullable;
import java.io.IOException;
import java.nio.charset.CharsetEncoder;
import java.util.Arrays;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jsoup/nodes/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import org.jsoup.select.NodeFilter;
import org.jsoup.select.NodeTraversor;
import org.jsoup.select.NodeVisitor;
import org.jspecify.annotations.Nullable;

import javax.annotation.Nullable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/jsoup/nodes/package-info.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
HTML document structure nodes.
*/
@NonnullByDefault
@NullMarked
package org.jsoup.nodes;

import org.jsoup.internal.NonnullByDefault;
import org.jspecify.annotations.NullMarked;
4 changes: 2 additions & 2 deletions src/main/java/org/jsoup/package-info.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
Contains the main {@link org.jsoup.Jsoup} class, which provides convenient static access to the jsoup functionality.
*/
@NonnullByDefault
@NullMarked
package org.jsoup;

import org.jsoup.internal.NonnullByDefault;
import org.jspecify.annotations.NullMarked;
2 changes: 1 addition & 1 deletion src/main/java/org/jsoup/parser/CharacterReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import org.jsoup.UncheckedIOException;
import org.jsoup.helper.Validate;
import org.jspecify.annotations.Nullable;

import javax.annotation.Nullable;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
Expand Down
Loading

0 comments on commit d11450c

Please sign in to comment.