From 7ebf1036451d1ca6dfa802bccebdbb89c8eed81a Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Wed, 4 Dec 2019 17:22:46 -0800 Subject: [PATCH] Update ImplementationRequest to match version 3.14 of the LSP spec --- .../DefinitionRequest.swift | 31 +------------- .../ImplementationRequest.swift | 2 +- .../LocationsOrLocationLinksResponse.swift | 40 +++++++++++++++++++ Sources/SourceKit/SourceKitServer.swift | 8 ++-- .../CodingTests.swift | 6 +-- .../SourceKitTests/ImplementationTests.swift | 6 ++- 6 files changed, 54 insertions(+), 39 deletions(-) create mode 100644 Sources/LanguageServerProtocol/LocationsOrLocationLinksResponse.swift diff --git a/Sources/LanguageServerProtocol/DefinitionRequest.swift b/Sources/LanguageServerProtocol/DefinitionRequest.swift index 6a5800ed..0b7520a7 100644 --- a/Sources/LanguageServerProtocol/DefinitionRequest.swift +++ b/Sources/LanguageServerProtocol/DefinitionRequest.swift @@ -24,7 +24,7 @@ /// - Returns: The location of the definition(s). public struct DefinitionRequest: TextDocumentRequest, Hashable { public static let method: String = "textDocument/definition" - public typealias Response = DefinitionResponse? + public typealias Response = LocationsOrLocationLinksResponse? /// The document in which to lookup the symbol location. public var textDocument: TextDocumentIdentifier @@ -37,32 +37,3 @@ public struct DefinitionRequest: TextDocumentRequest, Hashable { self.position = position } } - -public enum DefinitionResponse: ResponseType, Hashable { - case locations([Location]) - case locationLinks([LocationLink]) - - public init(from decoder: Decoder) throws { - if let locations = try? [Location](from: decoder) { - self = .locations(locations) - } else if let locationLinks = try? [LocationLink](from: decoder) { - self = .locationLinks(locationLinks) - } else if let location = try? Location(from: decoder) { - // Fallback: Decode single location as array with one element - self = .locations([location]) - } else { - let context = DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "DefinitionResponse could neither be decoded as [Location], nor as [LocationLink], nor as Location") - throw DecodingError.dataCorrupted(context) - } - } - - public func encode(to encoder: Encoder) throws { - switch self { - case .locations(let locations): - try locations.encode(to: encoder) - case .locationLinks(let locationLinks): - try locationLinks.encode(to: encoder) - } - } -} - diff --git a/Sources/LanguageServerProtocol/ImplementationRequest.swift b/Sources/LanguageServerProtocol/ImplementationRequest.swift index 63f763d2..aecfa4e7 100644 --- a/Sources/LanguageServerProtocol/ImplementationRequest.swift +++ b/Sources/LanguageServerProtocol/ImplementationRequest.swift @@ -25,7 +25,7 @@ /// protocol conforming types, subclasses, or overrides. public struct ImplementationRequest: TextDocumentRequest, Hashable { public static let method: String = "textDocument/implementation" - public typealias Response = [Location] + public typealias Response = LocationsOrLocationLinksResponse? /// The document in which the given symbol is located. public var textDocument: TextDocumentIdentifier diff --git a/Sources/LanguageServerProtocol/LocationsOrLocationLinksResponse.swift b/Sources/LanguageServerProtocol/LocationsOrLocationLinksResponse.swift new file mode 100644 index 00000000..3edf1881 --- /dev/null +++ b/Sources/LanguageServerProtocol/LocationsOrLocationLinksResponse.swift @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2019 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 +// +//===----------------------------------------------------------------------===// + +public enum LocationsOrLocationLinksResponse: ResponseType, Hashable { + case locations([Location]) + case locationLinks([LocationLink]) + + public init(from decoder: Decoder) throws { + if let locations = try? [Location](from: decoder) { + self = .locations(locations) + } else if let locationLinks = try? [LocationLink](from: decoder) { + self = .locationLinks(locationLinks) + } else if let location = try? Location(from: decoder) { + // Fallback: Decode single location as array with one element + self = .locations([location]) + } else { + let context = DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Expected [Location], [LocationLink], or Location") + throw DecodingError.dataCorrupted(context) + } + } + + public func encode(to encoder: Encoder) throws { + switch self { + case .locations(let locations): + try locations.encode(to: encoder) + case .locationLinks(let locationLinks): + try locationLinks.encode(to: encoder) + } + } +} + diff --git a/Sources/SourceKit/SourceKitServer.swift b/Sources/SourceKit/SourceKitServer.swift index 95710b93..74bd62dd 100644 --- a/Sources/SourceKit/SourceKitServer.swift +++ b/Sources/SourceKit/SourceKitServer.swift @@ -81,7 +81,7 @@ public final class SourceKitServer: LanguageServer { CompletionList(isIncomplete: false, items: [])) registerToolchainTextDocumentRequest(SourceKitServer.hover, nil) registerToolchainTextDocumentRequest(SourceKitServer.definition, .locations([])) - registerToolchainTextDocumentRequest(SourceKitServer.implementation, []) + registerToolchainTextDocumentRequest(SourceKitServer.implementation, .locations([])) registerToolchainTextDocumentRequest(SourceKitServer.symbolInfo, []) registerToolchainTextDocumentRequest(SourceKitServer.documentSymbolHighlight, nil) registerToolchainTextDocumentRequest(SourceKitServer.foldingRange, nil) @@ -627,13 +627,13 @@ extension SourceKitServer { if let error = result.failure { req.reply(.failure(error)) } else { - req.reply([]) + req.reply(.locations([])) } return } guard let usr = symbol.usr, let index = index else { - return req.reply([]) + return req.reply(.locations([])) } var occurs = index.occurrences(ofUSR: usr, roles: .baseOf) @@ -655,7 +655,7 @@ extension SourceKitServer { ) } - req.reply(locations) + req.reply(.locations(locations)) } let request = Request(symbolInfo, id: req.id, clientID: ObjectIdentifier(self), cancellation: req.cancellationToken, reply: callback) diff --git a/Tests/LanguageServerProtocolTests/CodingTests.swift b/Tests/LanguageServerProtocolTests/CodingTests.swift index 87934ab1..1f8a7ee7 100644 --- a/Tests/LanguageServerProtocolTests/CodingTests.swift +++ b/Tests/LanguageServerProtocolTests/CodingTests.swift @@ -298,7 +298,7 @@ final class CodingTests: XCTestCase { "Some documentation" """) - checkCoding(DefinitionResponse.locations([Location(uri: uri, range: range)]), json: """ + checkCoding(LocationsOrLocationLinksResponse.locations([Location(uri: uri, range: range)]), json: """ [ { "range" : \(rangejson.indented(4, skipFirstLine: true)), @@ -307,7 +307,7 @@ final class CodingTests: XCTestCase { ] """) - checkCoding(DefinitionResponse.locationLinks([LocationLink(targetUri: uri, targetRange: range, targetSelectionRange: range)]), json: """ + checkCoding(LocationsOrLocationLinksResponse.locationLinks([LocationLink(targetUri: uri, targetRange: range, targetSelectionRange: range)]), json: """ [ { "targetRange" : \(rangejson.indented(4, skipFirstLine: true)), @@ -322,7 +322,7 @@ final class CodingTests: XCTestCase { "range" : \(rangejson.indented(2, skipFirstLine: true)), "uri" : "\(urljson)" } - """, expected: DefinitionResponse.locations([Location(uri: uri, range: range)])) + """, expected: LocationsOrLocationLinksResponse.locations([Location(uri: uri, range: range)])) checkCoding(DocumentSymbolResponse.documentSymbols([DocumentSymbol(name: "mySymbol", kind: .function, range: range, selectionRange: range)]), json: """ [ diff --git a/Tests/SourceKitTests/ImplementationTests.swift b/Tests/SourceKitTests/ImplementationTests.swift index 71cf7612..6d04d070 100644 --- a/Tests/SourceKitTests/ImplementationTests.swift +++ b/Tests/SourceKitTests/ImplementationTests.swift @@ -25,7 +25,11 @@ final class ImplementationTests: XCTestCase { func impls(at testLoc: TestLocation) throws -> Set { let textDocument = testLoc.docIdentifier let request = ImplementationRequest(textDocument: textDocument, position: Position(testLoc)) - let implementations = try ws.sk.sendSync(request) + let response = try ws.sk.sendSync(request) + guard case .locations(let implementations) = response else { + XCTFail("Response was not locations") + return [] + } return Set(implementations) } func testLoc(_ name: String) -> TestLocation {