realm / SwiftLint

A tool to enforce Swift style and conventions.
https://realm.github.io/SwiftLint
MIT License
18.46k stars 2.2k forks source link

Add option for `opening_brace` rule not to trigger with multiline statements #5521

Open leonardosrodrigues0 opened 3 months ago

leonardosrodrigues0 commented 3 months ago

In case of multiline if and while statements, many adopt the style of putting the opening brace in a new line. This change add a new option to the rule to allow that style.

Closes #3720

SwiftLintBot commented 3 months ago
91 Messages
:book: Linting Aerial with this PR took 1.23s vs 1.23s on main (0% slower)
:book: Linting Alamofire with this PR took 1.79s vs 1.8s on main (0% faster)
:book: Linting Brave with this PR took 10.38s vs 10.43s on main (0% faster)
:book: Linting DuckDuckGo with this PR took 5.54s vs 5.54s on main (0% slower)
:book: Linting Firefox with this PR took 13.01s vs 12.99s on main (0% slower)
:book: Linting Kickstarter with this PR took 12.56s vs 12.6s on main (0% faster)
:book: Linting Moya with this PR took 0.69s vs 0.69s on main (0% slower)
:book: Linting NetNewsWire with this PR took 3.93s vs 3.92s on main (0% slower)
:book: Linting Nimble with this PR took 1.02s vs 1.03s on main (0% faster)
:book: Linting PocketCasts with this PR took 10.23s vs 10.23s on main (0% slower)
:book: Linting Quick with this PR took 0.46s vs 0.46s on main (0% slower)
:book: Linting Realm with this PR took 6.32s vs 6.34s on main (0% faster)
:book: Linting Sourcery with this PR took 3.16s vs 3.14s on main (0% slower)
:book: Linting Swift with this PR took 6.32s vs 6.29s on main (0% slower)
:book: Linting VLC with this PR took 1.67s vs 1.66s on main (0% slower)
:book: Linting Wire with this PR took 23.4s vs 23.42s on main (0% faster)
:book: Linting WordPress with this PR took 15.28s vs 15.34s on main (0% faster)
:book: This PR fixed a violation in Sourcery: /SourceryFramework/Sources/Parsing/Utils/AnnotationsParser.swift:129:13: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Sourcery: /SourceryRuntime/Sources/Common/Composer/Composer.swift:259:17: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/private/OSLog/OSLogMessage.swift:230:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/private/StdlibCollectionUnittest/COWLoggingArray.swift:62:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/private/StdlibUnittest/StdlibCoreExtras.swift:164:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/private/StdlibUnittest/StringConvertible.swift:25:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/Synchronization/AtomicOptional.swift:62:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/Synchronization/AtomicPointers.swift:845:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/Synchronization/AtomicRepresentable.swift:206:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/Character.swift:116:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/ClosedRange.swift:202:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/Codable.swift:1618:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/Codable.swift:535:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/Dictionary.swift:1370:7: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/Dictionary.swift:1377:7: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/DiscontiguousSlice.swift:314:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/ExistentialCollection.swift:1058:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/ExistentialCollection.swift:412:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/ExistentialCollection.swift:478:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/ExistentialCollection.swift:838:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/Integers.swift:578:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/KeyPath.swift:2416:3: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/MutableCollection.swift:62:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/OutputStream.swift:625:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/Pointer.swift:34:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/RandomAccessCollection.swift:35:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/Range.swift:219:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/Range.swift:687:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/RangeSetRanges.swift:242:7: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/RangeSetRanges.swift:250:7: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/SIMDVector.swift:101:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/SIMDVector.swift:85:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/SliceBuffer.swift:19:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/Sort.swift:599:7: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/Sort.swift:608:7: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/StaticBigInt.swift:36:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/StaticPrint.swift:784:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/String.swift:482:5: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/StringGraphemeBreaking.swift:837:7: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/StringIndexValidation.swift:209:5: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/StringIndexValidation.swift:235:5: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/StringIndexValidation.swift:371:5: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/StringProtocol.swift:26:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/StringUTF8Validation.swift:73:5: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/SwiftNativeNSArray.swift:156:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/UTF8.swift:236:5: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/UTF8.swift:313:5: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Swift: /stdlib/public/core/UnicodeScalarProperties.swift:1324:3: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Wire: /wire-ios-data-model/Source/MLS/MLSDecryptionService.swift:148:9: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Wire: /wire-ios-data-model/Source/MLS/MLSService.swift:1628:9: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Wire: /wire-ios-data-model/Source/Model/Message/V2Asset.swift:70:13: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Wire: /wire-ios-data-model/Source/Model/Message/V2Asset.swift:75:13: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Wire: /wire-ios-data-model/Source/Model/Message/V2Asset.swift:80:13: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Wire: /wire-ios-data-model/Source/Model/Message/V3Asset.swift:139:9: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Wire: /wire-ios-data-model/Source/Model/Message/V3Asset.swift:91:13: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Wire: /wire-ios-data-model/Source/Model/Message/ZMClientMessage+LinkPreview.swift:119:13: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Wire: /wire-ios-data-model/Source/Model/UserClient/UserClient+Patches.swift:100:9: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Wire: /wire-ios-notification-engine/Sources/NotificationSession.swift:488:9: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Wire: /wire-ios-request-strategy/Sources/Payloads/Processing/ConversationEventPayloadProcessor.swift:714:9: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Wire: /wire-ios-request-strategy/Sources/Request Strategies/Assets/Link Preview/LinkPreviewAssetUploadRequestStrategy.swift:170:9: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Wire: /wire-ios-sync-engine/Source/SessionManager/APIVersionResolver.swift:103:9: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Wire: /wire-ios/Wire-iOS/Sources/UserInterface/Calling/CallGridView/CallGridViewController.swift:81:13: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Wire: /wire-ios/Wire-iOS/Sources/UserInterface/Conversation/Content/Cells/Utility/MessageToolboxDataSource.swift:278:9: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Wire: /wire-ios/Wire-iOS/Sources/UserInterface/Conversation/Content/MessagePresenter.swift:153:9: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in Wire: /wire-ios/WireCommonComponents/AutomationHelper.swift:130:9: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in WordPress: /WordPress/Classes/Extensions/NSAttributedString+Helpers.swift:36:13: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in WordPress: /WordPress/Classes/Extensions/URL+Helpers.swift:65:17: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in WordPress: /WordPress/Classes/ViewRelated/Post/AbstractPostListViewController.swift:16:1: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in WordPress: /WordPress/Classes/ViewRelated/Post/PostTagPickerViewController.swift:269:9: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in WordPress: /WordPress/Classes/ViewRelated/Post/PostTagPickerViewController.swift:278:9: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in WordPress: /WordPress/Classes/ViewRelated/Post/PostTagPickerViewController.swift:286:9: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in WordPress: /WordPress/WordPressShareExtension/ShareTagsPickerViewController.swift:270:9: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in WordPress: /WordPress/WordPressShareExtension/ShareTagsPickerViewController.swift:279:9: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)
:book: This PR fixed a violation in WordPress: /WordPress/WordPressShareExtension/ShareTagsPickerViewController.swift:287:9: warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration (opening_brace)

