GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Keep //$NON-NLS-n$ markers valid: no inserted space, each marker on the line of its string by abashev · Pull Request #150 · openjavaformat/open-java-format

Conversation

@abashev

@abashev abashev commented Oct 25, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Collaborator

Eclipse marks a string literal that is deliberately not externalised with a trailing //$NON-NLS-n$ comment, where n is the position of the literal on its line. Eclipse recognises a marker only with that exact spelling and only on the line of its literal. The formatter broke this in three ways (#23); this fixes all three, in two commits.

Case 1: a space was inserted into a trailing marker

String a = "x"; //$NON-NLS-1$ came out as String a = "x"; // $NON-NLS-1$. A trailing line comment lands in the level of the statement's last break, and that level is written from its flat text when it fits on one line, so Comment.computeFlat() added the space itself, without the exemption that JavaCommentsHelper.rewrite() has for //noinspection and //$NON-NLS-n$. The missing-space rule is now one method, JavaCommentsHelper.addMissingSpace, applied by both paths, and the comment's width follows its flat text. A trailing /// comment that already had its space is no longer turned into // / either.

Cases 2 and 3: markers left behind when a statement is wrapped or reflowed

Before:

String message = Messages.format(
        "first argument that is long enough to matter",
        "second argument that is also rather long",
        "third one"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
String reflowed =
        "a single string literal that is far too long to fit into one hundred and twenty columns, so the"
                + " formatter reflows it"; //$NON-NLS-1$

After:

String message = Messages.format(
        "first argument that is long enough to matter", //$NON-NLS-1$
        "second argument that is also rather long", //$NON-NLS-1$
        "third one"); //$NON-NLS-1$
String reflowed =
        "a single string literal that is far too long to fit into one hundred and twenty" //$NON-NLS-1$
                + " columns, so the formatter reflows it"; //$NON-NLS-1$

OpsBuilder.build pairs each marker of a markers-only trailing comment with the n-th string literal of the comment's input line (within the same partial-format region) and puts a zero-text ReservedWidth after that literal, so the layout already counts the marker on the literal's line and a second run changes nothing. JavaOutput.appendNonNlsMarkers writes each paired marker at the end of its literal's output line, numbered by the literal's position among the string literals written there; a marker whose number has no literal stays where it was. A comment of markers is never wrapped. StringWrapper recomputes the markers of a reflowed chain's line from the new line structure: one marker after every piece, the markers of literals before and after the chain renumbered for their lines, with their room reserved per line.

Left alone by design: a mixed comment such as // note //$NON-NLS-1$, a line on which two reflowed chains change (only reachable with a wrap limit below the formatter's), and a chain that ends in a text block.

Also in this PR

  • The marker code hands its lists around as plain List (List.of, List.copyOf, Stream.toList), not Guava's ImmutableList.
  • The line-comment wrapper no longer keeps // MOE: comments on one line: google/MOE has been dead for years, so such a comment wraps like any other.
  • The conventions of the review, applied here and written down in CLAUDE.md: var for locals, no Error Prone @Immutable on the marker nodes, and the Apache header without a copyright line on the four new files (Audit the license headers of all source files #154 covers the rest of the tree).

Tests

Written first, and failing before each change: trailingLineCommentGetsItsMissingSpaceExceptIdeMarkers with the fixture ojf-issue-23-non-nls-trailing-marker (case 1); nonNlsMarkersStayOnTheLineOfTheirLiteral, aRunOfNonNlsMarkersIsNeverWrapped and the fixtures ojf-issue-23-wrapped-arguments, ojf-issue-23-reflowed-literal and ojf-issue-23-marked-literals (cases 2 and 3). The fixtures also run the idempotency checks. Unit tests cover the utility classes: NonNlsMarkersTest, ReservedWidthTest, and two JavaCommentsHelperTest cases for addMissingSpace.

Verification

  • ./gradlew test over all modules is green on the rebased branch; ./gradlew formatDiff changes nothing.
  • JDK 21 corpus, 15,747 files: case 1 changes 4 files, all a trailing /// ... comment that the flat path used to turn into // / ...; cases 2 and 3 change none, as the JDK carries no Eclipse markers.

Fixes #23. The same defect upstream: google/google-java-format#221, google/google-java-format#361.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
abashev added 5 commits October 25, 2026 15:03
@abashev
Keep //$NON-NLS-n$ and //noinspection markers intact after a statemen…
0e05ef7
…t that fits on one line

A trailing line comment lands in the level of the statement's last break, while
its forced line break lands in the enclosing level. When that level fits on one
line it is written from its flat text, and Comment.computeFlat added the space
after the slashes itself, bypassing the exemption that JavaCommentsHelper.rewrite
has for the IDE markers: `String a = "x"; //$NON-NLS-1$` came out as
`// $NON-NLS-1$`, which Eclipse no longer recognises.

The missing-space rule is now one method, JavaCommentsHelper.addMissingSpace,
applied by both paths, and the comment's width follows its flat text instead of
a hand-maintained + 1. A trailing `///` comment that already had its space is no
longer turned into `// /` either: 4 of the 15,747 JDK 21 sources change, all
that way.

The tests were written first: trailingLineCommentGetsItsMissingSpaceExceptIdeMarkers
and the ojf-issue-23-non-nls-trailing-marker fixture failed before the change.

The first of the three cases of #23. Same defect upstream:
google/google-java-format#221, google/google-java-format#361.
@abashev
Keep //$NON-NLS-n$ markers on the line of their string literal when a…
8c527b2
… statement is wrapped or reflowed

Eclipse numbers a marker by the position of its literal on the line and reads
it only there. The formatter left every marker of a wrapped call on the call's
last line, and gave a reflowed literal one marker, on its last piece.

OpsBuilder.build now pairs each marker of a markers-only trailing comment with
the n-th string literal of the comment's input line, within the same
partial-format region, and puts a zero-text ReservedWidth after that literal,
so the layout counts the marker on the literal's line and a second run changes
nothing. JavaOutput.appendNonNlsMarkers writes each paired marker at the end of
its literal's output line, numbered by the literal's position among the string
literals written there; a marker whose number has no literal stays where it
was. JavaCommentsHelper never wraps a comment of markers. StringWrapper
recomputes the markers of a reflowed chain's line from the new line structure,
one marker after every piece and the markers of the literals before and after
the chain renumbered for their lines, and reserves their room per line; a mixed
comment, a second changing chain on the line, or a chain that ends in a text
block leaves the markers alone.

The tests were written first: the fixtures ojf-issue-23-wrapped-arguments,
ojf-issue-23-reflowed-literal and ojf-issue-23-marked-literals, with
nonNlsMarkersStayOnTheLineOfTheirLiteral and aRunOfNonNlsMarkersIsNeverWrapped,
failed before the change. None of the 15,747 JDK 21 sources changes: the JDK
carries no Eclipse markers.

Fixes #23. Same defect upstream: google/google-java-format#221,
google/google-java-format#361.
@abashev
Hand the NON-NLS marker lists around as plain List
eed63c3
The marker code used Guava's ImmutableList for its lists of marker numbers
and literal indices. List.of, List.copyOf and Stream.toList give unmodifiable
lists without it, so the signatures take and return List. The field in
Comment carries the Immutable suppression the other doc nodes use for their
effectively immutable state.
@abashev
Cover NonNlsMarkers, ReservedWidth and addMissingSpace with unit tests
7bfdbdb
The fixtures exercise the marker code end to end only. NonNlsMarkersTest pins
which comments count as markers only, the order and the places in which the
numbers are read, and the spelling of a marker; ReservedWidthTest pins that a
reservation takes its width on the line and nothing else; the two
JavaCommentsHelperTest cases pin the missing-space rule and its exemptions.
@abashev
Wrap // MOE: line comments like any other
e17d404
google/MOE, the tool whose markers the line-comment wrapper kept on one line,
has been dead for years. Its special case goes, with the test that pinned it;
only the NON-NLS marker runs stay unwrapped.
This was referenced Oct 25, 2026
Audit the license headers of all source files #154
Open
Format MOE strip markers in javadoc like any other HTML comment #155
Merged
abashev added 4 commits October 25, 2026 18:30
@abashev
Start the files new in this change with the Apache header alone
42945bd
The fork's own files carry the Apache 2.0 header without a copyright line.
The four files this change adds were created with a Palantir one; CLAUDE.md
records the rule, and #154 covers the rest of the tree.
@abashev
Drop Error Prone's @immutable from the marker nodes
3d97ebe
Comment carried the annotation and needed a suppression for its List field,
and ReservedWidth had taken the annotation from its sibling nodes. Doc itself
is not annotated, so the check adds nothing here: the nodes are immutable by
construction.
@abashev
Use var for the locals of the marker code
a67fa95
The locals this change added declare their type with var where the
initializer gives it unchanged. The loop variables over a List<Integer> keep
int, so that they are not boxed, and the lambda keeps its target type.
@abashev
Write down the conventions for new code
308c0ad
CLAUDE.md: plain java.util collections instead of Guava's immutable ones,
javax.annotation.Nullable as the one nullability annotation, var for locals,
no Error Prone @immutable, and the Apache header without a copyright line on
a new file.
@abashev
abashev merged commit 8f3a269 into 21.X.X Oct 25, 2026
17 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@abashev
abashev deleted the fix/non-nls-marker-space branch October 25, 2026 19:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Keep //$NON-NLS-n$ markers valid: no inserted space, each marker on the line of its string

Uh oh!

There was an error while loading. Please reload this page.

1 participant

@abashev
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.