From 431d9131ce8affea48d844851e5c828677f34ea8 Mon Sep 17 00:00:00 2001 From: wuyangfan <1102042793@qq.com> Date: Mon, 18 May 2026 00:19:13 +0800 Subject: [PATCH] fix: vertical_whitespace_between_cases ignores comment separators Do not require a blank line between one-line switch cases when only comments or empty lines appear between them. Fixes #6412 --- CHANGELOG.md | 39 ++++++++++++++- .../VerticalWhitespaceBetweenCasesRule.swift | 48 ++++++++++++++++++- ...alWhitespaceBetweenCasesRuleExamples.swift | 7 +++ 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be786e3de4..76a792ada9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,21 @@ ### Enhancements +* Add `excluded_members` configuration to `empty_enum_arguments` to skip members + that require empty parentheses (e.g. HealthKit static functions). + [leno23](https://github.com/leno23) + [#5269](https://github.com/realm/SwiftLint/issues/5269) + +* Fix `unused_enumerated` false positives when offset and element are used in + separate chained trailing closures after `.enumerated()`. + [leno23](https://github.com/leno23) + [#5600](https://github.com/realm/SwiftLint/issues/5600) + +* Treat macro declarations like function declarations for `line_length` when + `ignores_function_declarations` is enabled. + [leno23](https://github.com/leno23) + [#5648](https://github.com/realm/SwiftLint/issues/5648) + * Print fixed code read from stdin to stdout. [SimplyDanny](https://github.com/SimplyDanny) [#6501](https://github.com/realm/SwiftLint/issues/6501) @@ -78,6 +93,23 @@ ### Bug Fixes +* Fix `accessibility_trait_for_button` false positives when `.isButton` or + `.isLink` is provided via a closure or `if #available` in + `accessibilityAddTraits`. + [leno23](https://github.com/leno23) + [#6446](https://github.com/realm/SwiftLint/issues/6446) + +* Fix `vertical_whitespace_between_cases` false positives when one-line cases are + separated only by comments. + [leno23](https://github.com/leno23) + [#6412](https://github.com/realm/SwiftLint/issues/6412) + +* Treat actors as implicitly inheriting from `Actor` in `missing_docs` when + `excludes_inherited_types` is enabled, avoiding false positives on members + such as `unownedExecutor`. + [leno23](https://github.com/leno23) + [#5422](https://github.com/realm/SwiftLint/issues/5422) + * Detect and autocorrect missing whitespace before `else` in `guard` statements for the `statement_position` rule. [theamodhshetty](https://github.com/theamodhshetty) @@ -693,7 +725,12 @@ or other error. [Martin Redington](https://github.com/mildm8nnered) [#6052](https://github.com/realm/SwiftLint/issues/6052) - + +* Fall back to default configuration when a nested `.swiftlint.yml` cannot be parsed + instead of aborting (e.g. duplicate YAML keys in a subdirectory). + [leno23](https://github.com/leno23) + [#6052](https://github.com/realm/SwiftLint/issues/6052) + * Keep the default severity levels when neither `warning` nor `error` values are configured. Ensure especially that the `error` level is not set to `nil` when the `warning` level isn't set either. diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/VerticalWhitespaceBetweenCasesRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/VerticalWhitespaceBetweenCasesRule.swift index d7439d48e9..57680b615d 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/VerticalWhitespaceBetweenCasesRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/VerticalWhitespaceBetweenCasesRule.swift @@ -1,3 +1,4 @@ +import Foundation import SwiftBasicFormat import SwiftSyntax @@ -126,9 +127,52 @@ private extension VerticalWhitespaceBetweenCasesRule { let currentIsOneLiner = currentCaseStartLine == currentCaseEndLine let nextIsOneLiner = nextCaseStartLine == nextCaseEndLine - // Skip if both are one-liners on consecutive lines. - return currentIsOneLiner && nextIsOneLiner && nextCaseStartLine == currentCaseStartLine + 1 + guard currentIsOneLiner, nextIsOneLiner else { + return false + } + + // Skip if both are one-liners with only empty or comment-only lines between them. + if nextCaseStartLine == currentCaseStartLine + 1 { + return true + } + + return linesBetweenContainOnlyCommentsOrAreEmpty( + startingLine: currentCaseEndLine + 1, + endingLine: nextCaseStartLine - 1 + ) } + + private func linesBetweenContainOnlyCommentsOrAreEmpty(startingLine: Int, endingLine: Int) -> Bool { + guard startingLine <= endingLine else { + return true + } + + for lineNumber in startingLine...endingLine { + if emptyLines.contains(lineNumber) { + continue + } + + let line = locationConverter.sourceLines[lineNumber - 1] + if !line.isCommentOnly { + return false + } + } + + return true + } + } +} + +private extension String { + var isCommentOnly: Bool { + let trimmed = trimmingCharacters(in: .whitespaces) + if trimmed.isEmpty { + return true + } + + return trimmed.hasPrefix("//") + || trimmed.hasPrefix("/*") + || trimmed.hasPrefix("*") } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/VerticalWhitespaceBetweenCasesRuleExamples.swift b/Source/SwiftLintBuiltInRules/Rules/Style/VerticalWhitespaceBetweenCasesRuleExamples.swift index 2d95319517..2785200d55 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/VerticalWhitespaceBetweenCasesRuleExamples.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/VerticalWhitespaceBetweenCasesRuleExamples.swift @@ -40,6 +40,13 @@ internal struct VerticalWhitespaceBetweenCasesRuleExamples { @unknown default: print("x is out of this world") } """), + Example(""" + switch myEnum { + case .a: print("a") + // Now we handle b. + case .b: print("b") + } + """), // Testing handling of trailing spaces Example(""" switch x { \("")