realm / SwiftLint

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

`unused_declaration` configuration causes Invalid configuration warning in `0.50.1` #4612

Closed username0x0a closed 1 year ago

username0x0a commented 1 year ago

New Issue Checklist

Describe the bug

Having unused_declaration enabled in the project like this:

opt_in_rules:
  ...
  - unused_declaration
  ...

unused_declaration:
  severity: warning

throws me a lot of console warnings:

Invalid configuration for 'unused_declaration'. Falling back to default.

Previously, SwiftLint 0.49.1 worked just fine with this setup, so I guess some syntax parsing issue is involved.

Complete output when running SwiftLint, including the stack trace and command used
flowie:kiwi-ios michi% swiftlint --quiet                       
Invalid configuration for 'unused_declaration'. Falling back to default.
Invalid configuration for 'unused_declaration'. Falling back to default.
Invalid configuration for 'unused_declaration'. Falling back to default.
...
(multiplied because of nesting)

Environment


# Warnings count threshold for linting issues
# When this threshold is reached, SwiftLint starts complaining -> the actual allowed maximum is THRESHOLD-1
warning_threshold: 5

excluded:
  - DerivedData

opt_in_rules:
  - capture_variable
  - closure_end_indentation
  - collection_alignment
  - comment_spacing
  - computed_accessors_order
  - contains_over_first_not_nil
  - convenience_type
  - deployment_target
  - discouraged_assert
  - discouraged_optional_boolean
  - duplicate_imports
  - duplicated_key_in_dictionary_literal
  - empty_string
  - empty_xctest_method
  - explicit_init
  - fallthrough
  - fatal_error_message
  - first_where
  - force_unwrapping
  - identical_operands
  - implicit_return
  - implicitly_unwrapped_optional
  - last_where
  - legacy_multiple
  - legacy_random
  - literal_expression_end_indentation
  - modifier_order
  - multiline_parameters
  - multiline_parameters_brackets
  - multiple_closures_with_trailing_closure
  - operator_usage_whitespace
  - optional_enum_case_matching
  - overridden_super_call
  - prefer_zero_over_explicit_init
  - private_outlet
  - prohibited_interface_builder
  - prohibited_super_call
  - redundant_nil_coalescing
  - self_in_property_initialization
  - single_test_class
  - sorted_first_last
  - syntactic_sugar
  - toggle_bool
  - unavailable_condition
  - unneeded_parentheses_in_closure_argument
  - untyped_error_in_catch
  - unused_capture_list
  - unused_declaration
  - unused_import
  - vertical_parameter_alignment_on_call
  - weak_delegate
  - xct_specific_matcher
  - yoda_condition
  # Could be added, but work work:
  # - prefer_self_in_static_references
  # Might be useful in future:
  # - balanced_xctest_lifecycle
  # - legacy_objc_type
  # - private_subject # Simon will like this!
  # - self_binding
  # - test_case_accessibility # testers will hate this

disabled_rules:
  # When registering for a notification using a block,
  # the opaque observer that is returned should be stored so it can be removed later
  - discarded_notification_center_observer

  # Lines should not have trailing whitespace
  - trailing_whitespace

  # Prefer `!= nil` over `let _ =`.
  # Disabled because the compiler already checks this.
  - unused_optional_binding

  # Underscores should be used as thousand separator in large decimal numbers
  - number_separator

  # http://www.openradar.me/36663633 and https://bugs.swift.org/browse/SR-6795
  - block_based_kvo

  # IB is not used - this is not necessary
  - valid_ibinspectable

  # IB is not used - this is not necessary
  - private_outlet

  # Guilty, we use some custom `.none` cases
  - discouraged_none_name

  # Does not take into account subclassing, therefore duplicate warnings
  - class_delegate_protocol

  # Done in SonarQube instead, sometimes it is better to have more params rather than a struct.
  - function_parameter_count

  # Done in SonarQube instead. FIXMEs can be kept, TODOs must be resolved.
  - todo

  # We don't want to force it hard
  - trailing_closure

  # Doesn't work when the file has no copyright header and no imports
  - leading_whitespace

  # We're not really that much into SJW wars.
  - inclusive_language

  # Trailing commas are good
  - trailing_comma

  # Sometimes we don't want private static props at the top
  - type_contents_order

  # Not really needed and pretty annoying with Bools with initial value
  - redundant_type_annotation

  # We need to treat ourselves sometimes.
  - anonymous_argument_in_multiline_closure

  # We abuse this like hell – well, who am I to judge? ¯\_(ツ)_/¯
  - return_value_from_void_function

  # We like to adopt multiple protocols with '&'
  - comma_inheritance

  # Get out of my sight! Conditions out of sight are bad.
  - for_where

  # Commented in case we want to look for something new -- do NOT commit these uncommented!
  # - file_length
  # - function_body_length
  # - type_body_length

