This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new 0072930827 fix(marshall): HoconTokenizer =+ two-char-lookahead guard
was a bug (TODO-137)
0072930827 is described below
commit 007293082747814ed373b9025c053aa20cb2885d
Author: James Bognar <[email protected]>
AuthorDate: Thu May 28 16:23:40 2026 -0400
fix(marshall): HoconTokenizer =+ two-char-lookahead guard was a bug
(TODO-137)
The c == '=' && peekChar() != '+' guard prevented EQUALS from being
emitted when followed by '+', causing IOException on any =+ sequence.
The += operator is handled by an independent c == '+' && peekChar() == '='
branch (reads '+' first), so the lookahead on the '=' branch was never
needed. Removed the guard and added an explanatory comment.
2 regression tests: g13_equalsFollowedByPlus and
g14_equalsAndPlusEqualsDontInterfere. Note: foo=+bar still fails
('+' is in UNQUOTED_FORBIDDEN) — tracked separately as MAYBE-136.
---
.../org/apache/juneau/hocon/HoconTokenizer.java | 5 ++++-
.../apache/juneau/hocon/HoconTokenizer_Test.java | 23 ++++++++++++++++++++++
juneau-utest/test-run-history.tsv | 1 +
3 files changed, 28 insertions(+), 1 deletion(-)
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/hocon/HoconTokenizer.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/hocon/HoconTokenizer.java
index 247be064ee..75d1f0964b 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/hocon/HoconTokenizer.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/hocon/HoconTokenizer.java
@@ -351,7 +351,10 @@ public class HoconTokenizer {
if (c == ':') {
return Token.of(TokenType.COLON);
}
- if (c == '=' && peekChar() != '+')
+ // '=' is always the EQUALS token regardless of the next
character.
+ // The '+=' (PLUS_EQUALS) operator is handled by the check
below, which reads '+' first;
+ // the two-char sequence '=+' is therefore never mistaken for a
partial '+='.
+ if (c == '=')
return Token.of(TokenType.EQUALS);
if (c == '+' && peekChar() == '=') {
readChar();
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/hocon/HoconTokenizer_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/hocon/HoconTokenizer_Test.java
index 013925ad6f..9db659da43 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/hocon/HoconTokenizer_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/hocon/HoconTokenizer_Test.java
@@ -155,4 +155,27 @@ class HoconTokenizer_Test extends TestBase {
t.skipWhitespaceAndComments();
assertEquals(UNQUOTED_STRING, t.read().type());
}
+
+ // Regression test for the '=+' lookahead bug (TODO-137).
+ // '=' is always EQUALS regardless of the following character; the '+='
(PLUS_EQUALS)
+ // operator is handled by a separate branch that reads '+' first, so
'=+' is never
+ // confused with a partial '+='.
+ @Test
+ void g13_equalsFollowedByPlus() throws Exception {
+ // '=' when the next char is '+' must still emit EQUALS, not
throw.
+ var t = tokenizer("=+");
+ assertEquals(EQUALS, t.read().type());
+ // '+' alone is in UNQUOTED_FORBIDDEN and has no continuation;
reading it throws.
+ assertThrows(IOException.class, t::read);
+ }
+
+ // Confirm '+=', '=', and their interleaving all tokenize independently
after the fix.
+ @Test
+ void g14_equalsAndPlusEqualsDontInterfere() throws Exception {
+ var t = tokenizer("= +=");
+ assertEquals(EQUALS, t.read().type());
+ t.skipWhitespaceAndComments();
+ assertEquals(PLUS_EQUALS, t.read().type());
+ assertEquals(EOF, t.read().type());
+ }
}
diff --git a/juneau-utest/test-run-history.tsv
b/juneau-utest/test-run-history.tsv
index 2219556d48..dfb1419683 100644
--- a/juneau-utest/test-run-history.tsv
+++ b/juneau-utest/test-run-history.tsv
@@ -48,3 +48,4 @@ timestamp git_sha branch tests_run failures
errors skipped surefire_sec wall_sec
2026-05-28T13:16:22Z 8a0a2edbf7ca master 125869 0 0 21
82.9 112 3
2026-05-28T19:24:27Z a26b6978a5bc master 125889 0 0 21
160
2026-05-28T20:05:34Z 60e4b5a8e813 master 125889 0 0 21
136
+2026-05-28T20:22:45Z 5e454b3a7988 master 125891 0 0 21
141