Compare commits
152 Commits
Author | SHA1 | Date |
---|---|---|
![]() |
3ec9bc85bc | |
![]() |
f5ea2492dc | |
![]() |
b89e43a799 | |
![]() |
c8cd311615 | |
![]() |
ba42a6aa36 | |
![]() |
83ab977a1b | |
![]() |
f12b8d66d3 | |
![]() |
e29de7a99f | |
![]() |
d32bf2b879 | |
![]() |
e5cf99088b | |
![]() |
7462187191 | |
![]() |
23326fc433 | |
![]() |
156f6aabc8 | |
![]() |
43190834c5 | |
![]() |
f1d5a55658 | |
![]() |
c735e6320f | |
![]() |
2f9997e2cc | |
![]() |
8f3eea06d3 | |
![]() |
a53a1f052b | |
![]() |
704c9ae116 | |
![]() |
521df18fdb | |
![]() |
a2ba0a0626 | |
![]() |
1094a3b70e | |
![]() |
754127924f | |
![]() |
3f039f26d5 | |
![]() |
671589b1d4 | |
![]() |
d938b2d3c3 | |
![]() |
7fd22e0d6e | |
![]() |
07740506b5 | |
![]() |
26d06bcebb | |
![]() |
fe312a06fe | |
![]() |
d73970e9d7 | |
![]() |
c0ea9d1925 | |
![]() |
405113f793 | |
![]() |
f4987071f0 | |
![]() |
306dec0fcc | |
![]() |
4d4a330d46 | |
![]() |
1e73835e83 | |
![]() |
866001db2f | |
![]() |
34f5ffa7f7 | |
![]() |
1b1b19a902 | |
![]() |
15a18fd4e8 | |
![]() |
5802fd99b1 | |
![]() |
e7bf813f15 | |
![]() |
3cf9585b2e | |
![]() |
8827fca693 | |
![]() |
9f7c57b719 | |
![]() |
73acbaf6d5 | |
![]() |
5616d858bc | |
![]() |
6cdb0aa689 | |
![]() |
7483e61615 | |
![]() |
87e230ce87 | |
![]() |
7f3b93147a | |
![]() |
7501d44b69 | |
![]() |
0ffe0c5911 | |
![]() |
c99a4286b8 | |
![]() |
8d5700afca | |
![]() |
1fa8e484c4 | |
![]() |
9e15e37255 | |
![]() |
97259e24d0 | |
![]() |
eb6d50a04c | |
![]() |
9c1678968f | |
![]() |
fa32fbc4f0 | |
![]() |
8822d40687 | |
![]() |
c0cf1bf5c9 | |
![]() |
444653bfd5 | |
![]() |
9138213121 | |
![]() |
6fd5f98d38 | |
![]() |
bc18ff14e3 | |
![]() |
5e15039554 | |
![]() |
7756793356 | |
![]() |
f0138ea1df | |
![]() |
6a2e973de3 | |
![]() |
e86c06c390 | |
![]() |
6b094dd711 | |
![]() |
9054ec0658 | |
![]() |
71b89e66de | |
![]() |
a7bc9e20c7 | |
![]() |
eaf34d7204 | |
![]() |
86d60400c1 | |
![]() |
740572f049 | |
![]() |
3541ef4d02 | |
![]() |
39a05f2c35 | |
![]() |
711d92e26f | |
![]() |
d8dfc3c937 | |
![]() |
3a2bb15ca3 | |
![]() |
a7e3909c6a | |
![]() |
72c2a5488d | |
![]() |
ea56405983 | |
![]() |
9c414932d8 | |
![]() |
8a21549ca9 | |
![]() |
4abcf5f0dd | |
![]() |
b2a4c9fcb9 | |
![]() |
603fff9a82 | |
![]() |
2544dc79d3 | |
![]() |
ea6b3b4d64 | |
![]() |
172b8b8a94 | |
![]() |
4c04cdafa7 | |
![]() |
165172e0fa | |
![]() |
3f52acd0a2 | |
![]() |
e14a73438f | |
![]() |
817de197d5 | |
![]() |
214a749ace | |
![]() |
fd4f9afb08 | |
![]() |
c241935635 | |
![]() |
46ff727a13 | |
![]() |
dc89109622 | |
![]() |
9c2525139a | |
![]() |
d601917e40 | |
![]() |
498b4c8fbe | |
![]() |
69fadb6918 | |
![]() |
f866ec32b1 | |
![]() |
6d51459323 | |
![]() |
21dc766c93 | |
![]() |
0f802f766a | |
![]() |
fbbccf9db8 | |
![]() |
8b72eb0406 | |
![]() |
c22d60fac0 | |
![]() |
1892c846b0 | |
![]() |
41290a23d3 | |
![]() |
5814ec1a1a | |
![]() |
f9b0e9f0af | |
![]() |
3ef44cf742 | |
![]() |
5aed7ce95c | |
![]() |
97fd216455 | |
![]() |
f127ba14dd | |
![]() |
74b82daba0 | |
![]() |
8c617d7412 | |
![]() |
a4f4680442 | |
![]() |
62b2914271 | |
![]() |
1b0f37c6f6 | |
![]() |
5226725689 | |
![]() |
e361e14c90 | |
![]() |
70a56a1420 | |
![]() |
409f117da9 | |
![]() |
7fe7bb28d9 | |
![]() |
bb11e6a0a7 | |
![]() |
eee97a7b2b | |
![]() |
cf1e2e27dc | |
![]() |
a2facce70c | |
![]() |
bd444fcd77 | |
![]() |
ee849bcb10 | |
![]() |
6d4bc78cb4 | |
![]() |
16e2bb0f18 | |
![]() |
b0cbb440c3 | |
![]() |
58a07eb452 | |
![]() |
82491e6f84 | |
![]() |
3d15419adb | |
![]() |
6a09af169e | |
![]() |
7dad240ea7 | |
![]() |
ca43d2359b | |
![]() |
da27f1c7fd |
3
.bazelrc
3
.bazelrc
|
@ -5,6 +5,9 @@ try-import %workspace%/user.bazelrc
|
|||
|
||||
build --macos_minimum_os=12.0 --host_macos_minimum_os=12.0
|
||||
build --disk_cache=~/.bazel_cache
|
||||
build --experimental_remote_cache_compression
|
||||
build --experimental_remote_build_event_upload=minimal
|
||||
build --nolegacy_important_outputs
|
||||
build --swiftcopt=-warnings-as-errors
|
||||
|
||||
build:release \
|
||||
|
|
|
@ -1 +1 @@
|
|||
6.1.1
|
||||
6.2.0
|
||||
|
|
|
@ -11,11 +11,19 @@ steps:
|
|||
- swift test --parallel -Xswiftc -DDISABLE_FOCUSED_EXAMPLES
|
||||
- label: "Danger"
|
||||
commands:
|
||||
- echo "--- Build Danger"
|
||||
- bazel build //tools:danger
|
||||
- echo "--- Install Bundler"
|
||||
- gem install bundler
|
||||
- echo "--- Bundle Install"
|
||||
- bundle install
|
||||
- echo "+++ Run Danger"
|
||||
- ./bazel-bin/tools/danger --verbose
|
||||
- bundle exec danger --verbose
|
||||
- label: "TSan Tests"
|
||||
commands:
|
||||
- echo "+++ Test"
|
||||
- bazel test --test_output=streamed --build_tests_only --features=tsan --test_timeout=1000 //Tests/...
|
||||
- bazel test --test_output=errors --build_tests_only --features=tsan --test_timeout=1000 //Tests/...
|
||||
- label: "Sourcery"
|
||||
commands:
|
||||
- echo "+++ Run Sourcery"
|
||||
- make --always-make sourcery
|
||||
- echo "+++ Diff Files"
|
||||
- git diff --quiet HEAD
|
||||
|
|
|
@ -9,7 +9,7 @@ on:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
name: update_swift_syntax
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# Mondays at 1pm UTC (9am EDT)
|
||||
- cron: "0 13 * * 1"
|
||||
|
||||
jobs:
|
||||
update_swift_syntax:
|
||||
runs-on: macos-12
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v3
|
||||
- name: Update SwiftSyntax
|
||||
id: update-swift-syntax
|
||||
run: ./tools/update-swift-syntax.sh
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Create PR
|
||||
if: steps.update-swift-syntax.outputs.needs_update == 'true'
|
||||
uses: peter-evans/create-pull-request@923ad837f191474af6b1721408744feb989a4c27
|
||||
with:
|
||||
title: Update SwiftSyntax
|
||||
body: |
|
||||
Diff: https://github.com/apple/swift-syntax/compare/${{ steps.update-swift-syntax.outputs.old_tag }}...${{ steps.update-swift-syntax.outputs.new_tag }}
|
||||
commit-message: Update SwiftSyntax
|
||||
delete-branch: true
|
||||
branch: update-swift-syntax
|
||||
branch-suffix: timestamp
|
|
@ -1,4 +1,4 @@
|
|||
module: SwiftLintFramework
|
||||
module: SwiftLintCore
|
||||
author: JP Simard, SwiftLint Contributors
|
||||
author_url: https://jpsim.com
|
||||
root_url: https://realm.github.io/SwiftLint/
|
||||
|
@ -7,13 +7,14 @@ github_file_prefix: https://github.com/realm/SwiftLint/tree/main
|
|||
swift_build_tool: spm
|
||||
theme: fullwidth
|
||||
clean: true
|
||||
copyright: '© 2022 [JP Simard](https://jpsim.com) under MIT.'
|
||||
copyright: '© 2023 [JP Simard](https://jpsim.com) under MIT.'
|
||||
|
||||
documentation: rule_docs/*.md
|
||||
hide_unlisted_documentation: true
|
||||
custom_categories_unlisted_prefix: ''
|
||||
exclude:
|
||||
- Source/SwiftLintFramework/Rules/**/*.swift
|
||||
# TODO: Document extensions
|
||||
- Source/SwiftLintCore/Extensions/*.swift
|
||||
custom_categories:
|
||||
- name: Rules
|
||||
children:
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
|
||||
/// The rule list containing all available rules built into SwiftLint.
|
||||
let builtInRules: [Rule.Type] = [
|
||||
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 %}
|
||||
{% endfor %}]
|
||||
|
||||
/// The rule list containing all available rules built into SwiftLint as well as native custom rules.
|
||||
public let primaryRuleList = RuleList(rules: builtInRules + extraRules())
|
|
@ -1,14 +1,14 @@
|
|||
@testable import SwiftLintBuiltInRules
|
||||
@_spi(TestHelper)
|
||||
@testable import SwiftLintFramework
|
||||
@testable import SwiftLintCore
|
||||
import SwiftLintTestHelpers
|
||||
import XCTest
|
||||
|
||||
// swiftlint:disable:next blanket_disable_command
|
||||
// swiftlint:disable file_length single_test_class type_name
|
||||
|
||||
{% for rule in types.structs %}
|
||||
{% if rule.name|hasSuffix:"Rule" %}
|
||||
class {{ rule.name }}GeneratedTests: XCTestCase {
|
||||
class {{ rule.name }}GeneratedTests: SwiftLintTestCase {
|
||||
func testWithDefaultConfiguration() {
|
||||
verifyRule({{ rule.name }}.description)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
/// The reporters list containing all the reporters built into SwiftLint.
|
||||
public let reportersList: [Reporter.Type] = [
|
||||
{% for reporter in types.structs where reporter.name|hasSuffix:"Reporter" %}
|
||||
{{ reporter.name }}.self{% if not forloop.last %},{% endif %}
|
||||
{% endfor %}
|
||||
]
|
|
@ -35,15 +35,20 @@ disabled_rules:
|
|||
- multiline_parameters
|
||||
- multiline_parameters_brackets
|
||||
- no_extension_access_modifier
|
||||
- no_fallthrough_only
|
||||
- no_grouping_extension
|
||||
- no_magic_numbers
|
||||
- prefer_nimble
|
||||
- prefer_self_in_static_references
|
||||
- prefixed_toplevel_constant
|
||||
- redundant_self_in_closure
|
||||
- required_deinit
|
||||
- self_binding
|
||||
- sorted_enum_cases
|
||||
- strict_fileprivate
|
||||
- superfluous_else
|
||||
- switch_case_on_newline
|
||||
- todo
|
||||
- trailing_closure
|
||||
- type_contents_order
|
||||
- unused_capture_list
|
||||
|
@ -60,16 +65,24 @@ number_separator:
|
|||
minimum_length: 5
|
||||
file_name:
|
||||
excluded:
|
||||
- SwiftSyntax+SwiftLint.swift
|
||||
- Exports.swift
|
||||
- GeneratedTests.swift
|
||||
- SwiftSyntax+SwiftLint.swift
|
||||
- TestHelpers.swift
|
||||
|
||||
balanced_xctest_lifecycle: &unit_test_configuration
|
||||
test_parent_classes:
|
||||
- SwiftLintTestCase
|
||||
- XCTestCase
|
||||
empty_xctest_method: *unit_test_configuration
|
||||
single_test_class: *unit_test_configuration
|
||||
|
||||
function_body_length: 60
|
||||
type_body_length: 400
|
||||
|
||||
custom_rules:
|
||||
rule_id:
|
||||
included: Source/SwiftLintFramework/Rules/.+/\w+\.swift
|
||||
included: Source/SwiftLintBuiltInRules/Rules/.+/\w+\.swift
|
||||
name: Rule ID
|
||||
message: Rule IDs must be all lowercase, snake case and not end with `rule`
|
||||
regex: ^\s+identifier:\s*("\w+_rule"|"\S*[^a-z_]\S*")
|
||||
|
@ -92,3 +105,4 @@ custom_rules:
|
|||
unused_import:
|
||||
always_keep_imports:
|
||||
- SwiftSyntaxBuilder # we can't detect uses of string interpolation of swift syntax nodes
|
||||
- SwiftLintFramework # now that this is a wrapper around other modules, don't treat as unused
|
||||
|
|
72
BUILD
72
BUILD
|
@ -13,24 +13,62 @@ load(
|
|||
# Targets
|
||||
|
||||
swift_library(
|
||||
name = "SwiftLintFramework",
|
||||
srcs = glob(
|
||||
["Source/SwiftLintFramework/**/*.swift"],
|
||||
exclude = ["Source/SwiftLintFramework/Rules/ExcludedFromBazel/ExtraRules.swift"],
|
||||
) + ["@swiftlint_extra_rules//:extra_rules"],
|
||||
module_name = "SwiftLintFramework",
|
||||
name = "SwiftLintCore",
|
||||
srcs = glob(["Source/SwiftLintCore/**/*.swift"]),
|
||||
module_name = "SwiftLintCore",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"@SwiftSyntax//:SwiftIDEUtils_opt",
|
||||
"@SwiftSyntax//:SwiftOperators_opt",
|
||||
"@SwiftSyntax//:SwiftParserDiagnostics_opt",
|
||||
"@SwiftSyntax//:SwiftSyntaxBuilder_opt",
|
||||
"@SwiftSyntax//:SwiftSyntax_opt",
|
||||
"@com_github_jpsim_sourcekitten//:SourceKittenFramework",
|
||||
"@com_github_apple_swift_syntax//:optlibs",
|
||||
"@sourcekitten_com_github_jpsim_yams//:Yams",
|
||||
"@swiftlint_com_github_scottrhoyt_swifty_text_table//:SwiftyTextTable",
|
||||
] + select({
|
||||
"@platforms//os:linux": ["@com_github_krzyzanowskim_cryptoswift//:CryptoSwift"],
|
||||
"//conditions:default": [],
|
||||
"//conditions:default": [":DyldWarningWorkaround"],
|
||||
}),
|
||||
)
|
||||
|
||||
swift_library(
|
||||
name = "SwiftLintBuiltInRules",
|
||||
srcs = glob(["Source/SwiftLintBuiltInRules/**/*.swift"]),
|
||||
module_name = "SwiftLintBuiltInRules",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":SwiftLintCore",
|
||||
],
|
||||
)
|
||||
|
||||
swift_library(
|
||||
name = "SwiftLintExtraRules",
|
||||
srcs = [
|
||||
"Source/SwiftLintExtraRules/Exports.swift",
|
||||
"@swiftlint_extra_rules//:extra_rules",
|
||||
],
|
||||
module_name = "SwiftLintExtraRules",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":SwiftLintCore",
|
||||
],
|
||||
)
|
||||
|
||||
swift_library(
|
||||
name = "SwiftLintFramework",
|
||||
srcs = glob(
|
||||
["Source/SwiftLintFramework/**/*.swift"],
|
||||
),
|
||||
module_name = "SwiftLintFramework",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":SwiftLintBuiltInRules",
|
||||
":SwiftLintCore",
|
||||
":SwiftLintExtraRules",
|
||||
],
|
||||
)
|
||||
|
||||
swift_library(
|
||||
name = "swiftlint.library",
|
||||
srcs = glob(["Source/swiftlint/**/*.swift"]),
|
||||
|
@ -64,6 +102,21 @@ apple_universal_binary(
|
|||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "DyldWarningWorkaroundSources",
|
||||
srcs = [
|
||||
"Source/DyldWarningWorkaround/DyldWarningWorkaround.c",
|
||||
"Source/DyldWarningWorkaround/include/objc_dupclass.h",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "DyldWarningWorkaround",
|
||||
srcs = ["//:DyldWarningWorkaroundSources"],
|
||||
includes = ["Source/DyldWarningWorkaround/include"],
|
||||
alwayslink = True,
|
||||
)
|
||||
|
||||
# Linting
|
||||
|
||||
filegroup(
|
||||
|
@ -80,9 +133,10 @@ filegroup(
|
|||
filegroup(
|
||||
name = "release_files",
|
||||
srcs = [
|
||||
"MODULE.bazel",
|
||||
"BUILD",
|
||||
"LICENSE",
|
||||
"MODULE.bazel",
|
||||
"//:DyldWarningWorkaroundSources",
|
||||
"//:LintInputs",
|
||||
"//Tests:BUILD",
|
||||
"//bazel:release_files",
|
||||
|
|
252
CHANGELOG.md
252
CHANGELOG.md
|
@ -1,3 +1,243 @@
|
|||
## Main
|
||||
|
||||
#### Breaking
|
||||
|
||||
* None.
|
||||
|
||||
#### Experimental
|
||||
|
||||
* None.
|
||||
|
||||
#### Enhancements
|
||||
|
||||
* Mention a rule's identifier in the console message that is printed when the
|
||||
rule's associated configuration entry contains invalid values.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
|
||||
* Silence `xct_specific_matcher` rule on "one argument asserts" if there are
|
||||
potential types or tuples involved in the comparison as types and tuples do
|
||||
not conform to `Equatable`.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[#4990](https://github.com/realm/SwiftLint/issues/4990)
|
||||
|
||||
* Add `grouping` option to the `sorted_imports` rule allowing
|
||||
to sort groups of imports defined by their preceding attributes
|
||||
(e.g. `@testable`, `@_exported`, ...).
|
||||
[hiltonc](https://github.com/hiltonc)
|
||||
|
||||
* Do not trigger `redundant_self_in_closure` rule when another idenfier `x` in
|
||||
scope shadows the field accessed by `self.x` to avoid semantical changes.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[#5010](https://github.com/realm/SwiftLint/issues/5010)
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* The option `validates_start_with_lowercase` can now be disabled by setting it
|
||||
to `off`.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[#5036](https://github.com/realm/SwiftLint/issues/5036)
|
||||
|
||||
* Do not trigger `prefer_self_in_static_references` rule on `typealias`
|
||||
declarations in classes.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[#5009](https://github.com/realm/SwiftLint/issues/5009)
|
||||
|
||||
* Do not trigger `prefer_self_in_static_references` rule on collection types in
|
||||
classes, but on initializers like `[C]()` in all types.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[#5042](https://github.com/realm/SwiftLint/issues/5042)
|
||||
|
||||
* Fix false positives on `redundant_objc_attribute` rule for enums
|
||||
and private members.
|
||||
[Martin Redington](https://github.com/mildm8nnered)
|
||||
[#4633](https://github.com/realm/SwiftLint/issues/4633)
|
||||
|
||||
* Fix autocorrect for `CGIntersectionRect` in `legacy_cggeometry_functions`
|
||||
rule.
|
||||
[Haoocen](https://github.com/Haoocen)
|
||||
[#5023](https://github.com/realm/SwiftLint/pull/5023)
|
||||
|
||||
* Fix false positives on `sorted_first_last` rule when `first`/`last` have
|
||||
a predicate.
|
||||
[woxtu](https://github.com/woxtu)
|
||||
[#3023](https://github.com/realm/SwiftLint/issues/3023)
|
||||
|
||||
## 0.52.2: Crisper Clearer Pleats
|
||||
|
||||
#### Breaking
|
||||
|
||||
* None.
|
||||
|
||||
#### Experimental
|
||||
|
||||
* None.
|
||||
|
||||
#### Enhancements
|
||||
|
||||
* Exclude simple assignments of the form `self.x = x` from being reported by
|
||||
the `redundant_self_in_closure` rule.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[#4988](https://github.com/realm/SwiftLint/issues/4988)
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* Make `unhandled_throwing_task` opt-in instead of enabled by default. The rule
|
||||
is still prone to false positives at this point, so this makes enabling the
|
||||
rule a conscious decision by end-users.
|
||||
[JP Simard](https://github.com/jpsim)
|
||||
[#4987](https://github.com/realm/SwiftLint/issues/4987)
|
||||
|
||||
* Fix `unhandled_throwing_task` false positives when the `Task` is returned or
|
||||
where the throwing code is handled in a `Result` initializer.
|
||||
[JP Simard](https://github.com/jpsim)
|
||||
[#4987](https://github.com/realm/SwiftLint/issues/4987)
|
||||
|
||||
## 0.52.1: Crisp Clear Pleats
|
||||
|
||||
#### Breaking
|
||||
|
||||
* None.
|
||||
|
||||
#### Experimental
|
||||
|
||||
* None.
|
||||
|
||||
#### Enhancements
|
||||
|
||||
* None.
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* Let the `validates_start_with_lowercase` option in name configurations
|
||||
expect a severity (warning or error). Not setting it disables the check.
|
||||
Boolean values are now deprecated. A `true` value enables the check as an
|
||||
error for the time being to keep the previous behavior.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[#2180](https://github.com/realm/SwiftLint/issues/2180)
|
||||
|
||||
* Fixed a false positive in `unhandled_throwing_task`.
|
||||
[kylebshr](https://github.com/kylebshr)
|
||||
[#4984](https://github.com/realm/SwiftLint/issues/4984)
|
||||
|
||||
* Fix Bazel release tarball for compiling on macOS.
|
||||
[JP Simard](https://github.com/jpsim)
|
||||
[#4985](https://github.com/realm/SwiftLint/issues/4985)
|
||||
|
||||
## 0.52.0: Crisp Clear Pleats
|
||||
|
||||
#### Breaking
|
||||
|
||||
* The `attributes` rule now expects attributes with arguments to be placed
|
||||
on their own line above the declaration they are supposed to influence.
|
||||
This applies to attributes with any kinds of arguments including single
|
||||
key path arguments which were previously handled in a different way. This
|
||||
behavior can be turned off by setting `attributes_with_arguments_always_on_line_above`
|
||||
to `false.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[#4843](https://github.com/realm/SwiftLint/issues/4843)
|
||||
|
||||
* The internal module structure for SwiftLint has changed to split the
|
||||
monolithic `SwiftLintFramework` into new `SwiftLintCore` for core linter
|
||||
infrastructure, `SwiftLintBuiltInRules` for built-in rules and
|
||||
`SwiftLintExtraRules` to add your own native rules to SwiftLint.
|
||||
[JP Simard](https://github.com/jpsim)
|
||||
|
||||
#### Experimental
|
||||
|
||||
* None.
|
||||
|
||||
#### Enhancements
|
||||
|
||||
* Add new `superfluous_else` rule that triggers on `if`-statements when an
|
||||
attached `else`-block can be removed, because all branches of the previous
|
||||
`if`-block(s) would certainly exit the current scope already.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
|
||||
* Add `sorted_enum_cases` rule which warns when enum cases are not sorted.
|
||||
[kimdv](https://github.com/kimdv)
|
||||
|
||||
* Add new `redundant_self_in_closure` rule that triggers in closures on
|
||||
explicitly used `self` when it's actually not needed due to:
|
||||
* Strongly captured `self` (`{ [self] in ... }`)
|
||||
* Closure used in a struct declaration (`self` can always be omitted)
|
||||
* Anonymous closures that are directly called (`{ ... }()`) as they are
|
||||
definitly not escaping
|
||||
* Weakly captured `self` with explicit unwrapping
|
||||
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[#59](https://github.com/realm/SwiftLint/issues/59)
|
||||
|
||||
* Extend `xct_specific_matcher` rule to check for boolean asserts on (un)equal
|
||||
comparisons. The rule can be configured with the matchers that should trigger
|
||||
rule violations. By default, all matchers trigger, but that can be limited to
|
||||
just `one-argument-asserts` or `two-argument-asserts`.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[JP Simard](https://github.com/jpsim)
|
||||
[#3726](https://github.com/realm/SwiftLint/issues/3726)
|
||||
|
||||
* Trigger `prefer_self_in_static_references` rule on more type references.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
|
||||
* Adds a new `reporters` command, to improve discoverability of reporters.
|
||||
[Martin Redington](https://github.com/mildm8nnered)
|
||||
[#4819](https://github.com/realm/SwiftLint/issues/4819)
|
||||
|
||||
* Adds `test_parent_classes` option to the `no_magic_numbers` rule.
|
||||
Violations within test classes will now be ignored by default.
|
||||
[Martin Redington](https://github.com/mildm8nnered)
|
||||
[#4896](https://github.com/realm/SwiftLint/issues/4896)
|
||||
|
||||
* Stop enforcing calls to super from the override functions `setUp()`,
|
||||
`tearDown()`, `setUpWithError()`, and `tearDownWithError()` in `XCTestCase`
|
||||
subclasses.
|
||||
[AndrewDMontgomery](https://github.com/andrewdmontgomery)
|
||||
[#4875](https://github.com/realm/SwiftLint/pull/4875)
|
||||
|
||||
* Prepend `warning: ` to error messages so that they show in Xcode.
|
||||
[whiteio](https://github.com/whiteio)
|
||||
[#4923](https://github.com/realm/SwiftLint/issues/4923)
|
||||
|
||||
* The `attributes` rule received a new boolean option
|
||||
`attributes_with_arguments_always_on_line_above` which is `true` by default.
|
||||
Setting it to `false` ensures that attributes with arguments like
|
||||
`@Persisted(primaryKey: true)` don't violate the rule if they are on the same
|
||||
line with the variable declaration.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[#4843](https://github.com/realm/SwiftLint/issues/4843)
|
||||
|
||||
* Add new `unhandled_throwing_task` rule that triggers when a Task with an
|
||||
implicit error type has unhandled trys or errors thrown inside its body.
|
||||
This results in errors being silently discarded, which may be unexpected.
|
||||
See this forum thread for more details: https://forums.swift.org/t/56066
|
||||
[kylebshr](https://github.com/kylebshr)
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* Fix `lower_acl_than_parent` rule rewriter by preserving leading whitespace.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[#4860](https://github.com/realm/SwiftLint/issues/4860)
|
||||
|
||||
* Ignore block comments in `let_var_whitespace` rule.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[#4871](https://github.com/realm/SwiftLint/issues/4871)
|
||||
|
||||
* Fix false positives in `indentation_width` rule.
|
||||
[Sven Münnich](https://github.com/svenmuennich)
|
||||
|
||||
* Do not trigger `reduce_boolean` on `reduce` methods with a first named
|
||||
argument that is different from `into`.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[#4894](https://github.com/realm/SwiftLint/issues/4894)
|
||||
|
||||
* Work around dyld warning about duplicate SwiftSyntax classes.
|
||||
[keith](https://github.com/keith)
|
||||
[#4782](https://github.com/realm/SwiftLint/issues/4782)
|
||||
|
||||
* Improve lint times of SwiftLintPlugin by moving the
|
||||
`excludedPaths(fileManager:)` operation out of the linting iterations.
|
||||
[andyyhope](https://github.com/andyyhope)
|
||||
[#4844](https://github.com/realm/SwiftLint/issues/4844)
|
||||
|
||||
## 0.51.0: bzllint
|
||||
|
||||
#### Breaking
|
||||
|
@ -11,6 +251,13 @@
|
|||
At the same time, make it an opt-in rule.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[#4615](https://github.com/realm/SwiftLint/issues/4615)
|
||||
|
||||
* Interpret strings in `excluded` option of `identifier_name`,
|
||||
`type_name` and `generic_type_name` rules as regular expression. Existing
|
||||
configurations should remain working without notice as long as they don't
|
||||
contain characters that must be escaped in regular expression.
|
||||
[Moly](https://github.com/kyounh12)
|
||||
[#4655](https://github.com/realm/SwiftLint/pull/4655)
|
||||
|
||||
#### Experimental
|
||||
|
||||
|
@ -45,11 +292,6 @@
|
|||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[#4707](https://github.com/realm/SwiftLint/issues/4707)
|
||||
|
||||
* Interpret strings in `excluded` option of `identifier_name`,
|
||||
`type_name` and `generic_type_name` rules as regex.
|
||||
[Moly](https://github.com/kyounh12)
|
||||
[#4655](https://github.com/realm/SwiftLint/pull/4655)
|
||||
|
||||
* Add new `direct_return` rule that triggers on `return` statements returning
|
||||
variables that have been declared in the statement before only.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
## Tutorial
|
||||
|
||||
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](https://vimeo.com/819268038).
|
||||
|
||||
## Pull Requests
|
||||
|
||||
All changes, no matter how trivial, must be done via pull request. Commits
|
||||
|
@ -58,7 +64,7 @@ $ make docker_test
|
|||
|
||||
## Rules
|
||||
|
||||
New rules should be added in the `Source/SwiftLintFramework/Rules` directory.
|
||||
New rules should be added in the `Source/SwiftLintBuiltInRules/Rules` directory.
|
||||
|
||||
Rules should conform to either the `Rule` or `ASTRule` protocols.
|
||||
|
||||
|
@ -98,11 +104,11 @@ configuration object via the `configuration` property:
|
|||
* If none of the provided `RuleConfiguration`s are applicable, you can create one
|
||||
specifically for your rule.
|
||||
|
||||
See [`ForceCastRule`](https://github.com/realm/SwiftLint/blob/main/Source/SwiftLintFramework/Rules/Idiomatic/ForceCastRule.swift)
|
||||
See [`ForceCastRule`](https://github.com/realm/SwiftLint/blob/main/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ForceCastRule.swift)
|
||||
for a rule that allows severity configuration,
|
||||
[`FileLengthRule`](https://github.com/realm/SwiftLint/blob/main/Source/SwiftLintFramework/Rules/Metrics/FileLengthRule.swift)
|
||||
[`FileLengthRule`](https://github.com/realm/SwiftLint/blob/main/Source/SwiftLintBuiltInRules/Rules/Metrics/FileLengthRule.swift)
|
||||
for a rule that has multiple severity levels,
|
||||
[`IdentifierNameRule`](https://github.com/realm/SwiftLint/blob/main/Source/SwiftLintFramework/Rules/Style/IdentifierNameRule.swift)
|
||||
[`IdentifierNameRule`](https://github.com/realm/SwiftLint/blob/main/Source/SwiftLintBuiltInRules/Rules/Style/IdentifierNameRule.swift)
|
||||
for a rule that allows name evaluation configuration:
|
||||
|
||||
``` yaml
|
||||
|
|
|
@ -16,7 +16,7 @@ has_app_changes = !modified_files.grep(/Source/).empty?
|
|||
has_test_changes = !modified_files.grep(/Tests/).empty?
|
||||
has_danger_changes = !modified_files.grep(/Dangerfile|tools\/oss-check|Gemfile/).empty?
|
||||
has_package_changes = !modified_files.grep(/Package\.swift/).empty?
|
||||
has_bazel_changes = !modified_files.grep(/\.bazelrc|\.bazelversion|WORKSPACE|bazel\/|BUILD/).empty?
|
||||
has_bazel_changes = !modified_files.grep(/\.bazelrc|\.bazelversion|WORKSPACE|bazel\/|BUILD|MODULE\.bazel/).empty?
|
||||
|
||||
# Add a CHANGELOG entry for app changes
|
||||
if !modified_files.include?('CHANGELOG.md') && has_app_changes
|
||||
|
|
74
Gemfile.lock
74
Gemfile.lock
|
@ -1,15 +1,14 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.5)
|
||||
CFPropertyList (3.0.6)
|
||||
rexml
|
||||
activesupport (6.1.7.3)
|
||||
activesupport (7.0.4.3)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
tzinfo (~> 2.0)
|
||||
zeitwerk (~> 2.3)
|
||||
addressable (2.8.1)
|
||||
addressable (2.8.4)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
algoliasearch (1.27.5)
|
||||
httpclient (~> 2.8, >= 2.8.3)
|
||||
|
@ -20,15 +19,15 @@ GEM
|
|||
cork
|
||||
nap
|
||||
open4 (~> 1.3)
|
||||
cocoapods (1.11.3)
|
||||
cocoapods (1.12.1)
|
||||
addressable (~> 2.8)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
cocoapods-core (= 1.11.3)
|
||||
cocoapods-core (= 1.12.1)
|
||||
cocoapods-deintegrate (>= 1.0.3, < 2.0)
|
||||
cocoapods-downloader (>= 1.4.0, < 2.0)
|
||||
cocoapods-downloader (>= 1.6.0, < 2.0)
|
||||
cocoapods-plugins (>= 1.0.0, < 2.0)
|
||||
cocoapods-search (>= 1.0.0, < 2.0)
|
||||
cocoapods-trunk (>= 1.4.0, < 2.0)
|
||||
cocoapods-trunk (>= 1.6.0, < 2.0)
|
||||
cocoapods-try (>= 1.1.0, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
escape (~> 0.0.4)
|
||||
|
@ -36,10 +35,10 @@ GEM
|
|||
gh_inspector (~> 1.0)
|
||||
molinillo (~> 0.8.0)
|
||||
nap (~> 1.0)
|
||||
ruby-macho (>= 1.0, < 3.0)
|
||||
ruby-macho (>= 2.3.0, < 3.0)
|
||||
xcodeproj (>= 1.21.0, < 2.0)
|
||||
cocoapods-core (1.11.3)
|
||||
activesupport (>= 5.0, < 7)
|
||||
cocoapods-core (1.12.1)
|
||||
activesupport (>= 5.0, < 8)
|
||||
addressable (~> 2.8)
|
||||
algoliasearch (~> 1.0)
|
||||
concurrent-ruby (~> 1.1)
|
||||
|
@ -61,58 +60,39 @@ GEM
|
|||
concurrent-ruby (1.2.2)
|
||||
cork (0.3.0)
|
||||
colored2 (~> 3.1)
|
||||
danger (8.6.1)
|
||||
danger (9.2.0)
|
||||
claide (~> 1.0)
|
||||
claide-plugins (>= 0.9.2)
|
||||
colored2 (~> 3.1)
|
||||
cork (~> 0.1)
|
||||
faraday (>= 0.9.0, < 2.0)
|
||||
faraday (>= 0.9.0, < 3.0)
|
||||
faraday-http-cache (~> 2.0)
|
||||
git (~> 1.7)
|
||||
kramdown (~> 2.3)
|
||||
kramdown-parser-gfm (~> 1.0)
|
||||
no_proxy_fix
|
||||
octokit (~> 4.7)
|
||||
octokit (~> 5.0)
|
||||
terminal-table (>= 1, < 4)
|
||||
escape (0.0.4)
|
||||
ethon (0.15.0)
|
||||
ethon (0.16.0)
|
||||
ffi (>= 1.15.0)
|
||||
faraday (1.10.2)
|
||||
faraday-em_http (~> 1.0)
|
||||
faraday-em_synchrony (~> 1.0)
|
||||
faraday-excon (~> 1.1)
|
||||
faraday-httpclient (~> 1.0)
|
||||
faraday-multipart (~> 1.0)
|
||||
faraday-net_http (~> 1.0)
|
||||
faraday-net_http_persistent (~> 1.0)
|
||||
faraday-patron (~> 1.0)
|
||||
faraday-rack (~> 1.0)
|
||||
faraday-retry (~> 1.0)
|
||||
faraday (2.7.4)
|
||||
faraday-net_http (>= 2.0, < 3.1)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-em_http (1.0.0)
|
||||
faraday-em_synchrony (1.0.0)
|
||||
faraday-excon (1.1.0)
|
||||
faraday-http-cache (2.4.1)
|
||||
faraday (>= 0.8)
|
||||
faraday-httpclient (1.0.1)
|
||||
faraday-multipart (1.0.4)
|
||||
multipart-post (~> 2)
|
||||
faraday-net_http (1.0.1)
|
||||
faraday-net_http_persistent (1.2.0)
|
||||
faraday-patron (1.0.0)
|
||||
faraday-rack (1.0.0)
|
||||
faraday-retry (1.0.3)
|
||||
faraday-net_http (3.0.2)
|
||||
ffi (1.15.5)
|
||||
fourflusher (2.3.1)
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.1.3)
|
||||
git (1.13.0)
|
||||
git (1.18.0)
|
||||
addressable (~> 2.8)
|
||||
rchardet (~> 1.8)
|
||||
httpclient (2.8.3)
|
||||
i18n (1.12.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jazzy (0.14.2)
|
||||
jazzy (0.14.3)
|
||||
cocoapods (~> 1.5)
|
||||
mustache (~> 1.1)
|
||||
open4 (~> 1.3)
|
||||
|
@ -122,7 +102,7 @@ GEM
|
|||
sassc (~> 2.1)
|
||||
sqlite3 (~> 1.3)
|
||||
xcinvoke (~> 0.3.0)
|
||||
json (2.6.2)
|
||||
json (2.6.3)
|
||||
kramdown (2.4.0)
|
||||
rexml
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
|
@ -130,19 +110,18 @@ GEM
|
|||
liferaft (0.0.6)
|
||||
minitest (5.18.0)
|
||||
molinillo (0.8.0)
|
||||
multipart-post (2.2.3)
|
||||
mustache (1.1.1)
|
||||
nanaimo (0.3.0)
|
||||
nap (1.1.0)
|
||||
netrc (0.11.0)
|
||||
no_proxy_fix (0.1.2)
|
||||
octokit (4.25.1)
|
||||
octokit (5.6.1)
|
||||
faraday (>= 1, < 3)
|
||||
sawyer (~> 0.9)
|
||||
open4 (1.3.4)
|
||||
public_suffix (4.0.7)
|
||||
rchardet (1.8.0)
|
||||
redcarpet (3.5.1)
|
||||
redcarpet (3.6.0)
|
||||
rexml (3.2.5)
|
||||
rouge (3.30.0)
|
||||
ruby-macho (2.5.1)
|
||||
|
@ -152,14 +131,14 @@ GEM
|
|||
sawyer (0.9.2)
|
||||
addressable (>= 2.3.5)
|
||||
faraday (>= 0.17.3, < 3)
|
||||
sqlite3 (1.4.4)
|
||||
sqlite3 (1.6.2-arm64-darwin)
|
||||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
typhoeus (1.4.0)
|
||||
ethon (>= 0.9.0)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
unicode-display_width (2.2.0)
|
||||
unicode-display_width (2.4.2)
|
||||
xcinvoke (0.3.0)
|
||||
liferaft (~> 0.0.6)
|
||||
xcodeproj (1.22.0)
|
||||
|
@ -169,11 +148,10 @@ GEM
|
|||
colored2 (~> 3.1)
|
||||
nanaimo (~> 0.3.0)
|
||||
rexml (~> 3.2.4)
|
||||
zeitwerk (2.6.7)
|
||||
|
||||
PLATFORMS
|
||||
arm64-darwin-21
|
||||
ruby
|
||||
arm64-darwin-22
|
||||
|
||||
DEPENDENCIES
|
||||
cocoapods
|
||||
|
@ -181,4 +159,4 @@ DEPENDENCIES
|
|||
jazzy
|
||||
|
||||
BUNDLED WITH
|
||||
2.3.8
|
||||
2.4.12
|
||||
|
|
11
MODULE.bazel
11
MODULE.bazel
|
@ -1,14 +1,15 @@
|
|||
module(
|
||||
name = "swiftlint",
|
||||
version = "0.51.0",
|
||||
version = "0.52.2",
|
||||
compatibility_level = 1,
|
||||
repo_name = "SwiftLint",
|
||||
)
|
||||
|
||||
bazel_dep(name = "bazel_skylib", version = "1.4.1", dev_dependency = True)
|
||||
bazel_dep(name = "platforms", version = "0.0.6")
|
||||
bazel_dep(name = "rules_apple", version = "2.2.0", repo_name = "build_bazel_rules_apple")
|
||||
bazel_dep(name = "rules_swift", version = "1.7.1", repo_name = "build_bazel_rules_swift")
|
||||
bazel_dep(name = "rules_xcodeproj", version = "1.3.3")
|
||||
bazel_dep(name = "rules_apple", version = "2.3.0", repo_name = "build_bazel_rules_apple")
|
||||
bazel_dep(name = "rules_swift", version = "1.8.0", repo_name = "build_bazel_rules_swift")
|
||||
bazel_dep(name = "rules_xcodeproj", version = "1.7.0")
|
||||
bazel_dep(name = "sourcekitten", version = "0.34.1", repo_name = "com_github_jpsim_sourcekitten")
|
||||
bazel_dep(name = "swift_argument_parser", version = "1.2.1", repo_name = "sourcekitten_com_github_apple_swift_argument_parser")
|
||||
bazel_dep(name = "yams", version = "5.0.5", repo_name = "sourcekitten_com_github_jpsim_yams")
|
||||
|
@ -16,7 +17,7 @@ bazel_dep(name = "yams", version = "5.0.5", repo_name = "sourcekitten_com_github
|
|||
swiftlint_repos = use_extension("//bazel:repos.bzl", "swiftlint_repos_bzlmod")
|
||||
use_repo(
|
||||
swiftlint_repos,
|
||||
"com_github_apple_swift_syntax",
|
||||
"SwiftSyntax",
|
||||
"com_github_johnsundell_collectionconcurrencykit",
|
||||
"com_github_krzyzanowskim_cryptoswift",
|
||||
"swiftlint_com_github_scottrhoyt_swifty_text_table",
|
||||
|
|
28
Makefile
28
Makefile
|
@ -30,14 +30,18 @@ VERSION_STRING=$(shell ./tools/get-version)
|
|||
|
||||
all: build
|
||||
|
||||
sourcery: Source/SwiftLintFramework/Models/PrimaryRuleList.swift Tests/GeneratedTests/GeneratedTests.swift
|
||||
sourcery: Source/SwiftLintBuiltInRules/Models/BuiltInRules.swift Source/SwiftLintCore/Models/ReportersList.swift Tests/GeneratedTests/GeneratedTests.swift
|
||||
|
||||
Source/SwiftLintFramework/Models/PrimaryRuleList.swift: Source/SwiftLintFramework/Rules/**/*.swift .sourcery/PrimaryRuleList.stencil
|
||||
sourcery --sources Source/SwiftLintFramework/Rules --templates .sourcery/PrimaryRuleList.stencil --output .sourcery
|
||||
mv .sourcery/PrimaryRuleList.generated.swift Source/SwiftLintFramework/Models/PrimaryRuleList.swift
|
||||
Source/SwiftLintBuiltInRules/Models/BuiltInRules.swift: Source/SwiftLintBuiltInRules/Rules/**/*.swift .sourcery/BuiltInRules.stencil
|
||||
./tools/sourcery --sources Source/SwiftLintBuiltInRules/Rules --templates .sourcery/BuiltInRules.stencil --output .sourcery
|
||||
mv .sourcery/BuiltInRules.generated.swift Source/SwiftLintBuiltInRules/Models/BuiltInRules.swift
|
||||
|
||||
Tests/GeneratedTests/GeneratedTests.swift: Source/SwiftLintFramework/Rules/**/*.swift .sourcery/GeneratedTests.stencil
|
||||
sourcery --sources Source/SwiftLintFramework/Rules --templates .sourcery/GeneratedTests.stencil --output .sourcery
|
||||
Source/SwiftLintCore/Models/ReportersList.swift: Source/SwiftLintCore/Reporters/*.swift .sourcery/ReportersList.stencil
|
||||
./tools/sourcery --sources Source/SwiftLintCore/Reporters --templates .sourcery/ReportersList.stencil --output .sourcery
|
||||
mv .sourcery/ReportersList.generated.swift Source/SwiftLintCore/Models/ReportersList.swift
|
||||
|
||||
Tests/GeneratedTests/GeneratedTests.swift: Source/SwiftLint*/Rules/**/*.swift .sourcery/GeneratedTests.stencil
|
||||
./tools/sourcery --sources Source/SwiftLintCore/Rules --sources Source/SwiftLintBuiltInRules/Rules --templates .sourcery/GeneratedTests.stencil --output .sourcery
|
||||
mv .sourcery/GeneratedTests.generated.swift Tests/GeneratedTests/GeneratedTests.swift
|
||||
|
||||
test: clean_xcode
|
||||
|
@ -117,6 +121,7 @@ zip_linux_release:
|
|||
chmod +x "$(TMP_FOLDER)/swiftlint"
|
||||
cp -f "$(LICENSE_PATH)" "$(TMP_FOLDER)"
|
||||
(cd "$(TMP_FOLDER)"; zip -yr - "swiftlint" "LICENSE") > "./swiftlint_linux.zip"
|
||||
gh release upload "$(VERSION_STRING)" swiftlint_linux.zip
|
||||
|
||||
package: build
|
||||
$(eval PACKAGE_ROOT := $(shell mktemp -d))
|
||||
|
@ -147,8 +152,8 @@ display_compilation_time:
|
|||
|
||||
publish:
|
||||
brew update && brew bump-formula-pr --tag=$(shell git describe --tags) --revision=$(shell git rev-parse HEAD) swiftlint
|
||||
# Workaround for https://github.com/CocoaPods/CocoaPods/issues/11185
|
||||
arch -arch x86_64 pod trunk push SwiftLint.podspec
|
||||
bundle install
|
||||
bundle exec pod trunk push SwiftLint.podspec
|
||||
|
||||
docs:
|
||||
swift run swiftlint generate-docs
|
||||
|
@ -165,7 +170,7 @@ endif
|
|||
$(eval NEW_VERSION_AND_NAME := $(filter-out $@,$(MAKECMDGOALS)))
|
||||
$(eval NEW_VERSION := $(shell echo $(NEW_VERSION_AND_NAME) | sed 's/:.*//' ))
|
||||
@sed -i '' 's/## Main/## $(NEW_VERSION_AND_NAME)/g' CHANGELOG.md
|
||||
@sed 's/__VERSION__/$(NEW_VERSION)/g' tools/Version.swift.template > Source/SwiftLintFramework/Models/Version.swift
|
||||
@sed 's/__VERSION__/$(NEW_VERSION)/g' tools/Version.swift.template > Source/SwiftLintCore/Models/Version.swift
|
||||
@sed -e '3s/.*/ version = "$(NEW_VERSION)",/' -i '' MODULE.bazel
|
||||
make clean
|
||||
make package
|
||||
|
@ -177,6 +182,11 @@ endif
|
|||
git tag -a $(NEW_VERSION) -m "$(NEW_VERSION_AND_NAME)"
|
||||
git push origin HEAD
|
||||
git push origin $(NEW_VERSION)
|
||||
./tools/create-github-release.sh "$(NEW_VERSION)"
|
||||
make publish
|
||||
./tools/add-new-changelog-section.sh
|
||||
git commit -a -m "Add new changelog section"
|
||||
git push origin HEAD
|
||||
|
||||
%:
|
||||
@:
|
||||
|
|
|
@ -9,6 +9,15 @@
|
|||
"version" : "0.2.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "cryptoswift",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/krzyzanowskim/CryptoSwift.git",
|
||||
"state" : {
|
||||
"revision" : "32f641cf24fc7abc1c591a2025e9f2f572648b0f",
|
||||
"version" : "1.7.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "sourcekitten",
|
||||
"kind" : "remoteSourceControl",
|
||||
|
@ -32,8 +41,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-syntax.git",
|
||||
"state" : {
|
||||
"revision" : "013a48e2312e57b7b355db25bd3ea75282ebf274",
|
||||
"version" : "0.50900.0-swift-DEVELOPMENT-SNAPSHOT-2023-02-06-a"
|
||||
"revision" : "165fc6d22394c1168ff76ab5d951245971ef07e5",
|
||||
"version" : "509.0.0-swift-DEVELOPMENT-SNAPSHOT-2023-06-05-a"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,26 +1,6 @@
|
|||
// swift-tools-version:5.7
|
||||
import PackageDescription
|
||||
|
||||
#if os(macOS)
|
||||
private let addCryptoSwift = false
|
||||
private let binaryPlugin = true
|
||||
#else
|
||||
private let addCryptoSwift = true
|
||||
private let binaryPlugin = false
|
||||
#endif
|
||||
|
||||
let frameworkDependencies: [Target.Dependency] = [
|
||||
.product(name: "IDEUtils", package: "swift-syntax"),
|
||||
.product(name: "SourceKittenFramework", package: "SourceKitten"),
|
||||
.product(name: "SwiftSyntax", package: "swift-syntax"),
|
||||
.product(name: "SwiftSyntaxBuilder", package: "swift-syntax"),
|
||||
.product(name: "SwiftParser", package: "swift-syntax"),
|
||||
.product(name: "SwiftOperators", package: "swift-syntax"),
|
||||
"SwiftyTextTable",
|
||||
"Yams",
|
||||
]
|
||||
+ (addCryptoSwift ? ["CryptoSwift"] : [])
|
||||
|
||||
let package = Package(
|
||||
name: "SwiftLint",
|
||||
platforms: [.macOS(.v12)],
|
||||
|
@ -31,18 +11,20 @@ let package = Package(
|
|||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/apple/swift-argument-parser.git", .upToNextMinor(from: "1.2.1")),
|
||||
.package(url: "https://github.com/apple/swift-syntax.git", exact: "0.50900.0-swift-DEVELOPMENT-SNAPSHOT-2023-02-06-a"),
|
||||
.package(url: "https://github.com/apple/swift-syntax.git", exact: "509.0.0-swift-DEVELOPMENT-SNAPSHOT-2023-06-05-a"),
|
||||
.package(url: "https://github.com/jpsim/SourceKitten.git", .upToNextMinor(from: "0.34.1")),
|
||||
.package(url: "https://github.com/jpsim/Yams.git", from: "5.0.5"),
|
||||
.package(url: "https://github.com/scottrhoyt/SwiftyTextTable.git", from: "0.9.0"),
|
||||
.package(url: "https://github.com/JohnSundell/CollectionConcurrencyKit.git", from: "0.2.0")
|
||||
] + (addCryptoSwift ? [.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", .upToNextMinor(from: "1.6.0"))] : []),
|
||||
.package(url: "https://github.com/JohnSundell/CollectionConcurrencyKit.git", from: "0.2.0"),
|
||||
.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", .upToNextMinor(from: "1.7.2"))
|
||||
],
|
||||
targets: [
|
||||
.plugin(
|
||||
name: "SwiftLintPlugin",
|
||||
capability: .buildTool(),
|
||||
dependencies: [
|
||||
.target(name: binaryPlugin ? "SwiftLintBinary" : "swiftlint")
|
||||
.target(name: "SwiftLintBinary", condition: .when(platforms: [.macOS])),
|
||||
.target(name: "swiftlint", condition: .when(platforms: [.linux]))
|
||||
]
|
||||
),
|
||||
.executableTarget(
|
||||
|
@ -61,9 +43,37 @@ let package = Package(
|
|||
]
|
||||
),
|
||||
.target(
|
||||
name: "SwiftLintFramework",
|
||||
dependencies: frameworkDependencies
|
||||
name: "SwiftLintCore",
|
||||
dependencies: [
|
||||
.product(name: "CryptoSwift", package: "CryptoSwift", condition: .when(platforms: [.linux])),
|
||||
.target(name: "DyldWarningWorkaround", condition: .when(platforms: [.macOS])),
|
||||
.product(name: "SourceKittenFramework", package: "SourceKitten"),
|
||||
.product(name: "SwiftIDEUtils", package: "swift-syntax"),
|
||||
.product(name: "SwiftOperators", package: "swift-syntax"),
|
||||
.product(name: "SwiftParser", package: "swift-syntax"),
|
||||
.product(name: "SwiftSyntax", package: "swift-syntax"),
|
||||
.product(name: "SwiftSyntaxBuilder", package: "swift-syntax"),
|
||||
.product(name: "SwiftyTextTable", package: "SwiftyTextTable"),
|
||||
.product(name: "Yams", package: "Yams"),
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "SwiftLintBuiltInRules",
|
||||
dependencies: ["SwiftLintCore"]
|
||||
),
|
||||
.target(
|
||||
name: "SwiftLintExtraRules",
|
||||
dependencies: ["SwiftLintCore"]
|
||||
),
|
||||
.target(
|
||||
name: "SwiftLintFramework",
|
||||
dependencies: [
|
||||
"SwiftLintBuiltInRules",
|
||||
"SwiftLintCore",
|
||||
"SwiftLintExtraRules"
|
||||
]
|
||||
),
|
||||
.target(name: "DyldWarningWorkaround"),
|
||||
.target(
|
||||
name: "SwiftLintTestHelpers",
|
||||
dependencies: [
|
||||
|
@ -104,8 +114,8 @@ let package = Package(
|
|||
),
|
||||
.binaryTarget(
|
||||
name: "SwiftLintBinary",
|
||||
url: "https://github.com/realm/SwiftLint/releases/download/0.51.0/SwiftLintBinary-macos.artifactbundle.zip",
|
||||
checksum: "9fbfdf1c2a248469cfbe17a158c5fbf96ac1b606fbcfef4b800993e7accf43ae"
|
||||
url: "https://github.com/realm/SwiftLint/releases/download/0.52.2/SwiftLintBinary-macos.artifactbundle.zip",
|
||||
checksum: "89651e1c87fb62faf076ef785a5b1af7f43570b2b74c6773526e0d5114e0578e"
|
||||
)
|
||||
]
|
||||
)
|
||||
|
|
41
README.md
41
README.md
|
@ -1,6 +1,6 @@
|
|||
# SwiftLint
|
||||
|
||||
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 [Ray Wenderlich's Swift Style Guide](https://github.com/raywenderlich/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
|
||||
|
@ -158,7 +158,10 @@ folder by default. To instruct Xcode where to find SwiftLint, you can either add
|
|||
`/opt/homebrew/bin` to the `PATH` environment variable in your build phase
|
||||
|
||||
```bash
|
||||
export PATH="$PATH:/opt/homebrew/bin"
|
||||
if [[ "$(uname -m)" == arm64 ]]; then
|
||||
export PATH="/opt/homebrew/bin:$PATH"
|
||||
fi
|
||||
|
||||
if which swiftlint > /dev/null; then
|
||||
swiftlint
|
||||
else
|
||||
|
@ -236,14 +239,6 @@ Add SwiftLint to a target using the `plugins` parameter.
|
|||
),
|
||||
```
|
||||
|
||||
|
||||
### AppCode
|
||||
|
||||
To integrate SwiftLint with AppCode, install
|
||||
[this plugin](https://plugins.jetbrains.com/plugin/9175) and configure
|
||||
SwiftLint's installed path in the plugin's preferences.
|
||||
The `fix` action is available via `⌥⏎`.
|
||||
|
||||
### Visual Studio Code
|
||||
|
||||
To integrate SwiftLint with [vscode](https://code.visualstudio.com), install the
|
||||
|
@ -313,6 +308,7 @@ SUBCOMMANDS:
|
|||
docs Open SwiftLint documentation website in the default web browser
|
||||
generate-docs Generates markdown documentation for all rules
|
||||
lint (default) Print lint warnings and errors
|
||||
reporters Display the list of reporters and their identifiers
|
||||
rules Display the list of rules and their identifiers
|
||||
version Display the current version of SwiftLint
|
||||
|
||||
|
@ -405,7 +401,7 @@ continues to contribute more over time.
|
|||
You can find an updated list of rules and more information about them
|
||||
[here](https://realm.github.io/SwiftLint/rule-directory.html).
|
||||
|
||||
You can also check [Source/SwiftLintFramework/Rules](https://github.com/realm/SwiftLint/tree/main/Source/SwiftLintFramework/Rules)
|
||||
You can also check [Source/SwiftLintBuiltInRules/Rules](https://github.com/realm/SwiftLint/tree/main/Source/SwiftLintBuiltInRules/Rules)
|
||||
directory to see their implementation.
|
||||
|
||||
### Opt-In Rules
|
||||
|
@ -554,13 +550,29 @@ identifier_name:
|
|||
- id
|
||||
- URL
|
||||
- GlobalAPIKey
|
||||
reporter: "xcode" # reporter type (xcode, json, csv, checkstyle, codeclimate, junit, html, emoji, sonarqube, markdown, github-actions-logging)
|
||||
reporter: "xcode" # reporter type (xcode, json, csv, checkstyle, codeclimate, junit, html, emoji, sonarqube, markdown, github-actions-logging, summary)
|
||||
```
|
||||
|
||||
You can also use environment variables in your configuration file,
|
||||
by using `${SOME_VARIABLE}` in a string.
|
||||
|
||||
#### Defining Custom Rules
|
||||
### Defining Custom Rules
|
||||
|
||||
In addition to the rules that the main SwiftLint project ships with, SwiftLint
|
||||
can also run two types of custom rules that you can define yourself in your own
|
||||
projects:
|
||||
|
||||
#### 1. Swift Custom Rules
|
||||
|
||||
These rules are written the same way as the Swift-based rules that ship with
|
||||
SwiftLint so they're fast, accurate, can leverage SwiftSyntax, can be unit
|
||||
tested, and more.
|
||||
|
||||
Using these requires building SwiftLint with Bazel as described in
|
||||
[this video](https://vimeo.com/820572803) or its associated code in
|
||||
[github.com/jpsim/swiftlint-bazel-example](https://github.com/jpsim/swiftlint-bazel-example).
|
||||
|
||||
#### 2. Regex Custom Rules
|
||||
|
||||
You can define custom regex-based rules in your configuration file using the
|
||||
following syntax:
|
||||
|
@ -625,6 +637,9 @@ which match to `keyword` and `identifier` in the above list.
|
|||
If using custom rules in combination with `only_rules`, make sure to add
|
||||
`custom_rules` as an item under `only_rules`.
|
||||
|
||||
Unlike Swift custom rules, you can use official SwiftLint builds
|
||||
(e.g. from Homebrew) to run regex custom rules.
|
||||
|
||||
### Auto-correct
|
||||
|
||||
SwiftLint can automatically correct certain violations. Files on disk are
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# SwiftLint
|
||||
|
||||
SwiftLint 是一个用于强制检查 Swift 代码风格和规定的一个工具,基本上以 [Ray Wenderlich's Swift 代码风格指南](https://github.com/raywenderlich/swift-style-guide)为基础。
|
||||
SwiftLint 是一个用于强制检查 Swift 代码风格和规定的一个工具,基本上以 [Kodeco's Swift 代码风格指南](https://github.com/kodecocodes/swift-style-guide)为基础。
|
||||
|
||||
SwiftLint Hook 了 [Clang](http://clang.llvm.org) 和 [SourceKit](http://www.jpsim.com/uncovering-sourcekit) 从而能够使用 [AST](http://clang.llvm.org/docs/IntroductionToTheClangAST.html) 来表示源代码文件的更多精确结果。
|
||||
|
||||
|
@ -167,7 +167,7 @@ SwiftLint 已经包含了超过 75 条规则,并且我们希望 Swift 社区
|
|||
|
||||
你可以在 [Rule Directory](https://realm.github.io/SwiftLint/rule-directory.html) 找到规则的更新列表和更多信息。
|
||||
|
||||
你也可以检视 [Source/SwiftLintFramework/Rules](Source/SwiftLintFramework/Rules) 目录来查看它们的实现。
|
||||
你也可以检视 [Source/SwiftLintBuiltInRules/Rules](Source/SwiftLintBuiltInRules/Rules) 目录来查看它们的实现。
|
||||
|
||||
`opt_in_rules` 默认是关闭的(即,你需要在你的配置文件中明确地打开它们)。
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# SwiftLint
|
||||
|
||||
SwiftLint는 스위프트 스타일 및 컨벤션을 강제하기 위한 도구로, [Ray Wenderlich 스위프트 스타일 가이드](https://github.com/raywenderlich/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) 표현을 사용합니다.
|
||||
|
||||
|
@ -75,7 +75,10 @@ fi
|
|||
그 이유는, 애플 실리콘 기반 맥에서 Homebrew는 기본적으로 바이너리들을 `/opt/homebrew/bin`에 저장하기 때문입니다. SwiftLint가 어디 있는지 찾는 것을 Xcode에 알려주기 위해, build phase에서 `/opt/homebrew/bin`를 `PATH` 환경 변수에 동시에 추가하여야 합니다.
|
||||
|
||||
```bash
|
||||
export PATH="$PATH:/opt/homebrew/bin"
|
||||
if [[ "$(uname -m)" == arm64 ]]; then
|
||||
export PATH="/opt/homebrew/bin:$PATH"
|
||||
fi
|
||||
|
||||
if which swiftlint > /dev/null; then
|
||||
swiftlint
|
||||
else
|
||||
|
@ -182,7 +185,7 @@ $ TOOLCHAINS=com.apple.dt.toolchain.Swift_2_3 swiftlint autocorrect
|
|||
|
||||
SwiftLint에는 200개가 넘는 룰들이 있고, 스위프트 커뮤니티(바로 여러분들!)는 이를 지속적으로 발전시켜 가고 있습니다. [풀 리퀘스트](CONTRIBUTING.md)는 언제나 환영입니다.
|
||||
|
||||
현재 구현된 룰 전체를 확인하려면 [Source/SwiftLintFramework/Rules](Source/SwiftLintFramework/Rules)를 살펴보세요.
|
||||
현재 구현된 룰 전체를 확인하려면 [Source/SwiftLintBuiltInRules/Rules](Source/SwiftLintBuiltInRules/Rules)를 살펴보세요.
|
||||
|
||||
`opt_in_rules`는 기본적으로 비활성화되어 있습니다. (즉, 설정 파일에서 명시적으로 해당 룰을 활성화해야 합니다.)
|
||||
|
||||
|
|
11
Releasing.md
11
Releasing.md
|
@ -8,16 +8,7 @@ For SwiftLint contributors, follow these steps to cut a release:
|
|||
* Top Loading
|
||||
* Fresh Out Of The Dryer
|
||||
1. Make sure you have the latest stable Xcode version installed and
|
||||
`xcode-select`ed.
|
||||
`xcode-select`ed
|
||||
1. Release new version: `make release "0.2.0: Tumble Dry"`
|
||||
1. Wait for the Docker CI job to finish then run: `make zip_linux_release`
|
||||
1. Create a GitHub release: https://github.com/realm/SwiftLint/releases/new
|
||||
* Specify the tag you just pushed from the dropdown.
|
||||
* Set the release title to the new version number & release name.
|
||||
* Add the changelog section to the release description text box.
|
||||
* Upload the bazel tarball & SHA-256 signature, pkg installer,
|
||||
portable zip, macos artifactbundle zip, and Linux zip
|
||||
you just built to the GitHub release binaries.
|
||||
* Click "Publish release".
|
||||
1. Publish to Homebrew and CocoaPods trunk: `make publish`
|
||||
1. Celebrate. :tada:
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
#ifdef __APPLE__
|
||||
|
||||
#include "objc_dupclass.h"
|
||||
|
||||
OBJC_DUPCLASS(_TtC11SwiftSyntax11SyntaxArena);
|
||||
OBJC_DUPCLASS(_TtC11SwiftSyntax13SyntaxVisitor);
|
||||
OBJC_DUPCLASS(_TtC11SwiftSyntax14SyntaxRewriter);
|
||||
OBJC_DUPCLASS(_TtC11SwiftSyntax16BumpPtrAllocator);
|
||||
OBJC_DUPCLASS(_TtC11SwiftSyntax16SyntaxAnyVisitor);
|
||||
OBJC_DUPCLASS(_TtC11SwiftSyntax18ParsingSyntaxArena);
|
||||
OBJC_DUPCLASS(_TtC11SwiftSyntax23SourceLocationConverter);
|
||||
OBJC_DUPCLASS(_TtC11SwiftSyntax26IncrementalParseTransition);
|
||||
OBJC_DUPCLASS(_TtC11SwiftSyntax35IncrementalParseReusedNodeCollector);
|
||||
|
||||
#endif // __APPLE__
|
|
@ -0,0 +1,19 @@
|
|||
// https://github.com/keith/objc_dupclass
|
||||
#include <stdint.h>
|
||||
|
||||
// TODO: This isn't entirely accurate, but I'm not sure how to more accurately determine
|
||||
#if (defined(__arm64__) || defined(DUPCLASS_FORCE_DATA_CONST)) && !defined(DUPCLASS_FORCE_DATA)
|
||||
#define SECTION "__DATA_CONST"
|
||||
#else
|
||||
#define SECTION "__DATA"
|
||||
#endif
|
||||
|
||||
// Struct layout from https://github.com/apple-oss-distributions/objc4/blob/8701d5672d3fd3cd817aeb84db1077aafe1a1604/runtime/objc-abi.h#L175-L183
|
||||
#define OBJC_DUPCLASS(kclass) \
|
||||
__attribute__((used)) __attribute__((visibility("hidden"))) \
|
||||
static struct { uint32_t version; uint32_t flags; const char name[64]; } \
|
||||
const __duplicate_class_##kclass = { 0, 0, #kclass }; \
|
||||
\
|
||||
__attribute__((used)) __attribute__((visibility("hidden"))) \
|
||||
__attribute__((section (SECTION",__objc_dupclass"))) \
|
||||
const void* __set___objc_dupclass_sym___duplicate_class_##kclass = &__duplicate_class_##kclass
|
|
@ -0,0 +1 @@
|
|||
@_exported import SwiftLintCore
|
|
@ -82,8 +82,8 @@ enum LegacyFunctionRuleHelper {
|
|||
}
|
||||
|
||||
return expr
|
||||
.with(\.leadingTrivia, node.leadingTrivia ?? .zero)
|
||||
.with(\.trailingTrivia, node.trailingTrivia ?? .zero)
|
||||
.with(\.leadingTrivia, node.leadingTrivia)
|
||||
.with(\.trailingTrivia, node.trailingTrivia)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
// Generated using Sourcery 2.0.0 — https://github.com/krzysztofzablocki/Sourcery
|
||||
// Generated using Sourcery 2.0.2 — https://github.com/krzysztofzablocki/Sourcery
|
||||
// DO NOT EDIT
|
||||
|
||||
/// The rule list containing all available rules built into SwiftLint.
|
||||
let builtInRules: [Rule.Type] = [
|
||||
public let builtInRules: [Rule.Type] = [
|
||||
AccessibilityLabelForImageRule.self,
|
||||
AccessibilityTraitForButtonRule.self,
|
||||
AnonymousArgumentInMultilineClosureRule.self,
|
||||
|
@ -33,7 +33,6 @@ let builtInRules: [Rule.Type] = [
|
|||
ContainsOverRangeNilComparisonRule.self,
|
||||
ControlStatementRule.self,
|
||||
ConvenienceTypeRule.self,
|
||||
CustomRules.self,
|
||||
CyclomaticComplexityRule.self,
|
||||
DeploymentTargetRule.self,
|
||||
DirectReturnRule.self,
|
||||
|
@ -107,7 +106,7 @@ let builtInRules: [Rule.Type] = [
|
|||
LegacyRandomRule.self,
|
||||
LetVarWhitespaceRule.self,
|
||||
LineLengthRule.self,
|
||||
LiteralExpressionEndIdentationRule.self,
|
||||
LiteralExpressionEndIndentationRule.self,
|
||||
LocalDocCommentRule.self,
|
||||
LowerACLThanParentRule.self,
|
||||
MarkRule.self,
|
||||
|
@ -166,6 +165,7 @@ let builtInRules: [Rule.Type] = [
|
|||
RedundantNilCoalescingRule.self,
|
||||
RedundantObjcAttributeRule.self,
|
||||
RedundantOptionalInitializationRule.self,
|
||||
RedundantSelfInClosureRule.self,
|
||||
RedundantSetAccessControlRule.self,
|
||||
RedundantStringEnumValueRule.self,
|
||||
RedundantTypeAnnotationRule.self,
|
||||
|
@ -179,13 +179,14 @@ let builtInRules: [Rule.Type] = [
|
|||
ShorthandOperatorRule.self,
|
||||
ShorthandOptionalBindingRule.self,
|
||||
SingleTestClassRule.self,
|
||||
SortedEnumCasesRule.self,
|
||||
SortedFirstLastRule.self,
|
||||
SortedImportsRule.self,
|
||||
StatementPositionRule.self,
|
||||
StaticOperatorRule.self,
|
||||
StrictFilePrivateRule.self,
|
||||
StrongIBOutletRule.self,
|
||||
SuperfluousDisableCommandRule.self,
|
||||
SuperfluousElseRule.self,
|
||||
SwitchCaseAlignmentRule.self,
|
||||
SwitchCaseOnNewlineRule.self,
|
||||
SyntacticSugarRule.self,
|
||||
|
@ -203,6 +204,7 @@ let builtInRules: [Rule.Type] = [
|
|||
TypesafeArrayInitRule.self,
|
||||
UnavailableConditionRule.self,
|
||||
UnavailableFunctionRule.self,
|
||||
UnhandledThrowingTaskRule.self,
|
||||
UnneededBreakInSwitchRule.self,
|
||||
UnneededParenthesesInClosureArgumentRule.self,
|
||||
UnownedVariableCaptureRule.self,
|
||||
|
@ -229,6 +231,3 @@ let builtInRules: [Rule.Type] = [
|
|||
XCTSpecificMatcherRule.self,
|
||||
YodaConditionRule.self
|
||||
]
|
||||
|
||||
/// The rule list containing all available rules built into SwiftLint as well as native custom rules.
|
||||
public let primaryRuleList = RuleList(rules: builtInRules + extraRules())
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct AnonymousArgumentInMultilineClosureRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "anonymous_argument_in_multiline_closure",
|
||||
|
@ -50,12 +48,7 @@ private extension AnonymousArgumentInMultilineClosureRule {
|
|||
override func visit(_ node: ClosureExprSyntax) -> SyntaxVisitorContinueKind {
|
||||
let startLocation = locationConverter.location(for: node.leftBrace.positionAfterSkippingLeadingTrivia)
|
||||
let endLocation = locationConverter.location(for: node.rightBrace.endPositionBeforeTrailingTrivia)
|
||||
|
||||
guard let startLine = startLocation.line, let endLine = endLocation.line, startLine != endLine else {
|
||||
return .skipChildren
|
||||
}
|
||||
|
||||
return .visitChildren
|
||||
return startLocation.line == endLocation.line ? .skipChildren : .visitChildren
|
||||
}
|
||||
|
||||
override func visitPost(_ node: IdentifierExprSyntax) {
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct BlockBasedKVORule: SwiftSyntaxRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "block_based_kvo",
|
||||
|
@ -47,13 +45,13 @@ private extension BlockBasedKVORule {
|
|||
case let parameterList = node.signature.input.parameterList,
|
||||
parameterList.count == 4,
|
||||
node.identifier.text == "observeValue",
|
||||
parameterList.compactMap(\.firstName?.text) == ["forKeyPath", "of", "change", "context"]
|
||||
parameterList.map(\.firstName.text) == ["forKeyPath", "of", "change", "context"]
|
||||
else {
|
||||
return
|
||||
}
|
||||
|
||||
let types = parameterList
|
||||
.compactMap { $0.type?.trimmedDescription.replacingOccurrences(of: " ", with: "") }
|
||||
.map { $0.type.trimmedDescription.replacingOccurrences(of: " ", with: "") }
|
||||
let firstTypes = ["String?", "Any?", "[NSKeyValueChangeKey:Any]?", "UnsafeMutableRawPointer?"]
|
||||
let secondTypes = ["String?", "Any?", "Dictionary<NSKeyValueChangeKey,Any>?", "UnsafeMutableRawPointer?"]
|
||||
if types == firstTypes || types == secondTypes {
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct ConvenienceTypeRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "convenience_type",
|
||||
|
@ -127,13 +125,21 @@ private extension ConvenienceTypeRule {
|
|||
override var skippableDeclarations: [DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] }
|
||||
|
||||
override func visitPost(_ node: StructDeclSyntax) {
|
||||
if hasViolation(inheritance: node.inheritanceClause, attributes: node.attributes, members: node.members) {
|
||||
if hasViolation(
|
||||
inheritance: node.inheritanceClause,
|
||||
attributes: node.attributes,
|
||||
members: node.memberBlock
|
||||
) {
|
||||
violations.append(node.structKeyword.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
}
|
||||
|
||||
override func visitPost(_ node: ClassDeclSyntax) {
|
||||
if hasViolation(inheritance: node.inheritanceClause, attributes: node.attributes, members: node.members) {
|
||||
if hasViolation(
|
||||
inheritance: node.inheritanceClause,
|
||||
attributes: node.attributes,
|
||||
members: node.memberBlock
|
||||
) {
|
||||
violations.append(node.classKeyword.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct DiscouragedAssertRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule {
|
||||
// MARK: - Properties
|
||||
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "discouraged_assert",
|
||||
|
@ -25,12 +23,6 @@ struct DiscouragedAssertRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderR
|
|||
]
|
||||
)
|
||||
|
||||
// MARK: - Life cycle
|
||||
|
||||
init() {}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(viewMode: .sourceAccurate)
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct DiscouragedNoneNameRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static var description = RuleDescription(
|
||||
identifier: "discouraged_none_name",
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct DiscouragedObjectLiteralRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule {
|
||||
var configuration = ObjectLiteralConfiguration()
|
||||
|
||||
init() {}
|
||||
var configuration = DiscouragedObjectLiteralConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "discouraged_object_literal",
|
||||
|
@ -31,9 +29,9 @@ struct DiscouragedObjectLiteralRule: SwiftSyntaxRule, OptInRule, ConfigurationPr
|
|||
|
||||
private extension DiscouragedObjectLiteralRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let configuration: ObjectLiteralConfiguration
|
||||
private let configuration: ConfigurationType
|
||||
|
||||
init(configuration: ObjectLiteralConfiguration) {
|
||||
init(configuration: ConfigurationType) {
|
||||
self.configuration = configuration
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct DiscouragedOptionalBooleanRule: OptInRule, ConfigurationProviderRule, SwiftSyntaxRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "discouraged_optional_boolean",
|
|
@ -1,9 +1,7 @@
|
|||
import SourceKittenFramework
|
||||
|
||||
struct DiscouragedOptionalCollectionRule: ASTRule, OptInRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "discouraged_optional_collection",
|
|
@ -2,7 +2,7 @@ import Foundation
|
|||
import SourceKittenFramework
|
||||
|
||||
struct DuplicateImportsRule: ConfigurationProviderRule, CorrectableRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
// List of all possible import kinds
|
||||
static let importKinds = [
|
||||
|
@ -11,8 +11,6 @@ struct DuplicateImportsRule: ConfigurationProviderRule, CorrectableRule {
|
|||
"var", "func"
|
||||
]
|
||||
|
||||
init() {}
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "duplicate_imports",
|
||||
name: "Duplicate Imports",
|
|
@ -4,9 +4,7 @@ import SourceKittenFramework
|
|||
private typealias SourceKittenElement = SourceKittenDictionary
|
||||
|
||||
struct ExplicitACLRule: OptInRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "explicit_acl",
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct ExplicitEnumRawValueRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "explicit_enum_raw_value",
|
|
@ -2,9 +2,7 @@ import SwiftSyntax
|
|||
import SwiftSyntaxBuilder
|
||||
|
||||
struct ExplicitInitRule: SwiftSyntaxCorrectableRule, ConfigurationProviderRule, OptInRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "explicit_init",
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct ExplicitTopLevelACLRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "explicit_top_level_acl",
|
||||
|
@ -83,7 +81,7 @@ private extension ExplicitTopLevelACLRule {
|
|||
|
||||
override func visitPost(_ node: VariableDeclSyntax) {
|
||||
if hasViolation(modifiers: node.modifiers) {
|
||||
violations.append(node.letOrVarKeyword.positionAfterSkippingLeadingTrivia)
|
||||
violations.append(node.bindingKeyword.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
}
|
||||
|
|
@ -3,8 +3,6 @@ import SwiftSyntax
|
|||
struct ExplicitTypeInterfaceRule: OptInRule, ConfigurationProviderRule, SwiftSyntaxRule {
|
||||
var configuration = ExplicitTypeInterfaceConfiguration()
|
||||
|
||||
init() {}
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "explicit_type_interface",
|
||||
name: "Explicit Type Interface",
|
|
@ -2,9 +2,7 @@ import Foundation
|
|||
import SourceKittenFramework
|
||||
|
||||
struct ExtensionAccessModifierRule: ASTRule, ConfigurationProviderRule, OptInRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "extension_access_modifier",
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct FallthroughRule: SwiftSyntaxRule, ConfigurationProviderRule, OptInRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "fallthrough",
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct FatalErrorMessageRule: SwiftSyntaxRule, ConfigurationProviderRule, OptInRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "fatal_error_message",
|
|
@ -2,12 +2,7 @@ import Foundation
|
|||
import SourceKittenFramework
|
||||
|
||||
struct FileNameNoSpaceRule: ConfigurationProviderRule, OptInRule, SourceKitFreeRule {
|
||||
var configuration = FileNameNoSpaceConfiguration(
|
||||
severity: .warning,
|
||||
excluded: []
|
||||
)
|
||||
|
||||
init() {}
|
||||
var configuration = FileNameNoSpaceConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "file_name_no_space",
|
||||
|
@ -25,7 +20,7 @@ struct FileNameNoSpaceRule: ConfigurationProviderRule, OptInRule, SourceKitFreeR
|
|||
}
|
||||
|
||||
return [StyleViolation(ruleDescription: Self.description,
|
||||
severity: configuration.severity.severity,
|
||||
severity: configuration.severity,
|
||||
location: Location(file: filePath, line: 1))]
|
||||
}
|
||||
}
|
|
@ -1,15 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct FileNameRule: ConfigurationProviderRule, OptInRule, SourceKitFreeRule {
|
||||
var configuration = FileNameConfiguration(
|
||||
severity: .warning,
|
||||
excluded: ["main.swift", "LinuxMain.swift"],
|
||||
prefixPattern: "",
|
||||
suffixPattern: "\\+.*",
|
||||
nestedTypeSeparator: "."
|
||||
)
|
||||
|
||||
init() {}
|
||||
var configuration = FileNameConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "file_name",
|
||||
|
@ -54,7 +46,7 @@ struct FileNameRule: ConfigurationProviderRule, OptInRule, SourceKitFreeRule {
|
|||
}
|
||||
|
||||
return [StyleViolation(ruleDescription: Self.description,
|
||||
severity: configuration.severity.severity,
|
||||
severity: configuration.severity,
|
||||
location: Location(file: filePath, line: 1))]
|
||||
}
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct ForWhereRule: SwiftSyntaxRule, ConfigurationProviderRule {
|
||||
var configuration = ForWhereRuleConfiguration()
|
||||
|
||||
init() {}
|
||||
var configuration = ForWhereConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "for_where",
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct ForceCastRule: ConfigurationProviderRule, SwiftSyntaxRule {
|
||||
var configuration = SeverityConfiguration(.error)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.error)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "force_cast",
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct ForceTryRule: ConfigurationProviderRule, SwiftSyntaxRule {
|
||||
var configuration = SeverityConfiguration(.error)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.error)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "force_try",
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct ForceUnwrappingRule: OptInRule, SwiftSyntaxRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "force_unwrapping",
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct FunctionDefaultParameterAtEndRule: SwiftSyntaxRule, ConfigurationProviderRule, OptInRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "function_default_parameter_at_end",
|
||||
|
@ -104,20 +102,20 @@ private extension FunctionSignatureSyntax {
|
|||
|
||||
private extension FunctionParameterSyntax {
|
||||
var isClosure: Bool {
|
||||
if isEscaping || type?.as(FunctionTypeSyntax.self) != nil {
|
||||
if isEscaping || type.is(FunctionTypeSyntax.self) {
|
||||
return true
|
||||
}
|
||||
|
||||
if let optionalType = type?.as(OptionalTypeSyntax.self),
|
||||
if let optionalType = type.as(OptionalTypeSyntax.self),
|
||||
let tuple = optionalType.wrappedType.as(TupleTypeSyntax.self) {
|
||||
return tuple.elements.onlyElement?.type.as(FunctionTypeSyntax.self) != nil
|
||||
}
|
||||
|
||||
if let tuple = type?.as(TupleTypeSyntax.self) {
|
||||
if let tuple = type.as(TupleTypeSyntax.self) {
|
||||
return tuple.elements.onlyElement?.type.as(FunctionTypeSyntax.self) != nil
|
||||
}
|
||||
|
||||
if let attrType = type?.as(AttributedTypeSyntax.self) {
|
||||
if let attrType = type.as(AttributedTypeSyntax.self) {
|
||||
return attrType.baseType.is(FunctionTypeSyntax.self)
|
||||
}
|
||||
|
||||
|
@ -125,7 +123,7 @@ private extension FunctionParameterSyntax {
|
|||
}
|
||||
|
||||
var isEscaping: Bool {
|
||||
guard let attrType = type?.as(AttributedTypeSyntax.self) else {
|
||||
guard let attrType = type.as(AttributedTypeSyntax.self) else {
|
||||
return false
|
||||
}
|
||||
|
|
@ -2,12 +2,10 @@ import Foundation
|
|||
import SwiftSyntax
|
||||
|
||||
struct GenericTypeNameRule: SwiftSyntaxRule, ConfigurationProviderRule {
|
||||
var configuration = NameConfiguration(minLengthWarning: 1,
|
||||
minLengthError: 0,
|
||||
maxLengthWarning: 20,
|
||||
maxLengthError: 1000)
|
||||
|
||||
init() {}
|
||||
var configuration = NameConfiguration<Self>(minLengthWarning: 1,
|
||||
minLengthError: 0,
|
||||
maxLengthWarning: 20,
|
||||
maxLengthError: 1000)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "generic_type_name",
|
||||
|
@ -57,33 +55,34 @@ struct GenericTypeNameRule: SwiftSyntaxRule, ConfigurationProviderRule {
|
|||
|
||||
private extension GenericTypeNameRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let configuration: NameConfiguration
|
||||
private let configuration: ConfigurationType
|
||||
|
||||
init(configuration: NameConfiguration) {
|
||||
init(configuration: ConfigurationType) {
|
||||
self.configuration = configuration
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
override func visitPost(_ node: GenericParameterSyntax) {
|
||||
let name = node.name.text
|
||||
guard !configuration.shouldExclude(name: name) else { return }
|
||||
guard !name.isEmpty, !configuration.shouldExclude(name: name) else { return }
|
||||
|
||||
let allowedSymbols = configuration.allowedSymbols.union(.alphanumerics)
|
||||
if !allowedSymbols.isSuperset(of: CharacterSet(charactersIn: name)) {
|
||||
if !configuration.allowedSymbolsAndAlphanumerics.isSuperset(of: CharacterSet(charactersIn: name)) {
|
||||
violations.append(
|
||||
ReasonedRuleViolation(
|
||||
position: node.positionAfterSkippingLeadingTrivia,
|
||||
reason: "Generic type name '\(name)' should only contain alphanumeric characters",
|
||||
reason: """
|
||||
Generic type name '\(name)' should only contain alphanumeric and other allowed characters
|
||||
""",
|
||||
severity: .error
|
||||
)
|
||||
)
|
||||
} else if configuration.validatesStartWithLowercase &&
|
||||
} else if let caseCheckSeverity = configuration.validatesStartWithLowercase.severity,
|
||||
!String(name[name.startIndex]).isUppercase() {
|
||||
violations.append(
|
||||
ReasonedRuleViolation(
|
||||
position: node.positionAfterSkippingLeadingTrivia,
|
||||
reason: "Generic type name '\(name)' should start with an uppercase character",
|
||||
severity: .error
|
||||
severity: caseCheckSeverity
|
||||
)
|
||||
)
|
||||
} else if let severity = configuration.severity(forLength: name.count) {
|
|
@ -1,12 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct ImplicitlyUnwrappedOptionalRule: SwiftSyntaxRule, ConfigurationProviderRule, OptInRule {
|
||||
var configuration = ImplicitlyUnwrappedOptionalConfiguration(
|
||||
mode: .allExceptIBOutlets,
|
||||
severityConfiguration: SeverityConfiguration(.warning)
|
||||
)
|
||||
|
||||
init() {}
|
||||
var configuration = ImplicitlyUnwrappedOptionalConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "implicitly_unwrapped_optional",
|
||||
|
@ -19,19 +14,30 @@ struct ImplicitlyUnwrappedOptionalRule: SwiftSyntaxRule, ConfigurationProviderRu
|
|||
Example("@IBOutlet var label: [UILabel!]"),
|
||||
Example("if !boolean {}"),
|
||||
Example("let int: Int? = 42"),
|
||||
Example("let int: Int? = nil")
|
||||
Example("let int: Int? = nil"),
|
||||
Example("""
|
||||
class MyClass {
|
||||
@IBOutlet
|
||||
weak var bar: SomeObject!
|
||||
}
|
||||
""", configuration: ["mode": "all_except_iboutlets"], excludeFromDocumentation: true)
|
||||
],
|
||||
triggeringExamples: [
|
||||
Example("let label: UILabel!"),
|
||||
Example("let IBOutlet: UILabel!"),
|
||||
Example("let labels: [UILabel!]"),
|
||||
Example("var ints: [Int!] = [42, nil, 42]"),
|
||||
Example("let label: IBOutlet!"),
|
||||
Example("let int: Int! = 42"),
|
||||
Example("let int: Int! = nil"),
|
||||
Example("var int: Int! = 42"),
|
||||
Example("let collection: AnyCollection<Int!>"),
|
||||
Example("func foo(int: Int!) {}")
|
||||
Example("let label: ↓UILabel!"),
|
||||
Example("let IBOutlet: ↓UILabel!"),
|
||||
Example("let labels: [↓UILabel!]"),
|
||||
Example("var ints: [↓Int!] = [42, nil, 42]"),
|
||||
Example("let label: ↓IBOutlet!"),
|
||||
Example("let int: ↓Int! = 42"),
|
||||
Example("let int: ↓Int! = nil"),
|
||||
Example("var int: ↓Int! = 42"),
|
||||
Example("let collection: AnyCollection<↓Int!>"),
|
||||
Example("func foo(int: ↓Int!) {}"),
|
||||
Example("""
|
||||
class MyClass {
|
||||
weak var bar: ↓SomeObject!
|
||||
}
|
||||
""")
|
||||
]
|
||||
)
|
||||
|
||||
|
@ -42,9 +48,9 @@ struct ImplicitlyUnwrappedOptionalRule: SwiftSyntaxRule, ConfigurationProviderRu
|
|||
|
||||
private extension ImplicitlyUnwrappedOptionalRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let mode: ImplicitlyUnwrappedOptionalModeConfiguration
|
||||
private let mode: ConfigurationType.ImplicitlyUnwrappedOptionalModeConfiguration
|
||||
|
||||
init(mode: ImplicitlyUnwrappedOptionalModeConfiguration) {
|
||||
init(mode: ConfigurationType.ImplicitlyUnwrappedOptionalModeConfiguration) {
|
||||
self.mode = mode
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct IsDisjointRule: SwiftSyntaxRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "is_disjoint",
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct JoinedDefaultParameterRule: SwiftSyntaxCorrectableRule, ConfigurationProviderRule, OptInRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "joined_default_parameter",
|
|
@ -1,7 +1,5 @@
|
|||
struct LegacyCGGeometryFunctionsRule: SwiftSyntaxCorrectableRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "legacy_cggeometry_functions",
|
||||
|
@ -70,7 +68,7 @@ struct LegacyCGGeometryFunctionsRule: SwiftSyntaxCorrectableRule, ConfigurationP
|
|||
Example("↓CGRectInset(rect, 5.0, -7.0)\n"): Example("rect.insetBy(dx: 5.0, dy: -7.0)\n"),
|
||||
Example("↓CGRectOffset(rect, -2, 8.3)\n"): Example("rect.offsetBy(dx: -2, dy: 8.3)\n"),
|
||||
Example("↓CGRectUnion(rect1, rect2)\n"): Example("rect1.union(rect2)\n"),
|
||||
Example("↓CGRectIntersection( rect1 ,rect2)\n"): Example("rect1.intersect(rect2)\n"),
|
||||
Example("↓CGRectIntersection( rect1 ,rect2)\n"): Example("rect1.intersection(rect2)\n"),
|
||||
Example("↓CGRectContainsRect( rect1,rect2 )\n"): Example("rect1.contains(rect2)\n"),
|
||||
Example("↓CGRectContainsPoint(rect ,point)\n"): Example("rect.contains(point)\n"),
|
||||
Example("↓CGRectIntersectsRect( rect1,rect2 )\n"): Example("rect1.intersects(rect2)\n"),
|
||||
|
@ -99,7 +97,7 @@ struct LegacyCGGeometryFunctionsRule: SwiftSyntaxCorrectableRule, ConfigurationP
|
|||
"CGRectContainsRect": .function(name: "contains", argumentLabels: [""]),
|
||||
"CGRectContainsPoint": .function(name: "contains", argumentLabels: [""]),
|
||||
"CGRectIntersectsRect": .function(name: "intersects", argumentLabels: [""]),
|
||||
"CGRectIntersection": .function(name: "intersect", argumentLabels: [""])
|
||||
"CGRectIntersection": .function(name: "intersection", argumentLabels: [""])
|
||||
]
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
|
@ -2,9 +2,7 @@ import SwiftSyntax
|
|||
import SwiftSyntaxBuilder
|
||||
|
||||
struct LegacyConstantRule: SwiftSyntaxCorrectableRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "legacy_constant",
|
||||
|
@ -63,8 +61,8 @@ private extension LegacyConstantRule {
|
|||
|
||||
correctionPositions.append(node.positionAfterSkippingLeadingTrivia)
|
||||
return ("\(raw: correction)" as ExprSyntax)
|
||||
.with(\.leadingTrivia, node.leadingTrivia ?? .zero)
|
||||
.with(\.trailingTrivia, node.trailingTrivia ?? .zero)
|
||||
.with(\.leadingTrivia, node.leadingTrivia)
|
||||
.with(\.trailingTrivia, node.trailingTrivia)
|
||||
}
|
||||
|
||||
override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax {
|
||||
|
@ -78,8 +76,8 @@ private extension LegacyConstantRule {
|
|||
|
||||
correctionPositions.append(node.positionAfterSkippingLeadingTrivia)
|
||||
return ("\(raw: calledExpression.identifier.text).pi" as ExprSyntax)
|
||||
.with(\.leadingTrivia, node.leadingTrivia ?? .zero)
|
||||
.with(\.trailingTrivia, node.trailingTrivia ?? .zero)
|
||||
.with(\.leadingTrivia, node.leadingTrivia)
|
||||
.with(\.trailingTrivia, node.trailingTrivia)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct LegacyConstructorRule: SwiftSyntaxCorrectableRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "legacy_constructor",
|
||||
|
@ -167,9 +165,9 @@ private extension LegacyConstructorRule {
|
|||
|
||||
correctionPositions.append(node.positionAfterSkippingLeadingTrivia)
|
||||
|
||||
let arguments = TupleExprElementListSyntax(node.argumentList.map { elem in
|
||||
let arguments = TupleExprElementListSyntax(node.argumentList.enumerated().map { index, elem in
|
||||
elem
|
||||
.with(\.label, .identifier(args[elem.indexInParent]))
|
||||
.with(\.label, .identifier(args[index]))
|
||||
.with(\.colon, .colonToken(trailingTrivia: .space))
|
||||
})
|
||||
let newExpression = identifierExpr.with(
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct LegacyHashingRule: SwiftSyntaxRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "legacy_hashing",
|
||||
|
@ -85,7 +83,7 @@ extension LegacyHashingRule {
|
|||
override func visitPost(_ node: VariableDeclSyntax) {
|
||||
guard
|
||||
node.parent?.is(MemberDeclListItemSyntax.self) == true,
|
||||
node.letOrVarKeyword.tokenKind == .keyword(.var),
|
||||
node.bindingKeyword.tokenKind == .keyword(.var),
|
||||
let binding = node.bindings.onlyElement,
|
||||
let identifier = binding.pattern.as(IdentifierPatternSyntax.self),
|
||||
identifier.identifier.text == "hashValue",
|
||||
|
@ -95,7 +93,7 @@ extension LegacyHashingRule {
|
|||
return
|
||||
}
|
||||
|
||||
violations.append(node.letOrVarKeyword.positionAfterSkippingLeadingTrivia)
|
||||
violations.append(node.bindingKeyword.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct LegacyMultipleRule: OptInRule, ConfigurationProviderRule, SwiftSyntaxRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "legacy_multiple",
|
|
@ -1,7 +1,5 @@
|
|||
struct LegacyNSGeometryFunctionsRule: SwiftSyntaxCorrectableRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "legacy_nsgeometry_functions",
|
|
@ -29,9 +29,7 @@ private let legacyObjcTypes = [
|
|||
]
|
||||
|
||||
struct LegacyObjcTypeRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "legacy_objc_type",
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct LegacyRandomRule: SwiftSyntaxRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static var description = RuleDescription(
|
||||
identifier: "legacy_random",
|
||||
|
@ -16,9 +14,9 @@ struct LegacyRandomRule: SwiftSyntaxRule, ConfigurationProviderRule {
|
|||
Example("Float.random(in: 0 ..< 1)\n")
|
||||
],
|
||||
triggeringExamples: [
|
||||
Example("↓arc4random(10)\n"),
|
||||
Example("↓arc4random()\n"),
|
||||
Example("↓arc4random_uniform(83)\n"),
|
||||
Example("↓drand48(52)\n")
|
||||
Example("↓drand48()\n")
|
||||
]
|
||||
)
|
||||
|
|
@ -2,9 +2,7 @@ import Foundation
|
|||
import SourceKittenFramework
|
||||
|
||||
struct NimbleOperatorRule: ConfigurationProviderRule, OptInRule, CorrectableRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "nimble_operator",
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct NoExtensionAccessModifierRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.error)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.error)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "no_extension_access_modifier",
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct NoFallthroughOnlyRule: SwiftSyntaxRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "no_fallthrough_only",
|
|
@ -1,9 +1,7 @@
|
|||
import SourceKittenFramework
|
||||
|
||||
struct NoGroupingExtensionRule: OptInRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "no_grouping_extension",
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct NoMagicNumbersRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule {
|
||||
init() {}
|
||||
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
var configuration = NoMagicNumbersConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "no_magic_numbers",
|
||||
|
@ -44,6 +42,20 @@ struct NoMagicNumbersRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule
|
|||
case positive = 2
|
||||
case negative = -2
|
||||
}
|
||||
"""),
|
||||
Example("""
|
||||
class FooTests: XCTestCase {
|
||||
let array: [Int] = []
|
||||
let bar = array[42]
|
||||
}
|
||||
"""),
|
||||
Example("""
|
||||
class FooTests: XCTestCase {
|
||||
class Bar {
|
||||
let array: [Int] = []
|
||||
let bar = array[42]
|
||||
}
|
||||
}
|
||||
""")
|
||||
],
|
||||
triggeringExamples: [
|
||||
|
@ -57,20 +69,27 @@ struct NoMagicNumbersRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule
|
|||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(viewMode: .sourceAccurate)
|
||||
Visitor(viewMode: .sourceAccurate, testParentClasses: configuration.testParentClasses)
|
||||
}
|
||||
}
|
||||
|
||||
private extension NoMagicNumbersRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let testParentClasses: Set<String>
|
||||
|
||||
init(viewMode: SyntaxTreeViewMode, testParentClasses: Set<String>) {
|
||||
self.testParentClasses = testParentClasses
|
||||
super.init(viewMode: viewMode)
|
||||
}
|
||||
|
||||
override func visitPost(_ node: FloatLiteralExprSyntax) {
|
||||
if node.floatingDigits.isMagicNumber {
|
||||
if node.isMemberOfATestClass(testParentClasses) == false, node.floatingDigits.isMagicNumber {
|
||||
violations.append(node.floatingDigits.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
}
|
||||
|
||||
override func visitPost(_ node: IntegerLiteralExprSyntax) {
|
||||
if node.digits.isMagicNumber {
|
||||
if node.isMemberOfATestClass(testParentClasses) == false, node.digits.isMagicNumber {
|
||||
violations.append(node.digits.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
}
|
||||
|
@ -92,3 +111,19 @@ private extension TokenSyntax {
|
|||
&& grandparent.as(PrefixOperatorExprSyntax.self)?.parent?.is(InitializerClauseSyntax.self) != true
|
||||
}
|
||||
}
|
||||
|
||||
private extension ExprSyntaxProtocol {
|
||||
func isMemberOfATestClass(_ testParentClasses: Set<String>) -> Bool {
|
||||
var parent = parent
|
||||
while parent != nil {
|
||||
if
|
||||
let classDecl = parent?.as(ClassDeclSyntax.self),
|
||||
classDecl.isXCTestCase(testParentClasses)
|
||||
{
|
||||
return true
|
||||
}
|
||||
parent = parent?.parent
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct ObjectLiteralRule: SwiftSyntaxRule, ConfigurationProviderRule, OptInRule {
|
||||
var configuration = ObjectLiteralConfiguration()
|
||||
|
||||
init() {}
|
||||
var configuration = ObjectLiteralConfiguration<Self>()
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "object_literal",
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct PatternMatchingKeywordsRule: SwiftSyntaxRule, ConfigurationProviderRule, OptInRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "pattern_matching_keywords",
|
||||
|
@ -57,12 +55,12 @@ private extension PatternMatchingKeywordsRule {
|
|||
}
|
||||
|
||||
guard list.count > 1,
|
||||
let firstLetOrVar = list.first?.letOrVarKeyword.tokenKind else {
|
||||
let firstLetOrVar = list.first?.bindingKeyword.tokenKind else {
|
||||
return
|
||||
}
|
||||
|
||||
let hasViolation = list.allSatisfy { elem in
|
||||
elem.letOrVarKeyword.tokenKind == firstLetOrVar
|
||||
elem.bindingKeyword.tokenKind == firstLetOrVar
|
||||
}
|
||||
|
||||
guard hasViolation else {
|
||||
|
@ -70,7 +68,7 @@ private extension PatternMatchingKeywordsRule {
|
|||
}
|
||||
|
||||
violations.append(contentsOf: list.compactMap { elem in
|
||||
return elem.letOrVarKeyword.positionAfterSkippingLeadingTrivia
|
||||
return elem.bindingKeyword.positionAfterSkippingLeadingTrivia
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct PreferNimbleRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "prefer_nimble",
|
|
@ -1,7 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct PreferZeroOverExplicitInitRule: SwiftSyntaxCorrectableRule, OptInRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "prefer_zero_over_explicit_init",
|
||||
|
@ -34,8 +34,6 @@ struct PreferZeroOverExplicitInitRule: SwiftSyntaxCorrectableRule, OptInRule, Co
|
|||
]
|
||||
)
|
||||
|
||||
init() {}
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
@ -80,8 +78,8 @@ private extension PreferZeroOverExplicitInitRule {
|
|||
.with(\.base, "\(raw: name)")
|
||||
return super.visit(
|
||||
newNode
|
||||
.with(\.leadingTrivia, node.leadingTrivia ?? .zero)
|
||||
.with(\.trailingTrivia, node.trailingTrivia ?? .zero)
|
||||
.with(\.leadingTrivia, node.leadingTrivia)
|
||||
.with(\.trailingTrivia, node.trailingTrivia)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct PrivateOverFilePrivateRule: ConfigurationProviderRule, SwiftSyntaxCorrectableRule {
|
||||
var configuration = PrivateOverFilePrivateRuleConfiguration()
|
||||
|
||||
init() {}
|
||||
var configuration = PrivateOverFilePrivateConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "private_over_fileprivate",
|
||||
|
@ -150,110 +148,123 @@ private extension PrivateOverFilePrivateRule {
|
|||
// don't call super in any of the `visit` methods to avoid digging into the children
|
||||
override func visit(_ node: ExtensionDeclSyntax) -> DeclSyntax {
|
||||
guard validateExtensions, let modifier = node.modifiers.fileprivateModifier,
|
||||
let modifierIndex = node.modifiers.fileprivateModifierIndex,
|
||||
!node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) else {
|
||||
return DeclSyntax(node)
|
||||
}
|
||||
|
||||
correctionPositions.append(modifier.positionAfterSkippingLeadingTrivia)
|
||||
let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifier: modifier))
|
||||
let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifierIndex: modifierIndex))
|
||||
return DeclSyntax(newNode)
|
||||
}
|
||||
|
||||
override func visit(_ node: ClassDeclSyntax) -> DeclSyntax {
|
||||
guard let modifier = node.modifiers.fileprivateModifier,
|
||||
let modifierIndex = node.modifiers.fileprivateModifierIndex,
|
||||
!node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) else {
|
||||
return DeclSyntax(node)
|
||||
}
|
||||
|
||||
correctionPositions.append(modifier.positionAfterSkippingLeadingTrivia)
|
||||
let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifier: modifier))
|
||||
let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifierIndex: modifierIndex))
|
||||
return DeclSyntax(newNode)
|
||||
}
|
||||
|
||||
override func visit(_ node: StructDeclSyntax) -> DeclSyntax {
|
||||
guard let modifier = node.modifiers.fileprivateModifier,
|
||||
let modifierIndex = node.modifiers.fileprivateModifierIndex,
|
||||
!node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) else {
|
||||
return DeclSyntax(node)
|
||||
}
|
||||
|
||||
correctionPositions.append(modifier.positionAfterSkippingLeadingTrivia)
|
||||
let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifier: modifier))
|
||||
let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifierIndex: modifierIndex))
|
||||
return DeclSyntax(newNode)
|
||||
}
|
||||
|
||||
override func visit(_ node: EnumDeclSyntax) -> DeclSyntax {
|
||||
guard let modifier = node.modifiers.fileprivateModifier,
|
||||
let modifierIndex = node.modifiers.fileprivateModifierIndex,
|
||||
!node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) else {
|
||||
return DeclSyntax(node)
|
||||
}
|
||||
|
||||
correctionPositions.append(modifier.positionAfterSkippingLeadingTrivia)
|
||||
let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifier: modifier))
|
||||
let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifierIndex: modifierIndex))
|
||||
return DeclSyntax(newNode)
|
||||
}
|
||||
|
||||
override func visit(_ node: ProtocolDeclSyntax) -> DeclSyntax {
|
||||
guard let modifier = node.modifiers.fileprivateModifier,
|
||||
let modifierIndex = node.modifiers.fileprivateModifierIndex,
|
||||
!node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) else {
|
||||
return DeclSyntax(node)
|
||||
}
|
||||
|
||||
correctionPositions.append(modifier.positionAfterSkippingLeadingTrivia)
|
||||
let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifier: modifier))
|
||||
let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifierIndex: modifierIndex))
|
||||
return DeclSyntax(newNode)
|
||||
}
|
||||
|
||||
override func visit(_ node: FunctionDeclSyntax) -> DeclSyntax {
|
||||
guard let modifier = node.modifiers.fileprivateModifier,
|
||||
let modifierIndex = node.modifiers.fileprivateModifierIndex,
|
||||
!node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) else {
|
||||
return DeclSyntax(node)
|
||||
}
|
||||
|
||||
correctionPositions.append(modifier.positionAfterSkippingLeadingTrivia)
|
||||
let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifier: modifier))
|
||||
let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifierIndex: modifierIndex))
|
||||
return DeclSyntax(newNode)
|
||||
}
|
||||
|
||||
override func visit(_ node: VariableDeclSyntax) -> DeclSyntax {
|
||||
guard let modifier = node.modifiers.fileprivateModifier,
|
||||
let modifierIndex = node.modifiers.fileprivateModifierIndex,
|
||||
!node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) else {
|
||||
return DeclSyntax(node)
|
||||
}
|
||||
|
||||
correctionPositions.append(modifier.positionAfterSkippingLeadingTrivia)
|
||||
let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifier: modifier))
|
||||
let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifierIndex: modifierIndex))
|
||||
return DeclSyntax(newNode)
|
||||
}
|
||||
|
||||
override func visit(_ node: TypealiasDeclSyntax) -> DeclSyntax {
|
||||
guard let modifier = node.modifiers.fileprivateModifier,
|
||||
let modifierIndex = node.modifiers.fileprivateModifierIndex,
|
||||
!node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) else {
|
||||
return DeclSyntax(node)
|
||||
}
|
||||
|
||||
correctionPositions.append(modifier.positionAfterSkippingLeadingTrivia)
|
||||
let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifier: modifier))
|
||||
let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifierIndex: modifierIndex))
|
||||
return DeclSyntax(newNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension ModifierListSyntax? {
|
||||
var fileprivateModifierIndex: ModifierListSyntax.Index? {
|
||||
self?.firstIndex(where: { $0.name.tokenKind == .keyword(.fileprivate) })
|
||||
}
|
||||
|
||||
var fileprivateModifier: DeclModifierSyntax? {
|
||||
self?.first { $0.name.tokenKind == .keyword(.fileprivate) }
|
||||
fileprivateModifierIndex.flatMap { self?[$0] }
|
||||
}
|
||||
}
|
||||
|
||||
private extension ModifierListSyntax {
|
||||
func replacing(fileprivateModifier: DeclModifierSyntax) -> ModifierListSyntax? {
|
||||
replacing(
|
||||
childAt: fileprivateModifier.indexInParent,
|
||||
func replacing(fileprivateModifierIndex: ModifierListSyntax.Index) -> ModifierListSyntax? {
|
||||
let fileprivateModifier = self[fileprivateModifierIndex]
|
||||
return replacing(
|
||||
childAt: self.distance(from: self.startIndex, to: fileprivateModifierIndex),
|
||||
with: fileprivateModifier.with(
|
||||
\.name,
|
||||
.keyword(
|
||||
.private,
|
||||
leadingTrivia: fileprivateModifier.leadingTrivia ?? .zero,
|
||||
trailingTrivia: fileprivateModifier.trailingTrivia ?? .zero
|
||||
leadingTrivia: fileprivateModifier.leadingTrivia,
|
||||
trailingTrivia: fileprivateModifier.trailingTrivia
|
||||
)
|
||||
)
|
||||
)
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct RedundantNilCoalescingRule: OptInRule, SwiftSyntaxCorrectableRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "redundant_nil_coalescing",
|
||||
|
@ -38,7 +36,8 @@ struct RedundantNilCoalescingRule: OptInRule, SwiftSyntaxCorrectableRule, Config
|
|||
private extension RedundantNilCoalescingRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
override func visitPost(_ node: TokenSyntax) {
|
||||
if node.tokenKind.isNilCoalescingOperator && node.nextToken?.tokenKind == .keyword(.nil) {
|
||||
if node.tokenKind.isNilCoalescingOperator,
|
||||
node.nextToken(viewMode: .sourceAccurate)?.tokenKind == .keyword(.nil) {
|
||||
violations.append(node.position)
|
||||
}
|
||||
}
|
|
@ -6,9 +6,7 @@ private let attributeNamesImplyingObjc: Set<String> = [
|
|||
]
|
||||
|
||||
struct RedundantObjcAttributeRule: SwiftSyntaxRule, SubstitutionCorrectableRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "redundant_objc_attribute",
|
||||
|
@ -70,6 +68,15 @@ private extension Syntax {
|
|||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var functionOrVariableModifiers: ModifierListSyntax? {
|
||||
if let functionDecl = self.as(FunctionDeclSyntax.self) {
|
||||
return functionDecl.modifiers
|
||||
} else if let variableDecl = self.as(VariableDeclSyntax.self) {
|
||||
return variableDecl.modifiers
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private extension AttributeListSyntax {
|
||||
|
@ -80,10 +87,12 @@ private extension AttributeListSyntax {
|
|||
|
||||
if hasAttributeImplyingObjC, parent?.is(ExtensionDeclSyntax.self) != true {
|
||||
return objcAttribute
|
||||
} else if parent?.is(EnumDeclSyntax.self) == true {
|
||||
return nil
|
||||
} else if parent?.isFunctionOrStoredProperty == true,
|
||||
let parentClassDecl = parent?.parent?.parent?.parent?.parent?.as(ClassDeclSyntax.self),
|
||||
parentClassDecl.attributes.contains(attributeNamed: "objcMembers") {
|
||||
return objcAttribute
|
||||
return parent?.functionOrVariableModifiers.isPrivateOrFileprivate == true ? nil : objcAttribute
|
||||
} else if let parentExtensionDecl = parent?.parent?.parent?.parent?.parent?.as(ExtensionDeclSyntax.self),
|
||||
parentExtensionDecl.attributes?.objCAttribute != nil {
|
||||
return objcAttribute
|
|
@ -13,7 +13,7 @@ struct RedundantObjcAttributeRuleExamples {
|
|||
class Foo {
|
||||
var bar: Any?
|
||||
@objc
|
||||
class Bar {
|
||||
class Bar: NSObject {
|
||||
@objc
|
||||
var foo: Any?
|
||||
}
|
||||
|
@ -59,14 +59,15 @@ struct RedundantObjcAttributeRuleExamples {
|
|||
Example("""
|
||||
@objcMembers
|
||||
class Foo {
|
||||
@objc
|
||||
class Bar: NSObject {
|
||||
@objc var foo: Any
|
||||
@objc var foo: Any?
|
||||
}
|
||||
}
|
||||
"""),
|
||||
Example("""
|
||||
@objcMembers
|
||||
class Foo {
|
||||
class Foo: NSObject {
|
||||
@objc class Bar {}
|
||||
}
|
||||
"""),
|
||||
|
@ -75,6 +76,59 @@ struct RedundantObjcAttributeRuleExamples {
|
|||
@objc(addElementsObject:)
|
||||
@NSManaged public func addToElements(_ value: BlockEditorSettingElement)
|
||||
}
|
||||
"""),
|
||||
Example("""
|
||||
@objcMembers
|
||||
public class Foo: NSObject {
|
||||
@objc
|
||||
private func handler(_ notification: Notification) {
|
||||
}
|
||||
|
||||
func registerForNotifications() {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(handler(_:)), name: nil, object: nil)
|
||||
}
|
||||
}
|
||||
"""),
|
||||
Example("""
|
||||
class Foo: NSObject { }
|
||||
|
||||
@objc extension Foo {
|
||||
@objc enum Bar: Int {
|
||||
case bar
|
||||
}
|
||||
|
||||
var bar: Bar { .bar }
|
||||
}
|
||||
"""),
|
||||
Example("""
|
||||
class Foo: NSObject { }
|
||||
|
||||
@objc extension Foo {
|
||||
@objc private enum Baz: Int {
|
||||
case baz
|
||||
}
|
||||
|
||||
private var baz: Baz { .baz }
|
||||
}
|
||||
"""),
|
||||
Example("""
|
||||
@objcMembers
|
||||
internal class Foo: NSObject {
|
||||
@objc
|
||||
private var baz: Int = 1
|
||||
|
||||
var x: Any? {
|
||||
value(forKey: "baz")
|
||||
}
|
||||
}
|
||||
"""),
|
||||
Example("""
|
||||
@objcMembers
|
||||
class Foo: NSObject {
|
||||
@objc enum Bar: Int {
|
||||
case bar
|
||||
}
|
||||
}
|
||||
""")
|
||||
]
|
||||
|
||||
|
@ -90,13 +144,13 @@ struct RedundantObjcAttributeRuleExamples {
|
|||
Example("↓@objc @IBDesignable class Foo {}"),
|
||||
Example("""
|
||||
@objcMembers
|
||||
class Foo {
|
||||
class Foo: NSObject {
|
||||
↓@objc var bar: Any?
|
||||
}
|
||||
"""),
|
||||
Example("""
|
||||
@objcMembers
|
||||
class Foo {
|
||||
class Foo: NSObject {
|
||||
↓@objc var bar: Any?
|
||||
↓@objc var foo: Any?
|
||||
@objc
|
||||
|
@ -126,7 +180,7 @@ struct RedundantObjcAttributeRuleExamples {
|
|||
"""),
|
||||
Example("""
|
||||
@objcMembers
|
||||
class Foo {
|
||||
class Foo: NSObject {
|
||||
@objcMembers
|
||||
class Bar: NSObject {
|
||||
↓@objc var foo: Any
|
||||
|
@ -160,23 +214,23 @@ struct RedundantObjcAttributeRuleExamples {
|
|||
Example("↓@objc @IBDesignable class Foo {}"): Example("@IBDesignable class Foo {}"),
|
||||
Example("""
|
||||
@objcMembers
|
||||
class Foo {
|
||||
class Foo: NSObject {
|
||||
↓@objc var bar: Any?
|
||||
}
|
||||
"""):
|
||||
Example("""
|
||||
@objcMembers
|
||||
class Foo {
|
||||
class Foo: NSObject {
|
||||
var bar: Any?
|
||||
}
|
||||
"""),
|
||||
Example("""
|
||||
@objcMembers
|
||||
class Foo {
|
||||
class Foo: NSObject {
|
||||
↓@objc var bar: Any?
|
||||
↓@objc var foo: Any?
|
||||
@objc
|
||||
class Bar {
|
||||
class Bar: NSObject {
|
||||
@objc
|
||||
var foo2: Any?
|
||||
}
|
||||
|
@ -184,11 +238,11 @@ struct RedundantObjcAttributeRuleExamples {
|
|||
"""):
|
||||
Example("""
|
||||
@objcMembers
|
||||
class Foo {
|
||||
class Foo: NSObject {
|
||||
var bar: Any?
|
||||
var foo: Any?
|
||||
@objc
|
||||
class Bar {
|
||||
class Bar: NSObject {
|
||||
@objc
|
||||
var foo2: Any?
|
||||
}
|
||||
|
@ -230,7 +284,7 @@ struct RedundantObjcAttributeRuleExamples {
|
|||
"""),
|
||||
Example("""
|
||||
@objcMembers
|
||||
class Foo {
|
||||
class Foo: NSObject {
|
||||
@objcMembers
|
||||
class Bar: NSObject {
|
||||
↓@objc var foo: Any
|
||||
|
@ -239,7 +293,7 @@ struct RedundantObjcAttributeRuleExamples {
|
|||
"""):
|
||||
Example("""
|
||||
@objcMembers
|
||||
class Foo {
|
||||
class Foo: NSObject {
|
||||
@objcMembers
|
||||
class Bar: NSObject {
|
||||
var foo: Any
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct RedundantOptionalInitializationRule: SwiftSyntaxCorrectableRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "redundant_optional_initialization",
|
||||
|
@ -121,7 +119,7 @@ struct RedundantOptionalInitializationRule: SwiftSyntaxCorrectableRule, Configur
|
|||
private extension RedundantOptionalInitializationRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
override func visitPost(_ node: VariableDeclSyntax) {
|
||||
guard node.letOrVarKeyword.tokenKind == .keyword(.var),
|
||||
guard node.bindingKeyword.tokenKind == .keyword(.var),
|
||||
!node.modifiers.containsLazy else {
|
||||
return
|
||||
}
|
||||
|
@ -141,7 +139,7 @@ private extension RedundantOptionalInitializationRule {
|
|||
}
|
||||
|
||||
override func visit(_ node: VariableDeclSyntax) -> DeclSyntax {
|
||||
guard node.letOrVarKeyword.tokenKind == .keyword(.var),
|
||||
guard node.bindingKeyword.tokenKind == .keyword(.var),
|
||||
!node.modifiers.containsLazy else {
|
||||
return super.visit(node)
|
||||
}
|
||||
|
@ -170,9 +168,9 @@ private extension RedundantOptionalInitializationRule {
|
|||
return newBinding
|
||||
}
|
||||
if binding.trailingComma != nil {
|
||||
return newBinding.with(\.typeAnnotation, binding.typeAnnotation?.with(\.trailingTrivia, .zero))
|
||||
return newBinding.with(\.typeAnnotation, binding.typeAnnotation?.with(\.trailingTrivia, Trivia()))
|
||||
}
|
||||
return newBinding.with(\.trailingTrivia, binding.initializer?.trailingTrivia ?? .zero)
|
||||
return newBinding.with(\.trailingTrivia, binding.initializer?.trailingTrivia ?? Trivia())
|
||||
})
|
||||
|
||||
return super.visit(node.with(\.bindings, newBindings))
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct RedundantSetAccessControlRule: ConfigurationProviderRule, SwiftSyntaxRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "redundant_set_access_control",
|
||||
|
@ -144,7 +142,7 @@ private extension DeclSyntax {
|
|||
|
||||
private extension ModifierListSyntax {
|
||||
var setAccessor: DeclModifierSyntax? {
|
||||
first { $0.detail?.detail.tokenKind == .keyword(.set) }
|
||||
first { $0.detail?.detail.tokenKind == .identifier("set") }
|
||||
}
|
||||
|
||||
var getAccessor: DeclModifierSyntax? {
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct RedundantStringEnumValueRule: SwiftSyntaxRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "redundant_string_enum_value",
|
||||
|
@ -73,7 +71,7 @@ private extension RedundantStringEnumValueRule {
|
|||
return
|
||||
}
|
||||
|
||||
let enumsWithExplicitValues = node.members.members
|
||||
let enumsWithExplicitValues = node.memberBlock.members
|
||||
.flatMap { member -> EnumCaseElementListSyntax in
|
||||
guard let enumCaseDecl = member.decl.as(EnumCaseDeclSyntax.self) else {
|
||||
return EnumCaseElementListSyntax([])
|
|
@ -2,7 +2,7 @@ import Foundation
|
|||
import SourceKittenFramework
|
||||
|
||||
struct RedundantTypeAnnotationRule: OptInRule, SubstitutionCorrectableRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "redundant_type_annotation",
|
|
@ -2,9 +2,7 @@ import Foundation
|
|||
import SourceKittenFramework
|
||||
|
||||
struct RedundantVoidReturnRule: ConfigurationProviderRule, SubstitutionCorrectableASTRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "redundant_void_return",
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct ReturnValueFromVoidFunctionRule: ConfigurationProviderRule, OptInRule, SwiftSyntaxRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "return_value_from_void_function",
|
|
@ -1,7 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct ShorthandOptionalBindingRule: OptInRule, SwiftSyntaxCorrectableRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static var description = RuleDescription(
|
||||
identifier: "shorthand_optional_binding",
|
||||
|
@ -79,8 +79,6 @@ struct ShorthandOptionalBindingRule: OptInRule, SwiftSyntaxCorrectableRule, Conf
|
|||
deprecatedAliases: ["if_let_shadowing"]
|
||||
)
|
||||
|
||||
init() {}
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
@ -96,7 +94,7 @@ struct ShorthandOptionalBindingRule: OptInRule, SwiftSyntaxCorrectableRule, Conf
|
|||
private class Visitor: ViolationsSyntaxVisitor {
|
||||
override func visitPost(_ node: OptionalBindingConditionSyntax) {
|
||||
if node.isShadowingOptionalBinding {
|
||||
violations.append(node.letOrVarKeyword.positionAfterSkippingLeadingTrivia)
|
||||
violations.append(node.bindingKeyword.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +120,7 @@ private class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter {
|
|||
correctionPositions.append(node.positionAfterSkippingLeadingTrivia)
|
||||
let newNode = node
|
||||
.with(\.initializer, nil)
|
||||
.with(\.pattern, node.pattern.with(\.trailingTrivia, node.trailingTrivia ?? .zero))
|
||||
.with(\.pattern, node.pattern.with(\.trailingTrivia, node.trailingTrivia))
|
||||
return super.visit(newNode)
|
||||
}
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct StaticOperatorRule: SwiftSyntaxRule, ConfigurationProviderRule, OptInRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "static_operator",
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct StrictFilePrivateRule: OptInRule, ConfigurationProviderRule, SwiftSyntaxRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "strict_fileprivate",
|
||||
|
@ -196,7 +194,7 @@ private extension StrictFilePrivateRule {
|
|||
return
|
||||
}
|
||||
if let varDecl = grandparent.as(VariableDeclSyntax.self) {
|
||||
let isSpecificForSetter = node.detail?.detail.tokenKind == .keyword(.set)
|
||||
let isSpecificForSetter = node.detail?.detail.tokenKind == .identifier("set")
|
||||
let firstImplementingProtocol = varDecl.bindings
|
||||
.flatMap { binding in
|
||||
let pattern = binding.pattern
|
|
@ -3,9 +3,7 @@ import SourceKittenFramework
|
|||
import SwiftSyntax
|
||||
|
||||
struct SyntacticSugarRule: CorrectableRule, ConfigurationProviderRule, SourceKitFreeRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "syntactic_sugar",
|
||||
|
@ -334,7 +332,7 @@ extension SimpleTypeIdentifierSyntax: SyntaxWithGenericClause {
|
|||
|
||||
extension SpecializeExprSyntax: SyntaxWithGenericClause {
|
||||
var typeName: String? {
|
||||
expression.as(IdentifierExprSyntax.self)?.firstToken?.text ??
|
||||
expression.as(IdentifierExprSyntax.self)?.firstToken(viewMode: .sourceAccurate)?.text ??
|
||||
expression.as(MemberAccessExprSyntax.self)?.name.text
|
||||
}
|
||||
var genericArguments: GenericArgumentClauseSyntax? { genericArgumentClause }
|
|
@ -2,9 +2,7 @@ import SwiftSyntax
|
|||
import SwiftSyntaxBuilder
|
||||
|
||||
struct ToggleBoolRule: SwiftSyntaxCorrectableRule, ConfigurationProviderRule, OptInRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static var description = RuleDescription(
|
||||
identifier: "toggle_bool",
|
||||
|
@ -79,8 +77,8 @@ private extension ToggleBoolRule {
|
|||
)
|
||||
.removingLast()
|
||||
.removingLast()
|
||||
.with(\.leadingTrivia, node.leadingTrivia ?? .zero)
|
||||
.with(\.trailingTrivia, node.trailingTrivia ?? .zero)
|
||||
.with(\.leadingTrivia, node.leadingTrivia)
|
||||
.with(\.trailingTrivia, node.trailingTrivia)
|
||||
|
||||
return super.visit(newNode)
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
import SwiftSyntax
|
||||
|
||||
struct TrailingSemicolonRule: SwiftSyntaxCorrectableRule, ConfigurationProviderRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "trailing_semicolon",
|
||||
|
@ -66,7 +64,7 @@ private extension TrailingSemicolonRule {
|
|||
}
|
||||
|
||||
correctionPositions.append(node.positionAfterSkippingLeadingTrivia)
|
||||
return .unknown("").with(\.trailingTrivia, node.trailingTrivia ?? .zero)
|
||||
return .unknown("").with(\.trailingTrivia, node.trailingTrivia)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +72,9 @@ private extension TrailingSemicolonRule {
|
|||
private extension TokenSyntax {
|
||||
var isTrailingSemicolon: Bool {
|
||||
tokenKind == .semicolon &&
|
||||
(trailingTrivia.containsNewlines() || (nextToken?.leadingTrivia.containsNewlines() == true))
|
||||
(
|
||||
trailingTrivia.containsNewlines() ||
|
||||
(nextToken(viewMode: .sourceAccurate)?.leadingTrivia.containsNewlines() == true)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -2,9 +2,7 @@ import Foundation
|
|||
import SwiftSyntax
|
||||
|
||||
struct TypeNameRule: SwiftSyntaxRule, ConfigurationProviderRule {
|
||||
var configuration = TypeNameRuleConfiguration()
|
||||
|
||||
init() {}
|
||||
var configuration = TypeNameConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "type_name",
|
||||
|
@ -26,9 +24,9 @@ struct TypeNameRule: SwiftSyntaxRule, ConfigurationProviderRule {
|
|||
|
||||
private extension TypeNameRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let configuration: TypeNameRuleConfiguration
|
||||
private let configuration: TypeNameConfiguration
|
||||
|
||||
init(configuration: TypeNameRuleConfiguration) {
|
||||
init(configuration: TypeNameConfiguration) {
|
||||
self.configuration = configuration
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
@ -94,20 +92,18 @@ private extension TypeNameRule {
|
|||
.strippingBackticks()
|
||||
.strippingLeadingUnderscoreIfPrivate(modifiers: modifiers)
|
||||
.strippingTrailingSwiftUIPreviewProvider(inheritedTypes: inheritedTypes)
|
||||
let allowedSymbols = nameConfiguration.allowedSymbols.union(.alphanumerics)
|
||||
|
||||
if !allowedSymbols.isSuperset(of: CharacterSet(charactersIn: name)) {
|
||||
if !nameConfiguration.allowedSymbolsAndAlphanumerics.isSuperset(of: CharacterSet(charactersIn: name)) {
|
||||
return ReasonedRuleViolation(
|
||||
position: identifier.positionAfterSkippingLeadingTrivia,
|
||||
reason: "Type name '\(name)' should only contain alphanumeric characters",
|
||||
reason: "Type name '\(name)' should only contain alphanumeric and other allowed characters",
|
||||
severity: .error
|
||||
)
|
||||
} else if nameConfiguration.validatesStartWithLowercase &&
|
||||
} else if let caseCheckSeverity = nameConfiguration.validatesStartWithLowercase.severity,
|
||||
name.first?.isLowercase == true {
|
||||
return ReasonedRuleViolation(
|
||||
position: identifier.positionAfterSkippingLeadingTrivia,
|
||||
reason: "Type name '\(name)' should start with an uppercase character",
|
||||
severity: .error
|
||||
severity: caseCheckSeverity
|
||||
)
|
||||
} else if let severity = nameConfiguration.severity(forLength: name.count) {
|
||||
return ReasonedRuleViolation(
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue