From 8978ae2ccb090107e50325d4159ff52a8ee83786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danny=20M=C3=B6sch?= Date: Thu, 15 Jan 2026 20:30:52 +0100 Subject: [PATCH] Add `--disable-sourcekit` flag to disable SourceKit (#6439) --- CHANGELOG.md | 5 ++++- .../SwiftLintCore/Extensions/Request+SwiftLint.swift | 10 ++++++---- Source/SwiftLintFramework/LintOrAnalyzeCommand.swift | 5 +++++ Source/swiftlint/Commands/Analyze.swift | 1 + Source/swiftlint/Commands/Lint.swift | 6 ++++++ Tests/FrameworkTests/LintOrAnalyzeOptionsTests.swift | 1 + 6 files changed, 23 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f5c0d2e2..68b416b3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,10 @@ ### Enhancements -* None. +* Add a `--disable-sourcekit` flag to the `lint` command to disable SourceKit when needed. + The environment variable `SWIFTLINT_DISABLE_SOURCEKIT` can still be used as well. + [SimplyDanny](https://github.com/SimplyDanny) + [#6282](https://github.com/realm/SwiftLint/issues/6282) ### Bug Fixes diff --git a/Source/SwiftLintCore/Extensions/Request+SwiftLint.swift b/Source/SwiftLintCore/Extensions/Request+SwiftLint.swift index cb0ce2940..47e304553 100644 --- a/Source/SwiftLintCore/Extensions/Request+SwiftLint.swift +++ b/Source/SwiftLintCore/Extensions/Request+SwiftLint.swift @@ -2,15 +2,17 @@ import Foundation import SourceKittenFramework public extension Request { - static let disableSourceKit = { + nonisolated(unsafe) static var disableSourceKitOverride = false + + static var disableSourceKit: Bool { #if SWIFTLINT_DISABLE_SOURCEKIT // Compile-time true #else // Runtime - ProcessInfo.processInfo.environment["SWIFTLINT_DISABLE_SOURCEKIT"] != nil + ProcessInfo.processInfo.environment["SWIFTLINT_DISABLE_SOURCEKIT"] != nil || disableSourceKitOverride #endif - }() + } func sendIfNotDisabled() throws -> [String: any SourceKitRepresentable] { // Skip safety checks if explicitly allowed (e.g., for testing or specific operations) @@ -45,7 +47,7 @@ public extension Request { } guard !Self.disableSourceKit else { - queuedFatalError("SourceKit is disabled by `SWIFTLINT_DISABLE_SOURCEKIT`.") + queuedFatalError("SourceKit is disabled by configuration.") } return try send() } diff --git a/Source/SwiftLintFramework/LintOrAnalyzeCommand.swift b/Source/SwiftLintFramework/LintOrAnalyzeCommand.swift index b3f16d86a..6444adc84 100644 --- a/Source/SwiftLintFramework/LintOrAnalyzeCommand.swift +++ b/Source/SwiftLintFramework/LintOrAnalyzeCommand.swift @@ -3,6 +3,7 @@ #endif import Dispatch import Foundation +import SourceKittenFramework // swiftlint:disable file_length @@ -53,6 +54,7 @@ package struct LintOrAnalyzeOptions { let onlyRule: [String] let autocorrect: Bool let format: Bool + let disableSourceKit: Bool let compilerLogPath: String? let compileCommands: String? let checkForUpdates: Bool @@ -81,6 +83,7 @@ package struct LintOrAnalyzeOptions { onlyRule: [String], autocorrect: Bool, format: Bool, + disableSourceKit: Bool, compilerLogPath: String?, compileCommands: String?, checkForUpdates: Bool) { @@ -108,6 +111,7 @@ package struct LintOrAnalyzeOptions { self.onlyRule = onlyRule self.autocorrect = autocorrect self.format = format + self.disableSourceKit = disableSourceKit self.compilerLogPath = compilerLogPath self.compileCommands = compileCommands self.checkForUpdates = checkForUpdates @@ -124,6 +128,7 @@ package struct LintOrAnalyzeOptions { package struct LintOrAnalyzeCommand { package static func run(_ options: LintOrAnalyzeOptions) async throws { + Request.disableSourceKitOverride = options.mode == .lint && options.disableSourceKit if let workingDirectory = options.workingDirectory { if !FileManager.default.changeCurrentDirectoryPath(workingDirectory) { throw SwiftLintError.usageError( diff --git a/Source/swiftlint/Commands/Analyze.swift b/Source/swiftlint/Commands/Analyze.swift index 5ae0f3ff3..968fb99e2 100644 --- a/Source/swiftlint/Commands/Analyze.swift +++ b/Source/swiftlint/Commands/Analyze.swift @@ -44,6 +44,7 @@ extension SwiftLint { onlyRule: common.onlyRule, autocorrect: common.fix, format: common.format, + disableSourceKit: false, compilerLogPath: compilerLogPath, compileCommands: compileCommands, checkForUpdates: common.checkForUpdates diff --git a/Source/swiftlint/Commands/Lint.swift b/Source/swiftlint/Commands/Lint.swift index eb267c714..56c8cca19 100644 --- a/Source/swiftlint/Commands/Lint.swift +++ b/Source/swiftlint/Commands/Lint.swift @@ -19,6 +19,11 @@ extension SwiftLint { var noCache = false @Flag(help: "Run all rules, even opt-in and disabled ones, ignoring `only_rules`.") var enableAllRules = false + @Flag( + name: .customLong("disable-sourcekit"), + help: "Do not dynamically load SourceKit at runtime. Skip and report rules that require it." + ) + var disableSourceKit = false @Argument(help: pathsArgumentDescription(for: .lint)) var paths = [String]() @@ -56,6 +61,7 @@ extension SwiftLint { onlyRule: common.onlyRule, autocorrect: common.fix, format: common.format, + disableSourceKit: disableSourceKit, compilerLogPath: nil, compileCommands: nil, checkForUpdates: common.checkForUpdates diff --git a/Tests/FrameworkTests/LintOrAnalyzeOptionsTests.swift b/Tests/FrameworkTests/LintOrAnalyzeOptionsTests.swift index 07ec49079..7913fc4a3 100644 --- a/Tests/FrameworkTests/LintOrAnalyzeOptionsTests.swift +++ b/Tests/FrameworkTests/LintOrAnalyzeOptionsTests.swift @@ -64,6 +64,7 @@ private extension LintOrAnalyzeOptions { onlyRule: [], autocorrect: false, format: false, + disableSourceKit: false, compilerLogPath: nil, compileCommands: nil, checkForUpdates: false