Skip to content

Commit d718f46

Browse files
committed
Adopt LSPAnyCodable in RegistrationOptions
1 parent e2c6854 commit d718f46

File tree

5 files changed

+375
-139
lines changed

5 files changed

+375
-139
lines changed

Sources/LanguageServerProtocol/SupportTypes/LSPAny.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,5 +171,15 @@ extension Array: LSPAnyCodable where Element: LSPAnyCodable {
171171
}
172172
}
173173

174+
extension String: LSPAnyCodable {
175+
public init?(fromLSPDictionary dictionary: [String : LSPAny]) {
176+
nil
177+
}
178+
179+
public func encodeToLSPAny() -> LSPAny {
180+
.string(self)
181+
}
182+
}
183+
174184
public typealias LSPObject = [String: LSPAny]
175185
public typealias LSPArray = [LSPAny]

Sources/LanguageServerProtocol/SupportTypes/RegistrationOptions.swift

Lines changed: 128 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,8 @@ import Foundation
1414

1515
/// Protocol for capability registration options, which must be encodable to
1616
/// `LSPAny` so they can be included in a `Registration`.
17-
public protocol RegistrationOptions: Hashable {
18-
func encodeIntoLSPAny(dict: inout [String: LSPAny])
19-
}
17+
public protocol RegistrationOptions: Hashable, LSPAnyCodable {
2018

21-
fileprivate func encode(strings: [String]) -> LSPAny {
22-
var values = [LSPAny]()
23-
values.reserveCapacity(strings.count)
24-
for str in strings {
25-
values.append(.string(str))
26-
}
27-
return .array(values)
2819
}
2920

3021
/// General text document registration options.
@@ -37,22 +28,20 @@ public struct TextDocumentRegistrationOptions: RegistrationOptions, Hashable {
3728
self.documentSelector = documentSelector
3829
}
3930

40-
public init(fromLSPAny value: LSPAny) {
41-
guard case let .dictionary(dict) = value else {
42-
return
43-
}
44-
31+
public init?(fromLSPDictionary dictionary: [String : LSPAny]) {
4532
var documentSelector: DocumentSelector?
46-
if let value = dict["documentSelector"] {
33+
34+
if let value = dictionary["documentSelector"] {
4735
documentSelector = DocumentSelector(fromLSPArray: value)
4836
}
4937

5038
self.documentSelector = documentSelector
5139
}
5240

53-
public func encodeIntoLSPAny(dict: inout [String: LSPAny]) {
54-
guard let documentSelector = documentSelector else { return }
55-
dict["documentSelector"] = documentSelector.encodeToLSPAny()
41+
public func encodeToLSPAny() -> LSPAny {
42+
guard let documentSelector = documentSelector else { return .null }
43+
44+
return .dictionary(["documentSelector": documentSelector.encodeToLSPAny()])
5645
}
5746
}
5847

@@ -72,18 +61,32 @@ public struct CompletionRegistrationOptions: RegistrationOptions, TextDocumentRe
7261
self.completionOptions = completionOptions
7362
}
7463

75-
public func encodeIntoLSPAny(dict: inout [String: LSPAny]) {
76-
textDocumentRegistrationOptions.encodeIntoLSPAny(dict: &dict)
64+
public init?(fromLSPDictionary dictionary: [String : LSPAny]) {
65+
guard let completionOptions = CompletionOptions(fromLSPDictionary: dictionary) else {
66+
return nil
67+
}
7768

78-
if let resolveProvider = completionOptions.resolveProvider {
79-
dict["resolveProvider"] = .bool(resolveProvider)
69+
self.completionOptions = completionOptions
70+
71+
guard let textDocumentRegistrationOptions = TextDocumentRegistrationOptions(fromLSPDictionary: dictionary) else {
72+
return nil
8073
}
81-
if let triggerCharacters = completionOptions.triggerCharacters {
82-
dict["triggerCharacters"] = encode(strings: triggerCharacters)
74+
75+
self.textDocumentRegistrationOptions = textDocumentRegistrationOptions
76+
}
77+
78+
public func encodeToLSPAny() -> LSPAny {
79+
var dict: [String : LSPAny] = [:]
80+
81+
if case .dictionary(let dictionary) = completionOptions.encodeToLSPAny() {
82+
dict.merge(dictionary) { (current, _) in current }
8383
}
84-
if let allCommitCharacters = completionOptions.allCommitCharacters {
85-
dict["allCommitCharacters"] = encode(strings: allCommitCharacters)
84+
85+
if case .dictionary(let dictionary) = textDocumentRegistrationOptions.encodeToLSPAny() {
86+
dict.merge(dictionary) { (current, _) in current }
8687
}
88+
89+
return .dictionary(dict)
8790
}
8891
}
8992

@@ -98,8 +101,19 @@ public struct FoldingRangeRegistrationOptions: RegistrationOptions, TextDocument
98101
self.foldingRangeOptions = foldingRangeOptions
99102
}
100103

101-
public func encodeIntoLSPAny(dict: inout [String: LSPAny]) {
102-
textDocumentRegistrationOptions.encodeIntoLSPAny(dict: &dict)
104+
public init?(fromLSPDictionary dictionary: [String : LSPAny]) {
105+
guard let textDocumentRegistrationOptions = TextDocumentRegistrationOptions(fromLSPDictionary: dictionary) else {
106+
return nil
107+
}
108+
109+
self.textDocumentRegistrationOptions = textDocumentRegistrationOptions
110+
111+
/// Currently empty in the spec.
112+
self.foldingRangeOptions = FoldingRangeOptions()
113+
}
114+
115+
public func encodeToLSPAny() -> LSPAny {
116+
textDocumentRegistrationOptions.encodeToLSPAny()
103117
// foldingRangeOptions is currently empty.
104118
}
105119
}
@@ -119,108 +133,32 @@ public struct SemanticTokensRegistrationOptions: RegistrationOptions, TextDocume
119133
self.semanticTokenOptions = semanticTokenOptions
120134
}
121135

122-
public init?(fromLSPAny value: LSPAny) {
123-
guard case let .dictionary(dict) = value else {
136+
public init?(fromLSPDictionary dictionary: [String : LSPAny]) {
137+
guard let textDocumentRegistrationOptions = TextDocumentRegistrationOptions(fromLSPDictionary: dictionary) else {
124138
return nil
125139
}
126140

127-
textDocumentRegistrationOptions = TextDocumentRegistrationOptions(fromLSPAny: value)
128-
129-
var range: ValueOrBool<SemanticTokensOptions.SemanticTokensRangeOptions>?
130-
if let rangeLSPAny = dict["range"] {
131-
switch rangeLSPAny {
132-
case let .bool(value):
133-
range = .bool(value)
134-
case .dictionary:
135-
range = .value(SemanticTokensOptions.SemanticTokensRangeOptions())
136-
default:
137-
break
138-
}
139-
}
140-
141-
var full: ValueOrBool<SemanticTokensOptions.SemanticTokensFullOptions>?
142-
if let fullLSPAny = dict["full"] {
143-
switch fullLSPAny {
144-
case let .bool(value):
145-
full = .bool(value)
146-
case let .dictionary(optionsDict):
147-
var delta: Bool?
148-
if let value = optionsDict["delta"],
149-
case let .bool(deltaValue) = value
150-
{
151-
delta = deltaValue
152-
}
153-
154-
full = .value(SemanticTokensOptions.SemanticTokensFullOptions(delta: delta))
155-
default:
156-
break
157-
}
158-
}
141+
self.textDocumentRegistrationOptions = textDocumentRegistrationOptions
159142

160-
guard case let .dictionary(legendDict) = dict["legend"] else {
143+
guard let semanticTokenOptions = SemanticTokensOptions(fromLSPDictionary: dictionary) else {
161144
return nil
162145
}
163146

164-
var tokenTypes: [String] = []
165-
if case let .array(types) = legendDict["tokenTypes"] {
166-
tokenTypes = types.compactMap {
167-
if case let .string(string) = $0 {
168-
return string
169-
}
170-
return nil
171-
}
172-
}
173-
174-
var tokenModifiers: [String] = []
175-
if case let .array(types) = legendDict["tokenModifiers"] {
176-
tokenModifiers = types.compactMap {
177-
if case let .string(string) = $0 {
178-
return string
179-
}
180-
return nil
181-
}
182-
}
183-
184-
let legend = SemanticTokensLegend(
185-
tokenTypes: tokenTypes,
186-
tokenModifiers: tokenModifiers
187-
)
188-
189-
semanticTokenOptions = SemanticTokensOptions(
190-
legend: legend,
191-
range: range,
192-
full: full
193-
)
147+
self.semanticTokenOptions = semanticTokenOptions
194148
}
195149

196-
public func encodeIntoLSPAny(dict: inout [String: LSPAny]) {
197-
textDocumentRegistrationOptions.encodeIntoLSPAny(dict: &dict)
198-
let legend = semanticTokenOptions.legend
199-
dict["legend"] = .dictionary([
200-
"tokenTypes": encode(strings: legend.tokenTypes),
201-
"tokenModifiers": encode(strings: legend.tokenModifiers),
202-
])
203-
if let range = semanticTokenOptions.range {
204-
let encodedRange: LSPAny
205-
switch range {
206-
case .bool(let value): encodedRange = .bool(value)
207-
case .value(_): encodedRange = .dictionary([:])
208-
}
209-
dict["range"] = encodedRange
150+
public func encodeToLSPAny() -> LSPAny {
151+
var dict: [String: LSPAny] = [:]
152+
153+
if case .dictionary(let dictionary) = textDocumentRegistrationOptions.encodeToLSPAny() {
154+
dict.merge(dictionary) { (current, _) in current }
210155
}
211-
if let full = semanticTokenOptions.full {
212-
let encodedFull: LSPAny
213-
switch full {
214-
case .bool(let value): encodedFull = .bool(value)
215-
case .value(let fullOptions):
216-
var encodedOptions: [String: LSPAny] = [:]
217-
if let delta = fullOptions.delta {
218-
encodedOptions["delta"] = .bool(delta)
219-
}
220-
encodedFull = .dictionary(encodedOptions)
221-
}
222-
dict["full"] = encodedFull
156+
157+
if case .dictionary(let dictionary) = semanticTokenOptions.encodeToLSPAny() {
158+
dict.merge(dictionary) { (current, _) in current }
223159
}
160+
161+
return .dictionary(dict)
224162
}
225163
}
226164

@@ -236,11 +174,32 @@ public struct InlayHintRegistrationOptions: RegistrationOptions, TextDocumentReg
236174
self.inlayHintOptions = inlayHintOptions
237175
}
238176

239-
public func encodeIntoLSPAny(dict: inout [String: LSPAny]) {
240-
textDocumentRegistrationOptions.encodeIntoLSPAny(dict: &dict)
177+
public init?(fromLSPDictionary dictionary: [String : LSPAny]) {
178+
self.inlayHintOptions = InlayHintOptions()
179+
180+
if case .bool(let resolveProvider) = dictionary["resolveProvider"] {
181+
self.inlayHintOptions.resolveProvider = resolveProvider
182+
}
183+
184+
guard let textDocumentRegistrationOptions = TextDocumentRegistrationOptions(fromLSPDictionary: dictionary) else {
185+
return nil
186+
}
187+
188+
self.textDocumentRegistrationOptions = textDocumentRegistrationOptions
189+
}
190+
191+
public func encodeToLSPAny() -> LSPAny {
192+
var dict: [String : LSPAny] = [:]
193+
241194
if let resolveProvider = inlayHintOptions.resolveProvider {
242195
dict["resolveProvider"] = .bool(resolveProvider)
243196
}
197+
198+
if case .dictionary(let dictionary) = textDocumentRegistrationOptions.encodeToLSPAny() {
199+
dict.merge(dictionary) { (current, _) in current }
200+
}
201+
202+
return .dictionary(dict)
244203
}
245204
}
246205

@@ -257,9 +216,29 @@ public struct DiagnosticRegistrationOptions: RegistrationOptions, TextDocumentRe
257216
self.diagnosticOptions = diagnosticOptions
258217
}
259218

260-
public func encodeIntoLSPAny(dict: inout [String: LSPAny]) {
261-
textDocumentRegistrationOptions.encodeIntoLSPAny(dict: &dict)
262-
diagnosticOptions.encodeIntoLSPAny(dict: &dict)
219+
public init?(fromLSPDictionary dictionary: [String : LSPAny]) {
220+
guard let textDocumentRegistrationOptions = TextDocumentRegistrationOptions(fromLSPDictionary: dictionary) else {
221+
return nil
222+
}
223+
224+
self.textDocumentRegistrationOptions = textDocumentRegistrationOptions
225+
226+
guard let diagnosticOptions = DiagnosticOptions(fromLSPDictionary: dictionary) else {
227+
return nil
228+
}
229+
self.diagnosticOptions = diagnosticOptions
230+
}
231+
232+
public func encodeToLSPAny() -> LSPAny {
233+
var dict: [String : LSPAny] = [:]
234+
if case .dictionary(let dictionary) = textDocumentRegistrationOptions.encodeToLSPAny() {
235+
dict.merge(dictionary) { (current, _) in current }
236+
}
237+
238+
if case .dictionary(let dictionary) = diagnosticOptions.encodeToLSPAny() {
239+
dict.merge(dictionary) { (current, _) in current }
240+
}
241+
return .dictionary(dict)
263242
}
264243
}
265244

@@ -272,8 +251,18 @@ public struct DidChangeWatchedFilesRegistrationOptions: RegistrationOptions {
272251
self.watchers = watchers
273252
}
274253

275-
public func encodeIntoLSPAny(dict: inout [String: LSPAny]) {
276-
dict["watchers"] = watchers.encodeToLSPAny()
254+
public init?(fromLSPDictionary dictionary: [String : LSPAny]) {
255+
guard let watchersArray = dictionary["watchers"],
256+
let watchers = [FileSystemWatcher](fromLSPArray: watchersArray)
257+
else {
258+
return nil
259+
}
260+
261+
self.watchers = watchers
262+
}
263+
264+
public func encodeToLSPAny() -> LSPAny {
265+
.dictionary(["watchers": watchers.encodeToLSPAny()])
277266
}
278267
}
279268

@@ -286,7 +275,17 @@ public struct ExecuteCommandRegistrationOptions: RegistrationOptions {
286275
self.commands = commands
287276
}
288277

289-
public func encodeIntoLSPAny(dict: inout [String: LSPAny]) {
290-
dict["commands"] = encode(strings: commands)
278+
public init?(fromLSPDictionary dictionary: [String : LSPAny]) {
279+
guard let commandsArray = dictionary["commands"],
280+
let commands = [String](fromLSPArray: commandsArray)
281+
else {
282+
return nil
283+
}
284+
285+
self.commands = commands
286+
}
287+
288+
public func encodeToLSPAny() -> LSPAny {
289+
.dictionary(["commands": commands.encodeToLSPAny()])
291290
}
292291
}

Sources/LanguageServerProtocol/SupportTypes/SemanticTokens.swift

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
/// The legend for a server's encoding of semantic tokens.
14-
public struct SemanticTokensLegend: Codable, Hashable {
14+
public struct SemanticTokensLegend: Codable, Hashable, LSPAnyCodable {
1515
/// The token types for a server.
1616
///
1717
/// Token types are looked up by indexing into this array, e.g. a `tokenType`
@@ -31,6 +31,29 @@ public struct SemanticTokensLegend: Codable, Hashable {
3131
self.tokenTypes = tokenTypes
3232
self.tokenModifiers = tokenModifiers
3333
}
34+
35+
public init?(fromLSPDictionary dictionary: [String : LSPAny]) {
36+
self.tokenTypes = []
37+
if let tokenTypesAny = dictionary["tokenTypes"],
38+
let tokenTypes = [String](fromLSPArray: tokenTypesAny)
39+
{
40+
self.tokenTypes = tokenTypes
41+
}
42+
43+
self.tokenModifiers = []
44+
if let tokenModifiersAny = dictionary["tokenModifiers"],
45+
let tokenModifiers = [String](fromLSPArray: tokenModifiersAny)
46+
{
47+
self.tokenModifiers = tokenModifiers
48+
}
49+
}
50+
51+
public func encodeToLSPAny() -> LSPAny {
52+
.dictionary([
53+
"tokenTypes": tokenTypes.encodeToLSPAny(),
54+
"tokenModifiers": tokenModifiers.encodeToLSPAny()
55+
])
56+
}
3457
}
3558

3659
/// The encoding format for semantic tokens. Currently only `relative` is supported.

0 commit comments

Comments
 (0)