Xcode has supported Swift Package Manager projects natively since Xcode 11, which has been out for over a year, where you can use Xcode by having it open the `Package.swift` manifest rather than a `.xcodeproj` or `.xcworkspace`. I've been primarily developing SwiftLint in Xcode using this approach for over a year, and despite a few nitpicks I have, it's been a joy to use. So I'd like to completely remove the Xcode project along with things that support it: * `SwiftLint.xcworkspace`/`SwiftLint.xcodeproj`: Neither of these are needed if we use `xed .` or `xed Package.swift` to develop SwiftLint in Xcode. * `Cartfile`/`Cartfile.private`/`Cartfile.resolved`/`.gitmodules`/`Carthage/`: These were used to manage dependencies as git submodules for use in the Xcode workspace, but that's no longer necessary if Xcode delegates to SwiftPM to manage dependencies for us. * Some scripts can be simplified, cleaned up or even completely removed. * **Reduce duplication:** Rather than update dependencies or files in multiples places, there will only be the package manifest and the Podfile * **Reduce merge conflicts:** This hasn't been too bad, but it's occasionally a pain when trying to land old PRs * **Reduce development overhead:** No need to manually make sure that files in the Xcode project are sorted alphabetically * **Reduce clone time:** No need to run `git submodules update --init --recursive` anymore I think this breaks Carthage users that pull in SwiftLintFramework as a dependency in a Cartfile. However I can't find any references to [`SwiftLintFramework` in any `Cartfile` files on GitHub](https://github.com/search?q=swiftlintframework+filename%3ACartfile&type=Code&ref=advsearch&l=&l=) so this doesn't appear to be worth continuing to maintain. Resolves https://github.com/realm/SwiftLint/issues/3412
5.9 KiB
Pull Requests
All changes, no matter how trivial, must be done via pull request. Commits
should never be made directly on the master branch. Prefer rebasing over
merging master into your PR branch to update it and resolve conflicts.
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 immediately, but this should be the exception, not the norm.
Building And Running Locally
Using Xcode
git clone https://github.com/realm/SwiftLint.gitcd SwiftLintxed .- Select the "swiftlint" scheme
cmd-opt-ropen 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.
Using the command line
git clone https://github.com/realm/SwiftLint.gitcd SwiftLintswift build [-c release]- Use the produced
swiftlintbinary from the command line, either by runningswift run [-c release] [swiftlint] [arguments]or by invoking the binary directly at.build/[release|debug]/swiftlint - [Optional] Attach LLDB:
lldb -- .build/[release|debug]/swiftlint [arguments]
Code Generation
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.
Tests
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 three supported build methods continue to work and pass tests.
$ xcodebuild -scheme swiftlint test
$ swift test
$ make docker_test
Rules
New rules should be added in the Source/SwiftLintFramework/Rules directory.
Rules should conform to either the Rule or ASTRule protocols.
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. This way adding a unit test for your new Rule is just a matter of
adding a test case in RulesTests.swift which simply calls
verifyRule(YourNewRule.description).
ConfigurationProviderRule
If your rule supports user-configurable options via .swiftlint.yml, you can
accomplish this by conforming to ConfigurationProviderRule. You must provide a
configuration object via the configuration property:
- The object provided must conform to
RuleConfiguration. - There are several provided
RuleConfigurations that cover the common patterns like configuring violation severity, violation severity levels, and evaluating names. - If none of the provided
RuleConfigurations are applicable, you can create one specifically for your rule.
See ForceCastRule
for a rule that allows severity configuration,
FileLengthRule
for a rule that has multiple severity levels,
IdentifierNameRule
for a rule that allows name evaluation configuration:
force_cast: warning
file_length:
warning: 800
error: 1200
identifier_name:
min_length:
warning: 3
error: 2
max_length: 20
excluded: id
If your rule is configurable, but does not fit the pattern of
ConfigurationProviderRule, you can conform directly to Rule:
init(configuration: AnyObject) throwswill be passed the result of parsing the value from.swiftlint.ymlassociated with your rule'sidentifieras a key (if present).configurationmay be of any type supported by YAML (e.g.Int,String,Array,Dictionary, etc.).- This initializer must throw if it does not understand the configuration, or it cannot be fully initialized with the configuration and default values.
- By convention, a failing initializer throws
ConfigurationError.UnknownConfiguration. - If this initializer fails, your rule will be initialized with its default
values by calling
init().
Tracking changes
All changes should be made via pull requests on GitHub.
When issuing a pull request, 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.

