diff --git a/Sources/Library/Schema/References/FilePath.swift b/Sources/Library/Schema/References/FilePath.swift index 0e6977b..bb2fdc4 100644 --- a/Sources/Library/Schema/References/FilePath.swift +++ b/Sources/Library/Schema/References/FilePath.swift @@ -82,7 +82,9 @@ extension XCSchema.FilePath: XCJSON.InlineKeyedCodable { let base = try Base(expansionVariable: expansionVariable).unwrap(orThrow: "Invalid path base: \(expansionVariable.smartQuoted)") try self.init(base: base, path: path) } else { - try self.init(base: string.hasPrefix("/") ? .absolute : .group, path: string.unescaping("<")) + // Match init(base:path:), which treats a leading ~ as absolute (Xcode expands it). + let isAbsolutePath = string.hasPrefix("/") || string.hasPrefix("~") + try self.init(base: isAbsolutePath ? .absolute : .group, path: string.unescaping("<")) } } diff --git a/Sources/Library/Serialization/Values/Value.swift b/Sources/Library/Serialization/Values/Value.swift index 8fc8e14..e73f3e1 100644 --- a/Sources/Library/Serialization/Values/Value.swift +++ b/Sources/Library/Serialization/Values/Value.swift @@ -164,7 +164,7 @@ extension XCJSON.Value: Decodable { } else if container.decodeNil() { self = .null } else { - throw NSError("Unrecongized JSON object") + throw NSError("Unrecognized JSON object") } } } diff --git a/Sources/Library/Utilities/Utilities.swift b/Sources/Library/Utilities/Utilities.swift index b6f0dee..7684271 100644 --- a/Sources/Library/Utilities/Utilities.swift +++ b/Sources/Library/Utilities/Utilities.swift @@ -454,14 +454,14 @@ extension String { } } - package enum UnscapingResult { + package enum UnescapingResult { case complete(String) case unescapedSequence(unescaped: String, remaining: String) case invalidEscapeSequence(Character) case unresolvedEscape } - package func unescapingUntilError(escapedCharacter: Character) -> UnscapingResult { + package func unescapingUntilError(escapedCharacter: Character) -> UnescapingResult { let escapeIndicator: Character = "\\" let hasEscaping = anySatisfy { candidate in (candidate == escapeIndicator) || (candidate == escapedCharacter) diff --git a/Sources/Tests/JSONTests.swift b/Sources/Tests/JSONTests.swift index 6fc2df4..42254f4 100644 --- a/Sources/Tests/JSONTests.swift +++ b/Sources/Tests/JSONTests.swift @@ -185,6 +185,9 @@ struct XCJSONRoundTrippingTests { expect(.group, "File.swift", roundTripsAndEncodesTo: "File.swift") expect(.absolute, "/File.swift", roundTripsAndEncodesTo: "/File.swift") + expect(.absolute, "~/project/File.swift", roundTripsAndEncodesTo: "~/project/File.swift") + expect(.absolute, "~", roundTripsAndEncodesTo: "~") + expect(.absolute, "~user/File.swift", roundTripsAndEncodesTo: "~user/File.swift") expect(.project, "File.swift", roundTripsAndEncodesTo: "/File.swift") expect(.sdk, "File.swift", roundTripsAndEncodesTo: "/File.swift") expect(.developer, "File.swift", roundTripsAndEncodesTo: "/File.swift") diff --git a/Sources/Tests/TestInstances.swift b/Sources/Tests/TestInstances.swift index 2577543..41a21e5 100644 --- a/Sources/Tests/TestInstances.swift +++ b/Sources/Tests/TestInstances.swift @@ -442,7 +442,7 @@ extension XCSchema.FilePath: TestInstanceDefining { var testCases: [Self] = [] var testPathFramgents = ["/", "A", "B", "<", ">", "USER", "\\"] testPathFramgents.enumerateAllSubsetPermutationJoinings { path in - if !path.hasPrefix("/") { + if !path.hasPrefix("/") && !path.hasPrefix("~") { for relativeBase in relativeBases { try! testCases.append(Self(base: relativeBase, path: path)) } @@ -452,6 +452,9 @@ extension XCSchema.FilePath: TestInstanceDefining { testPathFramgents.enumerateAllSubsetPermutationJoinings { path in try! testCases.append(Self(base: .absolute, path: "/" + path)) } + try! testCases.append(Self(base: .absolute, path: "~")) + try! testCases.append(Self(base: .absolute, path: "~/Sources/Foo.swift")) + try! testCases.append(Self(base: .absolute, path: "~user/file.swift")) return testCases }() } diff --git a/Sources/Tests/TestStringEscapingDuringEncoding.swift b/Sources/Tests/TestStringEscapingDuringEncoding.swift index d0f7567..eca8739 100644 --- a/Sources/Tests/TestStringEscapingDuringEncoding.swift +++ b/Sources/Tests/TestStringEscapingDuringEncoding.swift @@ -111,6 +111,9 @@ struct TestStringEscapingDuringEncoding { expect(.absolute, "/") expect(.absolute, "/.") expect(.absolute, "/..") + expect(.absolute, "~") + expect(.absolute, "~/.") + expect(.absolute, "~user") expect(.project, "")