With the binding of configurations to their associated rule types
"unknown configuration" errors can be made more specific mentioning
also the rule's identifier in the printed message.
Advantages of having typical errors at a common place:
* Error message styling can be harmonized
* Existing messages can be reused
* Overview of prefixes ('error: ', 'warning: ')
* Manage how to print them to the console
Because since it was included in a release a few days ago, we've had
several reports of false positives and so flipping to opt-in is
appropriate so users can determine for themselves if they should enable
the rule.
Over the years, SwiftLintFramework had become a fairly massive monolith,
containing over 400 source files with both core infrastructure and
rules.
Architecturally, the rules should rely on the core infrastructure but
not the other way around. There are two exceptions to this:
`custom_rules` and `superfluous_disable_command` which need special
integration with the linter infrastructure.
Now the time has come to formalize this architecture and one way to do
that is to move the core SwiftLint functionality out of
SwiftLintFramework and into a new SwiftLintCore module that the rules
can depend on.
Beyond enforcing architectural patterns, this also has the advantage of
speeding up incremental compilation by skipping rebuilding the core
functionality when iterating on rules.
Because the core functionality is always useful when building rules, I'm
opting to import SwiftLintCore in SwiftLintFramework as `@_exported` so
that it's implicitly available to all files in SwiftLintFramework
without needing to import it directly.
In a follow-up I'll also split the built-in rules and the extra rules
into their own modules. More modularization is possible from there, but
not planned.
The bulk of this PR just moves files from `Source/SwiftLintFramework/*`
to `Source/SwiftLintCore/*`. There are some other changes that can't be
split up into their own PRs:
* Change jazzy to document the SwiftLintCore module instead of
SwiftLintFramework.
* Change imports in unit tests to reflect where code was moved to.
* Update `sourcery` make rule to reflect where code was moved to.
* Create a new `coreRules` array and register those rules with the
registry. This allows the `custom_rules` and
`superfluous_disable_command` rule implementations to remain internal
to the SwiftLintCore module, preventing more implementation details
from leaking across architectural layers.
* Move `RuleRegistry.registerAllRulesOnce()` out of the type declaration
and up one level so it can access rules defined downstream from
SwiftLintCore.
Because the core functionality is always useful when building rules, I'm
opting to import SwiftLintCore in SwiftLintFramework as `@_exported` so
that it's implicitly available to all files in SwiftLintFramework
without needing to import it directly.
* Make some SwiftLintFramework declarations public
If built-in rules depend on them.
This will allow separating the rules from the core infrastructure in
separate modules in an upcoming PR.
It also helps formalize the API contract for what should be accessible
to rule implementations.
* Exclude extensions from jazzy
The CLI target shouldn't be importing SwiftLintFramework with
`@_spi(TestHelper)`. If the CLI target needs to access something in
SwiftLintFramework, that declaration should be `public`.
This will allow for registering rules that aren't compiled as part of
SwiftLintFramework.
Specifically this will allow us to split the built-in and extra rules
into separate modules, leading to faster incremental compilation when
working on rules since the rest of the framework won't need to be
rebuilt on every compilation.
To link to a video tutorial and example project for creating custom
rules written in Swift and to outline some of the advantages to using
these over regex custom rules.
So that either `one-argument-asserts` or `two-argument-asserts` or both
can be enabled.
The following configuration effectively reverts back to the rule
behavior prior to https://github.com/realm/SwiftLint/pull/3858:
```yaml
xct_specific_matcher:
matchers:
- two-argument-asserts
```
This uses a recent but unannounced (also read as private) feature of
dyld where it ignores duplicate Objective-C classes when they're in a
special format in the binary. c8a445f88f/dyld/PrebuiltLoader.cpp (L1660-L1662)
I think this is generally safe because hopefully people aren't actually
using the SwiftSyntax classes through the Objective-C runtime, but if
they are we'd still probably prefer to silence the noise and accept the
UB.
Fixes https://github.com/realm/SwiftLint/issues/4782
This API allows us to mostly remove `#if` conditionals which enables
cross compilation from macOS -> Linux. It also removes the thrashing of
Package.resolved if you compile in a docker image.
And pin the Ruby version to 2.7.5. rbenv was installed on all CI
machines using Homebrew, with Ruby 2.7.5 installed and set as the
global version. The `pre-command` script was also updated on all agents
to add rbenv binaries to the path and run `rbenv init`.
Remove rules_ruby integration and just use rbenv and ruby directly.
By adding a `tools/sourcery` script that downloads and runs Sourcery via
Bazel.
Previously, unrelated changes might include modifications to the
generated comment headers because contributors' local versions of
Sourcery would be used, which we don't control.
Also move the CI job to Buildkite where the bazel server is usually
already warmed up and running.
* Use Ubuntu 20.04 to release Linux binaries
Using the latest version of Ubuntu leads to incompatibilities with `glibc` versions from LTS versions.
* Use Ubuntu 20.04 for Azure pipelines
Since when releasing, many steps depend on the `build`, so we don't want
to clean mid-way through releasing.
Explicitly run `make clean` at the start of `make release`.
* Update bazel from 6.0.0 to 6.1.1
* Update rules_apple from 2.0.0 to 2.2.0
* Update rules_swift from 1.5.1 to 1.7.1
* Update rules_xcodeproj from 1.1.0 to 1.3.3
* Trim excess trailing and vertical whitespace
* Move `SwiftyTextTable` dependency into `frameworkDependencies`
* Adjust wording in README around analyzer rules in the `opt_in_rules`
section, since analyzer rules can only go in the `analyzer_rules`
section.
We always pass all of the Swift source files in the target to the tool, so we need to ensure that any exclusion rules in the configuration are respected.
* Merge `spacedBinaryOperator` and `unspacedBinaryOperator`
* New contextual keyword enums
* Update for removed `UnavailabilityConditionSyntax`
* Handle how attributes are now defined
This partially reverts commit 325d0ee1e4.
* Handle removal of `TokenListSyntax`
* Update `Package.swift`
* Extract some SwiftSyntax helpers
* Update to `0.50900.0-swift-DEVELOPMENT-SNAPSHOT-2023-02-06-a`
* Skip attributes with keypath arguments in `attributes` rule
To preserve the rule's existing behavior.
* Limit unowned_variable_capture violations to capture lists
* Add changelog entries
it's extremely time-consuming, taking 25 minutes lately, and we'll
hopefully have a better solution soon with the upcoming improvements
to dead code detection, taking less than 1 second to run.
```
(1/4) Collecting units and records (0.25s)
(2/4) Collecting protocol conformances (0.26s)
(3/4) Collecting declarations and references (0.04s)
(4/4) Calculating unused declarations (0.05s)
Source/SwiftLintFramework/Extensions/Configuration+IndentationStyle.swift:16:18: error: Unused declaration named 'init(_:)'
Source/SwiftLintFramework/Models/LinterCache.swift:53:13: error: Unused declaration named 'init(cache:location:fileManager:swiftVersion:)'
Source/SwiftLintFramework/Models/SwiftVersion.swift:25:16: error: Unused declaration named 'fiveDotTwo'
Source/SwiftLintFramework/Models/SwiftVersion.swift:27:16: error: Unused declaration named 'fiveDotThree'
Source/SwiftLintFramework/Models/SwiftVersion.swift:31:16: error: Unused declaration named 'fiveDotFive'
Source/SwiftLintFramework/Rules/Lint/CompilerProtocolInitRule.swift:85:5: error: Unused declaration named 'init(protocolName:types:arguments:)'
Found 6 unused declarations (0.61s)
```
* Revert "Skip tests requiring runfiles support when testing with rules_xcodeproj (#4694)"
This reverts commit 040096a641.
* Enable all tests when using rules_xcodeproj
Turns out we don't need runfiles support
(https://github.com/buildbuddy-io/rules_xcodeproj/issues/828) since the
tests run outside the sandbox in Xcode, so we can get the path to these
files from the `BUILD_WORKSPACE_DIRECTORY` environment variable that
`bazel test` sets.
* Use a binary target for the build tool plugin
* Merge `push_version` and `release` make commands
Instead of running `make push_version "0.2.0: Tumble Dry"` and then
`make release`, now run `make release "0.2.0: Tumble Dry"`, which will
build the release artifacts and update/push the new version to GitHub.
This allows the artifacts to use the new version, update the artifact
bundle checksum in the package manifest, then tag the release.
The Releasing.md instructions were updated to reflect this new workflow.
* Add `SwiftLintSourcePlugin` source plugin for SwiftPM
* Add changelog entry
* Remove SwiftLintSourcePlugin for now
* Build from Source on Linux
* Use a lower-level method of checking if a file is accessible
This shouldn’t trigger sandbox violations, I hope…
* Prevent an infinite recursion of the filesystem root
* Remove unnecessary logging
* Quieten the output so that Xcode only prints violations
* Break up comment to avoid line length warning
* Fix capitalization of Glibc import
Co-authored-by: JP Simard <jp@jpsim.com>
* Only lint Swift source files within the provided target
* Restore plugin display name to “SwiftLint”
* Xcode targets don’t always conform to the SourceModuleTarget
Use a “baser” way to get at the Swift sources of the current target
* Use the cache path as the outputFiles
This prevents the warning we’re seeing in Xcode on every build, but shouldn’t interfere with the re-run logic
* Look for configuration files manually in the project directory and parents
* Check if the file is readable, not just that it exists
* Move the Path helper into a separate file
* Fix a wayward apostrophe
Signed-off-by: Tony Arnold <tony@thecocoabots.com>
* Add an entry to the CHANGELOG
Signed-off-by: Tony Arnold <tony@thecocoabots.com>
Signed-off-by: Tony Arnold <tony@thecocoabots.com>
We have 6 CI machines now and these should run faster on bare metal
machines with lots of stuff already cached, like starting with an
existing git repo.
Moving the validation of doc comments in local scopes out of
`orphaned_doc_comment` and into a new opt-in `local_doc_comment` rule.
Addresses https://github.com/realm/SwiftLint/issues/4573.
Previously, it took a very long time to run `make release` since it had
to clean build everything.
With bazel, I'm more confident in incremental builds being solid, so it
now just takes a few seconds if there's anything cached, which is often
the case.
Which previously tried to build the SwiftLintTestHelpers module,
which is a test-only module.
This should fix building with precommit and Mint, both of which assume
you can build the CLI targets in a Swift package with the
`swift build -c release` command.
I find this rule to not help readability for this project at least,
where `Version(value: "0.50.0")` is a lot more descriptive than
`Self(value: "0.50.0")`.
We no longer need `_InternalSwiftSyntaxParser`, but we do need
`libswiftCore.so`.
Fixes https://github.com/realm/SwiftLint/issues/4501
Add a more useful validation test at the end of the Dockerfile.
In addition to running `swiftlint version`, also actually run the linter
which will exercise the SourceKit codepaths.
Now that we have more Buildkite machines, these should be faster than
running on Azure Pipelines.
Also remove the `//bazel:xcode_config` configurations since they should
no longer be in use.
With the memory increase related to
https://github.com/apple/swift-syntax/issues/921,
I wanted a way to quickly know how much memory was being used by
SwiftLint.
Here's how much memory it took to lint SwiftLint itself at various
versions in the last few weeks:
* 0.49.1: 223 MB
* 0.50.0-rc.1: 356 MB
* 0.50.0-rc.2: 444 MB
* main (458916174): 464 MB
```console
$ swiftlint --progress --benchmark
Linting Swift files in current working directory
529 of 529 [==============================] ETA: 0s (121 files/s)
Done linting! Found 0 violations, 0 serious in 529 files.
Memory used: 464 MB
$ swiftlint --progress --benchmark
Linting Swift files in current working directory
529 of 529 [==============================] ETA: 0s (16220 files/s)
Done linting! Found 0 violations, 0 serious in 529 files.
Memory used: 55.8 MB
```
* Migrate `implicitly_unwrapped_optional` to SwiftSyntax
* Update Source/SwiftLintFramework/Rules/RuleConfigurations/ImplicitlyUnwrappedOptionalConfiguration.swift
Co-authored-by: Danny Mösch <danny.moesch@icloud.com>
* Fix after rebase
Co-authored-by: Danny Mösch <danny.moesch@icloud.com>
* Add way to preprocess syntaxTree in SwiftSyntaxRule
* Update Source/SwiftLintFramework/Protocols/SwiftSyntaxRule.swift
Co-authored-by: Danny Mösch <danny.moesch@icloud.com>
* Update Source/SwiftLintFramework/Protocols/SwiftSyntaxRule.swift
Co-authored-by: Danny Mösch <danny.moesch@icloud.com>
Co-authored-by: Danny Mösch <danny.moesch@icloud.com>
A long-standing limitation with SourceKit's "editor open" request is
that we weren't able to get certain tokens, such as braces, brackets and
parentheses.
This meant that this code block would be counted as two lines:
```swift
print(
"hi"
)
```
because the trailing `)` would be treated as a whitespace line.
This meant that our "body length" family of rules that measure the
effective line count of declarations like functions, types or closures
would often significantly under-count the number of content lines in a
body.
Now with SwiftSyntax, we can get all tokens, including the ones
SourceKit was previously ignoring, so we can get much more accurate line
counts when ignoring whitespace and comments.
In addition, we weren't very thorough in how we measured body length.
As an exercise, how many lines long would you say the body of this
function is?
```swift
func hello() {
print("hello")
}
```
Does the body span one line or three lines?
I propose that we consistently ignore the left and right brace lines
when calculating the body line count of these scopes so that we measure
body line counts like this:
```swift
// 1 line
{ print("foo") }
// 1 line
{
}
// 1 line
{
print("foo")
}
// 2 lines
{
let sum = 1 + 2
print(sum)
}
```
Now with those changes in place, in order to keep the default
configuration thresholds to similar levels as before, we need to adjust
them slightly. Here's what I'm suggesting:
|Rule|Before|After|
|-|-|-|
|closure_body_length|20/100|30/100|
|function_body_length|40/100|50/100|
|type_body_length|200/350|250/350|
This is a pretty significant breaking change and I suspect we'll hear
from users who are surprised that some of their declarations now exceed
the rule limits, but I believe this new approach to calculating body
lines is more correct and intuitive compared to what we've had until
now.
OSSCheck is also going to report a bazillion changes with this, which is
expected given the scope of this change.
Replace `MemberAccessExprSyntax.functionCallBase` with
`ExprSyntax.asFunctionCall` so we can use it in more places.
Move `TokenKind.isEqualityComparison` into `SwiftSyntax+SwiftLint.swift`
When linting SwiftLint, this brings memory usage down by around 20%,
going from 372MB to 297MB.
This is achieved by removing the unused `RebuildQueue` and by clearing
cached data associated with files after processing them.
Depends on https://github.com/jpsim/SourceKitten/pull/749.
Otherwise this tries to build the SwiftLintTestHelpers module in release
mode, which fails.
Also, to build the actual executable CLI, we can't just
`swift build --target=swiftlint` because that doesn't produce a CLI,
just the object file for the binary. So we have to `swift run`.
* Rewrite IdenticalOperandsRule with SwiftSyntax
* Use folding algorithm from swift-format
* Add workaround for debug builds
* Update implementation after rebasing
* Use SwiftOperators
* Remove focused
This avoids potential stack overflows and slowness when just working on
SwiftLint itself with bazel. These compiles take a lot longer but as
long as you're not updating swift-syntax that should be a 1 time penalty
* Move generated rule tests to a dedicated GeneratedTests target
* Move integration tests to a dedicated IntegrationTests target
This will improve bazel cacheability by having fewer tests depend on all
lint inputs, which are only needed by the integration tests.
With SwiftSyntax rewriters, the visitors get called with the new nodes
after previous mutations have been applied, so it's not straightforward
to translate those back into the original source positions.
So only check the first locations.
Just staying up to date here.
There's no need to frequently update, but given that we just updated to
trunk, I wanted to make sure we can update without issues.
* ✨ (spm) add build tool plugin definition for swiftlint
* 📝 (changelog) add changelog item for the plugin
* 🐛 (cache) define cache path explicitly to avoid issues during build without issues
* 🎨 minor code cleanup
* 📝 document usage with Xcode as well as Swift packages
This is failing very often now due to FB11648454.
Given that we run these tests on macOS via SwiftPM and Bazel as well,
I'm satisfied with the amount of coverage we have on our tests without
this.
By using SwiftSyntax instead, we avoid the overhead of a SourceKit
request, which has a significant impact if none of the rules being
corrected use SourceKit.
Added rules filtering options, like in the `rules` subcommand.
<img width="880" alt="generate-docs--help" src="https://user-images.githubusercontent.com/7829589/189372666-2f5aba62-57a1-49dc-9155-c60f9e085984.png">
To achieve reuse with `rules` subcommand:
- extracted filtering logic into `RulesFilter` (and write tests)
- extracted filtering command line parameters into `RulesFilterOptions: ParsableArguments`
Vertical whitespace may be important for readability when the line
with the closing brace is not a trivial one (e.g. `} else if ... {`).
The configuration allows not enforcing the rule in such cases.
To enforce that `self` identifiers are consistently re-bound to a common
identifier name.
Configure `bind_identifier` to the name you want to use.
Defaults to `self`.
Addresses https://github.com/realm/SwiftLint/issues/2495
handle situation with async let _ = ....
let can not be removed from "async let _ = ..." because removing it produces invalid swift syntax
Co-authored-by: Martin Hosna <mhosna@samepage.io>
This cuts down on the boilerplate involved in writing SwiftSyntax-based
rules. May not be significant right now since most rules are still built
with SourceKit, but as we migrate more rules moving forward, this should
make it easier for rule authors to write rules that behave performantly
and correctly.
And move analyze CI job to Bazel
Which will benefit from caching previous results,
so if we make a PR that doesn't impact the analysis
results (i.e. changelog or docs) we might be able to
skip running this at all.
- added two triggering examples that are a common style, to make it immediately obvious that they trigger the rules
- also fixed a spelling mistake throughout the examples for the multiline_literal_brackets rule ("Gryffindor" is now correctly spelt)
And only warn once if it's disabled.
This check is expensive and as more rules move away from SourceKit to
SwiftSyntax, it's increasingly common for rules to not use SourceKit at
all.
In addition, SourceKit crashes used to be a lot more common but I
haven't seen one myself in quite a while.
Prints out something like this on macOS:
```
Version: 0.49.0-rc.1
Build ID: B43931F3-D096-3704-B41C-FC40673A3F96
```
This can be used to determine if two `swiftlint` executables are
identical.
To support this, we first must use an async entrypoint to the CLI, which
we do by changing the lint and analyze commands to conform to
`AsyncParsableCommand`.
The in order to map over the closures with suspension points, we pull in
CollectionConcurrencyKit as a new dependency.
This change does not touch SwiftLintFramework, only the CLI target.
Making it about 10x faster, finding some previously missed cases and
fixing some previously wrong corrections.
This pulls in the `Collection.windows(ofCount:)` function from Swift
Algorithms.
Run with `bazel test --spawn_strategy=standalone //Tests/...`
Consumers who define rules via `swiftlint_extra_rules` can run tests for
their custom rules too:
```
./bazelw test \
--spawn_strategy=standalone \
@SwiftLint//Tests:ExtraRulesTests
```
This change makes it possible to add native custom rules when building
SwiftLint via Bazel (possible as of
https://github.com/realm/SwiftLint/pull/4038).
First, add a local bazel repository where custom rules will be defined
to your project's `WORKSPACE`:
```python
local_repository(
name = "swiftlint_extra_rules",
path = "swiftlint_extra_rules",
)
```
Then in the extra rules directory, add an empty `WORKSPACE` and a
`BUILD` file with the following contents:
```python
filegroup(
name = "extra_rules",
srcs = glob(["*.swift"]),
visibility = ["//visibility:public"],
)
```
To add a rule (for example, `MyPrivateRule`) add the following two
files:
```swift
// ExtraRules.swift
func extraRules() -> [Rule.Type] {
[
MyPrivateRule.self,
]
}
```
```swift
// MyPrivateRule.swift
import SourceKittenFramework
import SwiftSyntax
struct MyPrivateRule: ConfigurationProviderRule {
var configuration = SeverityConfiguration(.error)
init() {}
static let description = RuleDescription(
identifier: "my_private_rule",
name: "My Private Rule",
description: "This is my private rule.",
kind: .idiomatic
)
func validate(file: SwiftLintFile) -> [StyleViolation] {
// Perform validation here...
}
}
```
Then you can reference the rule in your configuration or source files as
though they were built in to the official SwiftLint repo.
This means that you have access to SwiftLintFramework's internal API.
We make no guarantees as to the stability of these internal APIs,
although if you end up using something that gets removed please reach
out and we'll make a best effort to maintain some level of support.
This PR also improves the linter cache on macOS to make it correctly
invalidate previous results when custom native rules are edited. This
even works when doing local development of SwiftLint, where previous it
was necessary to use `--no-cache` when working on SwiftLint, now the
cache should always work.
Co-authored-by: Keith Smiley <keithbsmiley@gmail.com>
This will unblock using Swift Concurrency features and updating to the
latest versions of Swift Argument Parser.
This won't drop support for linting projects with an older toolchain /
Xcode selected, as long as SwiftLint was _built_ with 5.6+ and is
_running_ on macOS 12+. So the main breaking change for end users here
is requiring macOS 12 to run.
However, the upside to using Swift Concurrency features is worth the
breaking change in my opinion. Also being able to stay on recent Swift
Argument Parser releases.
This makes the added test cases work in Xcode 13.2 where the wrapping does not happen.
The call expression is the first substructure in the dictionary, while in Xcode 13.3
it's an argument containing the call expression.
There is no real benefit for this option. Files and folders to lint/analyze
can be passed to `swiftlint` as last arguments. There cannot be multiple
`--path` arguments. If there is more than one only the last path is considered.
Warns if a SwiftUI Image does not have an accessibility label and is not hidden from accessibility. When this is the case, the image's accessibility label defaults to the name of the image file causing a poor UX.
* Only skip autocorrect on files with errors
* Use other kind of warning so tests succeed on Linux
* Update CHANGELOG.md
Co-authored-by: JP Simard <jp@jpsim.com>
Co-authored-by: JP Simard <jp@jpsim.com>
We now have two Buildkite agents thanks to a newly added M1 Mac mini
from MacStadium. Running the analyze job should be considerably faster
than the VMs that run on Azure Pipelines, although still slower than
if we were to run them with Xcode 13.2.1 because of the performance
regressions described in https://github.com/realm/SwiftLint/issues/3920.
* Fix analyzer rules with Xcode 13.3
Looks like starting with Xcode 13.3 / Swift 5.6, cursor info requests
started canceling in-flight requests, so we need to pass
`key.cancel_on_subsequent_request: false` to bypass that.
Analyzer rules on Swift 5.6 are extremely slow, however. Not really
usable right now.
* Run analyzer rules one file at a time
* Add changelog entry
* Improve docstrings for `StringView+SwiftSyntax.swift`
* Move changelog entry to correct section & reword
* Change parameter type from `Int` to `ByteCount`
* Move AbsolutePosition / ByteCount conversion to internal API
* Only warn once if syntax tree cannot be parsed
* Move Syntactic Sugar examples to a dedicated file
* Change SyntacticSugarRuleVisitor from SyntaxAnyVisitor to SyntaxVisitor
* Add `SugaredType` enum to help with the implement `SyntacticSugarRule`
> [DEPRECATED] The `--path` flag is deprecated because it relies on
> being remembered across bundler invocations, which bundler will no
> longer do in future versions. Instead please use
> `bundle config set path 'vendor/bundle'`, and stop using this flag
The idea of this new Analyzer rule is to filter the calls of `map` before they are passed on to the classic ArrayInitRule which does the detailed checking of the lambda function block. The rule makes sure that only the `map` function is considered that is defined by the `Sequence` protocol.
* Add ability to focus on a specific test example
* Update CHANGELOG.md
Co-authored-by: JP Simard <jp@jpsim.com>
* Update CONTRIBUTING.md
Co-authored-by: JP Simard <jp@jpsim.com>
Co-authored-by: JP Simard <jp@jpsim.com>
Uses SwiftSyntax 5.5 on Linux when building with Swift 5.5. We use the 5.6 version of
SwiftSyntax when building with Swift 5.5 and 5.6 on macOS because we statically link
`lib_InternalSwiftSyntaxParser` thanks to
https://github.com/keith/StaticInternalSwiftSyntaxParser/releases/tag/5.6.
This keeps SwiftLint binaries portable across machines on macOS, regardless of
_where_ or even _if_ `lib_InternalSwiftSyntaxParser` is installed.
* Run TSan CI job with `--configuration release` to avoid stack overflows
* Add Swift 5.6 CI job
* Fix linker settings
SourceKitten: 0.31.1 to 0.32.0
SWXMLHash: 5.0.2 to 6.0.0
Also prevent swift-argument-parser from being updated to 1.1.0 which is
incompatible with our macOS version support.
Since `_InternalSwiftSyntaxParser` isn't in the search paths when building with the `-static-stdlib` flag, we have to manually pass an include path so the swift compiler discovers it. Unfortunately we cannot just pass `-I/usr/lib/swift` because that results in duplicate library errors since the libraries we're linking statically also live there as shared libraries. This first symlinks the module definition to the root of the checkout and uses `.` for the `-I`. Any temporary path could be used instead.
We've tried adding Swift Syntax support to SwiftLint in the past but had to turn it off in https://github.com/realm/SwiftLint/pull/3107 due to distribution and portability issues.
With https://github.com/keith/StaticInternalSwiftSyntaxParser it should be possible to avoid those issues by statically linking the internal Swift syntax parser so it's available no matter where users have Xcode installed on their computer.
By removing all calls to SourceKit (collecting comment commands + checking the current Swift version), there's a really significant performance improvement.
| Framework | Mean [ms] | Min [ms] | Max [ms] | Relative |
|:---|---:|---:|---:|---:|
| SourceKit | 517.8 ± 8.3 | 505.5 | 531.1 | 6.59 ± 0.43 |
| SwiftSyntax | 78.6 ± 5.0 | 72.6 | 92.1 | 1.00 |
In practice, the SourceKit overhead will continue being there for as long as any rule being run is still looking up the SwiftLint syntax map though.
* Disable Swift 5.4 CI jobs
* Remove SwiftLintFramework podspec
I couldn't find a single use in GitHub's search: https://github.com/search?q=SwiftLintFramework+filename%3APodfile+language%3ARuby+language%3ARuby&type=Code
Just not worth maintaining anymore.
* Change package swift tools version to 5.5
* Update docker_test to use Swift 5.5 image
* Clean up old Swift versions in SwiftVersionTests
Even though these older Swift versions should still be supported, these tests
can't be built against those versions so they're useless.
* Run docker commands with `--platform linux/amd64`
* Remove LinuxMain
It looks like tests are discovered dynamically on Linux as of recent
SwiftPM versions.
The option can be used if an example has mainly been added as another test case, but is not suitable
as a user example. User examples should be easy to understand. They should clearly show where and
why a rule is applied and where not. Complex examples with rarely used language constructs or
pathological use cases which are indeed important to test but not helpful for understanding can be
hidden from the documentation with this option.
* Change fingerprint generation to use relativeFile instead of location in order to support CI/CD on multiple machines.
* Created copy of location with relativeFile instead of file to generate fingerprint.
Co-authored-by: Henk Pors <hpors@anwb.nl>
While browsing the rules documentation, I noticed **many** rules were both in the Default Rules and in the Opt In Rules section.
After looking into it, the docs of the `drop(while predicate: (Element) throws -> Bool` function states:
A closure that takes an element of the sequence as its argument and returns true if the element should be skipped or false if it should be included. **Once the predicate returns false it will not be called again.**
This caused the `defaultRuleDocumentations` array to contain almost all `ruleDocumentation`.
Yesterday I started moving SwiftLint's CI jobs from Azure Pipelines to
GitHub Actions, which has nicer integrations with GitHub's web UI and
feels nicer & more lightweight overall.
However, GitHub Actions has a serious limitation compared to Azure
Pipelines, which is that it only has 5x macOS job concurrency vs Azure's
10x ([see Twitter](https://twitter.com/simjp/status/1326592600393068546)).
This leads to significant queuing when merging PRs or pushing to PRs in
a short span, which is the main way I work on SwiftLint when catching up
on PR/issue backlog every few months.
A quick timing check showed that a PR using Azure Pipelines (#3825) took
26m 47s vs GitHub Actions (#3824) took 32m 31s. These PRs were opened at
a time when no other CI jobs were running, so even though Azure
Pipelines already took 6 minutes less to run than GitHub Actions, that
difference would be even larger if there had been other PRs triggering
CI jobs at the same time.
So I think the best move for the project for the time being is to stay
with Azure Pipelines for its CI. If GitHub ever increases its macOS
concurrency to match Azure Pipelines's 10x we can explore this again.
Static references with `Self` are not allowed to define
* default values of properties,
* annotation parameter values and
* default method parameter values
in classes.
- Make "middle part" `.*` not so greedy with `?`.
- Use `(?!` negative look-ahead to improve matching.
- Added corresponding unit tests.
Co-authored-by: Sergei Shirokov <sshirokov@malwarebytes.com>
Since Homebrew installs to a path that isn't in Xcode's path by default, we need to add to the path to support the default location Homebrew installs SwiftLint on Apple Silicon.
From https://stackoverflow.com/a/66003612/118631
* add configuration for missing_docs
* fix MissingDocsRuleConfiguration
* add to changelog
* fix up Config default values and update tests
* use XCTAssertTrue and XCTAssertFalse
* fix line length violation
* finish up unit tests
* rever Package.resolved
* `excludes_extensions` defaults to `true` to skip reporting violations
for extensions with missing documentation comments.
* `excludes_inherited_types` defaults to `true` to skip reporting
violations for inherited declarations, like subclass overrides.
Add a screenshot that shows the `--no-cache` argument, because this is
what should be used in most cases, since the cache is enabled by
default, so the debugger won't stop in the implementation of a rule on a
subsequent run.
Also update the second screenshot from the same macOS version (Big Sur)
for consistency.
* Require Swift 5.3 or higher to build
* Remove Swift Version Support tables from readmes
These weren't exactly accurate because SwiftLint should still work with
older Swift versions long after we update the minimum version of Swift
needed to _build_ the tool. So I doubt this table was very helpful to
anyone.
Try a few things:
1. Sort InclusiveLanguageRule terms since they're a Set and don't have
deteministic ordering (will definitely help)
2. Fetch remote at the beginning of the script (likely to help)
3. Only fetch remote once (likely to help)
4. Sort branch & master output before diffing (unlikely to help)
5. Change diff filter from `d` to `AMRCU` (no idea if it will help)
When a declaration refers to an Objective-C type but doesn't have an
explicit `@objc` attribute.
It would have the string `@objc` embedded in its USR. So add a space so
we only trigger this condition when there's an explicit `@objc`
attribute in the declaration source code.
The triggering example added here didn't trigger before this change.
A colleague was confused by the output of `swiftlint autocorrect`, she
couldn't understand why SwiftLint told her it corrected thousands of
files when she only touched one.
The "Done correcting \(files.count) ..." output made her think that a
change was made on each of the `files`, when really they had only been
inspected.
A good solution would be to adopt a similar approach as the `lint`
command does.
Not being familiar with the codebase, I though a good first step could
have been to tweak the message a bit, making it clearer that the count
printed to the console is the inspected files.
That's because it can currently be difficult to know why a module is
referenced in a file.
To use, run SwiftLint with the environment variable set to the module
whose references you want to log to `stderr`:
SWIFTLINT_LOG_MODULE_USAGE=MyModule swiftlint analyze ...
That's because it can currently be difficult to know why a module is
referenced in a file.
To use, run SwiftLint with the environment variable set to the module
whose references you want to log to `stderr`:
SWIFTLINT_LOG_MODULE_USAGE=MyModule swiftlint analyze ...
* Integrate OS Signposts to help profile SwiftLint performance
* Split LintOrAnalyzeCommand.lintOrAnalyze(_:) into two functions
Using a builder reference type to share common mutable state.
Swift Playgrounds use `//:` to mark prose sections and `//:#` for embedded
content like images and localized prose, so those shouldn't violate the
space-after-comment rule.
I believe this will completely remove the bot.
Rationale: https://github.com/realm/SwiftLint/pull/3385#issuecomment-784411782
> I've changed my mind on this. I believe this is solving the wrong
> problem. It can be very disappointing for users when their issues /
> PRs remain ignored by maintainers for a long time, but I think it's
> worse when issues / PRs are automatically closed, and I don't think it
> actually helps with the health of the project, or make maintainer's
> lives easier.
>
> I can't guarantee anything, but I am working on a plan to improve the
> maintainership of SwiftLint moving forward, and hopefully that can be
> more impactful when it comes to responsiveness to community issues and
> PRs, and I believe that's a better way to triage issues and PRs.
For example you might have custom source tooling that does something
with types conforming to a procotol even if that type is never
explicitly referenced by other code.
A colleague was confused by the output of `swiftlint autocorrect`, she
couldn't understand why SwiftLint told her it corrected thousands of
files when she only touched one.
The "Done correcting \(files.count) ..." output made her think that a
change was made on each of the `files`, when really they had only been
inspected.
A good solution would be to adopt a similar approach as the `lint`
command does.
Not being familiar with the codebase, I though a good first step could
have been to tweak the message a bit, making it clearer that the count
printed to the console is the inspected files.
* Fix false positives on unused_declaration for outlets with accessors
* Also willSet/didSet
* fixup! Fix false positives on unused_declaration for outlets with accessors
* Remove NonPrivateXCTestMembersRule
I accidentally implemented this rule twice. So TestCaseAccessibilityRule
did the same thing but with a bit more behavior. This change deletes
NonPrivateXCTestMembersRule but also ports over the autocorrection from
it to TestCaseAccessibilityRule.
Provides:
- a runtime environment on ubuntu that does not include the Swift toolchain.
- supportintg `docker build https://github.com/realm/SwiftLint.git`
- add `libcurl4-openssl-dev` as build time dependency that introduced by #3058
* Add support for allowed terms in inclusive language rule
* Update changelog
* Move changelog entry to Enhancements section
Co-authored-by: JP Simard <jp@jpsim.com>
SwiftPM 5.3 uses the `XCBuild.framework` to generate universal binaries when it receives multiple `--arch` options.
In that case, `--show-bin-path` returns `.build/apple/Products/Release`.
This was extracting from another change that no longer needed it. It
should be helpful for anyone testing custom configuration with their
non-analyzer rules.
I added a random example of something that wasn't previously tested as
an example.
* BREAKING CHANGE: As `OverridenSuperCallConfiguration` is a
publicly-exposed struct, this rename should be considered breaking.
* Fix consoleDescription for OverriddenSuperCallConfiguration
1. Add some comments
2. Name variables when used in multiline closures
3. Change violation range length from 1 to 0, which simplifies the
substitution
4. Tweak indentation
* Remove Xcode project & Drop Carthage Support
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
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
Swift 5.2 has been officially released for over 7 months now, there's no
reason to keep supporting earlier versions when _building_ SwiftLint.
However, SwiftLint still supports _linting_ back up to Swift 3.0.
We currently try to derive the root path by using the path passed in. However, this doesn't allow us to actually get the root, just the containing directory of the path passed in. We also don't currently have a heuristic to use for deriving the root path for multiple paths passed in.
The fix (which fixes#3383) is to remove our root path calculation and just use the current working directory as the root instead.
This Fixes case when the right part of the expression is an array or a string
Previously, strings and comments tokens were ignored.
In the current implementation, matching done first and then those are filtered if the operator is within the string token
This was previously attempted in #3342, but produced a bug in the case where `--config` is used to specify a config from outside of the source tree. The `--config` argument wasn't always being used as an override, and was being merged with the config in the source tree. This has now been addressed and reverts the revert done in #3362.
Fixes#3341
Current events have renewed the conversation in our community about the roles of terminology with racist connotations in our software. Many companies and developers are now taking appropriate steps to remove this terminology from their codebases and products. (e.g. [GitHub](https://twitter.com/natfriedman/status/1271253144442253312)) This small rule prevents the use of declarations that contain any of the terms: whitelist, blacklist, master, and slave. It may be appropriate to add more terms to this list now or in the future.
Some attributes are parameterized, such as `@objc(name)`. Previously
these reported `attributes` violations because their contents weren't
included in the configuration, which would just have `@objc`.
As we discussed here https://github.com/realm/SwiftLint/pull/3325 sometimes current excluding algorithm maybe slower than excluding paths by absolute prefix. So I added option for such cases.
Based on what I've checked it works faster for next scenarios:
- the number of input files is relatively small (e.g. when using `use-script-input-files`) and excluded directories contain relatively big number of lintable files
- the number of excluded directories relatively small (e.g. Pods + ThirdParty) and globs not used
* Use the severity from the configuration
It was previously using a hardcoded value, that of the default configuration.
* Update CHANGELOG.md
* Correctly format CHANGELOG addition
* Improve "Working Directory" instructions in CONTRIBUTING.md (#1280)
The instruction wasn't clear to me and it took me some time to figure out what to insert into the "Working Directory" option.
Co-Authored-By: oonoo <2565796+oonoo@users.noreply.github.com>
* Improve "Arguments Passed On Launch" instructions in CONTRIBUTING.md (#1280)
I wasn't sure which arguments could be passed to SwiftLint. I referenced the Command Line paragraph in the README, it already lists the available arguments.
Co-Authored-By: oonoo <2565796+oonoo@users.noreply.github.com>
* Add more details to "Submodules" in CONTRIBUTING.md (#1280)
The reason to checkout git submodules wasn't mentioned. I added the use cases for submodules, as Swift Package Manager doesn't make use of the git submodules.
* Format "Using Xcode" in CONTRIBUTING.md (#1280)
Limit line length to 80 characters in "Using Xcode" section of CONTRIBUTING.md.
* Document changes in CHANGELOG.md (#1280)
* Add missing word
Co-authored-by: oonoo <2565796+oonoo@users.noreply.github.com>
Co-authored-by: JP Simard <jp@jpsim.com>
We weren't properly handling some new Xcode 12 compiler logs.
We also were marking declarations used by SwiftUI as unused
(`@main` and preview providers).
Fixes#3341
When SwiftLint searches for nested configurations and only one file has been passed in via the `paths` argument, SwiftLint returns early after inadvertently comparing the containing directory of the file-to-be-linted to itself. This happens because `rootDirectory` is calculated from `rootPath`, which is set to the file being linted in this scenario.
* Include Linux zip in list of GitHub release binaries
This matches what has been included in recent releases.
* Fix one more Linux zip reference
* Use all 1s for the numbered list in Releasing.md
Markdown renders the numbered list correctly, and this way one can easily reorder the steps
or add new steps without needing to renumber everything.
We were using this lock to guarantee a new ID for every file, but we can
get that benefit by using values that are guaranteed to be unique
without the need for locks, such as a UUID.
By using SourceKit's `index` request to index the entire source file,
we can avoid having to make `cursor-info` requests for every candidate
token in the file, which scales linearly with the number of candiate
tokens.
For the Yams project, this approach improved the total SwiftLint run
time by 4.6x: 7.9 down from 36.8s.
The SourceKit index response doesn't have everything we need to identify
declarations, so we still need to make some `cursor-info` requests,
mostly to detect overrides: protocol conformances and parent class
overrides.
This approach ends up finding more unused declarations because the index
contains more declared USRs than can be found by calling `cursor-info`
on candidate tokens in a file.
---
Remove unused declaration in ArrayInitRule
---
Update package versions
This allows custom rules to define an `excluded_match_kinds` array instead of listing out all but one or a few of the `SyntaxKind`s in `match_kinds`. Rules that include both `match_kinds` and `excluded_match_kinds` will be invalid, since there's not an obvious way to resolve the two without an arbitrary priority between them.
There are a lot of libraries dynamically linked, so it's unlikely to
work in most places other than the same Docker image used to build the
binary (latest official Swift Docker image).
It might still be useful if you can guarantee that you'll use this from
that image.
ldd .build/release/swiftlint
linux-vdso.so.1 (0x00007fff38db5000)
libswiftCore.so => /usr/lib/swift/linux/libswiftCore.so (0x00007f11503cd000)
libFoundation.so => /usr/lib/swift/linux/libFoundation.so (0x00007f114fba6000)
libswiftGlibc.so => /usr/lib/swift/linux/libswiftGlibc.so (0x00007f1151264000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f114f987000)
libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f114f784000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f114f580000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f114f1e2000)
libswiftDispatch.so => /usr/lib/swift/linux/libswiftDispatch.so (0x00007f115122b000)
libdispatch.so => /usr/lib/swift/linux/libdispatch.so (0x00007f114ef82000)
libBlocksRuntime.so => /usr/lib/swift/linux/libBlocksRuntime.so (0x00007f114ed7f000)
libFoundationXML.so => /usr/lib/swift/linux/libFoundationXML.so (0x00007f11511d2000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f114e98e000)
libicui18nswift.so.65 => /usr/lib/swift/linux/libicui18nswift.so.65 (0x00007f114e463000)
libicuucswift.so.65 => /usr/lib/swift/linux/libicuucswift.so.65 (0x00007f114e062000)
libicudataswift.so.65 => /usr/lib/swift/linux/libicudataswift.so.65 (0x00007f114c3b3000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f114c02a000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f114be12000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1151053000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f114bc0a000)
libxml2.so.2 => /usr/lib/x86_64-linux-gnu/libxml2.so.2 (0x00007f114b849000)
libicuuc.so.60 => /usr/lib/x86_64-linux-gnu/libicuuc.so.60 (0x00007f114b491000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f114b274000)
liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f114b04e000)
libicudata.so.60 => /usr/lib/x86_64-linux-gnu/libicudata.so.60 (0x00007f11494a5000)
This allows you to pass `@path/to/file` which will be read line by line
for the list of files to lint / analyze. This is useful if you want to
pass a massive list of files which will either exceed arg max, or
break most unix tools if you use script input files + env vars.
Sometimes we hit issues with SourceKit that cause this rule to produce
false positives of some imports. While we would prefer to fix all of
these cases whenever possible, this gives us a temporary escape hatch to
tell the rule never to remove imports of specific modules until the
fixes land in SwiftLint or Swift itself.
Currently this is for us to opt out of https://bugs.swift.org/browse/SR-13120
* Improve compile commands error handling
Previously when a compile commands file was invalid, it could be hard to
figure out what about it was wrong. This adds some more granular error
handling which hopefully helps provide valid files here.
* fix desc
* Fixups
* Update changelog
* Make what broke clear
* Reword changelog entry
Co-authored-by: JP Simard <jp@jpsim.com>
* Update CI to run jobs with Xcode 11.0 to 11.4
In the process, remove CI jobs running with Swift 5.0.x and indicate
in the changelog that the next release will be the last one to support
building with Swift 5.0.x.
* fixup! Update CI to run jobs with Xcode 11.0 to 11.4
* fixup! Update CI to run jobs with Xcode 11.0 to 11.4
* fixup! Update CI to run jobs with Xcode 11.0 to 11.4
* fixup! Update CI to run jobs with Xcode 11.0 to 11.4
* Disable Swift 5.2 tests on Linux due to SR-12500
* Update ruby gems
Mostly to get jazzy 0.13.2 with Swift 5.2 bug fixes.
* Fix false positives in valid_ibinspectable rule when using Swift 5.2
when defining inspectable properties in class extensions with computed
properties.
The following was triggering:
```swift
extension Foo {
@IBInspectable var color: UIColor {
set {
self.bar.textColor = newValue
}
get {
return self.bar.textColor
}
}
}
```
Fix by checking to see if an instance property has `set` keywords in its
body when running with Swift 5.2 or later.
* fixup! Fix false positives in valid_ibinspectable rule when using Swift 5.2
The following was triggering:
```swift
func printBoolOrTrue(_ expression: @autoclosure () throws -> Bool?) rethrows {
try print(expression() ?? true)
}
```
Fix by adding the `rethrows` attribute kind to the rule's blacklist.
For example, if `CGFloat` is used in a file where only `UIKit` is imported but not `CoreGraphics`, this will be a violation even if the file previously compiled.
This is because Swift allows referencing some declarations that are only transitively imported.
Enabling the `require_explicit_imports` configuration option will require that the module of every declaration referenced in a source file be explicitly imported.
This will add significant noise to the imports list, but has a few advantages:
1. It will be easier to understand all the dependencies explicitly referenced in a source file.
2. Correcting the `unused_import` rule will no longer introduce compilation errors in files that compiled prior to the correction.
If missing imports are added to a file when correcting it, the `sorted_imports` rule will be automatically run on that file.
If you with to allow some imports to be implicitly importable transitively, you may specify the `allowed_transitive_imports` configuration:
```yaml
unused_import:
require_explicit_imports: true
allowed_transitive_imports:
- module: Foundation
allowed_transitive_imports:
- CoreFoundation
- Darwin
- ObjectiveC
```
The new rules introduced in 0.39.0 that depend on SwiftSyntax have been temporarily removed as we work out release packaging issues.
* `prohibited_nan_comparison`
* `return_value_from_void_function`
* `tuple_pattern`
* `void_function_in_ternary`
See https://github.com/realm/SwiftLint/issues/3105 for details.
When multiple `@testable` imports are involved.
Because we use the `.dotMatchesLineSeparators` regular expression option, the dot was matching across lines when the intention was for it to just match `\w_` characters.
/// The rule list containing all available rules built into SwiftLint.
public let masterRuleList = RuleList(rules: [
public let builtInRules: [Rule.Type] = [
{% for rule in types.structs where rule.name|hasSuffix:"Rule" or rule.name|hasSuffix:"Rules" %} {{ rule.name }}.self{% if not forloop.last %},{% endif %}
{% for method in type.methods where method.parameters.count == 0 and method.shortName|hasPrefix:"test" and method|!annotated:"skipTestOnLinux" %} ("{{ method.shortName }}", {{ method.shortName }}){% if not forloop.last %},{% endif %}
{% endfor %}]
}
{% endfor %}
XCTMain([
{% for type in types.classes|based:"XCTestCase" %} testCase({{ type.name }}.allTests){% if not forloop.last %},{% endif %}
1. 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 a rule that allows name evaluation configuration:
``` yaml
@ -106,16 +145,40 @@ If your rule is configurable, but does not fit the pattern of
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.
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:
1. One Markdown unnumbered list item describing the change.
2. 2 trailing spaces on the last line describing the change.
2. 2 trailing spaces on the last line describing the change (so that Markdown renders each change [on its own line](https://daringfireball.net/projects/markdown/syntax#p)).
3. A list of Markdown hyperlinks to the contributors to the change. One entry
per line. Usually just one.
4. 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.
5. All CHANGELOG.md content is hard-wrapped at 80 characters.
## CI
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.
### Buildkite Setup
To bring up a new Buildkite worker from MacStadium:
1. Change account password
1. Update macOS to the latest version
1. Install Homebrew: https://brew.sh
1. Install Buildkite agent and other tools via Homebrew:
if !modified_files.include?('CHANGELOG.md') && has_app_changes
warn("Please include a CHANGELOG entry to credit yourself! \nYou can find it at [CHANGELOG.md](https://github.com/realm/SwiftLint/blob/master/CHANGELOG.md).")
warn("If this is a user-facing change, please include a CHANGELOG entry to credit yourself! \nYou can find it at [CHANGELOG.md](https://github.com/realm/SwiftLint/blob/main/CHANGELOG.md).")
markdown <<-MARKDOWN
Here's an example of your CHANGELOG entry:
```markdown
@ -30,7 +32,7 @@ Here's an example of your CHANGELOG entry:
A tool to enforce Swift style and conventions, loosely based on
[GitHub's Swift Style Guide](https://github.com/github/swift-style-guide).
A tool to enforce Swift style and conventions, loosely based on the now archived [GitHub Swift Style Guide](https://github.com/github/swift-style-guide). SwiftLint enforces the style guide rules that are generally accepted by the Swift community. These rules are well described in popular style guides like [Kodeco's Swift Style Guide](https://github.com/kodecocodes/swift-style-guide).
SwiftLint hooks into [Clang](http://clang.llvm.org) and
[SourceKit](http://www.jpsim.com/uncovering-sourcekit) to use the
@ -17,7 +16,7 @@ This project adheres to the [Contributor Covenant Code of Conduct](https://realm
By participating, you are expected to uphold this code. Please report
unacceptable behavior to [info@realm.io](mailto:info@realm.io).
> Language Switch: [中文](https://github.com/realm/SwiftLint/blob/master/README_CN.md), [한국어](https://github.com/realm/SwiftLint/blob/master/README_KR.md).
> Language Switch: [中文](https://github.com/realm/SwiftLint/blob/main/README_CN.md), [한국어](https://github.com/realm/SwiftLint/blob/main/README_KR.md).
## Installation
@ -42,7 +41,7 @@ in your Script Build Phases.
This is the recommended way to install a specific version of SwiftLint since it supports
installing a pinned version rather than simply the latest (which is the case with Homebrew).
Note that this will add the SwiftLint binaries, its dependencies' binaries and the Swift binary
Note that this will add the SwiftLint binaries, its dependencies' binaries, and the Swift binary
library distribution to the `Pods/` directory, so checking in this directory to SCM such as
git is discouraged.
@ -58,22 +57,77 @@ You can also install SwiftLint by downloading `SwiftLint.pkg` from the
[latest GitHub release](https://github.com/realm/SwiftLint/releases/latest) and
running it.
### Compiling from source:
### Installing from source:
You can also build from source by cloning this project and running
`script/bootstrap; make install` (Xcode 11.0 or later).
You can also build and install from source by cloning this project and running
`make install` (Xcode 13.3 or later).
### Known Installation Issues On MacOS Before 10.14.4
### Using Bazel
Starting with [SwiftLint 0.32.0](https://github.com/realm/SwiftLint/releases/tag/0.32.0), if you get
an error similar to `dyld: Symbol not found: _$s11SubSequenceSlTl` when running SwiftLint,
you'll need to install the [Swift 5 Runtime Support for Command Line Tools](https://support.apple.com/kb/DL1998).
Put this in your `MODULE.bazel`:
Alternatively, you can:
```bzl
bazel_dep(name = "swiftlint", version = "0.50.4", repo_name = "SwiftLint")
```
* Update to macOS 10.14.4 or later
* Install Xcode 10.2 or later at `/Applications/Xcode.app`
* Rebuild SwiftLint from source using Xcode 10.2 or later
SwiftLint는 스위프트 스타일 및 컨벤션을 강제하기 위한 도구로, [GitHub 스위프트 스타일 가이드](https://github.com/github/swift-style-guide)에 대략적인 기반을 두고 있습니다.
SwiftLint는 스위프트 스타일 및 컨벤션을 강제하기 위한 도구로, [Kodeco 스위프트 스타일 가이드](https://github.com/kodecocodes/swift-style-guide)에 대략적인 기반을 두고 있습니다.
SwiftLint는 좀 더 정확한 결과를 위해 [Clang](http://clang.llvm.org)과 [SourceKit](http://www.jpsim.com/uncovering-sourcekit)에 연결하여 소스 파일의 [AST](http://clang.llvm.org/docs/IntroductionToTheClangAST.html) 표현을 사용합니다.
이를 실행하면 다음번 `pod install` 실행시 SwiftLint 바이너리 및 `Pods/`에 있는 디펜던시들을 다운로드하고, Script Build Phases에서 `${PODS_ROOT}/SwiftLint/swiftlint` 명령을 사용할 수 있게 됩니다.
이를 실행하면 다음번 `pod install` 실행시 SwiftLint 바이너리 및 `Pods/`에 있는 디펜던시들을 다운로드하고, Script Build Phases에서 `${PODS_ROOT}/SwiftLint/swiftlint` 명령을 사용할 수 있게 됩니다.
CocoaPods를 사용하면 최신 버전 외에도 SwiftLint의 특정 버전을 설치할 수 있기 때문에 이 방법을 권장합니다. (Homebrew는 최신 버전만 설치 가능)
이렇게 했을때 SwiftLint 바이너리 및 그에 종속된 바이너리들과 스위프트 바이너리까지 `Pods/` 디렉토리에 추가되기 때문에, git 등의 SCM에 이런 디렉토리들을 체크인하는 것은 권장하지 않습니다.
이렇게 했을때 SwiftLint 바이너리 및 그에 종속된 바이너리들과 스위프트 바이너리까지 `Pods/` 디렉터리에 추가되기 때문에, git 등의 SCM에 이런 디렉터리들을 체크인하는 것은 권장하지 않습니다.
### [Mint](https://github.com/yonaskolb/mint)를 사용하는 경우:
```
@ -44,7 +44,7 @@ $ mint install realm/SwiftLint
### 소스를 직접 컴파일하는 경우:
본 프로젝트를 클론해서 빌드할 수도 있습니다. `git submodule update --init --recursive; make install` 명령을 사용합니다. (Xcode 10.2 이후 버전)
본 프로젝트를 클론해서 빌드할 수도 있습니다. `make install` 명령을 사용합니다. (Xcode 12.5 이후 버전)
## 사용 방법
@ -56,7 +56,7 @@ $ mint install realm/SwiftLint
### Xcode
SwiftLint를 Xcode 스킴에 통합하여 IDE 상에 경고나 에러를 표시할 수 있습니다. "Run Script Phase"를 새로 만들고 아래 스크립트를 추가하기만 하면 됩니다.
SwiftLint를 Xcode 프로젝트에 통합하여 IDE 상에 경고나 에러를 표시할 수 있습니다. 프로젝트의 파일 내비게이터에서 타겟 앱을 선택 후 "Build Phases" 탭으로 이동합니다. + 버튼을 클릭한 후 "Run Script Phase"를 선택합니다. 그 후 아래 스크립트를 추가하기만 하면 됩니다.
```bash
if which swiftlint >/dev/null; then
@ -68,6 +68,34 @@ fi

만약, 애플 실리콘 환경에서 Homebrew를 통해 SwiftLint를 설치했다면, 아마도 다음과 같은 경고를 겪었을 것입니다.
> warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint
그 이유는, 애플 실리콘 기반 맥에서 Homebrew는 기본적으로 바이너리들을 `/opt/homebrew/bin`에 저장하기 때문입니다. SwiftLint가 어디 있는지 찾는 것을 Xcode에 알려주기 위해, build phase에서 `/opt/homebrew/bin`를 `PATH` 환경 변수에 동시에 추가하여야 합니다.
```bash
if [[ "$(uname -m)" == arm64 ]]; then
export PATH="/opt/homebrew/bin:$PATH"
fi
if which swiftlint > /dev/null; then
swiftlint
else
echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi
```
혹은 아래와 같이 `/usr/local/bin`에 심볼릭 링크를 생성하여 실제 바이너리가 있는 곳으로 포인팅할 수 있습니다. :
당신은 SwiftLint phase를 'Compile Sources' 단계 직전으로 옮겨 컴파일 전에 에러를 빠르게 찾고 싶어 할 것입니다. 하지만, SwiftLint는 컴파일러의 구문 분석 단계를 완벽히 수행하는 유효한 Swift 코드를 실행하기 위해 설계되었습니다. 따라서, 'Compile Sources' 전에 SwiftLint를 실행하면 일부 부정확한 오류가 발생할 수도 있습니다.
만약 당신은 위반 사항(violations)을 동시에 수정하는 것을 원한다면, 스크립트에 `swiftlint` 대신 `swiftlint --fix && swiftlint`을 적어야 합니다. 이는 프로젝트의 수정 가능한 모든 위반 사항들이 수정되고 나머지 위반 사항에 대한 경고가 표시된다는 것을 의미합니다.
CocoaPods를 사용해서 설치한 경우는 아래 스크립트를 대신 사용합니다.
```bash
@ -95,7 +123,7 @@ fastlane 과정에서 SwiftLint를 사용하려면 [공식적인 fastlane 액션
```ruby
swiftlint(
mode: :lint, # SwiftLint 모드: :lint (디폴트) 아니면 :autocorrect
executable: "Pods/SwiftLint/swiftlint", # SwiftLint 바이너리 경로 (선택 가능). CocoaPods를 사용해서 설치한 경우는 이 옾션이 중요합니다
executable: "Pods/SwiftLint/swiftlint", # SwiftLint 바이너리 경로 (선택 가능). CocoaPods를 사용해서 설치한 경우는 이 옵션이 중요합니다
output_file: "swiftlint.result.json", # 결과 파일의 경로 (선택 가능)
reporter: "json", # 보고 유형 (선택 가능)
config_file: ".swiftlint-ci.yml", # 설정 파일의 경로 (선택 가능)
@ -116,16 +144,16 @@ Available commands:
version Display the current version of SwiftLint
```
스위프트 파일이 있는 디렉토리에서 `swiftlint`를 실행합니다. 디렉토리는 재귀적으로 탐색됩니다.
스위프트 파일이 있는 디렉터리에서 `swiftlint`를 실행합니다. 디렉터리는 재귀적으로 탐색됩니다.
`lint`나 `autocorrect`를 사용할 때 여러 파일(예를 들면, [`ExtraBuildPhase`](https://github.com/norio-nomura/ExtraBuildPhase) 플러그인에 의해 Xcode가 변경한 파일들 혹은 `git ls-files -m` 명령으로 인해 작업 트리에서 변경된 파일들)을 지정하려면 `--use-script-input-files` 옵션을 넘기고 다음 인스턴스 변수들을 설정하면 됩니다. `SCRIPT_INPUT_FILE_COUNT` and