Skip to content

fix: skip the indentation after a line continuation in a key - #98

Merged
quintesse merged 1 commit into
codejive:mainfrom
wleeaf:continuation-leading-whitespace
Oct 26, 2026
Merged

quintesse merged 1 commit into
codejive:mainfrom
wleeaf:continuation-leading-whitespace

Conversation

@wleeaf

@wleeaf wleeaf commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

A line continuation inside a key splits the key when the next line is indented:

Properties p = Properties.loadProperties(new StringReader("key\\\n  part=value\n"));
// {key=part=value}; java.util.Properties loads {keypart=value}

The parser ends a key at the first whitespace character. After \ and the line break it is at the start of the next line, so the indentation there ends the key, and the rest of the line becomes the value. An indented line that holds only a backslash has the same problem: " \\\n beta=2\n" loads the key "" with the value "beta=2" instead of beta=2. Values aren't affected, because whitespace doesn't end a value, and unescape() already skips the whitespace after a line continuation.

addChar() now also reads the whitespace at the start of the next line after a line continuation, so it becomes part of the current token's raw text, as it already does in values. unescape() drops it as before, so the key's text is keypart and its raw text keeps the original layout, and store() writes the file back exactly as it was read.

Tests: TestPropertiesParser.testLineContinuationInKey checks the tokens for key\ + newline + part=value, and TestProperties.testLineContinuationFollowedByIndentation checks both cases above against what java.util.Properties loads. Both fail without the change. mvn -B spotless:check package passes on JDK 21 (85 tests).

I found this by loading 20,000 generated .properties inputs with both this library and java.util.Properties and comparing the results. With the change, 461 inputs that differed now match the JDK. For every input, whether the store() round trip reloads the same map in the JDK is the same as before. One input that matched before now differs. In it, a line with only a backslash is followed by a line starting with #, which the JDK treats as a comment because the logical line is still empty. Before the change it matched only because a later line set the same key.

The whitespace at the start of a continued line ended the key, so
"key\" followed by "  part=value" was read as key "key" with the value
"part=value" instead of key "keypart". An indented line with only a
backslash gave an empty key. The whitespace after a line continuation is
now part of the token, like in values, and is skipped when unescaping.
@quintesse

Copy link
Copy Markdown
Collaborator

Another good catch! You're on fire! Thanks @wleeaf , you're help is really appreciated 👍

@quintesse
quintesse merged commit 24c356b into codejive:main Oct 26, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants