# Rule Reference, Grouped by Concern

Back to [SKILL.md](../SKILL.md).

This is an offline index of every rule identifier, so you can find the right
name without a network connection. The summaries are short on purpose. For
exact behaviour, options, whether a rule is correctable, and any rule that has
moved between categories in a newer release, the rule directory
(https://realm.github.io/SwiftLint/rule-directory.html) and
`swiftlint rules <identifier>` are authoritative.

Kind column:

- **D**: default rule, on unless listed in `disabled_rules` (101 rules).
- **O**: opt-in rule, off until listed in `opt_in_rules` (149 rules).
- **A**: analyzer rule, needs the type-checked AST; list it in
  `analyzer_rules` and run `swiftlint analyze --compiler-log-path <log>`
  (5 rules). The workflow is in
  [custom rules and analyze](custom-rules-and-analyze.md).

## Contents

- [1. Controlling SwiftLint itself](#1-controlling-swiftlint-itself)
- [2. Size and complexity](#2-size-and-complexity)
- [3. Crash-prone constructs](#3-crash-prone-constructs)
- [4. Naming](#4-naming)
- [5. Access control](#5-access-control)
- [6. SwiftUI, assets and accessibility](#6-swiftui-assets-and-accessibility)
- [7. Concurrency and errors](#7-concurrency-and-errors)
- [8. Legacy and Objective-C era APIs](#8-legacy-and-objective-c-era-apis)
- [9. UIKit, Interface Builder and object lifetime](#9-uikit-interface-builder-and-object-lifetime)
- [10. Collections and sequences](#10-collections-and-sequences)
- [11. Idiomatic expressions](#11-idiomatic-expressions)
- [12. Redundant or dead code](#12-redundant-or-dead-code)
- [13. Types, declarations and file organisation](#13-types-declarations-and-file-organisation)
- [14. Enums and switch](#14-enums-and-switch)
- [15. Whitespace, braces and punctuation](#15-whitespace-braces-and-punctuation)
- [16. Multi-line layout](#16-multi-line-layout)
- [17. Comments and documentation](#17-comments-and-documentation)
- [18. Availability and deployment](#18-availability-and-deployment)
- [19. Testing](#19-testing)
- [20. Analyzer-only extras](#20-analyzer-only-extras)

## 1. Controlling SwiftLint itself

| Rule | Kind | Flags |
|---|---|---|
| `blanket_disable_command` | D | a `swiftlint:disable` that is never re-enabled and so covers the rest of the file |
| `invalid_swiftlint_command` | D | malformed `swiftlint:` comment directives |
| `superfluous_disable_command` | D | disable directives for rules that would not have fired there |
| `custom_rules` | D | umbrella identifier for the regex rules defined under `custom_rules` |

## 2. Size and complexity

| Rule | Kind | Flags |
|---|---|---|
| `line_length` | D | lines longer than the configured limit |
| `file_length` | D | files with too many lines |
| `type_body_length` | D | type bodies with too many lines |
| `function_body_length` | D | function bodies with too many lines |
| `closure_body_length` | O | closure bodies with too many lines |
| `function_parameter_count` | D | functions taking too many parameters |
| `enum_case_associated_values_count` | O | enum cases carrying too many associated values |
| `large_tuple` | D | tuples with too many members |
| `cyclomatic_complexity` | D | functions with too many independent branches |
| `nesting` | D | types or functions nested too deeply |

## 3. Crash-prone constructs

| Rule | Kind | Flags |
|---|---|---|
| `force_cast` | D | forced casts with `as!` |
| `force_try` | D | `try!` |
| `force_unwrapping` | O | force unwraps with postfix `!` |
| `implicitly_unwrapped_optional` | O | declarations typed as `T!` |
| `fatal_error_message` | O | `fatalError()` calls with no explanation |
| `discouraged_assert` | O | `assert(false, ...)` where `assertionFailure` says it directly |
| `unavailable_function` | O | stub functions that only trap and should be marked `@available(*, unavailable)` |
| `unowned_variable_capture` | O | `unowned` captures; `weak` is the safer default |
| `self_in_property_initialization` | D | stored property initialisers that refer to `self` without being `lazy` |

## 4. Naming

| Rule | Kind | Flags |
|---|---|---|
| `identifier_name` | D | variable, function and case names outside the allowed length or casing |
| `type_name` | D | type names outside the allowed length or casing |
| `generic_type_name` | D | generic parameter names outside the allowed length or casing |
| `inclusive_language` | D | identifiers that use terms flagged as non-inclusive |
| `discouraged_none_name` | O | cases or static members called `none`, which collide with `Optional.none` |
| `prefixed_toplevel_constant` | O | global constants lacking the configured prefix (such as `k`) |
| `file_name` | O | files whose name does not match the main type they declare |
| `file_name_no_space` | O | file names containing spaces |

## 5. Access control

| Rule | Kind | Flags |
|---|---|---|
| `explicit_acl` | O | declarations without an explicit access level |
| `explicit_top_level_acl` | O | top-level declarations without an explicit access level |
| `extension_access_modifier` | O | extensions whose members all share an access level that could sit on the extension |
| `no_extension_access_modifier` | O | any access modifier placed on an extension itself |
| `lower_acl_than_parent` | O | members declared more visible than the type that holds them |
| `private_over_fileprivate` | D | `fileprivate` where `private` would do |
| `strict_fileprivate` | O | every use of `fileprivate` |
| `redundant_set_access_control` | D | `private(set)` style setters that repeat the property's own level |
| `private_action` | O | `@IBAction` methods that are not private |
| `private_outlet` | O | `@IBOutlet` properties that are not private |
| `private_subject` | O | Combine subjects exposed beyond private scope |
| `private_swiftui_state` | O | SwiftUI state property wrappers that are not private |

## 6. SwiftUI, assets and accessibility

| Rule | Kind | Flags |
|---|---|---|
| `accessibility_label_for_image` | O | images with no accessibility label and not marked decorative |
| `accessibility_trait_for_button` | O | tap-handling views missing a button or link trait |
| `prefer_asset_symbols` | O | image lookups by string name where a generated asset symbol exists |
| `object_literal` | O | image and color initialisers that could be object literals |
| `discouraged_object_literal` | O | `#imageLiteral` / `#colorLiteral`; the mirror of `object_literal` |

## 7. Concurrency and errors

| Rule | Kind | Flags |
|---|---|---|
| `unhandled_throwing_task` | O | `Task` closures that throw with nobody catching or awaiting the error |
| `async_without_await` | O | functions marked `async` whose body never awaits |
| `incompatible_concurrency_annotation` | O | public concurrency annotations that need `@preconcurrency` to stay usable from older language modes |
| `redundant_sendable` | D | `Sendable` conformances on types that are already implicitly sendable, such as actor-isolated ones |
| `unneeded_throws_rethrows` | O | `throws` or `rethrows` on bodies that cannot throw |
| `untyped_error_in_catch` | O | `catch let error` with no pattern; plain `catch` already binds `error` |

## 8. Legacy and Objective-C era APIs

| Rule | Kind | Flags |
|---|---|---|
| `legacy_cggeometry_functions` | D | `CGRectGetWidth` style free functions instead of properties |
| `legacy_nsgeometry_functions` | D | the AppKit `NSRect` equivalents of the above |
| `legacy_constant` | D | old constants such as `CGRectZero` or `M_PI` |
| `legacy_constructor` | D | `CGPointMake` style constructors |
| `legacy_hashing` | D | overriding `hashValue` instead of implementing `hash(into:)` |
| `legacy_random` | D | `arc4random` family calls instead of `.random(in:)` |
| `legacy_multiple` | O | `value % n == 0` where `isMultiple(of:)` reads better |
| `legacy_objc_type` | O | bridged Foundation reference types where a Swift value type exists |
| `legacy_uigraphics_function` | O | `UIGraphicsBeginImageContext` style calls instead of `UIGraphicsImageRenderer` |
| `block_based_kvo` | D | string-keyed KVO instead of the key-path, closure-based API |
| `discouraged_direct_init` | D | types that should not be created with a bare `init()`, such as `UIDevice` or `Bundle` |
| `compiler_protocol_init` | D | direct calls to literal-protocol initialisers like `init(arrayLiteral:)` |
| `ns_number_init_as_function_reference` | D | passing `NSNumber.init` as a function value, which resolves ambiguously |
| `nsobject_prefer_isequal` | D | `NSObject` subclasses defining `==` instead of overriding `isEqual` |
| `dynamic_inline` | D | `dynamic` combined with `@inline(__always)` |
| `redundant_objc_attribute` | D | `@objc` that another attribute (such as `@IBAction`) already implies |
| `non_optional_string_data_conversion` | D | `string.data(using: .utf8)!` where `Data(string.utf8)` cannot fail |
| `optional_data_string_conversion` | D | `String(decoding:as:)`, which silently repairs invalid bytes, where the failable initialiser is safer |

## 9. UIKit, Interface Builder and object lifetime

| Rule | Kind | Flags |
|---|---|---|
| `class_delegate_protocol` | D | delegate protocols not restricted to classes, so they cannot be held weakly |
| `weak_delegate` | O | delegate properties not declared `weak` |
| `strong_iboutlet` | O | outlets declared `weak` instead of strong |
| `valid_ibinspectable` | D | `@IBInspectable` on unsupported types or without an explicit type |
| `ibinspectable_in_extension` | O | `@IBInspectable` declared inside extensions |
| `prohibited_interface_builder` | O | any outlet or action, for projects that build UI in code only |
| `notification_center_detachment` | D | removing observers other than `self` from `NotificationCenter` inside `deinit` |
| `discarded_notification_center_observer` | O | ignoring the token returned by block-based `addObserver` |
| `overridden_super_call` | O | overrides of lifecycle methods (for example `viewWillAppear`) that forget to call `super` |
| `prohibited_super_call` | O | overrides that must not call `super`, such as `loadView` |
| `override_in_extension` | O | overriding declarations placed in extensions |
| `required_deinit` | O | classes without an explicit `deinit` |

## 10. Collections and sequences

| Rule | Kind | Flags |
|---|---|---|
| `empty_count` | O | `.count == 0` instead of `.isEmpty` |
| `empty_collection_literal` | O | comparing against `[]` or `[:]` instead of `.isEmpty` |
| `empty_string` | O | comparing against `""` instead of `.isEmpty` |
| `contains_over_filter_count` | O | `filter { }.count > 0` instead of `contains(where:)` |
| `contains_over_filter_is_empty` | O | `filter { }.isEmpty` instead of `contains(where:)` |
| `contains_over_first_not_nil` | O | `first(where:) != nil` instead of `contains(where:)` |
| `contains_over_range_nil_comparison` | O | `range(of:) != nil` instead of `contains` |
| `first_where` | O | `filter { }.first` instead of `first(where:)` |
| `last_where` | O | `filter { }.last` instead of `last(where:)` |
| `sorted_first_last` | O | `sorted().first` instead of `min()` / `max()` |
| `flatmap_over_map_reduce` | O | `map { }.reduce([], +)` instead of `flatMap` |
| `reduce_into` | O | `reduce` building a copy-on-write value where `reduce(into:)` avoids copies |
| `reduce_boolean` | D | `reduce(true)` / `reduce(false)` instead of `allSatisfy` / `contains` |
| `is_disjoint` | D | `intersection(_:).isEmpty` instead of `isDisjoint(with:)` |
| `array_init` | O | `map { $0 }` used to copy a sequence into an array |
| `unused_enumerated` | D | `.enumerated()` where the index or the element is never used |
| `duplicated_key_in_dictionary_literal` | D | the same key twice in one dictionary literal |
| `joined_default_parameter` | O | `joined(separator: "")`, which is the default |

## 11. Idiomatic expressions

| Rule | Kind | Flags |
|---|---|---|
| `syntactic_sugar` | D | `Array<T>`, `Optional<T>` and similar spelled out instead of `[T]`, `T?` |
| `shorthand_operator` | D | `a = a + b` instead of `a += b` |
| `toggle_bool` | O | `flag = !flag` instead of `flag.toggle()` |
| `prefer_key_path` | O | `{ $0.name }` closures where `\.name` works |
| `prefer_type_checking` | D | `value as? T != nil` instead of `value is T` |
| `prefer_zero_over_explicit_init` | O | `CGPoint(x: 0, y: 0)` and friends instead of `.zero` |
| `prefer_condition_list` | O | `&&` in conditions where a comma-separated list works |
| `prefer_self_in_static_references` | O | spelling out the type name inside its own static context instead of `Self` |
| `prefer_self_type_over_type_of_self` | O | `type(of: self)` instead of `Self` |
| `explicit_init` | O | `.init` called explicitly where the type name alone works |
| `identical_operands` | O | comparisons with the same expression on both sides |
| `yoda_condition` | O | the constant on the left of a comparison |
| `for_where` | D | a lone `if` inside a `for` loop that could be a `where` clause |
| `shorthand_optional_binding` | O | `if let value = value` instead of `if let value` |
| `self_binding` | O | rebinding `self` under a name other than the configured one |
| `number_separator` | O | long numeric literals without `_` grouping |
| `no_magic_numbers` | O | unnamed numeric literals in code |
| `nslocalizedstring_key` | O | `NSLocalizedString` keys that are not static string literals |
| `nslocalizedstring_require_bundle` | O | `NSLocalizedString` calls without an explicit bundle |
| `optional_enum_case_matching` | O | matching optional enums with `.case?` where `.case` suffices |
| `pattern_matching_keywords` | O | `let` / `var` repeated per element instead of once outside the tuple pattern |
| `unavailable_condition` | D | `#available` with an empty true branch where `#unavailable` fits |
| `unused_optional_binding` | D | `if let _ = value` instead of `value != nil` |
| `void_function_in_ternary` | D | calling `Void` functions from the branches of a ternary |
| `anonymous_argument_in_multiline_closure` | O | `$0` style arguments in closures that span several lines |
| `shorthand_argument` | O | `$0` style arguments used far from the opening brace or in complex expressions |
| `trailing_closure` | O | a final closure argument passed inside the parentheses |
| `multiple_closures_with_trailing_closure` | D | trailing-closure syntax when more than one closure is passed |

## 12. Redundant or dead code

| Rule | Kind | Flags |
|---|---|---|
| `redundant_discardable_let` | D | `let _ = call()` instead of `_ = call()` |
| `redundant_nil_coalescing` | O | `?? nil` |
| `redundant_self` | O | explicit `self.` where it is not needed |
| `redundant_type_annotation` | O | type annotations the initial value already makes obvious |
| `redundant_string_enum_value` | D | string raw values identical to the case name |
| `redundant_void_return` | D | `-> Void` written on functions |
| `redundant_final` | O | `final` that adds nothing because the context is already final |
| `implicit_getter` | D | an explicit `get` in a read-only computed property |
| `implicit_optional_initialization` | D | optional variables with a spelled-out or missing `= nil`, according to the configured style |
| `implicit_return` | O | `return` in single-expression bodies |
| `direct_return` | O | assigning to a local only to return it on the next line |
| `superfluous_else` | O | `else` after a branch that already exits |
| `return_value_from_void_function` | O | `return someVoidCall()` in a `Void` function |
| `empty_parameters` | D | `(Void) -> T` instead of `() -> T` |
| `empty_parentheses_with_trailing_closure` | D | empty `()` before a trailing closure |
| `empty_enum_arguments` | D | `case .loaded(_)` where `case .loaded` suffices |
| `no_empty_block` | O | empty code blocks |
| `unneeded_break_in_switch` | D | `break` at the end of a case that already has code |
| `unneeded_escaping` | O | `@escaping` on closures that never escape |
| `unneeded_override` | D | overrides whose only statement calls `super` |
| `unneeded_synthesized_initializer` | D | hand-written initialisers identical to the synthesised memberwise one |
| `unneeded_parentheses_in_closure_argument` | O | parentheses around closure parameter lists that do not need them |
| `unused_closure_parameter` | D | closure parameters that are never used and could be `_` |
| `unused_parameter` | O | function parameters that are never used |
| `unused_control_flow_label` | D | loop or statement labels nobody jumps to |
| `unused_setter_value` | D | setters that ignore `newValue` |
| `unused_import` | A | imports the file does not need; correctable |
| `unused_declaration` | A | private declarations never referenced |

## 13. Types, declarations and file organisation

| Rule | Kind | Flags |
|---|---|---|
| `file_types_order` | O | top-level declarations in a file out of the configured order |
| `type_contents_order` | O | members inside a type out of the configured order |
| `one_declaration_per_file` | O | more than one top-level type in a file |
| `no_grouping_extension` | O | extensions of a type declared in the same file used only for grouping |
| `modifier_order` | O | declaration modifiers in an inconsistent order |
| `attributes` | O | attributes placed on the wrong line relative to their declaration |
| `attribute_name_spacing` | D | a space between an attribute name and its parentheses |
| `computed_accessors_order` | D | getter and setter written in inconsistent order |
| `protocol_property_accessors_order` | D | `{ set get }` instead of `{ get set }` in protocol requirements |
| `convenience_type` | O | structs or classes used only as namespaces that should be caseless enums |
| `static_operator` | O | operators declared as free functions instead of static members |
| `static_over_final_class` | D | `final class` members where `static` means the same |
| `non_overridable_class_declaration` | O | `class` members inside final classes that should be `static` or `final class` |
| `sorted_imports` | O | imports out of alphabetical order |
| `duplicate_imports` | D | the same module imported more than once |
| `function_default_parameter_at_end` | O | defaulted parameters placed before required ones |
| `discouraged_default_parameter` | O | default argument values in declarations where the rule discourages them; see the directory for its scope |
| `discouraged_optional_boolean` | O | `Bool?`, a three-state boolean |
| `discouraged_optional_collection` | O | optional arrays, sets and dictionaries where empty would do |
| `explicit_type_interface` | O | properties declared without an explicit type |
| `variable_shadowing` | O | local names that shadow an outer binding |
| `let_var_whitespace` | O | `let` / `var` declarations not separated from other statements by a blank line |

## 14. Enums and switch

| Rule | Kind | Flags |
|---|---|---|
| `duplicate_enum_cases` | D | two enum cases with the same name |
| `explicit_enum_raw_value` | O | raw-valued enum cases without an explicit raw value |
| `raw_value_for_camel_cased_codable_enum` | O | camel-cased cases of `Codable` string enums with no raw value, which would encode oddly |
| `required_enum_case` | O | enums conforming to a configured protocol but missing a required case |
| `sorted_enum_cases` | O | enum cases out of alphabetical order |
| `switch_case_alignment` | D | `case` labels not aligned with their `switch` |
| `switch_case_on_newline` | O | case bodies on the same line as the label |
| `vertical_whitespace_between_cases` | O | missing blank line between switch cases |
| `no_fallthrough_only` | D | cases whose only statement is `fallthrough` |
| `fallthrough` | O | any use of `fallthrough` |
| `duplicate_conditions` | D | the same condition twice in one `if` / `else if` chain or `switch` |

## 15. Whitespace, braces and punctuation

| Rule | Kind | Flags |
|---|---|---|
| `trailing_whitespace` | D | spaces or tabs at line end |
| `trailing_newline` | D | files not ending in exactly one newline |
| `leading_whitespace` | D | whitespace at the very start of a file |
| `trailing_semicolon` | D | semicolons at line end |
| `trailing_comma` | D | trailing commas in collection literals, per the configured preference |
| `vertical_whitespace` | D | too many consecutive blank lines |
| `vertical_whitespace_opening_braces` | O | a blank line right after `{` |
| `vertical_whitespace_closing_braces` | O | a blank line right before `}` |
| `opening_brace` | D | `{` not on the same line as its declaration, or missing a space before it |
| `contrasted_opening_brace` | O | the opposite style: `{` must start its own line |
| `closing_brace` | D | a space between `}` and a following `)` |
| `closure_spacing` | O | missing spaces just inside closure braces |
| `closure_end_indentation` | O | a closing `}` not aligned with the line that opened the closure |
| `closure_parameter_position` | D | closure parameters not on the line of the opening brace |
| `literal_expression_end_indentation` | O | a closing bracket of a multi-line literal not aligned with its start |
| `colon` | D | spaces before a colon or not exactly one after it |
| `comma` | D | a space before a comma or none after it |
| `comma_inheritance` | O | `&` in inheritance lists where commas belong |
| `control_statement` | D | parentheses around `if`, `guard`, `while` or `switch` conditions |
| `statement_position` | D | `else` or `catch` not on the same line as the preceding `}` |
| `return_arrow_whitespace` | D | wrong spacing around `->` |
| `operator_usage_whitespace` | O | missing spaces around binary operators |
| `no_space_in_method_call` | D | a space between a function name and its `(` |
| `function_name_whitespace` | D | irregular spacing between `func`, the name and its generic or parameter clause |
| `period_spacing` | O | more than one space after a period in comments |
| `indentation_width` | O | indentation that is not a multiple of the configured width |
| `invisible_character` | D | zero-width and similar invisible characters in string literals |
| `void_return` | D | `-> ()` instead of `-> Void` |

## 16. Multi-line layout

| Rule | Kind | Flags |
|---|---|---|
| `multiline_arguments` | O | call arguments that mix one-per-line with several-per-line |
| `multiline_arguments_brackets` | O | multi-line call arguments whose parentheses are not on their own lines |
| `multiline_call_arguments` | O | multi-line calls with more arguments per line than allowed |
| `multiline_function_chains` | O | chained calls that are neither all on one line nor one per line |
| `multiline_literal_brackets` | O | multi-line collection literals whose brackets share a line with elements |
| `multiline_parameters` | O | declaration parameters that mix one-per-line with several-per-line |
| `multiline_parameters_brackets` | O | multi-line parameter lists whose parentheses are not on their own lines |
| `vertical_parameter_alignment` | D | wrapped declaration parameters not aligned with the first |
| `vertical_parameter_alignment_on_call` | O | wrapped call arguments not aligned with the first |
| `conditional_returns_on_newline` | O | `return` on the same line as its `if` or `guard` |
| `collection_alignment` | O | keys or values in a multi-line collection literal not aligned |

## 17. Comments and documentation

| Rule | Kind | Flags |
|---|---|---|
| `todo` | D | `TODO` and `FIXME` comments |
| `expiring_todo` | O | dated TODO or FIXME comments that are close to or past their date |
| `mark` | D | badly formatted `// MARK:` comments |
| `comment_spacing` | D | `//` not followed by a space |
| `missing_docs` | O | public or open declarations without documentation |
| `orphaned_doc_comment` | D | `///` comments that are not attached to any declaration |
| `local_doc_comment` | O | doc comments inside function bodies, where a regular comment belongs |
| `file_header` | O | file headers that do not match the configured pattern |

## 18. Availability and deployment

| Rule | Kind | Flags |
|---|---|---|
| `deployment_target` | D | availability checks already satisfied by the deployment target |

## 19. Testing

| Rule | Kind | Flags |
|---|---|---|
| `xctfail_message` | D | `XCTFail()` with no message |
| `private_unit_test` | D | `private` test methods, which XCTest silently never runs |
| `balanced_xctest_lifecycle` | O | a `setUp` without a matching `tearDown`, or the reverse |
| `empty_xctest_method` | O | test methods with empty bodies |
| `final_test_case` | O | test case classes not marked `final` |
| `single_test_class` | O | more than one test class per file |
| `test_case_accessibility` | O | non-test members of a test class that are not private |
| `xct_specific_matcher` | O | `XCTAssertEqual(x, true)` style assertions where a specific matcher exists |
| `prefer_nimble` | O | XCTest assertions in codebases standardised on Nimble |
| `nimble_operator` | O | Nimble free-function matchers where an operator form exists |
| `quick_discouraged_call` | O | real work done directly inside Quick `describe` / `context` blocks |
| `quick_discouraged_focused_test` | O | focused Quick specs such as `fit` or `fdescribe` left in |
| `quick_discouraged_pending_test` | O | pending Quick specs such as `xit` left in |

## 20. Analyzer-only extras

| Rule | Kind | Flags |
|---|---|---|
| `capture_variable` | A | closures that capture a mutable variable |
| `explicit_self` | A | instance member access without `self.` |
| `typesafe_array_init` | A | `Array(seq.map { ... })` where `map` already returns an array |

`unused_import` and `unused_declaration`, the other two analyzer rules, are
listed under redundant code above.
