Skip to content

Commit 3d9073d

Browse files
committed
fix: keep trailing comments separate from appended properties
Fixes #90
1 parent 5b80d85 commit 3d9073d

2 files changed

Lines changed: 39 additions & 0 deletions

File tree

‎src/main/java/org/codejive/properties/Properties.java‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,16 +513,37 @@ private Cursor addNewKeyValue(
513513
pos = afterLastProperty();
514514
}
515515

516+
boolean afterFinalComment = isAfterFinalComment(pos);
517+
516518
// Add a newline whitespace token if necessary
517519
pos = prepareNewLine(pos);
518520

521+
if (afterFinalComment) {
522+
// Keep a trailing comment free rather than attaching it to the new key.
523+
pos.addEol(eolType);
524+
}
525+
519526
// Add tokens for key, separator and value
520527
pos.add(new PropertiesParser.Token(PropertiesParser.Type.KEY, rawKey, key));
521528
pos.add(new PropertiesParser.Token(PropertiesParser.Type.SEPARATOR, "="));
522529
pos.add(new PropertiesParser.Token(PropertiesParser.Type.VALUE, rawValue, value));
523530
return pos;
524531
}
525532

533+
// Returns true only at the end of the token list when the last token is a comment,
534+
// optionally followed by one EOL. An existing blank line after the comment returns false.
535+
// Uses a copy so the insertion cursor is not moved.
536+
private boolean isAfterFinalComment(Cursor pos) {
537+
if (!pos.atEnd()) {
538+
return false;
539+
}
540+
Cursor previous = pos.copy().prev();
541+
if (previous.isEol()) {
542+
previous.prev();
543+
}
544+
return previous.isType(PropertiesParser.Type.COMMENT);
545+
}
546+
526547
// Prepare the list for adding a new line at the given position. It will make sure the cursor
527548
// is at a valid insertion point and that any required EOLs are added.
528549
private Cursor prepareNewLine(Cursor pos) {

‎src/test/java/org/codejive/properties/TestProperties.java‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,6 +1394,24 @@ void testPutFirstLineHeaderOnlyCrLf() throws IOException {
13941394
expectStoreText(p, "put=putVal\r\n # header\r\n");
13951395
}
13961396

1397+
@Test
1398+
void testPutLastLine() throws IOException {
1399+
final String given = "key=val\n" + "# trailer comment";
1400+
final String expected = "key=val\n" + "# trailer comment\n" + "\n" + "put=putVal";
1401+
Properties p = Properties.loadProperties(new StringReader(given));
1402+
p.put(p.last().next(), "put", "putVal");
1403+
expectStoreText(p, expected);
1404+
assertThat(p.getComment("put")).isEmpty();
1405+
}
1406+
1407+
@Test
1408+
void testPutLastLineWithFinalEol() throws IOException {
1409+
Properties p = Properties.loadProperties(new StringReader("key=val\r\n # trailer\r\n"));
1410+
p.put(p.last().next(), "put", "putVal");
1411+
expectStoreText(p, "key=val\r\n # trailer\r\n\r\nput=putVal\r\n");
1412+
assertThat(p.getComment("put")).isEmpty();
1413+
}
1414+
13971415
private void expectStoreText(Properties props, String expectedText) throws IOException {
13981416
StringWriter sw = new StringWriter();
13991417
props.store(sw);

0 commit comments

Comments
 (0)