📜 ⬆️ ⬇️

SwiftLint - clean and tidy iOS project

image Go

I think everyone knows how difficult it is to maintain compliance with the code style and agreements in an iOS project. Today we will talk about how to automate this process using SwiftLint utility.

SwiftLint is a utility from Realm developers for automatically checking Swift-code. The utility contains a set of rules based on the GitHub's Swift Style Guide and common sense. Of course, you can add your own rules. SwiftLint supports integration with Xcode, Appcode, Atom.

Installation and Setup
Download and install the latest release from the repository .
')
Or install through the terminal:

$ brew update $ brew install swiftlint 

You can update the utility like this:

 $ brew update $ brew upgrade swiftlint 

Switch to another version:

 $ brew switch swiftlint < > 

Check current version:

 swiftlint version 

Go to the project settings, Build Phases and add to the Run Script section:

 if which swiftlint >/dev/null; then swiftlint else echo "error: SwiftLint does not exist, download it from https://github.com/realm/SwiftLint" exit 1 fi 

Tip: it is highly recommended to use the “exit 1” command - this guarantees that all members of the team will install SwiftLint

First start
Now that SwiftLint is installed, code verification will occur at the end of each build of the project. After the first launch, you will most likely see something like:



Do not worry much, most errors and warnings are quite simple and easily fixable. Do not rush to fix them manually, since SwiftLint has a great auto-correction feature, it is safe enough. To use it in the terminal, go to the project directory and execute the command:

 swiftlint autocorrect 

We collect the project again: the number of errors has been reduced by several times, but the rest will have to be corrected manually.
Tip: do not add auto-correction in Run Script, otherwise programmers will not get used to thinking or will not even be aware of some conventions.

rules
The list of predefined rules can be seen by running the command:

 swiftlint rules 



Each rule has a description and a set of parameters:


You can also see the source of the rules for more understanding.

Separately, I want to highlight a few very useful rules:


Configuration
Most likely you will need to disable, configure or add any rules. To do this, you need to create a .swiftlint.yml file in the project root.

Available configuration options:

List of rules that need to be disabled:

 disabled_rules: - colon - comma - control_statement 

The list of optional rules that need to be enabled (disabled by default):

 opt_in_rules: - empty_count - missing_docs 

Exclude subdirectories or files:

 excluded: - Carthage - Pods - Source/ExcludedFolder - Source/ExcludedFile.swift 

Include subdirectories or files (alternatively excluded):

 included: - MyProject - MyProjectKeyboard - MyProjectTests 

Rule parameters (available parameters can be found in the list of rules):

 file_length: warning: 500 error: 600 

Report type (available options: xcode, json, csv, checkstyle, junit):

 reporter: xcode 

Maximum number of warnings allowed:

 warning_threshold: 15 

Tip: be sure to add warning_threshold to the configuration file so that the number of warnings does not increase.

Nested configurations
You can create multiple configuration files (.swiftlint.yml) for various subdirectories. SwiftLint will automatically use the configuration located in the folder with the scanned files. Parameters excluded and included for nested configurations will be ignored.

Add your own rules
SwiftLint allows you to add your own rules based on regular expressions. To do this, in the .swiftlint.yml file, add the custom_rules section. You can specify the following parameters for the rule:


Rule checking naming with suffix -id. (for example: userId is correct, userID is incorrect):

 custom_rules: id_suffix_naming: name: "Wrong name" regex: "(ID)" match_kinds: - comment - identifier message: "Use 'Id' instead 'ID'" severity: error 



Disable rules in code
If you want to disable checking in part of the code, use the following construction:

 // swiftlint:disable <rule1> [<rule2> <rule3>...] ......... // swiftlint:enable <rule1> [<rule2> <rule3>...] func printName() { // swiftlint:disable force_cast let name = loadName() as! String // swiftlint:enable force_cast print(name) } 

Project build speed
Obviously, using SwiftLint requires additional time when building a project. If the build speed noticeably sags, you should consider checking only the modified files. To do this, replace the test script in Build Phases with:

Script
 count=0 for file_path in $(git ls-files -om --exclude-from=.gitignore | grep ".swift$"); do export SCRIPT_INPUT_FILE_$count=$file_path count=$((count + 1)) done for file_path in $(git diff --cached --name-only | grep ".swift$"); do export SCRIPT_INPUT_FILE_$count=$file_path count=$((count + 1)) done export SCRIPT_INPUT_FILE_COUNT=$count swiftlint lint --use-script-input-files 


A few examples of SwiftLint configurations in well-known companies:

Kickstarter
 disabled_rules: - function_parameter_count - nesting - variable_name - weak_delegate - trailing_comma opt_in_rules: - empty_count - force_unwrapping - private_outlet line_length: 110 type_body_length: warning: 300 error: 400 excluded: - Carthage/ - Frameworks/ - Kickstarter-iOS.playground/ - Kickstarter-tvOS.playground/ - Library/Strings.swift - bin/strings.swift reporter: "xcode" custom_rules: localized_lensing: name: "Localized Lensing" regex: "\.~\s+Strings\s*\." message: "Capture calls to `Strings` functions using `%~ { _ in Strings... }`" severity: error 


Firefox
 disabled_rules: # rule identifiers to exclude from running - legacy_constructor - variable_name - legacy_cggeometry_functions - legacy_constant - todo - trailing_newline - empty_count - force_cast - type_name - function_body_length - missing_docs - conditional_binding_cascade - valid_docs - cyclomatic_complexity - type_body_length - function_parameter_count - force_try - control_statement - trailing_whitespace - leading_whitespace - operator_whitespace - file_length - mark opt_in_rules: # some rules are only opt-in - closing_brace - opening_brace - return_arrow_whitespace - trailing_semicolon - statement_position # Find all the available rules by running: # swiftlint rules included: # paths to include during linting. `--path` is ignored if present. excluded: # paths to ignore during linting. Takes precedence over `included`. - Carthage - Pods - Source/ExcludedFolder - Source/ExcludedFile.swift - ThirdParty - FxA - FxAClient - build # configurable rules can be customized from this configuration file # binary rules can set their severity level trailing_semicolon: error empty_count: error closing_brace: error opening_brace: error return_arrow_whitespace: error statement_position: error colon: error comma: error line_length: 1000 reporter: "json" # reporter type (xcode, json, csv, checkstyle) 


Realm
 included: - Realm/ObjectServerTests - RealmSwift - Realm/Swift variable_name: min_length: # not possible to disable this partial rule, so set it to zero warning: 0 error: 0 disabled_rules: - file_length - force_cast - force_try - function_body_length - todo - type_body_length - line_length - vertical_whitespace - syntactic_sugar 


Tinkoff
warning_threshold: 15

excluded:
- Pods
- MBUITest

disabled_rules:
- trailing_whitespace

line_length:
warning: 150

function_parameter_count:
warning: 10
error: 15

file_length:
warning: 500

type_body_length:
warning: 400
error: 450

SwiftLint allowed our ios development team to spend less time on code review, sticking to a single code style and improving code quality. If you are not using SwiftLint in your project, then be sure to try.

Useful links:

» SwiftLint repository
» SwiftLint rules list
» About checking only changed files
» GitHub's Swift Style Guide
» Tailor - an alternative to SwiftLint

Source: https://habr.com/ru/post/317892/


All Articles