Repository: jhy/jsoup
Pull request #2177 (2024-07-22 23:09:29)

Bump org.jspecify:jspecify from 0.3.0 to 1.0.0
Bumps [org.jspecify:jspecify](https://github.com/jspecify/jspecify) from 0.3.0 to 1.0.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/jspecify/jspecify/releases">org.jspecify:jspecify's releases</a>.</em></p>
<blockquote>
<h2>1.0.0</h2>
<p>JSpecify 1.0.0 is the first stable release of the only <a href="https://jspecify.dev/about/">consensus-driven</a>, tool-independent nullness annotations for Java code (with benefits for Kotlin interoperability). Future releases will add annotations for other kinds of static-analysis checks.</p>
<p>Check out our <a href="https://jspecify.dev/docs/using">usage page</a> for instructions on how to depend on JSpecify in your project and our guidelines on <a href="https://jspecify.dev/docs/whether">when to start</a> doing so. Also check out our <a href="https://jspecify.dev/docs/user-guide">User Guide</a>.</p>
<p>The 1.0.0 release contains four annotations:</p>
<ul>
<li><a href="https://jspecify.dev/docs/api/org/jspecify/annotations/Nullable.html"><code>@Nullable</code></a></li>
<li><a href="https://jspecify.dev/docs/api/org/jspecify/annotations/NonNull.html"><code>@NonNull</code></a></li>
<li><a href="https://jspecify.dev/docs/api/org/jspecify/annotations/NullMarked.html"><code>@NullMarked</code></a></li>
<li><a href="https://jspecify.dev/docs/api/org/jspecify/annotations/NullUnmarked.html"><code>@NullUnmarked</code></a></li>
</ul>
<h1>Artifacts</h1>
<ul>
<li><a href="https://jspecify.dev/docs/api/">Javadoc</a></li>
<li>Maven Central: <a href="https://repo.maven.apache.org/maven2/org/jspecify/jspecify/1.0.0/">org.jspecify:jspecify</a></li>
</ul>
<h1>Changes since version 0.3.0</h1>
<p>No code changes, only Javadoc changes and OSGI metadata.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/jspecify/jspecify/commit/b2a10e14bb81c1b7cb6e488c112fe55cb2218d7d"><code>b2a10e1</code></a> Set version to 1.0.0.</li>
<li><a href="https://github.com/jspecify/jspecify/commit/5bf4ae46059cc4821879ecae10522b77dd16c59b"><code>5bf4ae4</code></a> Run build workflow on any branch whose name starts with 'dev-'. Run the docs ...</li>
<li><a href="https://github.com/jspecify/jspecify/commit/87a28645c8aebac2882bd8d6f8f5d67558255319"><code>87a2864</code></a> add OSGi metadata and reproducible build (<a href="https://redirect.github.com/jspecify/jspecify/issues/428">#428</a>)</li>
<li><a href="https://github.com/jspecify/jspecify/commit/f0af7de6f72d01e3a8f3ffc9f528540de770f987"><code>f0af7de</code></a> Use Gradle toolchain to specify the jdk to use (<a href="https://redirect.github.com/jspecify/jspecify/issues/558">#558</a>)</li>
<li><a href="https://github.com/jspecify/jspecify/commit/378925a26fe7bda4acf3f113c01d1b59a374a186"><code>378925a</code></a> Update to gradle 8.9 (<a href="https://redirect.github.com/jspecify/jspecify/issues/557">#557</a>)</li>
<li><a href="https://github.com/jspecify/jspecify/commit/2e9ff601451cae849cc6eda1b3e6d9fce77656e9"><code>2e9ff60</code></a> Run docs action for <code>docs-1.0</code> branch. (<a href="https://redirect.github.com/jspecify/jspecify/issues/556">#556</a>)</li>
<li><a href="https://github.com/jspecify/jspecify/commit/48ffa9bd5536b88d07718cbac6a74624086a15bf"><code>48ffa9b</code></a> Direct people to file an issue in the reference checker repo (<a href="https://redirect.github.com/jspecify/jspecify/issues/552">#552</a>)</li>
<li><a href="https://github.com/jspecify/jspecify/commit/bc70dc48744df3f4e26a02b68f9c3088a7aac9ae"><code>bc70dc4</code></a> Exception parameters are intrinsically NonNull (<a href="https://redirect.github.com/jspecify/jspecify/issues/508">#508</a>)</li>
<li><a href="https://github.com/jspecify/jspecify/commit/dbb3673076922171dc4a7aca0f1cf1cd0ec352b8"><code>dbb3673</code></a> docs: Update docusaurus to 3.4 (<a href="https://redirect.github.com/jspecify/jspecify/issues/549">#549</a>)</li>
<li><a href="https://github.com/jspecify/jspecify/commit/9abe30d9ded9a088cca97bf2ce79aad603420484"><code>9abe30d</code></a> Run the build-documentation job (but not deployment) on pushes and pull reque...</li>
<li>Additional commits viewable in <a href="https://github.com/jspecify/jspecify/compare/v0.3.0...v1.0.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=org.jspecify:jspecify&package-manager=maven&previous-version=0.3.0&new-version=1.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/CHANGES.md b/CHANGES.md
index 2995fe15..059c903a 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -10,6 +10,8 @@
 
 * `Element.cssSelector()` would fail if the element's class contained a `*`
   character. [2169](https://github.com/jhy/jsoup/issues/2169)
+* When tracking source ranges, a text node following an invalid self-closing element may be left
+  untracked.[2175](https://github.com/jhy/jsoup/issues/2175)
 
 ## 1.18.1 (2024-Jul-10)
 
diff --git a/pom.xml b/pom.xml
index 7d88aac8..6412dd8d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -432,7 +432,7 @@
       <!-- org.jspecify.annotations.nonnull, with Apache 2 license. Build time only. -->
       <groupId>org.jspecify</groupId>
       <artifactId>jspecify</artifactId>
-      <version>0.3.0</version>
+      <version>1.0.0</version>
       <scope>provided</scope>
     </dependency>
   </dependencies>
diff --git a/src/main/java/org/jsoup/parser/Tokeniser.java b/src/main/java/org/jsoup/parser/Tokeniser.java
index 2416a66d..ff3bfa4f 100644
--- a/src/main/java/org/jsoup/parser/Tokeniser.java
+++ b/src/main/java/org/jsoup/parser/Tokeniser.java
@@ -49,8 +49,7 @@ final class Tokeniser {
     @Nullable private String lastStartTag; // the last start tag emitted, to test appropriate end tag
     @Nullable private String lastStartCloseSeq; // "</" + lastStartTag, so we can quickly check for that in RCData
 
-    private static final int Unset = -1;
-    private int markupStartPos, charStartPos = 0; // reader pos at the start of markup / characters. updated on state transition. Initialized to start (0), but set to Unset after emissions.
+    private int markupStartPos, charStartPos = 0; // reader pos at the start of markup / characters. markup updated on state transition, char on token emit.
 
     Tokeniser(TreeBuilder treeBuilder) {
         tagPending = startPending  = new Token.StartTag(treeBuilder);
@@ -90,7 +89,7 @@ final class Tokeniser {
         isEmitPending = true;
         token.startPos(markupStartPos);
         token.endPos(reader.pos());
-        charStartPos = Unset;
+        charStartPos = reader.pos(); // update char start when we complete a token emit
 
         if (token.type == Token.TokenType.StartTag) {
             Token.StartTag startTag = (Token.StartTag) token;
@@ -158,15 +157,9 @@ final class Tokeniser {
     }
 
     void transition(TokeniserState newState) {
-        // track markup / data position on state transitions
-        switch (newState) {
-            case TagOpen:
-                markupStartPos = reader.pos();
-                break;
-            case Data:
-                if (charStartPos == Unset) // don't reset when we are jumping between e.g data -> char ref -> data
-                    charStartPos = reader.pos();
-        }
+        // track markup position on state transitions
+        if (newState == TokeniserState.TagOpen)
+            markupStartPos = reader.pos();
 
         this.state = newState;
     }


Test patch:
diff --git a/src/test/java/org/jsoup/parser/PositionTest.java b/src/test/java/org/jsoup/parser/PositionTest.java
index 49d544c5..e8098095 100644
--- a/src/test/java/org/jsoup/parser/PositionTest.java
+++ b/src/test/java/org/jsoup/parser/PositionTest.java
@@ -487,6 +487,15 @@ class PositionTest {
         assertEquals("h1:0-9~12-17; id:4-6=7-8; #text:9-12; #text:17-18; h2:18-27~30-35; id:22-24=25-26; #text:27-30; h10:35-40~43-49; #text:40-43; ", track.toString());
     }
 
+    @Test void tracksAfterPSelfClose() {
+        // https://github.com/jhy/jsoup/issues/2175
+        String html = "foo<p/>bar &amp; 2";
+        Document doc = Jsoup.parse(html, TrackingHtmlParser);
+        StringBuilder track = new StringBuilder();
+        doc.body().forEachNode(node -> accumulatePositions(node, track));
+        assertEquals("body:0-0~18-18; #text:0-3; p:3-7~3-7; #text:7-18; ", track.toString());
+    }
+
     @Test void tracksFirstTextnode() {
         // https://github.com/jhy/jsoup/issues/2106
         String html = "foo<p></p>bar<p></p><div><b>baz</b></div>";