Introduce guarded filepath provider for file collection (#6435)

This commit is contained in:
Danny Mösch
2026-01-15 00:06:13 +01:00
committed by GitHub
parent 9a634bc8a0
commit faa5859155
8 changed files with 61 additions and 8 deletions
+1
View File
@@ -38,6 +38,7 @@ jobs:
name: SPM, macOS ${{ matrix.macOS }}, Xcode ${{ matrix.xcode }}
runs-on: macos-${{ matrix.macOS }}
strategy:
fail-fast: false
matrix:
include:
- macOS: '14'
+2 -2
View File
@@ -39,7 +39,7 @@ default.profraw
SwiftLint.xcodeproj
SwiftLint.pkg
*.zip
/*.zip
benchmark_*
docs/
rule_docs/
@@ -73,4 +73,4 @@ oss-check-summary.md
# VS Code
.vscode
.vscode
+5
View File
@@ -20,6 +20,11 @@
[SimplyDanny](https://github.com/SimplyDanny)
[#6423](https://github.com/realm/SwiftLint/issues/6423)
* Inform users about files being skipped due to impossible file system representation
instead of crashing.
[SimplyDanny](https://github.com/SimplyDanny)
[#6419](https://github.com/realm/SwiftLint/issues/6419)
* Ignore `override` functions in `async_without_await` rule.
[SimplyDanny](https://github.com/SimplyDanny)
[#6416](https://github.com/realm/SwiftLint/issues/6416)
+1
View File
@@ -203,6 +203,7 @@ let package = Package(
.testTarget(
name: "IntegrationTests",
dependencies: [
"SwiftLintCore",
"SwiftLintFramework",
"TestHelpers",
],
@@ -5,6 +5,18 @@ public extension URL {
withUnsafeFileSystemRepresentation { String(cString: $0!) }
}
var filepathGuarded: String? {
withUnsafeFileSystemRepresentation { ptr in
guard let ptr else {
Issue.genericError(
"File with URL '\(self)' cannot be represented as a file system path; skipping it"
).print()
return nil
}
return String(cString: ptr)
}
}
var isSwiftFile: Bool {
filepath.isFile && pathExtension == "swift"
}
@@ -71,7 +71,7 @@ extension FileManager: LintableFileManager, @unchecked @retroactive Sendable {
}
private func collectFiles(atPath absolutePath: URL, excluder: Excluder) -> [String] {
guard let enumerator = enumerator(atPath: absolutePath.filepath) else {
guard let root = absolutePath.filepathGuarded, let enumerator = enumerator(atPath: root) else {
return []
}
@@ -80,7 +80,9 @@ extension FileManager: LintableFileManager, @unchecked @retroactive Sendable {
while let element = enumerator.nextObject() as? String {
let absoluteElementPath = URL(fileURLWithPath: element, relativeTo: absolutePath)
let absoluteStandardizedElementPath = absoluteElementPath.standardized.filepath
guard let absoluteStandardizedElementPath = absoluteElementPath.standardized.filepathGuarded else {
continue
}
if absoluteElementPath.path.isFile {
if absoluteElementPath.pathExtension == "swift",
!excluder.excludes(path: absoluteStandardizedElementPath) {
@@ -3,7 +3,9 @@ import SwiftLintFramework
import TestHelpers
import XCTest
final class ConfigPathResolutionTests: SwiftLintTestCase {
@testable import SwiftLintCore
final class ConfigPathResolutionTests: SwiftLintTestCase, @unchecked Sendable {
private func fixturePath(_ scenario: String) -> URL {
URL(fileURLWithPath: #filePath)
.deletingLastPathComponent()
@@ -16,10 +18,8 @@ final class ConfigPathResolutionTests: SwiftLintTestCase {
let scenarioPath = fixturePath(scenario).filepath
let previousDir = FileManager.default.currentDirectoryPath
defer {
_ = FileManager.default.changeCurrentDirectoryPath(previousDir)
}
XCTAssert(FileManager.default.changeCurrentDirectoryPath(scenarioPath))
defer { _ = FileManager.default.changeCurrentDirectoryPath(previousDir) }
let config = Configuration(configurationFiles: configFile.map { [$0] } ?? [])
let files = config.lintableFiles(
@@ -169,4 +169,36 @@ final class ConfigPathResolutionTests: SwiftLintTestCase {
.contains("explicit_type_interface")
)
}
#if !os(Windows)
func testUnicodePrivateUseAreaCharacterInPath() async throws {
let fixture = fixturePath("_8_unicode_private_use_area")
let process = Process()
process.executableURL = URL(filePath: "/usr/bin/env", directoryHint: .notDirectory)
process.arguments = ["unzip", "-o", fixture.appending(path: "app.zip").filepath, "-d", fixture.filepath]
try process.run()
process.waitUntilExit()
defer { try? FileManager.default.removeItem(at: fixture.appending(path: "App")) }
if #available(macOS 26, *) {
XCTAssertEqual(
lintableFilePaths(in: "_8_unicode_private_use_area/App"),
["Resources/Settings.bundle/androidx.core:core-bundle.swift"]
)
} else {
let console = await Issue.captureConsole {
XCTAssert(lintableFilePaths(in: "_8_unicode_private_use_area/App").isEmpty)
}
XCTAssert(
console.contains(
"""
error: File with URL 'androidx.core:core-bundle.swift' \
cannot be represented as a file system path; skipping it
"""
)
)
}
}
#endif
}