The current algorithm is like "collect all included files and subtract all excluded files".
Collecting all included and all excluded files relies on the file system. This can become slow
when the patterns used to exclude files resolve to a large number of files.
The new approach only collects all lintable files and checks them against the exclude patterns.
This can be done by in-memory string-regex-match and does therefore not require file system accesses.
The new implementation also no longer traverses directories that already match an exclude pattern.
(cherry picked from commit 152355e36f)
At least ensure it compiles just fine on Windows.
* build: add CryptoSwift dependency for Windows
* SwiftLintBuiltInRules: treat Windows similar to Linux wrt `NSDataDetector`
* SwiftLintCore: initial pass for Windows support
Add some Windows specific handling for the paths in SwiftLintCore. The
one piece that this change does not cover is the handling of `glob` as
that is not an ISO C standard function and as such there is no `glob` on
Windows. This will be worked through separately.
* swiftlint: add a Windows port
This enables building the swiftlint command on Windows. There is no
system ioctl for terminal access, instead, we can use the Win32 Console
API surface to query the console size. In the case of a failure, assume
the width to be 80-columns (as the standard VGA console is 80x25).
* WIP/SwiftLintCore: port the `glob` function to Windows
Windows does not support `glob` as a standard C library function as that
is not part of the C standard. Attempt to emulate that through the use
of `FindFirstFileW` and `FindNextFile` to iterate the matching files
given a pattern. This should allow us to start enumerating the files as
if we had `glob` available.
The current algorithm is like "collect all included files and subtract all excluded files".
Collecting all included and all excluded files relies on the file system. This can become slow
when the patterns used to exclude files resolve to a large number of files.
The new approach only collects all lintable files and checks them against the exclude patterns.
This can be done by in-memory string-regex-match and does therefore not require file system accesses.
Ideally, SwiftLintCore would some day only contain components
that are needed to define rules. Consequently, it would be the
only bundle required to import for (external) rule development.
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.
* 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
* 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
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.
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 bumps the minimum version required to build SwiftLint to 4.2. The primary motivating factor to drop support for Swift 4.0-4.1.x is that SwiftLint now uses CryptoSwift, which requires 4.2.
* Add changelog entry
* Remove --allow-warnings flag from CocoaPods commands
* Update CryptoSwift to 0.13.0
* Migrate to Swift 4.2
* Remove CircleCI tests for Swift < 4.2
* Update English and Chinese README
Korean README doesn't yet have a version table like this.
* Update gems
* Add changelog entry for fixed compiler warnings
* Update CocoaPods to 1.6.0.beta.2
To work around https://github.com/CocoaPods/CocoaPods/issues/7708
The MIT license doesn't require that all files be prepended with this
licensing or copyright information. Realm confirmed that they're ok with this
change. This will enable some companies to contribute to SwiftLint and the
date & authorship information will remain accessible via git source control.