# Closing brace with closing parenthesis should not have any whitespaces in the middle
closing_brace: warning

# Closure end should have the same indentation as the line that started it
closure_end_indentation: warning

# Closure parameters should be on the same line as opening brace
closure_parameter_position: warning

# Colons should be next to the identifier
# when specifying a type
# and next to the key in dictionary literals
colon:
  severity: warning
  flexible_right_spacing: true

# There should be no space before and one after any comma
comma: warning

# The initializers declared in compiler protocols
# such as `ExpressibleByArrayLiteral` shouldn't be called directly
compiler_protocol_init: warning

# Getter and setters in computed properties and subscripts should be in a consistent order.
computed_accessors_order:
  severity: warning
  order: get_set

# Prefer contains over first(where:) != nil
contains_over_first_not_nil: warning

# if, for, while, do statements shouldn't wrap their conditionals in parentheses
control_statement: warning

# Types used for hosting only static members
# should be implemented as a caseless enum to avoid instantiation.
convenience_type: warning

# Complexity of function bodies should be limited
cyclomatic_complexity:
  ignores_case_statements: true

# Discouraged direct initialization of types that can be harmful.
discouraged_direct_init:
  severity: warning

# Prefer non-optional booleans over optional booleans.
discouraged_optional_boolean: warning

# avoid using 'dynamic' and '@inline(__always)' together
dynamic_inline: warning

# Enum can't contain multiple cases with the same name.
duplicate_enum_cases: warning

# Imports should only be declared once.
duplicate_imports: error

# Arguments can be omitted when matching enums with associated types if they are not used
empty_enum_arguments: warning

# Prefer `() ->` over `Void ->`
empty_parameters: warning

# When using trailing closures,
# empty parentheses should be avoided after the method call
empty_parentheses_with_trailing_closure: warning

# Prefer checking isEmpty over comparing string to an empty string literal.
empty_string: warning

# Empty XCTest method should be avoided.
empty_xctest_method: warning

# Matching an enum case against an optional enum without ‘?’ is supported on Swift 5.1 and above.
optional_enum_case_matching: warning

# Explicitly calling .init() should be avoided
explicit_init: warning

# Fallthrough should be avoided.
fallthrough: warning

# A fatalError call should have a message
fatal_error_message: warning

# Files should not span too many lines.
file_length:
  warning: 500
  error: 1350

# Prefer using `.first(where:)` over `.filter { }.first` in collections
first_where: warning

# Force casts should be avoided
force_cast: error

# Force tries should be avoided
force_try: error

# Force unwrapping should be avoided
force_unwrapping: error

# Functions bodies should not span too many lines.
function_body_length:
  warning: 45
  error: 100

# Generic type name should only contain alphanumeric characters,
# start with an uppercase character
# and span between X and Y characters in length
generic_type_name:
  max_length:
    error: 20

# Comparing two identical operands is likely a mistake
identical_operands: error

