-
Notifications
You must be signed in to change notification settings - Fork 274
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Avoid using decoders for retrieving dictionary data
- Loading branch information
Showing
9 changed files
with
203 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the Swift.org open source project | ||
// | ||
// Copyright (c) 2014 - 2018 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
import LanguageServerProtocol | ||
import Foundation | ||
import SKSupport | ||
|
||
/// Represents metadata that SourceKit-LSP injects at every command returned by code actions. | ||
/// The ExecuteCommand is not a TextDocumentRequest, so metadata is injected to allow SourceKit-LSP | ||
/// to determine where a command should be executed. | ||
public struct SourceKitLSPCommandMetadata: Codable, Hashable { | ||
|
||
public static func decode(fromDictionary dictionary: [String: CommandArgumentType]) -> SourceKitLSPCommandMetadata? { | ||
guard case .dictionary(let textDocumentDict)? = dictionary[CodingKeys.sourcekitlsp_textDocument.stringValue], | ||
case .string(let urlString)? = textDocumentDict[TextDocumentIdentifier.CodingKeys.url.stringValue], | ||
let url = URL(string: urlString) else | ||
{ | ||
return nil | ||
} | ||
let textDocument = TextDocumentIdentifier(url) | ||
return SourceKitLSPCommandMetadata(textDocument: textDocument) | ||
} | ||
|
||
public var sourcekitlsp_textDocument: TextDocumentIdentifier | ||
|
||
public init(textDocument: TextDocumentIdentifier) { | ||
self.sourcekitlsp_textDocument = textDocument | ||
} | ||
|
||
func asCommandArgument() -> CommandArgumentType { | ||
let textDocumentArgument = CommandArgumentType.dictionary( | ||
[TextDocumentIdentifier.CodingKeys.url.stringValue: .string(sourcekitlsp_textDocument.url.absoluteString)] | ||
) | ||
return .dictionary([CodingKeys.sourcekitlsp_textDocument.stringValue: textDocumentArgument]) | ||
} | ||
} | ||
|
||
extension CodeActionRequest { | ||
public func injectMetadata(atResponse response: CodeActionRequestResponse?) -> CodeActionRequestResponse? { | ||
let metadata = SourceKitLSPCommandMetadata(textDocument: textDocument) | ||
let metadataArgument = metadata.asCommandArgument() | ||
switch response { | ||
case .codeActions(var codeActions)?: | ||
for i in 0..<codeActions.count { | ||
codeActions[i].command?.arguments?.append(metadataArgument) | ||
} | ||
return .codeActions(codeActions) | ||
case .commands(var commands)?: | ||
for i in 0..<commands.count { | ||
commands[i].arguments?.append(metadataArgument) | ||
} | ||
return .commands(commands) | ||
case nil: | ||
return nil | ||
} | ||
} | ||
} | ||
|
||
extension ExecuteCommandRequest { | ||
/// The document in which the command was invoked. | ||
public var textDocument: TextDocumentIdentifier? { | ||
return metadata?.sourcekitlsp_textDocument | ||
} | ||
|
||
/// Optional metadata containing SourceKit-LSP information about this command. | ||
public var metadata: SourceKitLSPCommandMetadata? { | ||
guard case .dictionary(let dictionary)? = arguments?.last else { | ||
return nil | ||
} | ||
guard let metadata = SourceKitLSPCommandMetadata.decode(fromDictionary: dictionary) else { | ||
log("failed to decode lsp metadata in executeCommand request", level: .error) | ||
return nil | ||
} | ||
return metadata | ||
} | ||
|
||
/// Returns this Command's arguments without SourceKit-LSP's injected metadata, if it exists. | ||
public var argumentsWithoutLSPMetadata: [CommandArgumentType]? { | ||
guard metadata != nil else { | ||
return arguments | ||
} | ||
return arguments?.dropLast() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
import LanguageServerProtocol | ||
import SKSupport | ||
import SKTestSupport | ||
import XCTest | ||
|
||
@testable import SourceKit | ||
|
||
final class ExecuteCommandTests: XCTestCase { | ||
func testLSPCommandMetadataRetrieval() { | ||
var req = ExecuteCommandRequest(command: "", arguments: nil) | ||
XCTAssertNil(req.metadata) | ||
req.arguments = [1, 2, ""] | ||
XCTAssertNil(req.metadata) | ||
let url = URL(fileURLWithPath: "/a.swift") | ||
let textDocument = TextDocumentIdentifier(url) | ||
let metadata = SourceKitLSPCommandMetadata(textDocument: textDocument) | ||
req.arguments = [metadata.asCommandArgument(), 1, 2, ""] | ||
XCTAssertNil(req.metadata) | ||
req.arguments = [1, 2, "", [metadata.asCommandArgument()]] | ||
XCTAssertNil(req.metadata) | ||
req.arguments = [1, 2, "", metadata.asCommandArgument()] | ||
XCTAssertEqual(req.metadata, metadata) | ||
req.arguments = [metadata.asCommandArgument()] | ||
XCTAssertEqual(req.metadata, metadata) | ||
} | ||
|
||
func testLSPCommandMetadataRemoval() { | ||
var req = ExecuteCommandRequest(command: "", arguments: nil) | ||
XCTAssertNil(req.argumentsWithoutLSPMetadata) | ||
req.arguments = [1, 2, ""] | ||
XCTAssertEqual(req.arguments, req.argumentsWithoutLSPMetadata) | ||
let url = URL(fileURLWithPath: "/a.swift") | ||
let textDocument = TextDocumentIdentifier(url) | ||
let metadata = SourceKitLSPCommandMetadata(textDocument: textDocument) | ||
req.arguments = [metadata.asCommandArgument(), 1, 2, ""] | ||
XCTAssertEqual(req.arguments, req.argumentsWithoutLSPMetadata) | ||
req.arguments = [1, 2, "", [metadata.asCommandArgument()]] | ||
XCTAssertEqual(req.arguments, req.argumentsWithoutLSPMetadata) | ||
req.arguments = [1, 2, "", metadata.asCommandArgument()] | ||
XCTAssertEqual([1, 2, ""], req.argumentsWithoutLSPMetadata) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters