fix(fls): archive path folding measured against Swift
41 path pairs replayed in the Swift core decide which spellings name the same file. Two corrections: full Unicode case folding (ß, ligatures, final sigma, micro, long s) instead of toLowerCase, and width folding of the whole Halfwidth and Fullwidth Forms block. Swift treats composed and decomposed spellings as one dictionary key; here the writer refuses both. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -291,8 +291,47 @@ func readCorpus(root: URL) throws -> JSON {
|
||||
return result
|
||||
}
|
||||
|
||||
// MARK: - Archive path folding
|
||||
|
||||
struct PathCase: Decodable { let name: String; let first: String; let second: String }
|
||||
|
||||
/// Whether Swift's archive writer treats two entry paths as the same file.
|
||||
/// The folding itself is file-private in Swift; the export reports it as a
|
||||
/// duplicate entry when two carried entries collide.
|
||||
func foldPaths(_ cases: [PathCase]) -> [JSON] {
|
||||
cases.map { item in
|
||||
var result: JSON = ["name": item.name]
|
||||
// Swift compares strings by canonical equivalence: "é" and "e\u{301}"
|
||||
// are one dictionary key, so they never reach the archive writer.
|
||||
if item.first == item.second {
|
||||
result["outcome"] = "sameKey"
|
||||
return result
|
||||
}
|
||||
do {
|
||||
_ = try TopologyProjectStore.exportFiliusArchiveWithReport(
|
||||
from: TopologyEditorState(),
|
||||
supplementalEntries: [item.first: Data("1".utf8), item.second: Data("2".utf8)]
|
||||
)
|
||||
result["outcome"] = "distinct"
|
||||
} catch let error as TopologyFLSArchiveError {
|
||||
result["outcome"] = error.code == .duplicateEntry ? "collide" : error.code.rawValue
|
||||
} catch {
|
||||
result["outcome"] = "error: \(error)"
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Main
|
||||
|
||||
if CommandLine.arguments.count == 4, CommandLine.arguments[1] == "--path-folding" {
|
||||
let cases = try JSONDecoder().decode([PathCase].self, from: Data(contentsOf: URL(fileURLWithPath: CommandLine.arguments[2])))
|
||||
let data = try JSONSerialization.data(withJSONObject: foldPaths(cases), options: [.prettyPrinted, .sortedKeys])
|
||||
try (data + Data("\n".utf8)).write(to: URL(fileURLWithPath: CommandLine.arguments[3]))
|
||||
print("path folding: \(cases.count) cases")
|
||||
exit(0)
|
||||
}
|
||||
|
||||
if CommandLine.arguments.count == 4, CommandLine.arguments[1] == "--corpus" {
|
||||
let summary = try readCorpus(root: URL(fileURLWithPath: CommandLine.arguments[2]))
|
||||
let data = try JSONSerialization.data(withJSONObject: summary, options: [.prettyPrinted, .sortedKeys])
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -11,4 +11,5 @@ docker run --rm -v "$root:/work" -w /work/tools/swift-oracle swift:6.1-jammy sh
|
||||
set -e
|
||||
swift build -q
|
||||
.build/debug/Oracle /work/packages/core/test/scenarios
|
||||
.build/debug/Oracle --corpus /work/corpus /work/corpus/corpus.swift.json'
|
||||
.build/debug/Oracle --corpus /work/corpus /work/corpus/corpus.swift.json
|
||||
.build/debug/Oracle --path-folding /work/packages/fls/test/path-folding.cases.json /work/packages/fls/test/path-folding.swift.json'
|
||||
|
||||
Reference in New Issue
Block a user