Generated by :no_entry_sign: Danger

leonardosrodrigues0 commented 3 months ago

@SimplyDanny Could you take a look at this when you have some time? It would benefit many that are used to adopting this style.

I left the new option on by default just to check with the OSS projects, all the changes are the expected fixed violations.

leonardosrodrigues0 commented 2 months ago

I wonder why this new option does not apply likewise to guard and for (and maybe other statements). Any reason for that?

From the issue and my experience, the main focus would be if, while and guard, but guard has the else keyword that is used in the same line as the opening brace in this type of cases:

guard
    let child = parent.children.first,
    let grandchild = child.children.first,
    let greatGrandchild = grandchild.children.first
else {
    // Some code
}

I did, however, take a look at the OSS differences when we ignore the rule for multiline "predecessors of the body" for all statements affected by the rule. I checked all differences and it seems that this style is frequently adopted in type declarations (and extensions), as in:

extension RawRepresentable
where
    Self: AtomicOptionalRepresentable,
    RawValue: AtomicOptionalRepresentable
{
    // Some code
}

Considering this, I think that the new direction should be to let the option ignore all statements that are "multiline before the opening brace" (except for single keywords like do and defer). And if we go this way, I don't see a reason why we would leave functions and initializers (that are already ignored by the allowMultilineFunc option) with an independent option of all other statements.

Changing the existing option name and make it affect all statements would be a breaking change, and I don't have experience on how these are made in this project. Would we still support allowMultilineFunc but deprecate it?

Additionally, the new option name could be something like ignoreMultilineBracePredecessors, ignoreMultilineOpeningBracePredecessors or ignoreMultilineBodyPredecessors. I'm not sure if "predecessors" fits well here, but it is the best description I could create. On the other hand, ignoreMultilineStatements would be simpler but imprecise, as you pointed out.

SimplyDanny commented 2 months ago

Thank you for the write-up! So the topic applies to functions/initializers (already supported), types and statements (implemented by this PR).

I think that an existing option shouldn't suddenly support much more than it was intended for. But we may rename allow_multiline_func to something better matching while still supporting the current name for the time being.

Statements like if, while, guard and for should be associated with a separate option.

Types might be yet another category. We could merge them with the control-flow statements from the previous group (as both groups will be newly introduced). However, this doesn't really match, which would already be problematic when looking for an option name.

Talking about names: How about ignoreMultilineFunctionSignatures, ignoreMultilineStatementConditions and ignoreMultilineTypeHeaders?

leonardosrodrigues0 commented 2 months ago

I like the functions/initializers, types and statements separation and the name for the configuration options, I'll implement that.

But we may rename allow_multiline_func to something better matching while still supporting the current name for the time being.

How would we do that? I found this example being removed in #5107, should we mark the option as deprecated like this?

mutating func apply(configuration: Any) throws {
    // ...
    } else if let statementLevelConfiguration = configurationDict["statement_level"] {
        queuedPrintError(
            """
            warning: 'statement_level' has been renamed to 'function_level' and will be completely removed \
            in a future release.
            """
        )
        try functionLevel.apply(configuration: statementLevelConfiguration)
    }
    // ...
}
SimplyDanny commented 2 months ago

How would we do that? I found this example being removed in https://github.com/realm/SwiftLint/pull/5107, should we mark the option as deprecated like this?

The new macro approach doesn't support deprecation warnings well yet. I'm working on it though. For our PR, just leave the existing option as is for now. I'll take care of the rename once I found a good solution.

SimplyDanny commented 2 months ago

How would we do that? I found this example being removed in #5107, should we mark the option as deprecated like this?

The new macro approach doesn't support deprecation warnings well yet. I'm working on it though. For our PR, just leave the existing option as is for now. I'll take care of the rename once I found a good solution.

I've added a way to mark options as deprecated in #5540. Just in case you want to handle the rename here as well ... 😉