Skip to content

Commit 44a23ee

Browse files
authored
Fix bug where --type-body-marks remove wouldn't be respected on declarations with expected mark comment (#2200)
1 parent 5fe256c commit 44a23ee

File tree

2 files changed

+70
-15
lines changed

2 files changed

+70
-15
lines changed

Sources/Rules/OrganizeDeclarations.swift

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,16 @@ extension Formatter {
387387
let markDeclaration = tokenize("\(indentation)// \(markCommentBody)")
388388
let eligibleCommentRange = declaration.range.lowerBound ..< self.index(of: .nonSpaceOrCommentOrLinebreak, after: declaration.range.lowerBound - 1)!
389389

390+
// Remove any comments other than the expected mark comment if present
391+
removeExistingCategorySeparators(
392+
from: declaration,
393+
previousDeclaration: index == 0 ? nil : sortedDeclarations[index - 1].declaration,
394+
order: order,
395+
preserving: { commentBody in
396+
commentBody == markCommentBody
397+
}
398+
)
399+
390400
let matchingComments = singleLineComments(in: eligibleCommentRange, matching: { commentBody in
391401
commentBody == markCommentBody
392402
})
@@ -403,12 +413,6 @@ extension Formatter {
403413
insertLinebreak(at: tokenAfterComment)
404414
}
405415
} else {
406-
removeExistingCategorySeparators(
407-
from: declaration,
408-
previousDeclaration: index == 0 ? nil : sortedDeclarations[index - 1].declaration,
409-
order: order
410-
)
411-
412416
insertLinebreak(at: declaration.range.lowerBound)
413417
if options.lineAfterMarks {
414418
insertLinebreak(at: declaration.range.lowerBound)
@@ -461,13 +465,25 @@ extension Formatter {
461465
func removeExistingCategorySeparators(
462466
from declaration: Declaration,
463467
previousDeclaration: Declaration?,
464-
order: ParsedOrder
468+
order: ParsedOrder,
469+
preserving shouldPreserveComment: (_ commentBody: String) -> Bool = { _ in false }
465470
) {
466471
var matchingComments = matchingCategorySeparatorComments(in: declaration.leadingCommentRange, order: order)
472+
.map { $0.autoUpdating(in: self) }
473+
var preservedComment = false
467474

468475
while !matchingComments.isEmpty {
469476
let commentRange = matchingComments.removeFirst()
470477

478+
// Preserve the first comment matching the given closure
479+
if !preservedComment,
480+
let commentBody = index(after: commentRange.lowerBound, where: \.isCommentBody),
481+
shouldPreserveComment(tokens[commentBody].string)
482+
{
483+
preservedComment = true
484+
continue
485+
}
486+
471487
// Makes sure there are only whitespace or other comments before this comment.
472488
// Otherwise, we don't want to remove it.
473489
let tokensBeforeComment = tokens[declaration.range.lowerBound ..< commentRange.lowerBound]
@@ -483,16 +499,10 @@ extension Formatter {
483499
let rangeToRemove = startOfCommentLine ..< startOfNextDeclaration
484500
removeTokens(in: rangeToRemove)
485501

486-
// We specifically iterate from start to end here, instead of in reverse,
487-
// so we have to manually keep the existing indices up to date.
488-
matchingComments = matchingComments.map { commentRange in
489-
(commentRange.lowerBound - rangeToRemove.count)
490-
... (commentRange.upperBound - rangeToRemove.count)
491-
}
492-
493502
// Move any tokens from before the category separator into the previous declaration.
494503
// This makes sure that things like comments stay grouped in the same category.
495-
if let previousDeclaration, startOfCommentLine != 0 {
504+
// Don't do this is we preserved a previous comment, since this following comment is no longer the first one.
505+
if let previousDeclaration, startOfCommentLine != 0, !preservedComment {
496506
// Remove the tokens before the category separator from this declaration...
497507
let rangeBeforeComment = min(startOfCommentLine, declaration.range.lowerBound) ..< startOfCommentLine
498508
let tokensBeforeCommentLine = Array(tokens[rangeBeforeComment])

Tests/Rules/OrganizeDeclarationsTests.swift

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4204,4 +4204,49 @@ class OrganizeDeclarationsTests: XCTestCase {
42044204
exclude: [.blankLinesAtStartOfScope, .blankLinesAtEndOfScope]
42054205
)
42064206
}
4207+
4208+
func testRemovesAllUnnecessaryMarkAfterStandardMark() {
4209+
let input = """
4210+
public class Foo {
4211+
4212+
// MARK: Public
4213+
4214+
public func bar() {}
4215+
4216+
// MARK: Internal
4217+
4218+
// MARK: Implementation
4219+
4220+
func method() {}
4221+
4222+
// MARK: Testing
4223+
4224+
func testMethod() {}
4225+
4226+
}
4227+
"""
4228+
4229+
let output = """
4230+
public class Foo {
4231+
4232+
// MARK: Public
4233+
4234+
public func bar() {}
4235+
4236+
// MARK: Internal
4237+
4238+
func method() {}
4239+
4240+
func testMethod() {}
4241+
4242+
}
4243+
"""
4244+
4245+
testFormatting(
4246+
for: input, output,
4247+
rule: .organizeDeclarations,
4248+
options: FormatOptions(typeBodyMarks: .remove),
4249+
exclude: [.blankLinesAtStartOfScope, .blankLinesAtEndOfScope]
4250+
)
4251+
}
42074252
}

0 commit comments

Comments
 (0)