# Identifier names should only contain alphanumeric characters
# and start with a lowercase character
# or should only contain capital letters.
# In an exception to the above,
# variable names may start with a capital letter
# when they are declared static and immutable.
# Variable names should not be too long or too short
identifier_name:
  min_length: 2
  max_length: 80

# Type name should only contain alphanumeric characters,
# start with an uppercase character
# and span between X and Y characters in length
type_name:
  min_length: 2
  max_length: 80

# Computed read-only properties should avoid using the `get` keyword
implicit_getter: warning

# Prefer implicit returns in closures
implicit_return:
  severity: warning
  included: [closure]

# Implicitly unwrapped optionals should be avoided when possible
implicitly_unwrapped_optional:
  severity: warning
  mode: all

# Prefer using Set.isDisjoint(with:) over Set.intersection(_:).isEmpty
is_disjoint: warning

# Tuples shouldn't have too many members. Create a custom type instead
large_tuple:
  warning: 2
  error: 3

# Prefer using .last(where:) over .filter { }.last in collections
last_where: warning

# Struct extension properties and methods are preferred over legacy functions
legacy_cggeometry_functions: warning

# Struct-scoped constants are preferred over legacy global constants
legacy_constant: warning

# Swift constructors are preferred over legacy convenience functions
legacy_constructor: warning

# Prefer using the isMultiple(of:) function instead of using the remainder operator (%)
legacy_multiple: warning

# Struct extension properties and methods are preferred over legacy functions
legacy_nsgeometry_functions: warning

# Prefer using type.random(in:) over legacy functions
legacy_random: warning

# Lines should not span too many characters.
line_length:
  warning: 120
  error: 200

# Array and dictionary literal end
# should have the same indentation as the line that started it
literal_expression_end_indentation: warning

# MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
mark: warning

# Modifier order should be consistent.
modifier_order:
  preferred_modifier_order: [
    override, required, convenience, acl, setterACL,
    final, mutators, owned, lazy, typeMethods
  ]

# Functions and methods parameters should be either on the same line, or one per line
multiline_parameters:
  severity: warning
  allows_single_line: true

# Multiline parameters should have their surrounding brackets in a new line
multiline_parameters_brackets: warning

# Trailing closure syntax should not be used when passing more than one closure argument
multiple_closures_with_trailing_closure: warning

# Types should be nested at most X level deep,
# and statements should be nested at most Y levels deep.
nesting:
  type_level: 4
  function_level: 5

# An object should only remove itself as an observer in `deinit`
notification_center_detachment: warning

# Opening braces should be preceded by a single space
# and on the same line as the declaration
opening_brace:
  severity: warning
  allowMultilineFunc: false

# Operators should be surrounded by a single whitespace when they are being used
operator_usage_whitespace:
  severity: warning
  lines_look_around: 2
  skip_aligned_constants: true

# Operators should be surrounded by a single whitespace when defining them
operator_whitespace: warning

# A doc comment should be attached to a declaration.
orphaned_doc_comment: warning

# Some overridden methods should always call super
overridden_super_call:
  severity: warning

# Unit tests marked private are silently skipped
private_unit_test:
  severity: warning
  name: XCTestCase

# Creating views using Interface Builder should be avoided
prohibited_interface_builder: warning

# Some methods should not call super
prohibited_super_call:
  severity: warning

# When declaring properties in protocols, the order of accessors should be `get set`
protocol_property_accessors_order: warning

# Prefer `_ = foo()` over `let _ = foo()` when discarding a result from a function
redundant_discardable_let: warning

# nil coalescing operator is only evaluated
# if the lhs is nil, coalescing operator with nil as rhs is redundant
redundant_nil_coalescing: warning

# Initializing an optional variable with nil is redundant
redundant_optional_initialization: warning

# Property setter access level shouldn't be explicit
# if it's the same as the variable access level.
redundant_set_access_control: warning

# String enum values can be omitted when they are equal to the enumcase name
redundant_string_enum_value: warning

