In the interests of doing a little pre-Spring cleaning, I recently added SwiftLint (unsurprisingly, a Swift Linter) to my Speaker Alert project. After getting set up, my project was littered with hundreds of warnings, and not a few errors.
Seeing 700 warnings on any project is daunting, and enough to make any developer consider putting off or avoiding this linting business. Not only that, but these warnings can mask more serious issues and make it harder to correct real compilation problems. But a day or so later, I'd whittled down the warnings and rid myself of the errors. Along the way, I picked up a few practices that might make things easier when adding a linter to any non-trivial project.
The SwiftLint readme file does a great job of getting you up and running quickly, but there are a couple of gotchas I discovered.
Use the pkg installer
You can install SwiftLint using Homebrew, but I found this version to be a bit behind the current release. As of writing, the pace of development is pretty rapid, so if you download the pkg file direct from GitHub you'll be sure to get all the latest features and rules.
Run the script after linking
SwiftLint is included in a project by adding a "Run Script" phase that executes the
scriptlint command, adding any errors or warning to your build results.
I recommend putting this run script after the linking step, since errors during linting will stop the compilation process and mask any compilation errors, which are important if you're trying to correct these very linting errors.
Autocorrect is your friend
Some of the more basic issues (such as whitespace at the end of a line) can be automatically fixed by SwiftLint. Just use the command:
swiftlint autocorrect in your source directory.
You could also add this to your "Run Script" phase, but I've been holding off on doing this for the time being, to maintain more control as I get used to how the tool behaves.
Now comes the daunting part: fixing all the issues that SwiftLint can't fix itself! Helpfully, SwiftLint provides configuration options to allow rules to be turned off (since not everyone's going to agree 100% with their ruleset), and you can use this to your advantage when making a first pass at correcting issues in your project.
My approach was to disabled every rule, and then enable them one at a time, fixing issues as I went. This breaks down the problem into small pieces, which can be spread across time, or across a team.
To get started, just create .swiftlint.yml in your project's main source directory (where swiftlint is run) with a disable directive for all rules:
disabled_rules: - trailing_newline - opening_brace - empty_count - comma - colon - force_cast - type_name - variable_name_min_length - trailing_semicolon - force_try - function_body_length - nesting - variable_name - conditional_binding_cascade - variable_name_max_length - operator_whitespace - control_statement - legacy_constant - line_length - return_arrow_whitespace - trailing_whitespace - closing_brace - statement_position - type_body_length - todo - legacy_constructor - valid_docs - missing_docs - file_length - leading_whitespace
As rules are frequently added, you can get a full list for the current version with the command
Once you have all of the rules disabled and you can build without errors or warnings, you can remove rules from this list one-by-one, fixing the issues as you go. This simplifies the task, allows it to be distributed, and makes commits small so there's less chance a mistake somewhere down the line will force you to revert a huge piece of work.
This has the added advantage that you can more easily identify rules that you don't want to be run on your code. Personally, I don't have a problem with using TODO: statements, for example.
I'd heartily recommend adding SwiftLint to your project. Granted, many of the rules are a matter of preference and aesthetics (I think future me will be glad of having more readable code), but some can highlight serious bugs - forced casting comes to mind.
It can seem like a huge chore to get started, but if you break down the problem it won't be particularly onerous and you'll quickly reap the benefits of keeping your code clean and readable.
As a side benefit, SwiftLint is written in Swift, and structured to make adding rules easy. So it's fairly straightforward to fork the project for your organization and create rules to suit your own guidelines.