Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename getReferenceDocument request to textDocumentContent #1639

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
19 changes: 9 additions & 10 deletions Contributor Documentation/LSP Extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -596,29 +596,28 @@ export interface PeekDocumentsResult {
}
```

## `workspace/getReferenceDocument`
fwcd marked this conversation as resolved.
Show resolved Hide resolved
## `workspace/textDocumentContent`

Request from the client to the server asking for contents of a URI having a custom scheme.
For example: "sourcekit-lsp:"
Request from the client to the server for querying the contents of a document, potentially using a custom URI scheme (such as `sourcekit-lsp:`). This closely models the proposed LSP 3.18 request of the same name, thus can be removed once LSP 3.18 has been stabilized.

Enable the experimental client capability `"workspace/getReferenceDocument"` so that the server responds with reference document URLs for certain requests or commands whenever possible.
Currently requires enabling the experimental client capability `"workspace/textDocumentContent"` to have the server respond with custom `sourcekit-lsp:` URIs (e.g. in macro expansion requests).

- params: `GetReferenceDocumentParams`
- params: `TextDocumentContentParams`

- result: `GetReferenceDocumentResponse`
- result: `TextDocumentContentResponse`

```ts
export interface GetReferenceDocumentParams {
export interface TextDocumentContentParams {
/**
* The `DocumentUri` of the custom scheme url for which content is required
*/
uri: DocumentUri;
}

/**
* Response containing `content` of `GetReferenceDocumentRequest`
* Response containing the content of the requested document
*/
export interface GetReferenceDocumentResult {
content: string;
export interface TextDocumentContentResult {
text: string;
}
```
2 changes: 1 addition & 1 deletion Sources/LanguageServerProtocol/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ add_library(LanguageServerProtocol STATIC
Requests/ExecuteCommandRequest.swift
Requests/FoldingRangeRequest.swift
Requests/FormattingRequests.swift
Requests/GetReferenceDocumentRequest.swift
Requests/HoverRequest.swift
Requests/ImplementationRequest.swift
Requests/IndexedRenameRequest.swift
Expand All @@ -79,6 +78,7 @@ add_library(LanguageServerProtocol STATIC
Requests/ShutdownRequest.swift
Requests/SignatureHelpRequest.swift
Requests/SymbolInfoRequest.swift
Requests/TextDocumentContentRequest.swift
Requests/TriggerReindexRequest.swift
Requests/TypeDefinitionRequest.swift
Requests/TypeHierarchyPrepareRequest.swift
Expand Down
2 changes: 1 addition & 1 deletion Sources/LanguageServerProtocol/Messages.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ public let builtinRequests: [_RequestType.Type] = [
DocumentTestsRequest.self,
ExecuteCommandRequest.self,
FoldingRangeRequest.self,
GetReferenceDocumentRequest.self,
HoverRequest.self,
ImplementationRequest.self,
InitializeRequest.self,
Expand All @@ -71,6 +70,7 @@ public let builtinRequests: [_RequestType.Type] = [
ShutdownRequest.self,
SignatureHelpRequest.self,
SymbolInfoRequest.self,
TextDocumentContentRequest.self,
TriggerReindexRequest.self,
TypeDefinitionRequest.self,
TypeHierarchyPrepareRequest.self,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

/// Request from the client to the server asking for contents of a URI having a custom scheme
/// For example: "sourcekit-lsp:"
///
/// - Parameters:
/// - uri: The `DocumentUri` of the custom scheme url for which content is required
///
/// - Returns: `TextDocumentContentResponse` which contains the `content` to be displayed.
public struct TextDocumentContentRequest: RequestType {
public static let method: String = "workspace/textDocumentContent"
public typealias Response = TextDocumentContentResponse

public var uri: DocumentURI

public init(uri: DocumentURI) {
self.uri = uri
}
}

/// Response containing the content of the requested text document.
///
/// Please note, that the content of any subsequent open notifications for the
/// text document might differ from the returned content due to whitespace and
/// line ending normalizations done on the client.
public struct TextDocumentContentResponse: ResponseType {
public var text: String
fwcd marked this conversation as resolved.
Show resolved Hide resolved

public init(text: String) {
self.text = text
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ public struct WorkspaceClientCapabilities: Hashable, Codable, Sendable {

public var diagnostics: RefreshRegistrationCapability? = nil

public var textDocumentContent: DynamicRegistrationCapability? = nil

public init(
applyEdit: Bool? = nil,
workspaceEdit: WorkspaceEdit? = nil,
Expand All @@ -202,7 +204,8 @@ public struct WorkspaceClientCapabilities: Hashable, Codable, Sendable {
fileOperations: FileOperations? = nil,
inlineValue: RefreshRegistrationCapability? = nil,
inlayHint: RefreshRegistrationCapability? = nil,
diagnostics: RefreshRegistrationCapability? = nil
diagnostics: RefreshRegistrationCapability? = nil,
textDocumentContent: DynamicRegistrationCapability? = nil
) {
self.applyEdit = applyEdit
self.workspaceEdit = workspaceEdit
Expand All @@ -218,6 +221,7 @@ public struct WorkspaceClientCapabilities: Hashable, Codable, Sendable {
self.inlineValue = inlineValue
self.inlayHint = inlayHint
self.diagnostics = diagnostics
self.textDocumentContent = textDocumentContent
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1219,10 +1219,27 @@ public struct WorkspaceServerCapabilities: Codable, Hashable, Sendable {
public var willDelete: FileOperationRegistrationOptions?
}

/// Text document content provider options.
public struct TextDocumentContentOptions: Codable, Hashable, Sendable {
/// The schemes for which the server provides content.
public var schemes: [String]

public init(schemes: [String] = []) {
self.schemes = schemes
}
}

/// The server supports workspace folder.
public var workspaceFolders: WorkspaceFolders?

public init(workspaceFolders: WorkspaceFolders? = nil) {
/// The server supports the `workspace/textDocumentContent` request.
public var textDocumentContent: TextDocumentContentOptions?

public init(
workspaceFolders: WorkspaceFolders? = nil,
textDocumentContent: TextDocumentContentOptions? = nil
) {
self.workspaceFolders = workspaceFolders
self.textDocumentContent = textDocumentContent
}
}
2 changes: 1 addition & 1 deletion Sources/SourceKitLSP/Clang/ClangLanguageService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ extension ClangLanguageService {
return try await forwardRequestToClangd(req)
}

func getReferenceDocument(_ req: GetReferenceDocumentRequest) async throws -> GetReferenceDocumentResponse {
func textDocumentContent(_ req: TextDocumentContentRequest) async throws -> TextDocumentContentResponse {
throw ResponseError.unknown("unsupported method")
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/SourceKitLSP/LanguageService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ package protocol LanguageService: AnyObject, Sendable {

func executeCommand(_ req: ExecuteCommandRequest) async throws -> LSPAny?

func getReferenceDocument(_ req: GetReferenceDocumentRequest) async throws -> GetReferenceDocumentResponse
func textDocumentContent(_ req: TextDocumentContentRequest) async throws -> TextDocumentContentResponse

/// Perform a syntactic scan of the file at the given URI for test cases and test classes.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ enum MessageHandlingDependencyTracker: DependencyTracker {
} else {
self = .freestanding
}
case let request as GetReferenceDocumentRequest:
case let request as TextDocumentContentRequest:
self = .documentRequest(request.uri)
case is InitializeRequest:
self = .globalConfigurationChange
Expand Down
20 changes: 11 additions & 9 deletions Sources/SourceKitLSP/SourceKitLSPServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -746,8 +746,8 @@ extension SourceKitLSPServer: MessageHandler {
await request.reply { try await executeCommand(request.params) }
case let request as RequestAndReply<FoldingRangeRequest>:
await self.handleRequest(for: request, requestHandler: self.foldingRange)
case let request as RequestAndReply<GetReferenceDocumentRequest>:
await request.reply { try await getReferenceDocument(request.params) }
case let request as RequestAndReply<TextDocumentContentRequest>:
await request.reply { try await textDocumentContent(request.params) }
case let request as RequestAndReply<HoverRequest>:
await self.handleRequest(for: request, requestHandler: self.hover)
case let request as RequestAndReply<ImplementationRequest>:
Expand Down Expand Up @@ -987,7 +987,7 @@ extension SourceKitLSPServer {
// The below is a workaround for the vscode-swift extension since it cannot set client capabilities.
// It passes "workspace/peekDocuments" through the `initializationOptions`.
//
// Similarly, for "workspace/getReferenceDocument".
// Similarly for "workspace/textDocumentContent".
var clientCapabilities = req.capabilities
if case .dictionary(let initializationOptions) = req.initializationOptions {
if let peekDocuments = initializationOptions["workspace/peekDocuments"] {
Expand All @@ -999,12 +999,12 @@ extension SourceKitLSPServer {
}
}

if let getReferenceDocument = initializationOptions["workspace/getReferenceDocument"] {
if let textDocumentContent = initializationOptions["workspace/textDocumentContent"] {
if case .dictionary(var experimentalCapabilities) = clientCapabilities.experimental {
experimentalCapabilities["workspace/getReferenceDocument"] = getReferenceDocument
experimentalCapabilities["workspace/textDocumentContent"] = textDocumentContent
clientCapabilities.experimental = .dictionary(experimentalCapabilities)
} else {
clientCapabilities.experimental = .dictionary(["workspace/getReferenceDocument": getReferenceDocument])
clientCapabilities.experimental = .dictionary(["workspace/textDocumentContent": textDocumentContent])
}
}

Expand Down Expand Up @@ -1166,6 +1166,9 @@ extension SourceKitLSPServer {
workspaceFolders: .init(
supported: true,
changeNotifications: .bool(true)
),
textDocumentContent: .init(
schemes: [ReferenceDocumentURL.scheme]
)
),
callHierarchyProvider: .bool(true),
Expand All @@ -1176,7 +1179,6 @@ extension SourceKitLSPServer {
"workspace/tests": .dictionary(["version": .int(2)]),
"textDocument/tests": .dictionary(["version": .int(2)]),
"workspace/triggerReindex": .dictionary(["version": .int(1)]),
"workspace/getReferenceDocument": .dictionary(["version": .int(1)]),
])
)
}
Expand Down Expand Up @@ -1744,7 +1746,7 @@ extension SourceKitLSPServer {
return try await languageService.executeCommand(executeCommand)
}

func getReferenceDocument(_ req: GetReferenceDocumentRequest) async throws -> GetReferenceDocumentResponse {
func textDocumentContent(_ req: TextDocumentContentRequest) async throws -> TextDocumentContentResponse {
let primaryFileURI = try ReferenceDocumentURL(from: req.uri).primaryFile

guard let workspace = await workspaceForDocument(uri: primaryFileURI) else {
Expand All @@ -1755,7 +1757,7 @@ extension SourceKitLSPServer {
throw ResponseError.unknown("No Language Service for URI: \(primaryFileURI)")
}

return try await languageService.getReferenceDocument(req)
return try await languageService.textDocumentContent(req)
}

func codeAction(
Expand Down
2 changes: 1 addition & 1 deletion Sources/SourceKitLSP/Swift/MacroExpansion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ extension SwiftLanguageService {

if case .dictionary(let experimentalCapabilities) = self.capabilityRegistry.clientCapabilities.experimental,
case .bool(true) = experimentalCapabilities["workspace/peekDocuments"],
case .bool(true) = experimentalCapabilities["workspace/getReferenceDocument"]
case .bool(true) = experimentalCapabilities["workspace/textDocumentContent"]
{
let expansionURIs = try macroExpansionReferenceDocumentURLs.map {
return DocumentURI(try $0.url)
Expand Down
2 changes: 1 addition & 1 deletion Sources/SourceKitLSP/Swift/ReferenceDocumentURL.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import Foundation
import LanguageServerProtocol

/// A Reference Document is a document whose url scheme is `sourcekit-lsp:` and whose content can only be retrieved
/// using `GetReferenceDocumentRequest`. The enum represents a specific type of reference document and its
/// using `TextDocumentContentRequest`. The enum represents a specific type of reference document and its
/// associated value represents the data necessary to generate the document's contents and its url
///
/// The `url` will be of the form: `sourcekit-lsp://<document-type>/<display-name>?<parameters>`
Expand Down
6 changes: 3 additions & 3 deletions Sources/SourceKitLSP/Swift/SwiftLanguageService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1002,13 +1002,13 @@ extension SwiftLanguageService {
return nil
}

package func getReferenceDocument(_ req: GetReferenceDocumentRequest) async throws -> GetReferenceDocumentResponse {
package func textDocumentContent(_ req: TextDocumentContentRequest) async throws -> TextDocumentContentResponse {
let referenceDocumentURL = try ReferenceDocumentURL(from: req.uri)

switch referenceDocumentURL {
case let .macroExpansion(data):
return GetReferenceDocumentResponse(
content: try await macroExpansionManager.macroExpansion(for: data)
return TextDocumentContentResponse(
text: try await macroExpansionManager.macroExpansion(for: data)
)
}
}
Expand Down
Loading