diff --git a/Sources/LanguageServerProtocol/SupportTypes/DocumentURI.swift b/Sources/LanguageServerProtocol/SupportTypes/DocumentURI.swift index 5f593d747..ad50fb849 100644 --- a/Sources/LanguageServerProtocol/SupportTypes/DocumentURI.swift +++ b/Sources/LanguageServerProtocol/SupportTypes/DocumentURI.swift @@ -56,12 +56,21 @@ public struct DocumentURI: Codable, Hashable, Sendable { /// fallback mode that drops semantic functionality. public var pseudoPath: String { if storage.isFileURL { - return storage.withUnsafeFileSystemRepresentation { filePath in - if let filePath { - String(cString: filePath) - } else { - "" + return storage.withUnsafeFileSystemRepresentation { filePathPtr in + guard let filePathPtr else { + return "" } + let filePath = String(cString: filePathPtr) + #if os(Windows) + // VS Code spells file paths with a lowercase drive letter, while the rest of Windows APIs use an uppercase + // drive letter. Normalize the drive letter spelling to be uppercase. + if filePath.first?.isASCII ?? false, filePath.first?.isLetter ?? false, filePath.first?.isLowercase ?? false, + filePath.count > 1, filePath[filePath.index(filePath.startIndex, offsetBy: 1)] == ":" + { + return filePath.first!.uppercased() + filePath.dropFirst() + } + #endif + return filePath } } else { return storage.absoluteString diff --git a/Sources/SKTestSupport/SkipUnless.swift b/Sources/SKTestSupport/SkipUnless.swift index dbfe49777..69a9deb5b 100644 --- a/Sources/SKTestSupport/SkipUnless.swift +++ b/Sources/SKTestSupport/SkipUnless.swift @@ -418,6 +418,10 @@ package actor SkipUnless { try XCTSkipUnless(Platform.current == .darwin, message) } + package static func platformIsWindows(_ message: String) throws { + try XCTSkipUnless(Platform.current == .windows, message) + } + package static func platformSupportsTaskPriorityElevation() throws { #if os(macOS) guard #available(macOS 14.0, *) else { diff --git a/Sources/SwiftExtensions/URLExtensions.swift b/Sources/SwiftExtensions/URLExtensions.swift index 024e91f6f..cfac5ae81 100644 --- a/Sources/SwiftExtensions/URLExtensions.swift +++ b/Sources/SwiftExtensions/URLExtensions.swift @@ -67,11 +67,21 @@ extension URL { guard self.isFileURL else { throw FilePathError.noFileURL(self) } - return try self.withUnsafeFileSystemRepresentation { buffer in - guard let buffer else { + return try self.withUnsafeFileSystemRepresentation { filePathPtr in + guard let filePathPtr else { throw FilePathError.noFileSystemRepresentation(self) } - return String(cString: buffer) + let filePath = String(cString: filePathPtr) + #if os(Windows) + // VS Code spells file paths with a lowercase drive letter, while the rest of Windows APIs use an uppercase + // drive letter. Normalize the drive letter spelling to be uppercase. + if filePath.first?.isASCII ?? false, filePath.first?.isLetter ?? false, filePath.first?.isLowercase ?? false, + filePath.count > 1, filePath[filePath.index(filePath.startIndex, offsetBy: 1)] == ":" + { + return filePath.first!.uppercased() + filePath.dropFirst() + } + #endif + return filePath } } } diff --git a/Tests/SourceKitLSPTests/PullDiagnosticsTests.swift b/Tests/SourceKitLSPTests/PullDiagnosticsTests.swift index 51ca9fb18..bcbcd2c11 100644 --- a/Tests/SourceKitLSPTests/PullDiagnosticsTests.swift +++ b/Tests/SourceKitLSPTests/PullDiagnosticsTests.swift @@ -48,6 +48,35 @@ final class PullDiagnosticsTests: XCTestCase { XCTAssertEqual(diagnostic.range, Position(line: 1, utf16index: 2)..