From 91e3ea4b79004a92cdcd564d2f3a50f537ee6a0f Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 20 Nov 2025 17:55:42 -0800 Subject: [PATCH 1/3] Tests: introduce `testOnWindows` to `Example` Mirror the `testOnLinux` for Windows with a `testOnWindows`. This allows us to skip some tests dynamically as we do on Linux. --- .../Rules/Lint/UnusedImportRuleExamples.swift | 6 +++--- Source/SwiftLintCore/Models/Example.swift | 4 ++++ Tests/TestHelpers/TestHelpers.swift | 5 +++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/Lint/UnusedImportRuleExamples.swift b/Source/SwiftLintBuiltInRules/Rules/Lint/UnusedImportRuleExamples.swift index fdd33285e1..91e06e138f 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Lint/UnusedImportRuleExamples.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Lint/UnusedImportRuleExamples.swift @@ -190,7 +190,7 @@ struct UnusedImportRuleExamples { "allowed_transitive_imports": ["CoreFoundation", "Dispatch"], ] as [String: any Sendable], ], - ] as [String: any Sendable], testMultiByteOffsets: false, testOnLinux: false): + ] as [String: any Sendable], testMultiByteOffsets: false, testOnLinux: false, testOnWindows: false): Example(""" import Foundation typealias Foo = CFArray @@ -202,7 +202,7 @@ struct UnusedImportRuleExamples { dispatchMain() """, configuration: [ "require_explicit_imports": true - ], testMultiByteOffsets: false, testOnLinux: false): + ], testMultiByteOffsets: false, testOnLinux: false, testOnWindows: false): Example(""" import CoreFoundation import Dispatch @@ -236,7 +236,7 @@ struct UnusedImportRuleExamples { class A {} """, configuration: [ "require_explicit_imports": true - ], testMultiByteOffsets: false, testOnLinux: false): + ], testMultiByteOffsets: false, testOnLinux: false, testOnWindows: false): Example(""" import CoreFoundation import Foundation diff --git a/Source/SwiftLintCore/Models/Example.swift b/Source/SwiftLintCore/Models/Example.swift index cc9e46737e..f1a232b505 100644 --- a/Source/SwiftLintCore/Models/Example.swift +++ b/Source/SwiftLintCore/Models/Example.swift @@ -28,6 +28,8 @@ public struct Example: Sendable { package private(set) var testDisableCommand: Bool /// Whether the example should be tested on Linux public private(set) var testOnLinux: Bool + /// Whether the example should be tested on Windows + public private(set) var testOnWindows: Bool /// The path to the file where the example was created public private(set) var file: StaticString /// The line in the file where the example was created @@ -68,6 +70,7 @@ public extension Example { testWrappingInString: Bool = true, testDisableCommand: Bool = true, testOnLinux: Bool = true, + testOnWindows: Bool = true, file: StaticString = #filePath, line: UInt = #line, excludeFromDocumentation: Bool = false) { @@ -75,6 +78,7 @@ public extension Example { self.configuration = configuration self.testMultiByteOffsets = testMultiByteOffsets self.testOnLinux = testOnLinux + self.testOnWindows = testOnWindows self.file = file self.line = line self.excludeFromDocumentation = excludeFromDocumentation diff --git a/Tests/TestHelpers/TestHelpers.swift b/Tests/TestHelpers/TestHelpers.swift index 07d6e107fb..cadbc390a0 100644 --- a/Tests/TestHelpers/TestHelpers.swift +++ b/Tests/TestHelpers/TestHelpers.swift @@ -265,6 +265,11 @@ private func testCorrection(_ correction: (Example, Example), guard correction.0.testOnLinux else { return } +#endif +#if os(Windows) + guard correction.0.testOnWindows else { + return + } #endif var config = configuration if let correctionConfiguration = correction.0.configuration, From 8549a9a6ceb8dafb84b5739c6294c41b19bbbf8b Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 21 Nov 2025 09:42:31 -0800 Subject: [PATCH 2/3] Tests: adjust flag computation for Windows Windows isolates XCTest/Testing from the platform SDK as they are not part of the redistributable components. We adjust the flags by querying the partial path information and computing the location for the `XCTest` module for the tests. Additionally, enable the ObjC interop on the test cases to allow parsing `@objc` modifiers on declarations. This allows us to pass the GeneratedTests test suite. --- Tests/TestHelpers/TestHelpers.swift | 64 +++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/Tests/TestHelpers/TestHelpers.swift b/Tests/TestHelpers/TestHelpers.swift index cadbc390a0..1ac73ed47a 100644 --- a/Tests/TestHelpers/TestHelpers.swift +++ b/Tests/TestHelpers/TestHelpers.swift @@ -4,6 +4,45 @@ import XCTest import SwiftLintFramework +#if os(Windows) +private struct PlatformInfo { + struct DefaultProperties { + let versionXCTest: String + let versionSwiftTesting: String + let swiftFlags: [String]? + } + + let defaults: DefaultProperties +} + +extension PlatformInfo.DefaultProperties: Decodable { + enum CodingKeys: String, CodingKey { + case versionXCTest = "XCTEST_VERSION" + case versionSwiftTesting = "SWIFT_TESTING_VERSION" + case swiftFlags = "SWIFTC_FLAGS" + } +} + +extension PlatformInfo: Decodable { + enum CodingKeys: String, CodingKey { + case defaults = "DefaultProperties" + } +} + +private let info: PlatformInfo = { + let sdk = URL(fileURLWithPath: sdkPath(), isDirectory: true) + .deletingLastPathComponent() + .deletingLastPathComponent() + .deletingLastPathComponent() + .appendingPathComponent("Info.plist") + guard let data = try? Data(contentsOf: sdk), + let info = try? PropertyListDecoder().decode(PlatformInfo.self, from: data) else { + fatalError("invalid platorm SDK - couldn't decode \(sdk.path)") + } + return info +}() +#endif + // swiftlint:disable file_length private let violationMarker = "↓" @@ -28,12 +67,29 @@ private extension SwiftLintFile { .appendingPathComponent("Library") .appendingPathComponent("Frameworks") .path - return [ - "-F", - frameworks, + + let arguments = [ + "-F", frameworks, "-sdk", sdk, - "-j4", path!, + "-Xfrontend", "-enable-objc-interop", + "-j4", + path!, ] +#if os(Windows) + let XCTestPath = URL(fileURLWithPath: sdk, isDirectory: true) + .deletingLastPathComponent() + .deletingLastPathComponent() + .appendingPathComponent("Library") + .appendingPathComponent("XCTest-\(info.defaults.versionXCTest)") + .appendingPathComponent("usr") + .appendingPathComponent("lib") + .appendingPathComponent("swift") + .appendingPathComponent("windows") + .path + return ["-I", XCTestPath] + arguments +#else + return arguments +#endif } } From e1662172e888ee1d91cb56945595d563f663b710 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 27 Nov 2025 21:16:45 -0800 Subject: [PATCH 3/3] Update Tests/TestHelpers/TestHelpers.swift MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Danny Mösch --- Tests/TestHelpers/TestHelpers.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/TestHelpers/TestHelpers.swift b/Tests/TestHelpers/TestHelpers.swift index 1ac73ed47a..5c03260836 100644 --- a/Tests/TestHelpers/TestHelpers.swift +++ b/Tests/TestHelpers/TestHelpers.swift @@ -37,7 +37,7 @@ private let info: PlatformInfo = { .appendingPathComponent("Info.plist") guard let data = try? Data(contentsOf: sdk), let info = try? PropertyListDecoder().decode(PlatformInfo.self, from: data) else { - fatalError("invalid platorm SDK - couldn't decode \(sdk.path)") + fatalError("invalid platform SDK - couldn't decode \(sdk.path)") } return info }()