SwiftLint icon indicating copy to clipboard operation
SwiftLint copied to clipboard

Migrate Custom Rules from SourceKit to SwiftSyntax

Open jpsim opened this issue 6 months ago • 1 comments

Breaking Change: Custom rules now default to SwiftSyntax mode for pattern matching. This provides significant performance improvements but may have subtle behavioral differences from the previous SourceKit implementation. Users should test their custom rules and adjust as needed. A temporary sourcekit mode is available for rules that cannot be migrated yet.

Breaking Change Details

  • New Default: Custom rules now use swiftsyntax mode by default
  • Legacy Option: Set execution_mode: sourcekit or default_execution_mode: sourcekit to restore previous behavior temporarily
  • Action Required: Test your custom rules after upgrading and migrate to SwiftSyntax mode where possible

Configuration

Control execution mode at two levels:

custom_rules:
  # To restore previous behavior for all rules (temporary):
  default_execution_mode: sourcekit

  my_rule:
    regex: "pattern"
    # Defaults to swiftsyntax now

  legacy_rule:
    regex: "pattern"
    execution_mode: sourcekit  # Use legacy mode for specific rules

Why This Change?

  • Performance: SwiftSyntax mode eliminates SourceKit process overhead
  • Reliability: No more SourceKit crashes or hangs
  • Future-Proof: SwiftLint is migrating away from SourceKit entirely

Migration Guide

  1. Test First: Run your existing custom rules and check for differences
  2. Adjust Rules: Most rules should work identically in SwiftSyntax mode
  3. Use Legacy Mode: For rules that must maintain exact SourceKit behavior, set execution_mode: sourcekit temporarily
  4. Report Issues: Help us improve SwiftSyntax mode by reporting incompatibilities

Technical Implementation

SwiftSyntaxKindBridge

Enables kind filtering (match_kinds/excluded_match_kinds) without SourceKit:

  • Maps SwiftSyntax classifications to SourceKit syntax kinds
  • Covers common use cases with best-effort compatibility
  • Some edge cases may differ from SourceKit behavior

ConditionallySourceKitFree Protocol

Allows CustomRules to skip SourceKit initialization when all rules use SwiftSyntax:

  • Dramatic performance improvement when SourceKit isn't needed
  • Maintains SourceKit availability for legacy rules

Important Notes

  • Not Full Compatibility: While we've worked to maintain compatibility, differences exist. Test thoroughly.
  • Temporary Legacy Support: The sourcekit mode is a temporary measure. Plan to migrate all rules to SwiftSyntax.
  • Future Deprecation: SourceKit mode will be removed in a future version.

Benefits of Migrating

  • Faster linting (no SourceKit startup cost)
  • Lower memory usage
  • Better reliability (no SourceKit crashes)
  • Future-proof your configuration

This change represents a major step in SwiftLint's evolution toward a fully SwiftSyntax-based architecture. We encourage all users to test and migrate their custom rules to the new SwiftSyntax mode, using the legacy SourceKit mode only as a temporary measure for rules that cannot yet be migrated.

jpsim avatar Jun 21 '25 19:06 jpsim

18 Messages
:book: Building this branch resulted in a binary size of 25224.16 KiB vs 25221.15 KiB when built on main (0% larger).
:book: Linting Aerial with this PR took 1.09 s vs 1.04 s on main (4% slower).
:book: Linting Alamofire with this PR took 1.38 s vs 1.38 s on main (0% slower).
:book: Linting Brave with this PR took 9.63 s vs 9.6 s on main (0% slower).
:book: Linting DuckDuckGo with this PR took 24.98 s vs 24.96 s on main (0% slower).
:book: Linting Firefox with this PR took 11.82 s vs 11.85 s on main (0% faster).
:book: Linting Kickstarter with this PR took 10.87 s vs 10.83 s on main (0% slower).
:book: Linting Moya with this PR took 0.55 s vs 0.55 s on main (0% slower).
:book: Linting NetNewsWire with this PR took 3.18 s vs 3.16 s on main (0% slower).
:book: Linting Nimble with this PR took 0.84 s vs 0.84 s on main (0% slower).
:book: Linting PocketCasts with this PR took 9.01 s vs 8.98 s on main (0% slower).
:book: Linting Quick with this PR took 0.49 s vs 0.49 s on main (0% slower).
:book: Linting Realm with this PR took 4.79 s vs 4.78 s on main (0% slower).
:book: Linting Sourcery with this PR took 2.42 s vs 2.42 s on main (0% slower).
:book: Linting Swift with this PR took 5.56 s vs 5.54 s on main (0% slower).
:book: Linting VLC with this PR took 1.47 s vs 1.47 s on main (0% slower).
:book: Linting Wire with this PR took 22.29 s vs 22.26 s on main (0% slower).
:book: Linting WordPress with this PR took 12.82 s vs 12.81 s on main (0% slower).

Generated by :no_entry_sign: Danger

SwiftLintBot avatar Jun 21 '25 20:06 SwiftLintBot