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 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
- with(field: String, value: Json)
65
+ write(space: Option[String] = None): String
59
66
  target js sync """
60
- if(typeof self_ !== 'object' || self_ === null || Array.isArray(self_)) {
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, JsValue]): Unit {
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, JsValue]): ResultOrError {
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(system.js().null().toJson())
86
- | _ => self.handleUnsupported(system.js())
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, JsValue]
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(js: JsSystem): ResultOrError {
107
+ handleUnsupported(): ResultOrError {
108
108
  Error(1234, "Unsupported method")
109
109
  }
110
110
 
111
- handleInitialize(system: NodeSystem, parameters: Map[String, JsValue]): ResultOrError {
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 = js.object()
114
+ let anyFireflyFile = Json.object()
116
115
  .with("filters", [
117
- js.object()
118
- .with("pattern", js.object()
116
+ Json.object()
117
+ .with("pattern", Json.object()
119
118
  .with("glob", "**/*.ff")
120
119
  .with("matches", "file")
121
120
  )
122
- ].toArray())
121
+ ])
123
122
 
124
- let o = js.object()
125
- .with("capabilities", js.object()
126
- .with("textDocumentSync", js.object()
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", js.object()
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", js.object()
139
- .with("triggerCharacters", js.array([".", " ", "("].map {js.value(_)}))
140
- .with("allCommitCharacters", js.array([";"].map {js.value(_)}))
137
+ .with("completionProvider", Json.object()
138
+ .with("triggerCharacters", [".", " ", "("])
139
+ .with("allCommitCharacters", [";"])
141
140
  )
142
- .with("signatureHelpProvider", js.object()
143
- .with("triggerCharacters", js.array(["("].map {js.value(_)}))
144
- .with("retriggerCharacters", js.array([","].map {js.value(_)}))
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", js.object()
160
+ .with("serverInfo", Json.object()
162
161
  .with("name", "Firefly Language Server")
163
162
  .with("version", "0.0.0")
164
163
  )
165
- Result(o.toJson())
164
+ Result(o.write())
166
165
  }
167
166
 
168
- handleDiagnostic(system: NodeSystem, parameters: Map[String, JsValue]): ResultOrError {
167
+ handleDiagnostic(system: NodeSystem, parameters: Map[String, Json]): ResultOrError {
169
168
  let js = system.js()
170
- let uri = parameters.grab("textDocument").get("uri").grabString()
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 = js.object()
179
- .with("range", self.tokenLocationToLspRange(js, tokenLocation))
180
- .with("severity", 1 /* Error */)
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 = js.object()
184
+ let o = Json.object()
186
185
  .with("kind", "full")
187
- .with("items", diagnostics.toArray())
188
- Result(o.toJson())
186
+ .with("items", diagnostics)
187
+ Result(o.write())
189
188
  }
190
189
 
191
- handleDocumentSymbol(system: NodeSystem, parameters: Map[String, JsValue]): ResultOrError {
192
- let js = system.js()
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(js, _)}
197
- Result(js.array(lspSymbols).toJson())
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, JsValue]): ResultOrError {
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(js, self.rootPath.grab(), _)}
245
- Result(js.array(jsSymbols).toJson())
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, JsValue]): Unit {
249
- let js = system.js()
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.get("range").isNullOrUndefined()) {throw(LanguageServerException("Expected a complete contentChange"))} else:
258
- let content = contentChange.get("text").grabString()
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, JsValue]): Unit {
263
- let js = system.js()
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.toJson())
276
+ Result(o.write())
282
277
  }
283
278
 
284
- handleCompletion(system: NodeSystem, parameters: Map[String, JsValue]): ResultOrError {
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, JsValue]): ResultOrError {
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.get("activeSignatureHelp") | help
318
- } {!help.isNullOrUndefined() && help.hasOwn("signatures")} {
319
- help.get("signatures").get(0) | activeSignature
320
- } {!activeSignature.isNullOrUndefined()} {
321
- activeSignature.get("parameters").grabArray().last() | Some(fakeParameter)
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.get("label").grabString() == "/* Call " + h.callAt.show() + " */"
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 {system.js().null()}).toJson())
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 => js.null()
339
+ | None => Json.null()
346
340
  | Some(tokens) =>
347
341
  let lspTokens = tokens.map {self.tokenLocationToLspLocation(system, _)}
348
- js.array(lspTokens)
342
+ Json.list(lspTokens)
349
343
  }
350
- Result(o.toJson())
344
+ Result(o.write())
351
345
  }
352
346
 
353
- handleRename(system: NodeSystem, parameters: Map[String, JsValue]): ResultOrError {
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(js.null().toJson())
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(js.object(), {| o, Pair(file, fileTokens) =>
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
- js.object()
375
- .with("range", self.tokenLocationToLspRange(js, tokenLocation))
367
+ Json.object()
368
+ .with("range", self.tokenLocationToLspRange(tokenLocation))
376
369
  .with("newText", newName)
377
370
  }
378
- o.with(uri, js.array(fileChanges))
371
+ o.with(uri, fileChanges)
379
372
  })
380
- let o = js.object().with("changes", allChanges)
381
- Result(o.toJson())
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(js: JsSystem, method: String, params: JsValue): JsValue {
453
- js.object()
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, JsValue]): Location {
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, JsValue]): Location {
516
- let uri = parameters.grab("textDocument").get("uri").grabString()
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").get("line").grabInt() + 1
519
- let column = parameters.grab("position").get("character").grabInt() + 1
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): JsValue {
524
- let js = system.js()
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(js, tokenLocation))
518
+ .with("range", self.tokenLocationToLspRange(tokenLocation))
528
519
  }
529
520
 
530
- tokenLocationToLspRange(js: JsSystem, tokenLocation: TokenLocation): JsValue {
531
- js.object()
532
- .with("start", js.object()
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", js.object()
527
+ .with("end", Json.object()
537
528
  .with("line", tokenLocation.endLine - 1)
538
529
  .with("character", tokenLocation.endColumn - 1)
539
530
  )
@@ -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): JsValue {
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 {js.null()}
33
+ }.else {Json.null()}
35
34
  }
36
35
 
37
- handleHover(system: NodeSystem, handler: Handler, lspHook: LspHook): JsValue {
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
- js.object().with("contents",
77
- js.object()
78
- .with("kind", "markdown")
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 {js.null()}
78
+ }.else {Json.null()}
82
79
  }