# Returning Void in a function declaration is redundant
redundant_void_return: warning

# Return arrow and return type should be separated by a single space or on a separate line
return_arrow_whitespace: warning

# Prefer shorthand operators (+=, -=, *=, /=) over doing the operation and assigning
shorthand_operator: warning

# Test files should contain a single QuickSpec or XCTestCase class
single_test_class: warning

# Prefer using min() or max() over sorted().first or sorted().last
sorted_first_last: warning

# Else and catch should be on the same line, one space after the previous declaration
statement_position:
  severity: warning

# SwiftLint 'disable' commands are superfluous
# when the disabled rule would not have triggered a violation in the disabled region.
superfluous_disable_command: warning

# Case statements should vertically align with their enclosing switch statement,
# or indented if configured otherwise.
switch_case_alignment:
  severity: warning
  indented_cases: true

# Shorthand syntactic sugar should be used, i.e. [Int] instead of Array<Int>
syntactic_sugar: warning

# Prefer someBool.toggle() over someBool = !someBool
toggle_bool: warning

# Trailing commas in arrays and dictionaries should be avoided/enforced (mandatory_comma)
# FIXME: Keep this for an enforcement later
# trailing_comma:
#   severity: warning
#   mandatory_comma: true

# Files should have a single trailing newline
trailing_newline: warning

# Lines should not have trailing semicolons
trailing_semicolon: warning

# Type bodies should not span too many lines.
type_body_length:
  warning: 300
  error: 450

# Avoid using unneeded break statements
unneeded_break_in_switch: warning

# Parentheses are not needed when declaring closure arguments
unneeded_parentheses_in_closure_argument: warning

# Catch statements should not declare error variables without type casting
untyped_error_in_catch: warning

# Unused parameter in a closure should be replaced with _
unused_closure_parameter: warning

# Declarations should be actually used somewhere
unused_declaration:
  severity: warning

# When the index or the item is not used, `.enumerated()` can be removed
unused_enumerated: warning

# Function parameters should be aligned vertically
# if they're in multiple lines in a declaration
vertical_parameter_alignment: warning

# Function parameters should be aligned vertically
# if they're in multiple lines in a method call
vertical_parameter_alignment_on_call: warning

# Limit vertical whitespace to a single empty line
vertical_whitespace:
  severity: warning
  max_empty_lines: 1

# Prefer `-> Void` over `-> ()`
void_return: warning

# Delegates should be weak to avoid reference cycles
weak_delegate: warning

# Prefer specific XCTest matchers over XCTAssertEqual and XCTAssertNotEqual
xct_specific_matcher: warning

# The variable should be placed on the left,
# the constant on the right of a comparison operator
yoda_condition: warning
jpsim commented 1 year ago

unused_declaration is an analyzer rule so it should go in the analyzer_rules section of your config file, not in opt_in_rules.

username0x0a commented 1 year ago

When moving it from opt_in_rules to a newly created analyzer_rules, it makes no difference. Also it doesn't complain about different, unused_import rule we also have in opt_in_rules section now.

The warning only dismisses if I delete or comment out the configuration customisation placed on the root level:

# unused_declaration:
#   severity: warning

So it complains about this part. 🤔

username0x0a commented 1 year ago

Thanks, @SimplyDanny! 👍 It would probably be also nice to check what @jpsim mentioned, that is placement of rules in proper sections. 🤔 'Cause at this moment, it can really be a bit confusing as we read (altho an Analyser rule) being Enabled by default: No, one might really feel an urge to place it in opt_in_rules instead of proper analyzer_rules section, but it seems like it works anyway.

SimplyDanny commented 1 year ago

Yes, the current implementation doesn't care where Analyzer rules are placed. It might only be helpful for users to have these special rules separated.

We could add a warning recommending to place the rule in analyzer_rules instead.

jpsim commented 1 year ago

Thanks for digging into this @SimplyDanny, there were two issues and I was only seeing one of them.