This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Removed the SpecViolations by introducing an protocol and casting to …

…in the JsonRpcProtocol layer.
  • Loading branch information...
owensd committed May 29, 2017
1 parent c1739ce commit 8e2de14124fae91cf0d02c873acd16f9e93f5ef2
@@ -104,11 +104,12 @@ extension ClientCapabilities: Decodable {
public static func decode(_ data: JSValue?) throws -> ClientCapabilities {
let workspace = try? WorkspaceClientCapabilities.decode(data["workspace"])
let textDocument = try? TextDocumentClientCapabilities.decode(data["workspace"])

let experimental = data["experimental"] ?? .null

return ClientCapabilities(
workspace: workspace,
textDocument: textDocument,
experimental: data["experimental"] ?? .null)
experimental: experimental as? AnyEncodable)
}
}

@@ -198,7 +199,7 @@ extension Registration: Decodable {
throw "The `method` parameter is required."
}

return Registration(id: id, method: method, registerOptions: data["registerOptions"])
return Registration(id: id, method: method, registerOptions: data["registerOptions"] as? AnyEncodable)
}
}

@@ -234,7 +235,8 @@ extension DidChangeConfigurationParams: Decodable {
public typealias EncodableType = JSValue

public static func decode(_ data: JSValue?) throws -> DidChangeConfigurationParams {
return DidChangeConfigurationParams(settings: data?["settings"] ?? .null)
let encodable = (data?["settings"] ?? .null) as! AnyEncodable
return DidChangeConfigurationParams(settings: encodable)
}
}

@@ -639,7 +641,7 @@ extension CompletionItem: Decodable {
textEdit: textEdit,
additionalTextEdits: additionalEdits,
command: command,
data: data
data: data as? AnyEncodable
)
}
}
@@ -674,7 +676,7 @@ extension Command: Decodable {
return Command(
title: title,
command: command,
arguments: data["arguments"] ?? .null
arguments: (data["arguments"] ?? .null) as? AnyEncodable
)
}
}
@@ -840,7 +842,7 @@ extension CodeLens: Decodable {
return CodeLens(
range: range,
command: command,
data: data
data: data as? AnyEncodable
)
}
}
@@ -13,6 +13,12 @@ import os.log
@available(macOS 10.12, *)
fileprivate let log = OSLog(subsystem: "com.kiadstudios.jsonrpcprotocol", category: "Encodable")

extension JSValue: AnyEncodable {
public func encode() -> Any {
return self
}
}

