Skip to content

Commit 72aefff

Browse files
authored
Merge pull request #193 from ahoppen/document-uri
Add support for non-URL URIs
2 parents fcfaa50 + 947825b commit 72aefff

File tree

50 files changed

+660
-463
lines changed

Some content is hidden

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

50 files changed

+660
-463
lines changed

Package.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ let package = Package(
4040
"LSPTestSupport",
4141
"SourceKit",
4242
"tibs", // Never imported, needed at runtime
43+
"TSCUtility",
4344
]
4445
),
4546
.testTarget(

Sources/BuildServerProtocol/BuildTargets.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
//===----------------------------------------------------------------------===//
1212
import LanguageServerProtocol
1313

14+
public typealias URI = DocumentURI
15+
1416
/// The workspace build targets request is sent from the client to the server to
1517
/// ask for the list of all available build targets in the workspace.
1618
public struct BuildTargets: RequestType, Hashable {
@@ -38,7 +40,7 @@ public struct BuildTarget: Codable, Hashable {
3840
/// allowed to map to the same base directory, and a build target is not
3941
/// required to have a base directory. A base directory does not determine the
4042
/// sources of a target, see buildTarget/sources.
41-
public var baseDirectory: URL?
43+
public var baseDirectory: URI?
4244

4345
/// Free-form string tags to categorize or label this build target.
4446
/// For example, can be used by the client to:
@@ -62,7 +64,7 @@ public struct BuildTarget: Codable, Hashable {
6264

6365
public init(id: BuildTargetIdentifier,
6466
displayName: String?,
65-
baseDirectory: URL?,
67+
baseDirectory: URI?,
6668
tags: [BuildTargetTag],
6769
capabilities: BuildTargetCapabilities,
6870
languageIds: [Language],
@@ -78,9 +80,9 @@ public struct BuildTarget: Codable, Hashable {
7880
}
7981

8082
public struct BuildTargetIdentifier: Codable, Hashable {
81-
public var uri: URL
83+
public var uri: URI
8284

83-
public init(uri: URL) {
85+
public init(uri: URI) {
8486
self.uri = uri
8587
}
8688
}
@@ -166,7 +168,7 @@ public struct SourceItem: Codable, Hashable {
166168
/// Either a text document or a directory. A directory entry must end with a
167169
/// forward slash "/" and a directory entry implies that every nested text
168170
/// document within the directory belongs to this source item.
169-
public var uri: URL
171+
public var uri: URI
170172

171173
/// Type of file of the source item, such as whether it is file or directory.
172174
public var kind: SourceItemKind
@@ -205,7 +207,7 @@ public struct OutputsItem: Codable, Hashable {
205207
public var target: BuildTargetIdentifier
206208

207209
/// The output paths for sources that belong to this build target.
208-
public var outputPaths: [URL]
210+
public var outputPaths: [URI]
209211
}
210212

211213
/// The build target changed notification is sent from the server to the client

Sources/BuildServerProtocol/FileOptions.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ public struct SourceKitOptions: RequestType, Hashable {
1717
public static let method: String = "textDocument/sourceKitOptions"
1818
public typealias Response = SourceKitOptionsResult
1919

20-
/// The URL of the document to get options for
21-
public var uri: URL
20+
/// The URI of the document to get options for
21+
public var uri: URI
2222

23-
public init(uri: URL) {
23+
public init(uri: URI) {
2424
self.uri = uri
2525
}
2626
}

Sources/BuildServerProtocol/InitializeBuild.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ public struct InitializeBuild: RequestType, Hashable {
3939
public var bspVersion: String
4040

4141
/// The rootUri of the workspace
42-
public var rootUri: URL
42+
public var rootUri: URI
4343

4444
/// The capabilities of the client
4545
public var capabilities: BuildClientCapabilities
4646

47-
public init(displayName: String, version: String, bspVersion: String, rootUri: URL, capabilities: BuildClientCapabilities) {
47+
public init(displayName: String, version: String, bspVersion: String, rootUri: URI, capabilities: BuildClientCapabilities) {
4848
self.displayName = displayName
4949
self.version = version
5050
self.bspVersion = bspVersion

Sources/BuildServerProtocol/RegisterForChangeNotifications.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ public struct RegisterForChanges: RequestType {
2020
public static let method: String = "textDocument/registerForChanges"
2121
public typealias Response = VoidResponse
2222

23-
/// The URL of the document to get options for.
24-
public var uri: URL
23+
/// The URI of the document to get options for.
24+
public var uri: URI
2525

2626
/// Whether to register or unregister for the file.
2727
public var action: RegisterAction
2828

29-
public init(uri: URL, action: RegisterAction) {
29+
public init(uri: URI, action: RegisterAction) {
3030
self.uri = uri
3131
self.action = action
3232
}
@@ -43,8 +43,8 @@ public enum RegisterAction: String, Hashable, Codable {
4343
public struct FileOptionsChangedNotification: NotificationType {
4444
public static let method: String = "build/sourceKitOptionsChanged"
4545

46-
/// The URL of the document that has changed settings.
47-
public var uri: URL
46+
/// The URI of the document that has changed settings.
47+
public var uri: URI
4848

4949
/// The updated options for the registered file.
5050
public var updatedOptions: SourceKitOptionsResult
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import Foundation
14+
15+
public struct DocumentURI: Codable, Hashable {
16+
/// The URL that store the URIs value
17+
private let storage: URL
18+
19+
public var fileURL: URL? {
20+
if storage.isFileURL {
21+
return storage
22+
} else {
23+
return nil
24+
}
25+
}
26+
27+
/// Returns a filepath if the URI is a URL. If the URI is not a URL, returns
28+
/// the full URI as a fallback.
29+
/// This value is intended to be used when interacting with sourcekitd which
30+
/// expects a file path but is able to handle arbitrary strings as well in a
31+
/// fallback mode that drops semantic functionality.
32+
public var pseudoPath: String {
33+
if storage.isFileURL {
34+
return storage.path
35+
} else {
36+
return storage.absoluteString
37+
}
38+
}
39+
40+
/// Returns the URI as a string.
41+
public var stringValue: String {
42+
return storage.absoluteString
43+
}
44+
45+
/// Construct a DocumentURI from the given URI string, automatically parsing
46+
/// it either as a URL or an opaque URI.
47+
public init(string: String) {
48+
guard let url = URL(string: string) else {
49+
fatalError("Failed to construct DocumentURI from '\(string)'")
50+
}
51+
self.init(url)
52+
}
53+
54+
public init(_ url: URL) {
55+
self.storage = url
56+
assert(self.storage.scheme != nil, "Received invalid URI without a scheme '\(self.storage.absoluteString)'")
57+
}
58+
59+
public init(from decoder: Decoder) throws {
60+
self.init(string: try decoder.singleValueContainer().decode(String.self))
61+
}
62+
63+
public func encode(to encoder: Encoder) throws {
64+
try storage.absoluteString.encode(to: encoder)
65+
}
66+
}

Sources/LanguageServerProtocol/InitializeRequest.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
///
2020
/// - Parameters:
2121
/// - processId: The process identifier (pid) of the client process.
22-
/// - rootURL: The workspace URL, or nil if no workspace is open.
22+
/// - rootURI: The workspace URI, or nil if no workspace is open.
2323
/// - initializationOptions: User-provided options.
2424
/// - capabilities: The capabilities provided by the client editor.
2525
/// - trace: Whether to enable tracing.
@@ -39,13 +39,13 @@ public struct InitializeRequest: RequestType, Hashable {
3939

4040
/// The workspace path, or nil if no workspace is open.
4141
///
42-
/// - Note: deprecated in favour of `rootURL`.
42+
/// - Note: deprecated in favour of `rootURI`.
4343
public var rootPath: String? = nil
4444

45-
/// The workspace URL, or nil if no workspace is open.
45+
/// The workspace URI, or nil if no workspace is open.
4646
///
4747
/// Takes precedence over the deprecated `rootPath`.
48-
public var rootURL: URL?
48+
public var rootURI: DocumentURI?
4949

5050
/// User-provided options.
5151
public var initializationOptions: LSPAny? = nil
@@ -68,15 +68,15 @@ public struct InitializeRequest: RequestType, Hashable {
6868
public init(
6969
processId: Int? = nil,
7070
rootPath: String? = nil,
71-
rootURL: URL?,
71+
rootURI: DocumentURI?,
7272
initializationOptions: LSPAny? = nil,
7373
capabilities: ClientCapabilities,
7474
trace: Tracing = .off,
7575
workspaceFolders: [WorkspaceFolder]?)
7676
{
7777
self.processId = processId
7878
self.rootPath = rootPath
79-
self.rootURL = rootURL
79+
self.rootURI = rootURI
8080
self.initializationOptions = initializationOptions
8181
self.capabilities = capabilities
8282
self.trace = trace
@@ -88,7 +88,7 @@ extension InitializeRequest: Codable {
8888
private enum CodingKeys: String, CodingKey {
8989
case processId
9090
case rootPath
91-
case rootURL = "rootUri"
91+
case rootURI = "rootUri"
9292
case initializationOptions
9393
case capabilities
9494
case trace

Sources/LanguageServerProtocol/Location.swift

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,15 @@
1313
/// Range within a particular document.
1414
///
1515
/// For a location where the document is implied, use `Position` or `Range<Position>`.
16-
public struct Location: ResponseType, Hashable {
16+
public struct Location: ResponseType, Hashable, Codable {
1717

18-
public var url: URL
18+
public var uri: DocumentURI
1919

2020
@CustomCodable<PositionRange>
2121
public var range: Range<Position>
2222

23-
public init(url: URL, range: Range<Position>) {
24-
self.url = url
23+
public init(uri: DocumentURI, range: Range<Position>) {
24+
self.uri = uri
2525
self._range = CustomCodable<PositionRange>(wrappedValue: range)
2626
}
2727
}
28-
29-
// Encode using the key "uri" to match LSP.
30-
extension Location: Codable {
31-
private enum CodingKeys: String, CodingKey {
32-
case url = "uri"
33-
case range
34-
}
35-
}

Sources/LanguageServerProtocol/PublishDiagnostics.swift

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,19 @@
2222
/// to coalesce the notification across multiple changes in a short period of time.
2323
///
2424
/// - Parameters:
25-
/// - url: The document in which the diagnostics should be shown.
25+
/// - uri: The document in which the diagnostics should be shown.
2626
/// - diagnostics: The complete list of diagnostics in the document, if any.
27-
public struct PublishDiagnostics: NotificationType, Hashable {
27+
public struct PublishDiagnostics: NotificationType, Hashable, Codable {
2828
public static let method: String = "textDocument/publishDiagnostics"
2929

3030
/// The document in which the diagnostics should be shown.
31-
public var url: URL
31+
public var uri: DocumentURI
3232

3333
/// The complete list of diagnostics in the document, if any.
3434
public var diagnostics: [Diagnostic]
3535

36-
public init(url: URL, diagnostics: [Diagnostic]) {
37-
self.url = url
36+
public init(uri: DocumentURI, diagnostics: [Diagnostic]) {
37+
self.uri = uri
3838
self.diagnostics = diagnostics
3939
}
4040
}
41-
42-
extension PublishDiagnostics: Codable {
43-
private enum CodingKeys: String, CodingKey {
44-
case url = "uri"
45-
case diagnostics
46-
}
47-
}

Sources/LanguageServerProtocol/TextDocumentIdentifier.swift

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,43 +10,28 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
import struct Foundation.URL
14-
15-
/// Convenience alias so that you don't need to add Foundation import to use.
16-
public typealias URL = Foundation.URL
17-
1813
/// Unique identifier for a document.
19-
public struct TextDocumentIdentifier: Hashable {
14+
public struct TextDocumentIdentifier: Hashable, Codable {
2015

21-
/// A URL that uniquely identifies the document.
22-
public var url: URL
16+
/// A URI that uniquely identifies the document.
17+
public var uri: DocumentURI
2318

24-
public init(_ url: URL) {
25-
self.url = url
26-
}
27-
}
28-
29-
// Encode using the key "uri" to match LSP.
30-
extension TextDocumentIdentifier: Codable {
31-
private enum CodingKeys: String, CodingKey {
32-
case url = "uri"
19+
public init(_ uri: DocumentURI) {
20+
self.uri = uri
3321
}
3422
}
3523

3624
extension TextDocumentIdentifier: LSPAnyCodable {
3725
public init?(fromLSPDictionary dictionary: [String : LSPAny]) {
38-
guard case .string(let urlString)? = dictionary[CodingKeys.url.stringValue] else {
39-
return nil
40-
}
41-
guard let url = URL(string: urlString) else {
26+
guard case .string(let uriString)? = dictionary[CodingKeys.uri.stringValue] else {
4227
return nil
4328
}
44-
self.url = url
29+
self.uri = DocumentURI(string: uriString)
4530
}
4631

4732
public func encodeToLSPAny() -> LSPAny {
4833
return .dictionary([
49-
CodingKeys.url.stringValue: .string(url.absoluteString)
34+
CodingKeys.uri.stringValue: .string(uri.stringValue)
5035
])
5136
}
5237
}

Sources/LanguageServerProtocol/TextDocumentItem.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
/// The content and metadata of a text document.
1414
public struct TextDocumentItem: Hashable {
1515

16-
public var url: URL
16+
public var uri: DocumentURI
1717

1818
public var language: Language
1919

@@ -23,8 +23,8 @@ public struct TextDocumentItem: Hashable {
2323
/// The content of the document.
2424
public var text: String
2525

26-
public init(url: URL, language: Language, version: Int, text: String) {
27-
self.url = url
26+
public init(uri: DocumentURI, language: Language, version: Int, text: String) {
27+
self.uri = uri
2828
self.language = language
2929
self.version = version
3030
self.text = text
@@ -33,7 +33,7 @@ public struct TextDocumentItem: Hashable {
3333

3434
extension TextDocumentItem: Codable {
3535
private enum CodingKeys: String, CodingKey {
36-
case url = "uri"
36+
case uri
3737
case language = "languageId"
3838
case version
3939
case text

0 commit comments

Comments
 (0)