Introduce
SwiftLint is a source code execution engine that follows the styles and rules of the Swift language.
It will integrate in Apple’s Source Kit framework to analyze the project’s source code and ensure that the syntax and style of the source code follow agreed conventions in the project.
Steps for SwiftLint integration
To integrate SwiftLint into the project, we need to perform the following steps:
- Install SwiftLint
- Integration with XCode
- Integration process verification
- Configure rules and rules
Step 1: Install SwiftLint
There are many ways to install SwiftLint
Install via Brew
brew install swiftlint
Install via CocoaPods
We will have to follow the following line into the Podfile pod 'SwiftLint'
file pod 'SwiftLint'
This will allow us to download the SwiftLint source code and packages when running the pod install command and when running the script $ {PODS_ROOT} / SwiftLint / swiftlint in the build. phase
Install via Mint
$ mint install realm/SwiftLint
Install using the pre-build package
We can download and install the pre-build package SwiftLint.pkg on Github. The following message may appear on the installation process.
We need to authorize the SwiftLint.pkg file by going to Menu> System Preferences …> Security & Privacy> General then click the Open Anyway button.
Integration with XCode
We will need to integrate with Xcode for SwiftLint to parse the code and display warnings and errors in the IDE when building code. We will add “Run Script Phase” with the following content:
1 2 3 4 5 6 | if which swiftlint >/dev/null; then swiftlint else echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint" fi |
Integration process verification
To check if the integration has been successful or not? We just need to build the project Product> Build (⌘B) , if we see many warnings, or errors related to the syntax and style of the code, it means the integration was successful.
Configure rules
The SwiftLint bundle includes more than 75 basic rules and we don’t always use these rules. So we will configure the rules that will be used in the project via the .swiftlint.yml file
1 2 3 | $ touch .swiftlint.yml $ open .swiftlint.yml |
We try to configure the following content:
1 2 3 4 5 6 7 8 9 10 | disabled_rules: - force_cast - force_unwrapping line_length: warning: 200 error: 250 ignores_function_declarations: true ignores_comments: true ignores_urls: true |
With the above configuration, we will receive an alert when a line of code is over 200 characters long, and receive an error message when a line of code is more than 250 characters long. No warnings are displayed when force_cast and force_unwrapping
The rule configuration includes:
- disabled_rules: list of unused rules
- opt_in_rules: list of usage rules
- analyzer_rules: rules for parsers
We can refer to the configuration file below for my project
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | reporter: "xcode" # reporter type (xcode, json, csv, checkstyle, junit, html, emoji) excluded: # paths to ignore during linting. Takes precedence over `included`. - Carthage - Pods disabled_rules: # rule identifiers to exclude from running - trailing_whitespace - force_cast - force_unwrapping - force_try - empty_enum_arguments - overridden_super_call - sorted_imports # - colon # Default configuration: warning, flexible_right_spacing: false, apply_to_dictionaries: true # - comma # Default configuration: warning # - opening_brace # - todo # - empty_parentheses_with_trailing_closure # - empty_string # - unused_closure_parameter # - unused_setter_value # - unused_optional_binding # - redundant_void_return # - void_return # - redundant_string_enum_value # - redundant_objc_attribute # - closure_parameter_position # - control_statement # - notification_center_detachment # - legacy_constructor # - for_where # - unneeded_break_in_switch # - implicit_getter # - duplicate_imports # - trailing_newline opt_in_rules: # some rules are only opt-in # - missing_docs - yoda_condition # Default configuration: warning - empty_count # Default configuration: error, only_after_dot: false - empty_string # Default configuration: warning - closure_end_indentation # Default configuration: warning - closure_spacing # Default configuration: warning - explicit_init # Default configuration: warning - first_where # Default configuration: warning - number_separator # Default configuration: warning, minimum_length: 0 - explicit_failure_calls - fatal_error_message # - extension_access_modifier # - implicitly_unwrapped_optional # - operator_usage_whitespace - vertical_parameter_alignment_on_call - multiline_parameters # - multiple_empty_lines # Defined into custom roles - nesting - private_outlet - prohibited_super_call - protocol_property_accessors_order - redundant_nil_coalescing - syntactic_sugar - comments_space - comments_capitalized_ignore_possible_code - comments_capitalized_find_possible_code line_length: warning: 200 error: 250 ignores_function_declarations: true ignores_comments: true ignores_urls: true function_body_length: warning: 80 error: 150 function_parameter_count: warning: 4 error: 6 type_name: # class name min_length: 3 max_length: warning: 60 error: 80 type_body_length: warning: 300 error: 500 file_length: warning: 500 error: 800 ignore_comment_only_lines: true identifier_name: # Variable name allowed_symbols: "_" min_length: 1 max_length: warning: 60 error: 80 excluded: - id - URL - GlobalAPIKey vertical_whitespace: # warning, max_empty_lines: 1 max_empty_lines: 3 large_tuple: warning: 4 error: 5 private_outlet: allow_private_set: true #nesting: # type_level: # warning: 3 # error: 6 # statement_level: # warning: 5 # error: 10 number_separator: minimum_length: 8 #cyclomatic complexity below 4 is considered good; #cyclomatic complexity between 5 and 7 is considered medium complexity, #between 8 and 10 is high complexity, #and above that is extreme complexity. cyclomatic_complexity: ignores_case_statements: true warning: 7 error: 11 custom_rules: comments_space: # From https://github.com/brandenr/swiftlintconfig name: "Space After Comment" regex: '(^ *//w+)' message: "There should be a space after //" severity: warning comments_capitalized_ignore_possible_code: name: "Capitalize First Word In Comment" regex: "(^ +// +(?!swiftlint)[a-z]+)" message: "The first word of a comment should be capitalized" severity: warning explicit_failure_calls: name: “Avoid asserting ‘false’” regex: ‘((assert|precondition)(false)’ message: “Use assertionFailure() or preconditionFailure() instead.” severity: warning multiple_empty_lines: name: "Multiple Empty Lines" regex: '((?:s*n){3,})' message: "There are too many line breaks" severity: error force_https: # From https://github.com/Twigz/Game name: "Force HTTPS over HTTP" regex: "((?i)http(?!s))" match_kinds: string message: "HTTPS should be favored over HTTP" severity: warning already_true: regex: "== true" message: "Don't compare to true, just use the bool value." already_bool: regex: "== false" message: "Don't compare to false, just use !value." |
Reference source