Skip to content

Run SwiftSyntax-mode custom rules without SourceKit - #6847

Draft
bprinsta wants to merge 1 commit into
realm:mainfrom
bprinsta:fix-swiftsyntax-custom-rules
Draft

Run SwiftSyntax-mode custom rules without SourceKit#6847
bprinsta wants to merge 1 commit into
realm:mainfrom
bprinsta:fix-swiftsyntax-custom-rules

Conversation

@bprinsta

Copy link
Copy Markdown

Fixes (partially) #6129.

execution_mode: swiftsyntax (#6128) currently only affects how custom_rules is classified: CustomRules.isEffectivelySourceKitFree reports the rule as SourceKit-free, but validate still matches via file.match(pattern:excludingSyntaxKinds:), which reads file.syntaxMap — a SourceKit request.

This has two consequences when SourceKit access is prohibited (the fully static Linux binary built with SWIFTLINT_DISABLE_SOURCEKIT, or --disable-sourcekit):

  • Rules in the default SourceKit mode make the whole custom_rules group get skipped with Skipping enabled rule 'custom_rules' because it requires SourceKit and SourceKit access is prohibited. — expected, but it means pure-regex custom rules cannot run on the static Linux binary at all.
  • Rules explicitly opted into swiftsyntax mode crash the process: the skip-gate opens because the rule claims to be SourceKit-free, then the first match hits Request.sendIfNotDisabled()queuedFatalError("SourceKit is disabled by configuration.") (exit 134).

Repro for the crash on 0.63.2–0.65.0:

# config.yml
custom_rules:
  no_foobar:
    regex: 'FOOBAR'
    message: "no foobar"
    execution_mode: swiftsyntax
$ swiftlint lint --no-cache --config config.yml --disable-sourcekit Test.swift
SourceKit is disabled by configuration.: file Request+SwiftLint.swift, line 50
[1]    abort      swiftlint lint --no-cache --config config.yml --disable-sourcekit Test.swift

SwiftSyntaxKindBridge already exists to serve exactly this purpose but nothing calls it. This PR wires it in:

  • CustomRules.validate resolves each rule's effective execution mode (shared with isEffectivelySourceKitFree via a new CustomRulesConfiguration.effectiveExecutionMode(for:)) and, for swiftsyntax-mode rules, matches with syntax kinds derived from SwiftSyntax classifications instead of SourceKit.
  • SwiftLintFile.matchWithSwiftSyntaxKinds(pattern:excludingSyntaxKinds:range:captureGroup:) implements the SourceKit-free variant, reusing the existing match plumbing with a SwiftLintSyntaxMap built from swiftSyntaxDerivedSourceKittenTokens.
  • SwiftLintSyntaxMap gains a package init(tokens:).

match_kinds/excluded_match_kinds filtering works in both modes; kinds in SwiftSyntax mode come from SwiftSyntaxKindBridge.mapClassification, so results can differ slightly from SourceKit's syntax map in edge cases (as documented on the bridge).

Tests: two new tests in CustomRulesTests run swiftsyntax-mode rules (with and without match_kinds) under Request.disableSourceKitOverride = true — both crash before this change.

`execution_mode: swiftsyntax` only affected how `custom_rules` was
classified: `isEffectivelySourceKitFree` reported the rule as
SourceKit-free, but `validate` still resolved syntax kinds through the
SourceKit-backed syntax map. With SourceKit access prohibited (the fully
static Linux binary or `--disable-sourcekit`), SwiftSyntax-mode rules
therefore crashed with "SourceKit is disabled by configuration" instead
of linting.

Derive syntax kinds from SwiftSyntax classifications via the existing
SwiftSyntaxKindBridge when a custom rule's effective execution mode is
`swiftsyntax`, leaving the SourceKit path untouched for rules in
SourceKit mode.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@SwiftLintBot

Copy link
Copy Markdown
19 Messages
📖 Building this branch resulted in a binary size of 28423.84 KiB vs 28420.1 KiB when built on main (0% larger).
📖 Linting Aerial with this PR took 0.64 s vs 0.66 s on main (3% faster).
📖 Linting Alamofire with this PR took 0.91 s vs 0.94 s on main (3% faster).
📖 Linting Brave with this PR took 6.01 s vs 6.04 s on main (0% faster).
📖 Linting DuckDuckGo with this PR took 26.9 s vs 26.9 s on main (0% slower).
📖 Linting Firefox with this PR took 10.68 s vs 10.67 s on main (0% slower).
📖 Linting Kickstarter with this PR took 7.21 s vs 7.35 s on main (1% faster).
📖 Linting Moya with this PR took 0.36 s vs 0.38 s on main (5% faster).
📖 Linting NetNewsWire with this PR took 2.34 s vs 2.33 s on main (0% slower).
📖 Linting Nimble with this PR took 0.53 s vs 0.55 s on main (3% faster).
📖 Linting PocketCasts with this PR took 6.88 s vs 6.9 s on main (0% faster).
📖 Linting Quick with this PR took 0.35 s vs 0.35 s on main (0% slower).
📖 Linting Realm with this PR took 2.84 s vs 2.85 s on main (0% faster).
📖 Linting Sourcery with this PR took 1.64 s vs 1.64 s on main (0% slower).
📖 Linting Swift with this PR took 4.28 s vs 4.23 s on main (1% slower).
📖 Linting SwiftLintPerformanceTests with this PR took 0.16 s vs 0.16 s on main (0% slower).
📖 Linting VLC with this PR took 1.21 s vs 1.25 s on main (3% faster).
📖 Linting Wire with this PR took 15.37 s vs 15.37 s on main (0% slower).
📖 Linting WordPress with this PR took 9.76 s vs 9.69 s on main (0% slower).

Generated by 🚫 Danger

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants