Skip to content

Preserve trailing comments in OrderedImports rule#1205

Merged
allevato merged 2 commits into
swiftlang:mainfrom
itsybitsybootsy:fix/ordered-imports-preserve-comments
May 15, 2026
Merged

Preserve trailing comments in OrderedImports rule#1205
allevato merged 2 commits into
swiftlang:mainfrom
itsybitsybootsy:fix/ordered-imports-preserve-comments

Conversation

@itsybitsybootsy
Copy link
Copy Markdown
Contributor

Problem

OrderedImports runs every source file through a convertToCodeBlockItems pass that walks the categorised Line array and flushes accumulated trivia onto each syntax node via pendingLeadingTrivia. When the input ends with trivia after the last syntax node — typically a free-standing comment that import reordering pushed past the final import — the accumulator is silently dropped at the end of the loop.

import A

// Comment

import B

becomes

import A
import B

The // Comment is silently lost.

Fix

Append any leftover trivia containing comments to the trailing trivia of the last code block item before convertToCodeBlockItems returns. The loop synthesised a trailing run of newlines after every iteration to separate the current line from the next; those are meaningless when no following line exists and are stripped first so the output doesn't gain spurious blank lines.

After the fix:

import A
import B

// Comment

Tests

Added testCommentBetweenImportGroupsIsPreserved to OrderedImportsTests.swift covering the reproducer from the issue.

swift test locally: 913 tests, 1 skipped, 0 failures.

Resolves #1080.


This contribution was developed with the help of Claude Code. The fix, regression test, and the full local test suite were reviewed manually before submitting.

The `OrderedImports` rule runs every source file through a
`convertToCodeBlockItems` pass that accumulates trivia in
`pendingLeadingTrivia` and flushes it onto each successive syntax node.
When the input ends with trivia after the last syntax node — typically a
comment that import reordering pushed past the final import — the
accumulator is silently dropped at the end of the loop.

Append any leftover trivia containing comments to the trailing trivia of
the last code block item before returning. Trailing newlines that the
loop synthesised for separation before nonexistent following lines are
stripped first so the output doesn't gain spurious blank lines.

Resolves swiftlang#1080.
Comment on lines +489 to +497
let hasComment = pendingLeadingTrivia.contains { piece in
switch piece {
case .lineComment, .blockComment, .docLineComment, .docBlockComment:
return true
default:
return false
}
}
if hasComment, !output.isEmpty {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let hasComment = pendingLeadingTrivia.contains { piece in
switch piece {
case .lineComment, .blockComment, .docLineComment, .docBlockComment:
return true
default:
return false
}
}
if hasComment, !output.isEmpty {
if pendingLeadingTrivia.hasAnyComments, !output.isEmpty {

We already have a helper for this in Trivia+Convenience.swift.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in a7dc786. Wrapped in Trivia(pieces:) since pendingLeadingTrivia is [TriviaPiece].

Copy link
Copy Markdown
Member

@allevato allevato left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the bug fix!

@allevato allevato merged commit e0b1f28 into swiftlang:main May 15, 2026
30 checks 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.

Comment-only code blocks are removed when OrderedImports is enabled

2 participants