If you'd like to write a SwiftLint rule but aren't sure how to start,
please watch and follow along with
this video tutorial
.
All changes, no matter how trivial, must be done via pull requests. Commits
should never be made directly on the
main
branch. If possible, avoid mixing
different aspects in one pull request. Prefer squashing if there are commits
that are not reasonable alone. To update your PR branch and resolve conflicts,
prefer rebasing over merging
main
.
If you have commit access to SwiftLint and believe your change to be trivial
and not worth waiting for review, you may open a pull request and merge it
immediately, but this should be the exception, not the norm.
Building and Running Locally
git clone https://github.com/realm/SwiftLint.git
cd SwiftLint
xed .
- Select the "swiftlint" scheme.
cmd-opt-r
to open the scheme options.
- Set the "Arguments Passed On Launch" you want in the "Arguments" tab. See
available arguments
in the README
.
- Set the "Working Directory" in the "Options" tab to the path where you would like
to execute SwiftLint ? a folder that contains Swift source files.
- Hit "Run".
Arguments
|
Options
|
|
|
Then you can use the full power of Xcode/LLDB/Instruments to develop and debug your changes to SwiftLint.
git clone https://github.com/realm/SwiftLint.git
cd SwiftLint
swift build [-c release]
- Use the produced
swiftlint
binary from the command line, either by running
swift run [-c release] [swiftlint] [arguments]
or by invoking the binary directly at
.build/[release|debug]/swiftlint
- For debugging, attach LLDB:
lldb -- .build/[release|debug]/swiftlint [arguments]
If XCTest cases or functions are added/removed/renamed, or if rules are
added/removed/renamed, you'll need to run
make sourcery
, which requires that
Sourcery
be installed on your
machine. This will update source files to reflect these changes.
SwiftLint supports building via Xcode and Swift Package Manager on macOS, and
with Swift Package Manager on Linux. When contributing code changes, please
ensure that all four supported build methods continue to work and pass tests:
xcodebuild -scheme swiftlint
test
-destination
'
platform=macOS
'
swift
test
make bazel_test
make docker_test
New rules should be added in the
Source/SwiftLintBuiltInRules/Rules
directory.
Prefer implementing new rules with the help of SwiftSyntax. Look for the
@SwiftSyntaxRule
attribute for examples and use the same on your own rule.
New rules should conform to either
Rule
or
OptInRule
depending on whether
they shall be enabled by default or opt-in, respectively.
All new rules or changes to existing rules should be accompanied by unit tests.
Whenever possible, prefer adding tests via the
triggeringExamples
and
nonTriggeringExamples
properties of a rule's
description
rather than adding
those test cases in the unit tests directly. This makes it easier to understand
what rules do by reading their source, and simplifies adding more test cases
over time. With
make sourcery
, you ensure that all test cases are automatically
checked in unit tests. Moreover, the examples added to a rule will appear in the
rule's rendered documentation accessible from the
Rule Directory
.
For debugging purposes, examples can be marked as
focused
. If there are any
focused examples found, then only those will be run when running all tests for that
rule.
nonTriggeringExamples:
[
Example
(
"
let x: [Int]
"
)
,
Example
(
"
let x: [Int: String]
"
)
.
focused
(
)
// Only this one will be run in tests.
]
,
triggeringExamples:
[
Example
(
"
let x: ↓Array<String>
"
)
,
Example
(
"
let x: ↓Dictionary<Int, String>
"
)
]
Every rule is configurable via
.swiftlint.yml
, even if only by settings its default
severity. This is done by setting the
configuration
property of a rule as:
var
configuration
=
SeverityConfiguration
<
Self
>
(
.
warning
)
If a rule requires more options, a specific configuration can be implemented
and associated with the rule via its
configuration
property. Check for rules providing
their own configurations as extensive examples or check out
Configuring them in
.swiftlint.yml
looks like:
force_cast
:
warning
file_length
:
warning
:
800
error
:
1200
identifier_name
:
min_length
:
warning
:
3
error
:
2
max_length
:
20
excluded
:
id
All changes should be made via pull requests on GitHub.
When issuing a pull request with user-facing changes, please add a
summary of your changes to the
CHANGELOG.md
file.
We follow the same syntax as CocoaPods' CHANGELOG.md:
- One Markdown unnumbered list item describing the change.
- 2 trailing spaces on the last line describing the change (so that Markdown renders each change
on its own line
).
- A list of Markdown hyperlinks to the contributors to the change. One entry
per line. Usually just one.
- A list of Markdown hyperlinks to the issues the change addresses. One entry
per line. Usually just one. If there was no issue tracking this change,
you may instead link to the change's pull request.
- All CHANGELOG.md content is hard-wrapped at 80 characters.
SwiftLint uses Azure Pipelines for most of its CI jobs, primarily because
they're the only CI provider to have a free tier with 10x concurrency on macOS.
Some CI jobs run in GitHub Actions (e.g. Docker).
Some CI jobs run on Buildkite using Mac Minis from MacStadium. These are jobs
that benefit from being run on the latest Xcode & macOS versions on bare metal.
To bring up a new Buildkite worker from MacStadium:
- Change account password
- Update macOS to the latest version
- Install Homebrew:
https://brew.sh
- Install Buildkite agent and other tools via Homebrew:
brew install aria2 bazelisk htop buildkite/buildkite/buildkite-agent robotsandpencils/made/xcodes
- Install latest Xcode version:
xcodes update && xcodes install 14.0.0
- Add
DANGER_GITHUB_API_TOKEN
and
HOME
to
/opt/homebrew/etc/buildkite-agent/hooks/environment
- Configure and launch buildkite agent:
brew info buildkite-agent
/
https://buildkite.com/organizations/swiftlint/agents#setup-macos