Skip to content

Commit ea76b63

Browse files
authored
Use Windows-style paths with backslashes in SourceKit-LSP compiler arguments for plugins (#8118)
`URL.path` returns a URL path with forward slashes. We need to go through `withUnsafeFileSystemRepresentation` to get a Windows file system path with backslashes. Fixes swiftlang/sourcekit-lsp#1775
1 parent 00a2e2f commit ea76b63

File tree

1 file changed

+37
-1
lines changed

1 file changed

+37
-1
lines changed

Sources/SourceKitLSPAPI/PluginTargetBuildDescription.swift

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,43 @@ struct PluginTargetBuildDescription: BuildTarget {
6666
// FIXME: This is very odd and we should clean this up by merging `ManifestLoader` and `DefaultPluginScriptRunner` again.
6767
var args = ManifestLoader.interpreterFlags(for: self.toolsVersion, toolchain: toolchain)
6868
// Note: we ignore the `fileURL` here as the expectation is that we get a commandline for the entire target in case of Swift. Plugins are always assumed to only consist of Swift files.
69-
args += sources.map { $0.path }
69+
args += try sources.map { try $0.filePath }
7070
return args
7171
}
7272
}
73+
74+
fileprivate enum FilePathError: Error, CustomStringConvertible {
75+
case noFileSystemRepresentation(URL)
76+
case noFileURL(URL)
77+
78+
var description: String {
79+
switch self {
80+
case .noFileSystemRepresentation(let url):
81+
return "\(url.description) cannot be represented as a file system path"
82+
case .noFileURL(let url):
83+
return "\(url.description) is not a file URL"
84+
}
85+
}
86+
}
87+
88+
fileprivate extension URL {
89+
/// Assuming that this is a file URL, the path with which the file system refers to the file. This is similar to
90+
/// `path` but has two differences:
91+
/// - It uses backslashes as the path separator on Windows instead of forward slashes
92+
/// - It throws an error when called on a non-file URL.
93+
///
94+
/// `filePath` should generally be preferred over `path` when dealing with file URLs.
95+
var filePath: String {
96+
get throws {
97+
guard self.isFileURL else {
98+
throw FilePathError.noFileURL(self)
99+
}
100+
return try self.withUnsafeFileSystemRepresentation { buffer in
101+
guard let buffer else {
102+
throw FilePathError.noFileSystemRepresentation(self)
103+
}
104+
return String(cString: buffer)
105+
}
106+
}
107+
}
108+
}

0 commit comments

Comments
 (0)