firefly-compiler 0.4.10 → 0.4.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/Array.ff +8 -0
- package/core/Json.ff +123 -11
- package/lsp/Handler.ff +79 -88
- package/lsp/HoverHandler.ff +7 -10
- package/lsp/LanguageServer.ff +30 -33
- package/lsp/SignatureHelpHandler.ff +12 -13
- package/lsp/SymbolHandler.ff +17 -17
- package/output/js/ff/core/Array.mjs +16 -0
- package/output/js/ff/core/Json.mjs +376 -17
- package/package.json +2 -2
- package/vscode/package.json +1 -1
package/core/Array.ff
CHANGED
|
@@ -180,6 +180,14 @@ extend self[T]: Array[T] {
|
|
|
180
180
|
}
|
|
181
181
|
return result;
|
|
182
182
|
"""
|
|
183
|
+
|
|
184
|
+
flatMap[S](body: T => Array[S]): Array[S] {
|
|
185
|
+
let results = Stack.make()
|
|
186
|
+
self.each {x =>
|
|
187
|
+
results.pushArray(body(x))
|
|
188
|
+
}
|
|
189
|
+
results.drain()
|
|
190
|
+
}
|
|
183
191
|
|
|
184
192
|
sortBy[S: Order](body: T => S): Array[T] {
|
|
185
193
|
self.sortWith {Ordering.compare(body(_), body(_))}
|
package/core/Json.ff
CHANGED
|
@@ -9,11 +9,6 @@ read(json: String): Option[Json]
|
|
|
9
9
|
}
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
|
-
write(json: Json, space: Option[String] = None): String
|
|
13
|
-
target js sync """
|
|
14
|
-
return JSON.stringify(json_, null, space_.value_);
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
12
|
string(json: String): Json
|
|
18
13
|
target js sync """
|
|
19
14
|
return json_;
|
|
@@ -53,17 +48,30 @@ object(): Json
|
|
|
53
48
|
return {};
|
|
54
49
|
"""
|
|
55
50
|
|
|
51
|
+
fields(body: ((String, Json) => Unit) => Unit): Json
|
|
52
|
+
target js sync """
|
|
53
|
+
const result = {};
|
|
54
|
+
body_((k, v) => {result[k] = v});
|
|
55
|
+
return result;
|
|
56
|
+
"""
|
|
57
|
+
target js async """
|
|
58
|
+
const result = {};
|
|
59
|
+
await body_((k, v) => {result[k] = v}, $task);
|
|
60
|
+
return result;
|
|
61
|
+
"""
|
|
62
|
+
|
|
56
63
|
extend self: Json {
|
|
57
64
|
|
|
58
|
-
|
|
65
|
+
write(space: Option[String] = None): String
|
|
59
66
|
target js sync """
|
|
60
|
-
|
|
61
|
-
throw new Error('Not an object: ' + JSON.stringify(self_));
|
|
62
|
-
}
|
|
63
|
-
return {...self_, [field_]: value_};
|
|
67
|
+
return JSON.stringify(self_, null, space_.value_);
|
|
64
68
|
"""
|
|
69
|
+
|
|
70
|
+
with[T: JsonLike](field: String, value: T): Json {
|
|
71
|
+
internalWith(field, toJson(value))
|
|
72
|
+
}
|
|
65
73
|
|
|
66
|
-
merge(that: Json)
|
|
74
|
+
merge(that: Json): Json
|
|
67
75
|
target js sync """
|
|
68
76
|
if(typeof self_ !== 'object' || self_ === null || Array.isArray(self_)) {
|
|
69
77
|
throw new Error('Not an object: ' + JSON.stringify(self_));
|
|
@@ -104,6 +112,38 @@ extend self: Json {
|
|
|
104
112
|
if(!Array.isArray(self_)) throw new Error('Not an array: ' + JSON.stringify(self_));
|
|
105
113
|
return self_;
|
|
106
114
|
"""
|
|
115
|
+
|
|
116
|
+
grabMap(): Map[String, Json] {
|
|
117
|
+
mutable map = Map.empty()
|
|
118
|
+
self.each {key, value =>
|
|
119
|
+
map = map.add(key, value)
|
|
120
|
+
}
|
|
121
|
+
map
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
getString(): Option[String] {
|
|
125
|
+
if(self.isString()) {self.grabString()}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
getInt(): Option[Int] {
|
|
129
|
+
if(self.isInt()) {self.grabInt()}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
getFloat(): Option[Float] {
|
|
133
|
+
if(self.isFloat()) {self.grabFloat()}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
getBool(): Option[Bool] {
|
|
137
|
+
if(self.isBool()) {self.grabBool()}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
getArray(): Option[Array[Json]] {
|
|
141
|
+
if(self.isArray()) {self.grabArray()}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
getMap(): Option[Map[String, Json]] {
|
|
145
|
+
if(self.isObject()) {self.grabMap()}
|
|
146
|
+
}
|
|
107
147
|
|
|
108
148
|
isString(): Bool
|
|
109
149
|
target js sync """
|
|
@@ -151,6 +191,11 @@ extend self: Json {
|
|
|
151
191
|
return typeof self_ === 'array' ? self_[key] ?? null : null;
|
|
152
192
|
"""
|
|
153
193
|
|
|
194
|
+
hasField(key: String): Bool
|
|
195
|
+
target js sync """
|
|
196
|
+
return typeof self_ === 'object' && self_ !== null && !Array.isArray(self_) && Object.hasOwn(self_, key_);
|
|
197
|
+
"""
|
|
198
|
+
|
|
154
199
|
getField(key: String): Option[Json]
|
|
155
200
|
target js sync """
|
|
156
201
|
return typeof self_ === 'object' && self_ !== null && !Array.isArray(self_) && Object.hasOwn(self_, key_)
|
|
@@ -191,6 +236,12 @@ extend self: Json {
|
|
|
191
236
|
self.each {field, value => stack.push(body(field, value))}
|
|
192
237
|
stack.drain()
|
|
193
238
|
}
|
|
239
|
+
|
|
240
|
+
flatMap[T](body: (String, Json) => Array[T]): Array[T] {
|
|
241
|
+
let stack = Stack.make()
|
|
242
|
+
self.each {field, value => stack.pushArray(body(field, value))}
|
|
243
|
+
stack.drain()
|
|
244
|
+
}
|
|
194
245
|
|
|
195
246
|
each(body: (String, Json) => Unit) {
|
|
196
247
|
if(!self.isObject()) {throw(GrabException())}
|
|
@@ -204,6 +255,14 @@ extend self: Json {
|
|
|
204
255
|
|
|
205
256
|
}
|
|
206
257
|
|
|
258
|
+
internalWith(field: String, json: Json): Json
|
|
259
|
+
target js sync """
|
|
260
|
+
if(typeof self_ !== 'object' || self_ === null || Array.isArray(self_)) {
|
|
261
|
+
throw new Error('Not an object: ' + JSON.stringify(self_));
|
|
262
|
+
}
|
|
263
|
+
return {...self_, [field_]: value_};
|
|
264
|
+
"""
|
|
265
|
+
|
|
207
266
|
internalEach(self: Json, body: (String, Json) => Unit): Unit
|
|
208
267
|
target js sync "for(const [key, value] of Object.entries(self_)) body_(key, value)"
|
|
209
268
|
target js async "for(const [key, value] of Object.entries(self_)) await body_(key, value, $task)"
|
|
@@ -211,3 +270,56 @@ internalEach(self: Json, body: (String, Json) => Unit): Unit
|
|
|
211
270
|
internalEachWhile(self: Json, body: (String, Json) => Bool): Unit
|
|
212
271
|
target js sync "for(const [key, value] of Object.entries(self_)) if(!body_(key, value)) break"
|
|
213
272
|
target js async "for(const [key, value] of Object.entries(self_)) if(!await body_(key, value, $task)) break"
|
|
273
|
+
|
|
274
|
+
trait T: JsonLike {
|
|
275
|
+
toJson(value: T): Json
|
|
276
|
+
fromJson(json: Json): Option[T]
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
instance Json: JsonLike {
|
|
280
|
+
toJson(value: Json): Json {value}
|
|
281
|
+
fromJson(json: Json): Option[Json] {Some(json)}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
instance String: JsonLike {
|
|
285
|
+
toJson(value: String): Json {string(value)}
|
|
286
|
+
fromJson(json: Json): Option[String] {_.getString()}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
instance Int: JsonLike {
|
|
290
|
+
toJson(value: Int): Json {int(value)}
|
|
291
|
+
fromJson(json: Json): Option[Int] {_.getInt()}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
instance Float: JsonLike {
|
|
295
|
+
toJson(value: Float): Json {float(value)}
|
|
296
|
+
fromJson(json: Json): Option[Float] {_.getFloat()}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
instance Bool: JsonLike {
|
|
300
|
+
toJson(value: Bool): Json {bool(value)}
|
|
301
|
+
fromJson(json: Json): Option[Bool] {_.getBool()}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
instance Array[T: JsonLike]: JsonLike {
|
|
305
|
+
toJson(value: Array[T]): Json {array(value.map(toJson))}
|
|
306
|
+
fromJson(json: Json): Option[Array[T]] {
|
|
307
|
+
json.getArray().flatMap {array =>
|
|
308
|
+
mutable convertible = True
|
|
309
|
+
let stack = Stack.make()
|
|
310
|
+
array.eachWhile {item =>
|
|
311
|
+
fromJson(item).{
|
|
312
|
+
| None => convertible = False
|
|
313
|
+
| Some(value) => stack.push(value)
|
|
314
|
+
}
|
|
315
|
+
convertible
|
|
316
|
+
}
|
|
317
|
+
if(convertible) {stack.drain()}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
instance List[T: JsonLike]: JsonLike {
|
|
323
|
+
toJson(value: List[T]): Json {list(value.map(toJson))}
|
|
324
|
+
fromJson(json: Json): Option[List[T]] {fromJson[Array[T]](json).map {_.toList()}}
|
|
325
|
+
}
|
package/lsp/Handler.ff
CHANGED
|
@@ -46,7 +46,7 @@ data TokenLocation(
|
|
|
46
46
|
|
|
47
47
|
extend self: Handler {
|
|
48
48
|
|
|
49
|
-
handleNotification(system: NodeSystem, method: String, parameters: Map[String,
|
|
49
|
+
handleNotification(system: NodeSystem, method: String, parameters: Map[String, Json]): Unit {
|
|
50
50
|
method.{
|
|
51
51
|
| "initialized" =>
|
|
52
52
|
| "textDocument/didChange" =>
|
|
@@ -57,7 +57,7 @@ extend self: Handler {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
handleRequest(system: NodeSystem, method: String, parameters: Map[String,
|
|
60
|
+
handleRequest(system: NodeSystem, method: String, parameters: Map[String, Json]): ResultOrError {
|
|
61
61
|
method.{
|
|
62
62
|
| "initialize" => self.handleInitialize(system, parameters)
|
|
63
63
|
| "textDocument/diagnostic" => self.handleDiagnostic(system, parameters)
|
|
@@ -82,15 +82,15 @@ extend self: Handler {
|
|
|
82
82
|
self.handleReferences(system, targetAt, local = True)
|
|
83
83
|
}
|
|
84
84
|
| "workspace/symbol" => self.printTime(system.mainTask(), "handleWorkspaceSymbol") {self.handleWorkspaceSymbol(system, parameters)}
|
|
85
|
-
| "shutdown" => Result(
|
|
86
|
-
| _ => self.handleUnsupported(
|
|
85
|
+
| "shutdown" => Result(Json.null().write())
|
|
86
|
+
| _ => self.handleUnsupported()
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
handleTokenRequestWithCache(
|
|
91
91
|
system: NodeSystem
|
|
92
92
|
method: String
|
|
93
|
-
parameters: Map[String,
|
|
93
|
+
parameters: Map[String, Json]
|
|
94
94
|
handle: Location => ResultOrError
|
|
95
95
|
): ResultOrError {
|
|
96
96
|
let targetAt = self.findTokenFromParameters(system, parameters)
|
|
@@ -104,44 +104,43 @@ extend self: Handler {
|
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
handleUnsupported(
|
|
107
|
+
handleUnsupported(): ResultOrError {
|
|
108
108
|
Error(1234, "Unsupported method")
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
handleInitialize(system: NodeSystem, parameters: Map[String,
|
|
112
|
-
let js = system.js()
|
|
111
|
+
handleInitialize(system: NodeSystem, parameters: Map[String, Json]): ResultOrError {
|
|
113
112
|
self.rootPath = Some(system.pathFromUrl(parameters.grab("rootUri").grabString()))
|
|
114
113
|
|
|
115
|
-
let anyFireflyFile =
|
|
114
|
+
let anyFireflyFile = Json.object()
|
|
116
115
|
.with("filters", [
|
|
117
|
-
|
|
118
|
-
.with("pattern",
|
|
116
|
+
Json.object()
|
|
117
|
+
.with("pattern", Json.object()
|
|
119
118
|
.with("glob", "**/*.ff")
|
|
120
119
|
.with("matches", "file")
|
|
121
120
|
)
|
|
122
|
-
]
|
|
121
|
+
])
|
|
123
122
|
|
|
124
|
-
let o =
|
|
125
|
-
.with("capabilities",
|
|
126
|
-
.with("textDocumentSync",
|
|
123
|
+
let o = Json.object()
|
|
124
|
+
.with("capabilities", Json.object()
|
|
125
|
+
.with("textDocumentSync", Json.object()
|
|
127
126
|
.with("openClose", True)
|
|
128
127
|
.with("change", 1 /* TextDocumentSyncKind.Full */)
|
|
129
128
|
)
|
|
130
129
|
.with("hoverProvider", True)
|
|
131
130
|
.with("definitionProvider", True)
|
|
132
131
|
.with("documentHighlightProvider", True)
|
|
133
|
-
.with("diagnosticProvider",
|
|
132
|
+
.with("diagnosticProvider", Json.object()
|
|
134
133
|
.with("interFileDependencies", False)
|
|
135
134
|
.with("workspaceDiagnostics", False)
|
|
136
135
|
)
|
|
137
136
|
.with("documentSymbolProvider", True)
|
|
138
|
-
.with("completionProvider",
|
|
139
|
-
.with("triggerCharacters",
|
|
140
|
-
.with("allCommitCharacters",
|
|
137
|
+
.with("completionProvider", Json.object()
|
|
138
|
+
.with("triggerCharacters", [".", " ", "("])
|
|
139
|
+
.with("allCommitCharacters", [";"])
|
|
141
140
|
)
|
|
142
|
-
.with("signatureHelpProvider",
|
|
143
|
-
.with("triggerCharacters",
|
|
144
|
-
.with("retriggerCharacters",
|
|
141
|
+
.with("signatureHelpProvider", Json.object()
|
|
142
|
+
.with("triggerCharacters", ["("])
|
|
143
|
+
.with("retriggerCharacters", [","])
|
|
145
144
|
)
|
|
146
145
|
.with("referencesProvider", True)
|
|
147
146
|
.with("workspaceSymbolProvider", True)
|
|
@@ -158,16 +157,16 @@ extend self: Handler {
|
|
|
158
157
|
)*/
|
|
159
158
|
.with("renameProvider", True)
|
|
160
159
|
)
|
|
161
|
-
.with("serverInfo",
|
|
160
|
+
.with("serverInfo", Json.object()
|
|
162
161
|
.with("name", "Firefly Language Server")
|
|
163
162
|
.with("version", "0.0.0")
|
|
164
163
|
)
|
|
165
|
-
Result(o.
|
|
164
|
+
Result(o.write())
|
|
166
165
|
}
|
|
167
166
|
|
|
168
|
-
handleDiagnostic(system: NodeSystem, parameters: Map[String,
|
|
167
|
+
handleDiagnostic(system: NodeSystem, parameters: Map[String, Json]): ResultOrError {
|
|
169
168
|
let js = system.js()
|
|
170
|
-
let uri = parameters.grab("textDocument").
|
|
169
|
+
let uri = parameters.grab("textDocument").field("uri").grabString()
|
|
171
170
|
let path = system.pathFromUrl(uri)
|
|
172
171
|
let fireflyPath = system.path(".")
|
|
173
172
|
let diagnostics = try {
|
|
@@ -175,26 +174,25 @@ extend self: Handler {
|
|
|
175
174
|
[]
|
|
176
175
|
} catch {| CompileError(at, message), error =>
|
|
177
176
|
let tokenLocation = self.findToken(system, at)
|
|
178
|
-
let diagnostic =
|
|
179
|
-
.with("range", self.tokenLocationToLspRange(
|
|
180
|
-
.with("severity", 1
|
|
177
|
+
let diagnostic = Json.object()
|
|
178
|
+
.with("range", self.tokenLocationToLspRange(tokenLocation))
|
|
179
|
+
.with("severity", 1)
|
|
181
180
|
.with("message", message)
|
|
182
181
|
[diagnostic]
|
|
183
182
|
} grab()
|
|
184
183
|
|
|
185
|
-
let o =
|
|
184
|
+
let o = Json.object()
|
|
186
185
|
.with("kind", "full")
|
|
187
|
-
.with("items", diagnostics
|
|
188
|
-
Result(o.
|
|
186
|
+
.with("items", diagnostics)
|
|
187
|
+
Result(o.write())
|
|
189
188
|
}
|
|
190
189
|
|
|
191
|
-
handleDocumentSymbol(system: NodeSystem, parameters: Map[String,
|
|
192
|
-
let
|
|
193
|
-
let uri = parameters.grab("textDocument").get("uri").grabString()
|
|
190
|
+
handleDocumentSymbol(system: NodeSystem, parameters: Map[String, Json]): ResultOrError {
|
|
191
|
+
let uri = parameters.grab("textDocument").field("uri").grabString()
|
|
194
192
|
let path = system.pathFromUrl(uri)
|
|
195
193
|
let symbols = self.getDocumentSymbolsWithCache(system, path)
|
|
196
|
-
let lspSymbols = symbols.map {SymbolHandler.documentSymbolToLsp(
|
|
197
|
-
Result(
|
|
194
|
+
let lspSymbols = symbols.map {SymbolHandler.documentSymbolToLsp(_)}
|
|
195
|
+
Result(Json.list(lspSymbols).write())
|
|
198
196
|
}
|
|
199
197
|
|
|
200
198
|
getDocumentSymbols(system: NodeSystem, path: Path): List[DocumentSymbol] {
|
|
@@ -227,8 +225,7 @@ extend self: Handler {
|
|
|
227
225
|
}
|
|
228
226
|
}
|
|
229
227
|
|
|
230
|
-
handleWorkspaceSymbol(system: NodeSystem, parameters: Map[String,
|
|
231
|
-
let js = system.js()
|
|
228
|
+
handleWorkspaceSymbol(system: NodeSystem, parameters: Map[String, Json]): ResultOrError {
|
|
232
229
|
let query = parameters.grab("query").grabString()
|
|
233
230
|
let files = self.printTime(system.mainTask(), "findFireflyFiles") {Builder.findFireflyFiles(self.rootPath.grab())}
|
|
234
231
|
let symbols = files.flatMap {file =>
|
|
@@ -241,27 +238,25 @@ extend self: Handler {
|
|
|
241
238
|
}
|
|
242
239
|
}
|
|
243
240
|
let limitedSymbols = symbols.sortBy {_.name.size()}.takeFirst(100)
|
|
244
|
-
let jsSymbols = limitedSymbols.map {SymbolHandler.workspaceSymbolToLsp(
|
|
245
|
-
Result(
|
|
241
|
+
let jsSymbols = limitedSymbols.map {SymbolHandler.workspaceSymbolToLsp(self.rootPath.grab(), _)}
|
|
242
|
+
Result(Json.list(jsSymbols).write())
|
|
246
243
|
}
|
|
247
244
|
|
|
248
|
-
handleDidChange(system: NodeSystem, parameters: Map[String,
|
|
249
|
-
let
|
|
250
|
-
let uri = parameters.grab("textDocument").get("uri").grabString()
|
|
245
|
+
handleDidChange(system: NodeSystem, parameters: Map[String, Json]): Unit {
|
|
246
|
+
let uri = parameters.grab("textDocument").field("uri").grabString()
|
|
251
247
|
let path = system.pathFromUrl(uri)
|
|
252
248
|
self.responseCache = Map.empty()
|
|
253
249
|
self.fileSymbolsCache = self.fileSymbolsCache.remove(path.absolute())
|
|
254
250
|
let contentChanges = parameters.grab("contentChanges").grabArray()
|
|
255
251
|
if(contentChanges.size() != 1) {throw(LanguageServerException("Expected a single element in contentChanges"))} else:
|
|
256
252
|
let contentChange = contentChanges.grab(0)
|
|
257
|
-
if(!contentChange.
|
|
258
|
-
let content = contentChange.
|
|
253
|
+
if(!contentChange.field("range").isNull()) {throw(LanguageServerException("Expected a complete contentChange"))} else:
|
|
254
|
+
let content = contentChange.field("text").grabString()
|
|
259
255
|
self.virtualFiles = self.virtualFiles.add(path.absolute(), content)
|
|
260
256
|
}
|
|
261
257
|
|
|
262
|
-
handleDidClose(system: NodeSystem, parameters: Map[String,
|
|
263
|
-
let
|
|
264
|
-
let uri = parameters.grab("textDocument").get("uri").grabString()
|
|
258
|
+
handleDidClose(system: NodeSystem, parameters: Map[String, Json]): Unit {
|
|
259
|
+
let uri = parameters.grab("textDocument").field("uri").grabString()
|
|
265
260
|
let path = system.pathFromUrl(uri)
|
|
266
261
|
self.virtualFiles = self.virtualFiles.remove(path.absolute())
|
|
267
262
|
}
|
|
@@ -278,10 +273,10 @@ extend self: Handler {
|
|
|
278
273
|
} else {
|
|
279
274
|
HoverHandler.handleHover(system, self, lspHook)
|
|
280
275
|
}
|
|
281
|
-
Result(o.
|
|
276
|
+
Result(o.write())
|
|
282
277
|
}
|
|
283
278
|
|
|
284
|
-
handleCompletion(system: NodeSystem, parameters: Map[String,
|
|
279
|
+
handleCompletion(system: NodeSystem, parameters: Map[String, Json]): ResultOrError {
|
|
285
280
|
let location = self.findLocationFromParameters(system, parameters)
|
|
286
281
|
let token = self.findToken(system, location, insertToken = True)
|
|
287
282
|
let completionAt = Location(
|
|
@@ -300,7 +295,7 @@ extend self: Handler {
|
|
|
300
295
|
Result(o.toJson())
|
|
301
296
|
}
|
|
302
297
|
|
|
303
|
-
handleSignatureHelp(system: NodeSystem, parameters: Map[String,
|
|
298
|
+
handleSignatureHelp(system: NodeSystem, parameters: Map[String, Json]): ResultOrError {
|
|
304
299
|
let cursorAt = self.findLocationFromParameters(system, parameters)
|
|
305
300
|
let lspHook = LspHook.make(at = Some(cursorAt), definedAt = None, insertIdentifier = False, trackSymbols = False)
|
|
306
301
|
try {
|
|
@@ -314,13 +309,13 @@ extend self: Handler {
|
|
|
314
309
|
} grab()
|
|
315
310
|
let o = lspHook.results().collectFirst {
|
|
316
311
|
| ParseArgumentHook h {parameters.get("context") | Some(context)} {
|
|
317
|
-
context.
|
|
318
|
-
} {!help.
|
|
319
|
-
help.
|
|
320
|
-
} {!activeSignature.
|
|
321
|
-
activeSignature.
|
|
312
|
+
context.field("activeSignatureHelp") | help
|
|
313
|
+
} {!help.isNull() && help.hasField("signatures")} {
|
|
314
|
+
help.field("signatures").index(0) | activeSignature
|
|
315
|
+
} {!activeSignature.isNull()} {
|
|
316
|
+
activeSignature.field("parameters").grabArray().last() | Some(fakeParameter)
|
|
322
317
|
} {
|
|
323
|
-
fakeParameter.
|
|
318
|
+
fakeParameter.field("label").grabString() == "/* Call " + h.callAt.show() + " */"
|
|
324
319
|
} =>
|
|
325
320
|
Some(SignatureHelpHandler.pickActiveParameter(help, h.argumentIndex, h.parameterName))
|
|
326
321
|
| ParseArgumentHook h =>
|
|
@@ -335,29 +330,27 @@ extend self: Handler {
|
|
|
335
330
|
| _ =>
|
|
336
331
|
None
|
|
337
332
|
}
|
|
338
|
-
Result((o.else {
|
|
333
|
+
Result((o.else {Json.null()}).write())
|
|
339
334
|
}
|
|
340
335
|
|
|
341
336
|
handleReferences(system: NodeSystem, targetAt: Location, local: Bool): ResultOrError {
|
|
342
337
|
let tokens = self.findReferences(system, targetAt, local)
|
|
343
|
-
let js = system.js()
|
|
344
338
|
let o = tokens.{
|
|
345
|
-
| None =>
|
|
339
|
+
| None => Json.null()
|
|
346
340
|
| Some(tokens) =>
|
|
347
341
|
let lspTokens = tokens.map {self.tokenLocationToLspLocation(system, _)}
|
|
348
|
-
|
|
342
|
+
Json.list(lspTokens)
|
|
349
343
|
}
|
|
350
|
-
Result(o.
|
|
344
|
+
Result(o.write())
|
|
351
345
|
}
|
|
352
346
|
|
|
353
|
-
handleRename(system: NodeSystem, parameters: Map[String,
|
|
347
|
+
handleRename(system: NodeSystem, parameters: Map[String, Json]): ResultOrError {
|
|
354
348
|
let newName = parameters.grab("newName").grabString()
|
|
355
349
|
let targetAt = self.findTokenFromParameters(system, parameters)
|
|
356
350
|
let tokens = self.findReferences(system, targetAt, False)
|
|
357
|
-
let js = system.js()
|
|
358
351
|
tokens.{
|
|
359
352
|
| None => Error(-32602, "Token definition not found") // InvalidParams
|
|
360
|
-
| Some([]) => Result(
|
|
353
|
+
| Some([]) => Result(Json.null().write())
|
|
361
354
|
| Some([first, ..._] @ tokens) =>
|
|
362
355
|
let oldName = first.raw
|
|
363
356
|
Log.trace("Rename '" + oldName + "' to '" + newName + "'")
|
|
@@ -368,17 +361,17 @@ extend self: Handler {
|
|
|
368
361
|
badTokens.each {t => Log.trace("Rename bad token: " + Show.show(t))}
|
|
369
362
|
|
|
370
363
|
let byFile = goodTokens.map {t => Pair(t.file, t)}.group()
|
|
371
|
-
let allChanges = byFile.toList().foldLeft(
|
|
364
|
+
let allChanges = byFile.toList().foldLeft(Json.object(), {| o, Pair(file, fileTokens) =>
|
|
372
365
|
let uri = system.path(file).url()
|
|
373
366
|
let fileChanges = fileTokens.map {tokenLocation =>
|
|
374
|
-
|
|
375
|
-
.with("range", self.tokenLocationToLspRange(
|
|
367
|
+
Json.object()
|
|
368
|
+
.with("range", self.tokenLocationToLspRange(tokenLocation))
|
|
376
369
|
.with("newText", newName)
|
|
377
370
|
}
|
|
378
|
-
o.with(uri,
|
|
371
|
+
o.with(uri, fileChanges)
|
|
379
372
|
})
|
|
380
|
-
let o =
|
|
381
|
-
Result(o.
|
|
373
|
+
let o = Json.object().with("changes", allChanges)
|
|
374
|
+
Result(o.write())
|
|
382
375
|
}
|
|
383
376
|
}
|
|
384
377
|
|
|
@@ -409,7 +402,6 @@ extend self: Handler {
|
|
|
409
402
|
|
|
410
403
|
//Log.trace("definedAtList: " + Show.show(definedAtList))
|
|
411
404
|
|
|
412
|
-
let js = system.js()
|
|
413
405
|
definedAtList.first().{
|
|
414
406
|
| Some(definedAt) =>
|
|
415
407
|
//Log.trace("handleReferences definedAt: " + Show.show(definedAt))
|
|
@@ -449,8 +441,8 @@ extend self: Handler {
|
|
|
449
441
|
}
|
|
450
442
|
}
|
|
451
443
|
|
|
452
|
-
makeNotificationMessage(
|
|
453
|
-
|
|
444
|
+
makeNotificationMessage(method: String, params: Json): Json {
|
|
445
|
+
Json.object()
|
|
454
446
|
.with("jsonrpc", "2.0")
|
|
455
447
|
.with("method", method)
|
|
456
448
|
.with("params", params)
|
|
@@ -502,7 +494,7 @@ extend self: Handler {
|
|
|
502
494
|
} grab()
|
|
503
495
|
}
|
|
504
496
|
|
|
505
|
-
findTokenFromParameters(system: NodeSystem, parameters: Map[String,
|
|
497
|
+
findTokenFromParameters(system: NodeSystem, parameters: Map[String, Json]): Location {
|
|
506
498
|
let location = self.findLocationFromParameters(system, parameters)
|
|
507
499
|
let token = self.findToken(system, location)
|
|
508
500
|
Location(
|
|
@@ -512,28 +504,27 @@ extend self: Handler {
|
|
|
512
504
|
)
|
|
513
505
|
}
|
|
514
506
|
|
|
515
|
-
findLocationFromParameters(system: NodeSystem, parameters: Map[String,
|
|
516
|
-
let uri = parameters.grab("textDocument").
|
|
507
|
+
findLocationFromParameters(system: NodeSystem, parameters: Map[String, Json]): Location {
|
|
508
|
+
let uri = parameters.grab("textDocument").field("uri").grabString()
|
|
517
509
|
let path = system.pathFromUrl(uri)
|
|
518
|
-
let line = parameters.grab("position").
|
|
519
|
-
let column = parameters.grab("position").
|
|
510
|
+
let line = parameters.grab("position").field("line").grabInt() + 1
|
|
511
|
+
let column = parameters.grab("position").field("character").grabInt() + 1
|
|
520
512
|
Location(path.absolute(), line, column)
|
|
521
513
|
}
|
|
522
514
|
|
|
523
|
-
tokenLocationToLspLocation(system: NodeSystem, tokenLocation: TokenLocation):
|
|
524
|
-
|
|
525
|
-
js.object()
|
|
515
|
+
tokenLocationToLspLocation(system: NodeSystem, tokenLocation: TokenLocation): Json {
|
|
516
|
+
Json.object()
|
|
526
517
|
.with("uri", system.path(tokenLocation.file).url())
|
|
527
|
-
.with("range", self.tokenLocationToLspRange(
|
|
518
|
+
.with("range", self.tokenLocationToLspRange(tokenLocation))
|
|
528
519
|
}
|
|
529
520
|
|
|
530
|
-
tokenLocationToLspRange(
|
|
531
|
-
|
|
532
|
-
.with("start",
|
|
521
|
+
tokenLocationToLspRange(tokenLocation: TokenLocation): Json {
|
|
522
|
+
Json.object()
|
|
523
|
+
.with("start", Json.object()
|
|
533
524
|
.with("line", tokenLocation.startLine - 1)
|
|
534
525
|
.with("character", tokenLocation.startColumn - 1)
|
|
535
526
|
)
|
|
536
|
-
.with("end",
|
|
527
|
+
.with("end", Json.object()
|
|
537
528
|
.with("line", tokenLocation.endLine - 1)
|
|
538
529
|
.with("character", tokenLocation.endColumn - 1)
|
|
539
530
|
)
|
package/lsp/HoverHandler.ff
CHANGED
|
@@ -4,8 +4,7 @@ import Environment from ff:compiler
|
|
|
4
4
|
import Syntax from ff:compiler
|
|
5
5
|
import Handler
|
|
6
6
|
|
|
7
|
-
handleGoToDefinition(system: NodeSystem, handler: Handler, lspHook: LspHook):
|
|
8
|
-
let js = system.js()
|
|
7
|
+
handleGoToDefinition(system: NodeSystem, handler: Handler, lspHook: LspHook): Json {
|
|
9
8
|
let definedAt = lspHook.results().collect {
|
|
10
9
|
| ResolveSymbolHook h => Some(h.symbol.definedAt)
|
|
11
10
|
| ResolveTypeHook h => Some(h.symbol.definedAt)
|
|
@@ -31,11 +30,10 @@ handleGoToDefinition(system: NodeSystem, handler: Handler, lspHook: LspHook): Js
|
|
|
31
30
|
definedAt.first().map {at =>
|
|
32
31
|
let token = handler.findToken(system, at)
|
|
33
32
|
handler.tokenLocationToLspLocation(system, token)
|
|
34
|
-
}.else {
|
|
33
|
+
}.else {Json.null()}
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
handleHover(system: NodeSystem, handler: Handler, lspHook: LspHook):
|
|
38
|
-
let js = system.js()
|
|
36
|
+
handleHover(system: NodeSystem, handler: Handler, lspHook: LspHook): Json {
|
|
39
37
|
let typeAndEffect = lspHook.results().collectFirst {
|
|
40
38
|
| InferLookupHook h {h.instantiated.value | Some(instantiated)} =>
|
|
41
39
|
let t = h.unification.substitute(instantiated.scheme.signature.returnType)
|
|
@@ -73,10 +71,9 @@ handleHover(system: NodeSystem, handler: Handler, lspHook: LspHook): JsValue {
|
|
|
73
71
|
| TConstructor(_, "Q$", _) => "*This call may be asynchronous.*"
|
|
74
72
|
| _ => ""
|
|
75
73
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
.with("value", "```\n" + t.show([]) + "\n```\n" + extra)
|
|
74
|
+
Json.object().with("contents", Json.object()
|
|
75
|
+
.with("kind", "markdown")
|
|
76
|
+
.with("value", "```\n" + t.show([]) + "\n```\n" + extra)
|
|
80
77
|
)
|
|
81
|
-
}.else {
|
|
78
|
+
}.else {Json.null()}
|
|
82
79
|
}
|