Allow --stdin-path with non-existing files (#2382)

Co-authored-by: calda <1811727+calda@users.noreply.github.com>
This commit is contained in:
Copilot
2026-02-18 13:33:33 -08:00
committed by Cal Stephens
parent 0fee45048a
commit e2d82b2f8b
4 changed files with 135 additions and 7 deletions
+6 -4
View File
@@ -581,15 +581,16 @@ func processArguments(_ args: [String], environment: [String: String] = [:], in
print("warning: --stdin-path option only applies when using stdin", as: .warning)
}
let stdinURL = try parsePath(stdinPath, for: "stdin-path", in: directory)
let resourceValues = try getResourceValues(
// Try to get resource values, but if file doesn't exist, just use the path
let resourceValues = try? getResourceValues(
for: stdinURL.standardizedFileURL,
keys: [.creationDateKey, .pathKey]
)
var formatOptions = options.formatOptions ?? .default
formatOptions.fileInfo = FileInfo(
filePath: resourceValues.path,
creationDate: resourceValues.creationDate
filePath: resourceValues?.path ?? stdinURL.standardizedFileURL.path,
creationDate: resourceValues?.creationDate
)
options.formatOptions = formatOptions
}
@@ -793,7 +794,8 @@ func processArguments(_ args: [String], environment: [String: String] = [:], in
return
}
let resourceValues = try getResourceValues(
// Try to get resource values, but allow nil for non-existing files
let resourceValues = try? getResourceValues(
for: stdinURL.standardizedFileURL,
keys: [.creationDateKey, .pathKey]
)
+3 -3
View File
@@ -312,7 +312,7 @@ public func enumerateFiles(withInputURL inputURL: URL,
handler: handler)
}
func collectFileInfo(inputURL: URL, options: Options, resourceValues: URLResourceValues) -> FileInfo {
func collectFileInfo(inputURL: URL, options: Options, resourceValues: URLResourceValues?) -> FileInfo {
let fileHeaderRuleEnabled = options.rules?.contains(FormatRule.fileHeader.name) ?? false
let shouldGetGitInfo = fileHeaderRuleEnabled &&
options.formatOptions?.fileHeader.needsGitInfo == true
@@ -320,8 +320,8 @@ func collectFileInfo(inputURL: URL, options: Options, resourceValues: URLResourc
let gitInfo = shouldGetGitInfo ? GitFileInfo(url: inputURL) : nil
return FileInfo(
filePath: resourceValues.path,
creationDate: gitInfo?.creationDate ?? resourceValues.creationDate,
filePath: resourceValues?.path ?? inputURL.path,
creationDate: gitInfo?.creationDate ?? resourceValues?.creationDate,
replacements: [
.author: ReplacementType(gitInfo?.author),
.authorName: ReplacementType(gitInfo?.authorName),
+90
View File
@@ -1001,6 +1001,96 @@ final class CommandLineTests: XCTestCase {
}
}
func testStdinPathWithNonExistingFile() throws {
var output = [String]()
CLI.print = { message, type in
switch type {
case .raw, .content:
output.append(message)
case .error, .warning:
XCTFail(message)
case .info, .success:
break
}
}
var readCount = 0
CLI.readLine = {
readCount += 1
switch readCount {
case 1:
return "func foo()\n"
case 2:
return "{\n"
case 3:
return "bar()\n"
case 4:
return "}"
default:
return nil
}
}
// Use a path that doesn't exist
let nonExistingPath = "/tmp/deleted_file_\(UUID().uuidString).swift"
_ = processArguments([
"",
"stdin",
"--stdin-path", nonExistingPath,
], in: "")
// Should still format the input, despite file not existing
XCTAssertEqual(output, ["""
func foo() {
bar()
}
"""])
}
func testStdinPathWithNonExistingFileExcluded() throws {
var output = [String]()
CLI.print = { message, type in
switch type {
case .raw, .content:
output.append(message)
case .error, .warning:
XCTFail(message)
case .info, .success:
break
}
}
var readCount = 0
CLI.readLine = {
readCount += 1
switch readCount {
case 1:
return "func foo()\n"
case 2:
return "{\n"
case 3:
return "bar()\n"
case 4:
return "}"
default:
return nil
}
}
// Use a path that doesn't exist but matches exclusion pattern
let nonExistingPath = "/tmp/excluded/deleted_file.swift"
_ = processArguments([
"",
"stdin",
"--stdin-path", nonExistingPath,
"--exclude", "/tmp/excluded",
], in: "")
// Should NOT format because the path is excluded
XCTAssertEqual(output, ["func foo()\n{\nbar()\n}"])
}
func testSwiftVersionFileWithNoConfigFile() throws {
var errors = [String]()
+36
View File
@@ -728,6 +728,42 @@ final class FileHeaderTests: XCTestCase {
let options = FormatOptions(fileHeader: "// {file}.", fileInfo: FileInfo())
XCTAssertThrowsError(try format(input, rules: [.fileHeader], options: options))
}
func testFileHeaderWithFilePathButNoCreationDate() {
let input = """
let foo = bar
"""
let output = """
// File: test.swift
let foo = bar
"""
let fileInfo = FileInfo(filePath: "/path/to/test.swift", creationDate: nil)
let options = FormatOptions(fileHeader: "// File: {file}", fileInfo: fileInfo)
testFormatting(for: input, output, rule: .fileHeader, options: options)
}
func testFileHeaderWithFilePathButNoCreationDateDoesNotUseCreatedPlaceholder() {
let input = """
let foo = bar
"""
let fileInfo = FileInfo(filePath: "/path/to/test.swift", creationDate: nil)
let options = FormatOptions(fileHeader: "// Created: {created}", fileInfo: fileInfo)
XCTAssertThrowsError(try format(input, rules: [.fileHeader], options: options))
}
func testFileHeaderWithExistingHeaderAndNoCreationDate() {
let input = """
// Existing header
// Created on 2020-01-01
let foo = bar
"""
let fileInfo = FileInfo(filePath: "/path/to/test.swift", creationDate: nil)
let options = FormatOptions(fileHeader: "// New header\n// Created: {created}", fileInfo: fileInfo)
// When creation date is unavailable and template uses {created}, throws error even if file has existing header
XCTAssertThrowsError(try format(input, rules: [.fileHeader], options: options))
}
}
private enum TestDateFormat: String {