Skip to content

Commit 951e923

Browse files
committed
Use withUnsafeFileSystemRepresentation to get the path of a URL on disk
`URL.path` returns forward slashes in the path on Windows (swiftlang/swift-foundation#973) where we expect backslashes. Work around that by defining our own `filePath` property that is backed by `withUnsafeFileSystemRepresentation`, which produces backslashes. rdar://137963660
1 parent fd279fc commit 951e923

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+284
-174
lines changed

Sources/BuildSystemIntegration/BuildSystemManager.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
587587
logger.error("Toolchain is not a file URL")
588588
return nil
589589
}
590-
return try AbsolutePath(validating: toolchainUrl.path)
590+
return try AbsolutePath(validating: toolchainUrl.filePath)
591591
}
592592
if let toolchainPath {
593593
if let toolchain = await self.toolchainRegistry.toolchain(withPath: toolchainPath) {
@@ -645,10 +645,10 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
645645
result.formUnion(targets)
646646
}
647647
if !filesAndDirectories.directories.isEmpty,
648-
let documentPath = AbsolutePath(validatingOrNil: document.fileURL?.path)
648+
let documentPath = AbsolutePath(validatingOrNil: try? document.fileURL?.filePath)
649649
{
650650
for (directory, info) in filesAndDirectories.directories {
651-
guard let directoryPath = AbsolutePath(validatingOrNil: directory.fileURL?.path) else {
651+
guard let directoryPath = AbsolutePath(validatingOrNil: try? directory.fileURL?.filePath) else {
652652
continue
653653
}
654654
if documentPath.isDescendant(of: directoryPath) {

Sources/BuildSystemIntegration/CompilationDatabase.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ package struct JSONCompilationDatabase: CompilationDatabase, Equatable, Codable
264264
if let indices = pathToCommands[uri] {
265265
return indices.map { commands[$0] }
266266
}
267-
if let fileURL = uri.fileURL, let indices = pathToCommands[DocumentURI(fileURL.realpath)] {
267+
if let fileURL = try? uri.fileURL?.realpath, let indices = pathToCommands[DocumentURI(fileURL)] {
268268
return indices.map { commands[$0] }
269269
}
270270
return []

Sources/BuildSystemIntegration/DetermineBuildSystem.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
package import LanguageServerProtocol
1515
import SKLogging
1616
package import SKOptions
17+
import SwiftExtensions
1718
import ToolchainRegistry
1819

1920
import struct TSCBasic.AbsolutePath
2021
#else
2122
import LanguageServerProtocol
2223
import SKLogging
2324
import SKOptions
25+
import SwiftExtensions
2426
import ToolchainRegistry
2527

2628
import struct TSCBasic.AbsolutePath
@@ -42,7 +44,7 @@ package func determineBuildSystem(
4244
buildSystemPreference.insert(defaultBuildSystem, at: 0)
4345
}
4446
guard let workspaceFolderUrl = workspaceFolder.fileURL,
45-
let workspaceFolderPath = try? AbsolutePath(validating: workspaceFolderUrl.path)
47+
let workspaceFolderPath = try? AbsolutePath(validating: workspaceFolderUrl.filePath)
4648
else {
4749
return nil
4850
}
@@ -58,7 +60,7 @@ package func determineBuildSystem(
5860
}
5961
case .swiftPM:
6062
if let projectRootURL = SwiftPMBuildSystem.projectRoot(for: workspaceFolderUrl, options: options),
61-
let projectRoot = try? AbsolutePath(validating: projectRootURL.path)
63+
let projectRoot = try? AbsolutePath(validating: projectRootURL.filePath)
6264
{
6365
return .swiftPM(projectRoot: projectRoot)
6466
}

Sources/BuildSystemIntegration/ExternalBuildSystemAdapter.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import LanguageServerProtocol
1616
import LanguageServerProtocolJSONRPC
1717
import SKLogging
1818
import SKOptions
19+
import SwiftExtensions
1920

2021
import struct TSCBasic.AbsolutePath
2122
import func TSCBasic.getEnvSearchPaths
@@ -224,7 +225,7 @@ actor ExternalBuildSystemAdapter {
224225
.filter { $0.pathExtension == "json" }
225226

226227
if let configFileURL = jsonFiles?.sorted(by: { $0.lastPathComponent < $1.lastPathComponent }).first,
227-
let configFilePath = AbsolutePath(validatingOrNil: configFileURL.path)
228+
let configFilePath = AbsolutePath(validatingOrNil: try? configFileURL.filePath)
228229
{
229230
return configFilePath
230231
}

Sources/BuildSystemIntegration/SwiftPMBuildSystem.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -238,14 +238,16 @@ package actor SwiftPMBuildSystem: BuiltInBuildSystem {
238238
private var targetDependencies: [BuildTargetIdentifier: Set<BuildTargetIdentifier>] = [:]
239239

240240
static package func projectRoot(for path: URL, options: SourceKitLSPOptions) -> URL? {
241-
var path = path.realpath
241+
guard var path = orLog("Getting realpath for project root", { try path.realpath }) else {
242+
return nil
243+
}
242244
while true {
243245
let packagePath = path.appending(component: "Package.swift")
244246
if (try? String(contentsOf: packagePath, encoding: .utf8))?.contains("PackageDescription") ?? false {
245247
return path
246248
}
247249

248-
if (try? AbsolutePath(validating: path.path))?.isRoot ?? true {
250+
if (try? AbsolutePath(validating: path.filePath))?.isRoot ?? true {
249251
break
250252
}
251253
path.deleteLastPathComponent()
@@ -572,7 +574,7 @@ package actor SwiftPMBuildSystem: BuiltInBuildSystem {
572574
package func sourceKitOptions(
573575
request: TextDocumentSourceKitOptionsRequest
574576
) async throws -> TextDocumentSourceKitOptionsResponse? {
575-
guard let url = request.textDocument.uri.fileURL, let path = try? AbsolutePath(validating: url.path) else {
577+
guard let url = request.textDocument.uri.fileURL, let path = try? AbsolutePath(validating: url.filePath) else {
576578
// We can't determine build settings for non-file URIs.
577579
return nil
578580
}
@@ -587,7 +589,7 @@ package actor SwiftPMBuildSystem: BuiltInBuildSystem {
587589
}
588590

589591
if !swiftPMTarget.sources.lazy.map(DocumentURI.init).contains(request.textDocument.uri),
590-
let substituteFile = swiftPMTarget.sources.sorted(by: { $0.path < $1.path }).first
592+
let substituteFile = swiftPMTarget.sources.sorted(by: { $0.description < $1.description }).first
591593
{
592594
logger.info("Getting compiler arguments for \(url) using substitute file \(substituteFile)")
593595
// If `url` is not part of the target's source, it's most likely a header file. Fake compiler arguments for it
@@ -600,7 +602,7 @@ package actor SwiftPMBuildSystem: BuiltInBuildSystem {
600602
let buildSettings = FileBuildSettings(
601603
compilerArguments: try await compilerArguments(for: DocumentURI(substituteFile), in: swiftPMTarget),
602604
workingDirectory: projectRoot.pathString
603-
).patching(newFile: DocumentURI(path.asURL.realpath), originalFile: DocumentURI(substituteFile))
605+
).patching(newFile: DocumentURI(try path.asURL.realpath), originalFile: DocumentURI(substituteFile))
604606
return TextDocumentSourceKitOptionsResponse(
605607
compilerArguments: buildSettings.compilerArguments,
606608
workingDirectory: buildSettings.workingDirectory

Sources/Diagnose/DiagnoseCommand.swift

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package import ArgumentParser
1515
import Foundation
1616
import ToolchainRegistry
17+
import SwiftExtensions
1718

1819
import struct TSCBasic.AbsolutePath
1920
import class TSCBasic.Process
@@ -22,6 +23,7 @@ import class TSCUtility.PercentProgressAnimation
2223
import ArgumentParser
2324
import Foundation
2425
import ToolchainRegistry
26+
import SwiftExtensions
2527

2628
import struct TSCBasic.AbsolutePath
2729
import class TSCBasic.Process
@@ -172,7 +174,7 @@ package struct DiagnoseCommand: AsyncParsableCommand {
172174
.deletingLastPathComponent()
173175
.deletingLastPathComponent()
174176

175-
guard let toolchain = try Toolchain(AbsolutePath(validating: toolchainPath.path)),
177+
guard let toolchain = try Toolchain(AbsolutePath(validating: toolchainPath.filePath)),
176178
let sourcekitd = toolchain.sourcekitd
177179
else {
178180
continue
@@ -223,7 +225,7 @@ package struct DiagnoseCommand: AsyncParsableCommand {
223225
#if os(macOS)
224226
reportProgress(.collectingLogMessages(progress: 0), message: "Collecting log messages")
225227
let outputFileUrl = bundlePath.appendingPathComponent("log.txt")
226-
guard FileManager.default.createFile(atPath: outputFileUrl.path, contents: nil) else {
228+
guard FileManager.default.createFile(atPath: try outputFileUrl.filePath, contents: nil) else {
227229
throw GenericError("Failed to create log.txt")
228230
}
229231
let fileHandle = try FileHandle(forWritingTo: outputFileUrl)
@@ -316,7 +318,7 @@ package struct DiagnoseCommand: AsyncParsableCommand {
316318
@MainActor
317319
private func addSwiftVersion(toBundle bundlePath: URL) async throws {
318320
let outputFileUrl = bundlePath.appendingPathComponent("swift-versions.txt")
319-
guard FileManager.default.createFile(atPath: outputFileUrl.path, contents: nil) else {
321+
guard FileManager.default.createFile(atPath: try outputFileUrl.filePath, contents: nil) else {
320322
throw GenericError("Failed to create file at \(outputFileUrl)")
321323
}
322324
let fileHandle = try FileHandle(forWritingTo: outputFileUrl)
@@ -333,9 +335,9 @@ package struct DiagnoseCommand: AsyncParsableCommand {
333335
continue
334336
}
335337

336-
try fileHandle.write(contentsOf: "\(swiftUrl.path) --version\n".data(using: .utf8)!)
338+
try fileHandle.write(contentsOf: "\(swiftUrl.filePath) --version\n".data(using: .utf8)!)
337339
let process = Process(
338-
arguments: [swiftUrl.path, "--version"],
340+
arguments: [try swiftUrl.filePath, "--version"],
339341
outputRedirection: .stream(
340342
stdout: { try? fileHandle.write(contentsOf: $0) },
341343
stderr: { _ in }
@@ -417,7 +419,7 @@ package struct DiagnoseCommand: AsyncParsableCommand {
417419
Bundle created.
418420
When filing an issue at https://github.com/swiftlang/sourcekit-lsp/issues/new,
419421
please attach the bundle located at
420-
\(bundlePath.path)
422+
\(try bundlePath.filePath)
421423
"""
422424
)
423425

@@ -428,7 +430,7 @@ package struct DiagnoseCommand: AsyncParsableCommand {
428430
// is responsible for showing the diagnose bundle location to the user
429431
if self.bundleOutputPath == nil {
430432
do {
431-
_ = try await Process.run(arguments: ["open", "-R", bundlePath.path], workingDirectory: nil)
433+
_ = try await Process.run(arguments: ["open", "-R", bundlePath.filePath], workingDirectory: nil)
432434
} catch {
433435
// If revealing the bundle in Finder should fail, we don't care. We still printed the bundle path to stdout.
434436
}

Sources/Diagnose/ReproducerBundle.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
import Foundation
14+
import SwiftExtensions
1415
import ToolchainRegistry
1516

1617
/// Create a folder that contains all files that should be necessary to reproduce a sourcekitd crash.
@@ -26,7 +27,7 @@ func makeReproducerBundle(for requestInfo: RequestInfo, toolchain: Toolchain, bu
2627
encoding: .utf8
2728
)
2829
if let toolchainPath = toolchain.path {
29-
try toolchainPath.asURL.realpath.path
30+
try toolchainPath.asURL.realpath.filePath
3031
.write(
3132
to: bundlePath.appendingPathComponent("toolchain.txt"),
3233
atomically: true,
@@ -59,7 +60,7 @@ func makeReproducerBundle(for requestInfo: RequestInfo, toolchain: Toolchain, bu
5960
// aren't user specific and would bloat the reproducer bundle.
6061
continue
6162
}
62-
let dest = URL(fileURLWithPath: bundlePath.path + path)
63+
let dest = URL(fileURLWithPath: try bundlePath.filePath + path)
6364
try? FileManager.default.createDirectory(at: dest.deletingLastPathComponent(), withIntermediateDirectories: true)
6465
try? FileManager.default.copyItem(at: URL(fileURLWithPath: String(path)), to: dest)
6566
}

Sources/Diagnose/RequestInfo.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313
#if compiler(>=6)
1414
package import Foundation
1515
import RegexBuilder
16+
import SwiftExtensions
1617
#else
1718
import Foundation
1819
import RegexBuilder
20+
import SwiftExtensions
1921
#endif
2022

2123
/// All the information necessary to replay a sourcektid request.
@@ -48,7 +50,7 @@ package struct RequestInfo: Sendable {
4850
requestTemplate
4951
.replacingOccurrences(of: "$OFFSET", with: String(offset))
5052
.replacingOccurrences(of: "$COMPILER_ARGS", with: compilerArgs)
51-
.replacingOccurrences(of: "$FILE", with: file.path)
53+
.replacingOccurrences(of: "$FILE", with: try file.filePath.replacing(#"\"#, with: #"\\"#))
5254
}
5355

5456
/// A fake value that is used to indicate that we are reducing a `swift-frontend` issue instead of a sourcekitd issue.

Sources/Diagnose/SourceKitDRequestExecutor.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
#if compiler(>=6)
1414
package import Foundation
1515
import SourceKitD
16+
import SwiftExtensions
1617

1718
import struct TSCBasic.AbsolutePath
1819
import class TSCBasic.Process
1920
import struct TSCBasic.ProcessResult
2021
#else
2122
import Foundation
2223
import SourceKitD
24+
import SwiftExtensions
2325

2426
import struct TSCBasic.AbsolutePath
2527
import class TSCBasic.Process
@@ -147,9 +149,9 @@ package class OutOfProcessSourceKitRequestExecutor: SourceKitRequestExecutor {
147149
package func runSwiftFrontend(request: RequestInfo) async throws -> SourceKitDRequestResult {
148150
try request.fileContents.write(to: temporarySourceFile, atomically: true, encoding: .utf8)
149151

150-
let arguments = request.compilerArgs.replacing(["$FILE"], with: [temporarySourceFile.path])
152+
let arguments = request.compilerArgs.replacing(["$FILE"], with: [try temporarySourceFile.filePath])
151153

152-
let process = Process(arguments: [swiftFrontend.path] + arguments)
154+
let process = Process(arguments: [try swiftFrontend.filePath] + arguments)
153155
try process.launch()
154156
let result = try await process.waitUntilExit()
155157

@@ -167,9 +169,9 @@ package class OutOfProcessSourceKitRequestExecutor: SourceKitRequestExecutor {
167169
"debug",
168170
"run-sourcekitd-request",
169171
"--sourcekitd",
170-
sourcekitd.path,
172+
try sourcekitd.filePath,
171173
"--request-file",
172-
temporaryRequestFile.path,
174+
try temporaryRequestFile.filePath,
173175
]
174176
)
175177
try process.launch()

Sources/InProcessClient/InProcessSourceKitLSPClient.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public final class InProcessSourceKitLSPClient: Sendable {
6868
let serverToClientConnection = LocalConnection(receiverName: "client")
6969
self.server = SourceKitLSPServer(
7070
client: serverToClientConnection,
71-
toolchainRegistry: ToolchainRegistry(installPath: AbsolutePath(validatingOrNil: toolchainPath?.path)),
71+
toolchainRegistry: ToolchainRegistry(installPath: AbsolutePath(validatingOrNil: try? toolchainPath?.filePath)),
7272
options: options,
7373
testHooks: TestHooks(),
7474
onExit: {

0 commit comments

Comments
 (0)