extension String: Encodable {
public func encode() -> JSValue {
return JSValue(self)
@@ -73,7 +79,7 @@ extension Command: Encodable {
json["title"] = title.encode()
json["command"] = command.encode()
if let arguments = arguments {
json["arguments"] = arguments
json["arguments"] = arguments.encode() as? JSValue
}
return json
}
@@ -437,7 +443,7 @@ extension ParameterInformation: Encodable {

extension DidChangeConfigurationParams: Encodable {
public func encode() -> JSValue {
return settings
return settings.encode() as! JSValue
}
}

@@ -478,7 +484,7 @@ extension CompletionItem: Encodable {
json["command"] = command.encode()
}
if let data = data {
json["data"] = data
json["data"] = data.encode() as? JSValue
}

return json
@@ -565,6 +571,17 @@ extension DiagnosticSeverity: Encodable {
}
}

extension Registration: Encodable {
public func encode() -> JSValue {
var json: JSValue = [:]
json["id"] = id.encode()
json["method"] = method.encode()
if let options = registerOptions?.encode() {
json["registerOptions"] = options as? JSValue
}
return json
}
}

extension LanguageServerResponse: Encodable {
private func encode<EncodingType>(_ requestId: RequestId, _ encodables: [EncodingType]?) -> JSValue where EncodingType: Encodable {
@@ -15,7 +15,7 @@ public struct ClientCapabilities {
public init(
workspace: WorkspaceClientCapabilities? = nil,
textDocument: TextDocumentClientCapabilities? = nil,
experimental: JSValue? = nil) {
experimental: AnyEncodable? = nil) {
self.workspace = workspace
self.textDocument = textDocument
self.experimental = experimental
@@ -28,8 +28,7 @@ public struct ClientCapabilities {
public var textDocument: TextDocumentClientCapabilities?

/// Experimental client capabilities.
/// SpecViolation: Value should be `Any`.
public var experimental: JSValue?
public var experimental: AnyEncodable?
}

/// `TextDocumentClientCapabilities` define capabilities the editor/tool provides on text documents.
@@ -7,7 +7,7 @@ import JSONLib

/// General parameters to to register for a capability.
public struct Registration {
public init(id: String, method: String, registerOptions: JSValue? = nil) {
public init(id: String, method: String, registerOptions: AnyEncodable? = nil) {
self.id = id
self.method = method
self.registerOptions = registerOptions
@@ -20,8 +20,7 @@ public struct Registration {
public var method: String

/// Options necessary for the registration.
/// SpecViolation: Value should be `Any`.
public var registerOptions: JSValue?
public var registerOptions: AnyEncodable?
}

public struct RegistrationParams {
@@ -9,7 +9,7 @@ import JSONLib
/// in the UI. Commands are identified using a string identifier and the protocol currently doesn't
/// specify a set of well known commands. So executing a command requires some tool extension code.
public struct Command {
public init(title: String, command: String, arguments: JSValue? = nil) {
public init(title: String, command: String, arguments: AnyEncodable? = nil) {
self.title = title
self.command = command
self.arguments = arguments
@@ -22,6 +22,5 @@ public struct Command {
public var command: String

/// Arguments that the command handler should be invoked with.
/// SpecViolation: Value should be `Any`.
public var arguments: JSValue?
public var arguments: AnyEncodable?
}
@@ -51,7 +51,7 @@ public struct CompletionItem {
textEdit: TextEdit? = nil,
additionalTextEdits: [TextEdit]? = nil,
command: Command? = nil,
data: JSValue? = nil) {
data: AnyEncodable? = nil) {
self.label = label
self.kind = kind
self.detail = detail
@@ -115,8 +115,7 @@ public struct CompletionItem {

/// An data entry field that is preserved on a completion item between a completion and a
/// completion resolve request.
/// SpecViolation: Value should be `Any`.
public var data: JSValue?
public var data: AnyEncodable?
}

/// The kind of a completion entry.
@@ -21,6 +21,14 @@ public protocol Encodable {
func encode() -> EncodableType
}

/// Defines a protocol that is useful when the type is not part of the known types for the Language
/// Server Protocol. This is necessary due to limitations in Swift's type system representation.
/// Without this, we have to expose leaky abstractions from our serialization layers, such as
/// `JSValue`.
public protocol AnyEncodable {
func encode() -> Any
}

/// Defines a generic protocol used to decode a given type into the data necessary for use within
/// the `MessageProtocol` layers.
public protocol Decodable {
@@ -328,7 +328,7 @@ public struct CodeLensParams {
/// A code lens is _unresolved_ when no command is associated to it. For performance reasons the
/// creation of a code lens and resolving should be done in two stages.
public struct CodeLens {
public init(range: Range, command: Command? = nil, data: JSValue? = nil) {
public init(range: Range, command: Command? = nil, data: AnyEncodable? = nil) {
self.range = range
self.command = command
self.data = data
@@ -342,8 +342,7 @@ public struct CodeLens {

/// A data entry field that is preserved on a code lens item between
/// a code lens and a code lens resolve request.
/// SpecViolation: Value should be `Any`.
public var data: JSValue?
public var data: AnyEncodable?
}

public struct DocumentLinkParams {
@@ -5,14 +5,13 @@

import JSONLib

// SpecViolation: settings: Any
public struct DidChangeConfigurationParams {
public init(settings: JSValue) {
public init(settings: AnyEncodable) {
self.settings = settings
}

/// The actual changed settings
public var settings: JSValue
public var settings: AnyEncodable
}

public struct DidChangeWatchedFilesParams {
@@ -51,6 +51,24 @@ final class EncodableTests: XCTestCase {
XCTAssertEqual(encoded["message"].string, "happy days")
}

func testEncodable005() {
let options: JSValue = [
"hello": "world",
"just": [
"some": "data",
"value": 12
]
]
let registration = Registration(id: "1234", method: "complete", registerOptions: options)
let encoded = registration.encode()
XCTAssertEqual(encoded["id"].string, "1234")
XCTAssertEqual(encoded["method"].string, "complete")
XCTAssertEqual(encoded["registerOptions"]["hello"].string, "world")
XCTAssertEqual(encoded["registerOptions"]["just"]["some"].string, "data")
XCTAssertEqual(encoded["registerOptions"]["just"]["value"].integer, 12)
}


static var allTests = [
("testEncodable001", testEncodable001),
("testEncodable002", testEncodable002),

0 comments on commit 8e2de14

Please sign in to comment.