firefly-compiler 0.4.4 → 0.4.6
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/.hintrc +5 -0
- package/README.md +42 -61
- package/compiler/Compiler.ff +6 -2
- package/compiler/Deriver.ff +10 -0
- package/compiler/Environment.ff +2 -1
- package/compiler/JsEmitter.ff +29 -17
- package/compiler/Resolver.ff +1 -1
- package/core/.firefly/package.ff +1 -2
- package/core/Box.ff +7 -0
- package/core/BuildSystem.ff +5 -4
- package/core/Core.ff +4 -0
- package/core/HttpClient.ff +1 -1
- package/core/JsValue.ff +22 -1
- package/core/Lock.ff +4 -4
- package/core/NodeSystem.ff +12 -3
- package/core/Path.ff +1 -1
- package/core/SourceLocation.ff +41 -0
- package/core/Stack.ff +6 -6
- package/core/StringMap.ff +3 -3
- package/lsp/LanguageServer.ff +32 -7
- package/lsp/stderr.txt +1 -0
- package/lsp/stdin.txt +11 -0
- package/lsp/stdout.txt +41 -0
- package/lux/.firefly/package.ff +2 -0
- package/lux/Lux.ff +473 -0
- package/lux/LuxEvent.ff +116 -0
- package/lux/Main.ff +126 -0
- package/lux/Main2.ff +144 -0
- package/meetup/AutoCompletion.ff +6 -0
- package/output/js/ff/compiler/Builder.mjs +444 -440
- package/output/js/ff/compiler/Compiler.mjs +416 -410
- package/output/js/ff/compiler/Dependencies.mjs +389 -385
- package/output/js/ff/compiler/Deriver.mjs +1170 -1166
- package/output/js/ff/compiler/Dictionaries.mjs +1309 -1305
- package/output/js/ff/compiler/Environment.mjs +1015 -1005
- package/output/js/ff/compiler/Inference.mjs +4268 -4264
- package/output/js/ff/compiler/JsEmitter.mjs +5391 -5353
- package/output/js/ff/compiler/JsImporter.mjs +266 -262
- package/output/js/ff/compiler/LspHook.mjs +793 -789
- package/output/js/ff/compiler/Main.mjs +1699 -1695
- package/output/js/ff/compiler/Parser.mjs +4008 -4004
- package/output/js/ff/compiler/Patterns.mjs +927 -923
- package/output/js/ff/compiler/Resolver.mjs +2307 -2303
- package/output/js/ff/compiler/Substitution.mjs +1150 -1146
- package/output/js/ff/compiler/Syntax.mjs +12434 -12430
- package/output/js/ff/compiler/Token.mjs +3096 -3092
- package/output/js/ff/compiler/Tokenizer.mjs +593 -589
- package/output/js/ff/compiler/Unification.mjs +1752 -1748
- package/output/js/ff/compiler/Wildcards.mjs +608 -604
- package/output/js/ff/compiler/Workspace.mjs +687 -683
- package/output/js/ff/core/Any.mjs +143 -139
- package/output/js/ff/core/Array.mjs +547 -543
- package/output/js/ff/core/AssetSystem.mjs +274 -270
- package/output/js/ff/core/Atomic.mjs +154 -150
- package/output/js/ff/core/Bool.mjs +152 -141
- package/output/js/ff/core/Box.mjs +112 -0
- package/output/js/ff/core/BrowserSystem.mjs +126 -122
- package/output/js/ff/core/Buffer.mjs +395 -391
- package/output/js/ff/core/BuildSystem.mjs +296 -290
- package/output/js/ff/core/Channel.mjs +189 -185
- package/output/js/ff/core/Char.mjs +149 -145
- package/output/js/ff/core/Core.mjs +300 -288
- package/output/js/ff/core/Duration.mjs +116 -112
- package/output/js/ff/core/Equal.mjs +179 -175
- package/output/js/ff/core/Error.mjs +142 -138
- package/output/js/ff/core/FileHandle.mjs +150 -146
- package/output/js/ff/core/Float.mjs +225 -214
- package/output/js/ff/core/HttpClient.mjs +190 -186
- package/output/js/ff/core/Instant.mjs +109 -105
- package/output/js/ff/core/Int.mjs +265 -254
- package/output/js/ff/core/IntMap.mjs +280 -276
- package/output/js/ff/core/JsSystem.mjs +238 -234
- package/output/js/ff/core/JsValue.mjs +714 -664
- package/output/js/ff/core/List.mjs +2334 -2321
- package/output/js/ff/core/Lock.mjs +230 -226
- package/output/js/ff/core/Log.mjs +163 -159
- package/output/js/ff/core/Map.mjs +362 -358
- package/output/js/ff/core/NodeSystem.mjs +302 -283
- package/output/js/ff/core/Nothing.mjs +104 -100
- package/output/js/ff/core/Option.mjs +1015 -1002
- package/output/js/ff/core/Ordering.mjs +730 -726
- package/output/js/ff/core/Pair.mjs +331 -318
- package/output/js/ff/core/Path.mjs +546 -542
- package/output/js/ff/core/RbMap.mjs +1940 -1936
- package/output/js/ff/core/Serializable.mjs +428 -424
- package/output/js/ff/core/Set.mjs +254 -250
- package/output/js/ff/core/Show.mjs +205 -201
- package/output/js/ff/core/SourceLocation.mjs +229 -0
- package/output/js/ff/core/Stack.mjs +541 -537
- package/output/js/ff/core/Stream.mjs +1304 -1300
- package/output/js/ff/core/String.mjs +365 -354
- package/output/js/ff/core/StringMap.mjs +280 -276
- package/output/js/ff/core/Task.mjs +320 -316
- package/output/js/ff/core/Try.mjs +507 -503
- package/output/js/ff/core/Unit.mjs +151 -103
- package/package.json +29 -29
- package/vscode/package-lock.json +5 -5
- package/vscode/package.json +1 -1
package/core/Stack.ff
CHANGED
|
@@ -99,32 +99,32 @@ extend self[T]: Stack[T] {
|
|
|
99
99
|
|
|
100
100
|
fill(value: T, start: Int = 0, end: Int = 9007199254740991): Unit
|
|
101
101
|
target js sync """
|
|
102
|
-
|
|
102
|
+
self_.array.fill(value_, start_, end_);
|
|
103
103
|
"""
|
|
104
104
|
|
|
105
105
|
copy(target: Int, start: Int, end: Int): Unit
|
|
106
106
|
target js sync """
|
|
107
|
-
|
|
107
|
+
self_.array.copyWithin(target_, start_, end_);
|
|
108
108
|
"""
|
|
109
109
|
|
|
110
110
|
delete(start: Int, deleteCount: Int): Unit
|
|
111
111
|
target js sync """
|
|
112
|
-
|
|
112
|
+
self_.array.splice(start_, deleteCount_);
|
|
113
113
|
"""
|
|
114
114
|
|
|
115
115
|
insert(start: Int, value: T, deleteCount: Int = 0): Unit
|
|
116
116
|
target js sync """
|
|
117
|
-
|
|
117
|
+
self_.array.splice(start_, deleteCount_, value_);
|
|
118
118
|
"""
|
|
119
119
|
|
|
120
120
|
insertAll(start: Int, value: Stack[T], deleteCount: Int = 0): Unit
|
|
121
121
|
target js sync """
|
|
122
|
-
|
|
122
|
+
self_.array.splice(start_, deleteCount_, ...value_.array);
|
|
123
123
|
"""
|
|
124
124
|
|
|
125
125
|
insertArray(start: Int, value: Array[T], deleteCount: Int = 0): Unit
|
|
126
126
|
target js sync """
|
|
127
|
-
|
|
127
|
+
self_.array.splice(start_, deleteCount_, ...value_);
|
|
128
128
|
"""
|
|
129
129
|
|
|
130
130
|
each(body: T => Unit): Unit
|
package/core/StringMap.ff
CHANGED
|
@@ -32,11 +32,11 @@ extend self[V]: StringMap[V] {
|
|
|
32
32
|
size(): Int
|
|
33
33
|
target js sync "return self_.size"
|
|
34
34
|
|
|
35
|
-
each(body: (String, V) => Unit):
|
|
36
|
-
target js sync "
|
|
35
|
+
each(body: (String, V) => Unit): Unit
|
|
36
|
+
target js sync "self_.forEach((v, k) => body_(k, v))"
|
|
37
37
|
target js async "for(const [k, v] of self_) await body_(k, v)"
|
|
38
38
|
|
|
39
|
-
eachWhile(body: (String, V) => Bool):
|
|
39
|
+
eachWhile(body: (String, V) => Bool): Unit
|
|
40
40
|
target js sync "for(const [k, v] of self_) if(!body_(k, v)) break"
|
|
41
41
|
target js async "for(const [k, v] of self_) if(!await body_(k, v)) break"
|
|
42
42
|
|
package/lsp/LanguageServer.ff
CHANGED
|
@@ -17,17 +17,26 @@ capability RequestMessage(
|
|
|
17
17
|
parameters: Map[String, JsValue]
|
|
18
18
|
)
|
|
19
19
|
|
|
20
|
+
logMessages = False
|
|
20
21
|
|
|
21
22
|
main(system: NodeSystem) {
|
|
23
|
+
let logDirectory = if(logMessages) {
|
|
24
|
+
let directory = system.path(".").slash("messages")
|
|
25
|
+
if(directory.isDirectory()) {directory.delete()}
|
|
26
|
+
directory.createDirectory()
|
|
27
|
+
directory
|
|
28
|
+
}
|
|
29
|
+
|
|
22
30
|
let fireflyPath = system.path(".")
|
|
23
31
|
let handler = Handler(fireflyPath, None, Map.empty(), [].toSet(), Map.empty(), Map.empty())
|
|
24
32
|
try {
|
|
25
33
|
mutable input = system.readStream()
|
|
26
|
-
let responseChannel: Channel[JsValue] = system.mainTask().channel()
|
|
34
|
+
let responseChannel: Channel[Pair[JsValue, String]] = system.mainTask().channel()
|
|
27
35
|
system.mainTask().spawn {_ =>
|
|
28
36
|
while {True} {
|
|
29
37
|
let body = responseChannel.read()
|
|
30
|
-
let json = body.toJson(Some(" ")).toBuffer()
|
|
38
|
+
let json = body.first.toJson(Some(" ")).toBuffer()
|
|
39
|
+
logDirectory.each {logMessage(_, "response", body.first, body.second)}
|
|
31
40
|
system.writeText("Content-Length: " + json.size() + "\r\n\r\n")
|
|
32
41
|
system.writeBuffer(json)
|
|
33
42
|
}
|
|
@@ -38,13 +47,14 @@ main(system: NodeSystem) {
|
|
|
38
47
|
input = requestPair.second
|
|
39
48
|
let request = requestPair.first
|
|
40
49
|
let message = parseRequestMessage(request.object)
|
|
50
|
+
logDirectory.each {logMessage(_, "request", request.object, message.method)}
|
|
41
51
|
spawn(message.id) {_ =>
|
|
42
52
|
if(message.method == "$/cancelRequest") {
|
|
43
53
|
abort(Some(parseMessageId(message.parameters.grab("id"))))
|
|
44
54
|
}
|
|
45
55
|
try {
|
|
46
56
|
handleRequestMessage(system, handler, message).each {body =>
|
|
47
|
-
responseChannel.write(body)
|
|
57
|
+
responseChannel.write(Pair(body, message.method))
|
|
48
58
|
}
|
|
49
59
|
} catchAny {error =>
|
|
50
60
|
let problem = if(error.name() == "AbortError") {
|
|
@@ -55,7 +65,8 @@ main(system: NodeSystem) {
|
|
|
55
65
|
Error(-32603, "Internal error")
|
|
56
66
|
}
|
|
57
67
|
message.id.each {id =>
|
|
58
|
-
|
|
68
|
+
let body = makeResponseMessage(system.js(), id, problem)
|
|
69
|
+
responseChannel.write(Pair(body, message.method))
|
|
59
70
|
}
|
|
60
71
|
} grab()
|
|
61
72
|
}
|
|
@@ -74,17 +85,17 @@ taskGroup[K: Order, R](
|
|
|
74
85
|
mutable tasks = [].toMap()
|
|
75
86
|
function spawn(key: K, body: Task => Unit): Task {
|
|
76
87
|
let body2 = {task =>
|
|
77
|
-
lock.do {tasks = tasks.add(key, task)}
|
|
88
|
+
lock.do(reentrant = True) {tasks = tasks.add(key, task)}
|
|
78
89
|
try {
|
|
79
90
|
body(task)
|
|
80
91
|
} finally {
|
|
81
|
-
lock.do {tasks = tasks.remove(key)}
|
|
92
|
+
lock.do(reentrant = True) {tasks = tasks.remove(key)}
|
|
82
93
|
} grab()
|
|
83
94
|
}
|
|
84
95
|
parentTask.spawn(body2)
|
|
85
96
|
}
|
|
86
97
|
function abort(key: K): Unit {
|
|
87
|
-
lock.do {tasks.get(key).each {_.abort()}}
|
|
98
|
+
lock.do(reentrant = True) {tasks.get(key).each {_.abort()}}
|
|
88
99
|
}
|
|
89
100
|
groupBody(spawn, abort)
|
|
90
101
|
}
|
|
@@ -227,3 +238,17 @@ makeResponseMessage(js: JsSystem, id: MessageId, result: ResultOrError): JsValue
|
|
|
227
238
|
}
|
|
228
239
|
o
|
|
229
240
|
}
|
|
241
|
+
|
|
242
|
+
logMessage(directory: Path, messageType: String, body: JsValue, method: String) {
|
|
243
|
+
let id = if(method == "$/cancelRequest") {
|
|
244
|
+
Some(body.get("params").get("id").grabInt())
|
|
245
|
+
} else {
|
|
246
|
+
body.getOwn("id").map {_.grabInt()}
|
|
247
|
+
}
|
|
248
|
+
let number = directory.entries().toList().size()
|
|
249
|
+
let idName = id.map {_ + ""}.else {"_"}
|
|
250
|
+
let methodName = method.replace("$", "notification").replace("/", "_")
|
|
251
|
+
let fileName = number + "-id-" + idName + "-" + messageType + "-" + methodName + ".json"
|
|
252
|
+
let path = directory.slash(fileName)
|
|
253
|
+
path.writeText(body.toJson(Some(" ")))
|
|
254
|
+
}
|
package/lsp/stderr.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
End of input while parsing request headers
|
package/lsp/stdin.txt
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Content-Length: 5836
|
|
2
|
+
|
|
3
|
+
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":43727,"clientInfo":{"name":"Visual Studio Code","version":"1.76.2"},"locale":"en","rootPath":"/Users/ahnfelt/Downloads/firefly-boot","rootUri":"file:///Users/ahnfelt/Downloads/firefly-boot","capabilities":{"workspace":{"applyEdit":true,"workspaceEdit":{"documentChanges":true,"resourceOperations":["create","rename","delete"],"failureHandling":"textOnlyTransactional","normalizesLineEndings":true,"changeAnnotationSupport":{"groupsOnLabel":true}},"configuration":true,"didChangeWatchedFiles":{"dynamicRegistration":true,"relativePatternSupport":true},"symbol":{"dynamicRegistration":true,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},"tagSupport":{"valueSet":[1]},"resolveSupport":{"properties":["location.range"]}},"codeLens":{"refreshSupport":true},"executeCommand":{"dynamicRegistration":true},"didChangeConfiguration":{"dynamicRegistration":true},"workspaceFolders":true,"semanticTokens":{"refreshSupport":true},"fileOperations":{"dynamicRegistration":true,"didCreate":true,"didRename":true,"didDelete":true,"willCreate":true,"willRename":true,"willDelete":true},"inlineValue":{"refreshSupport":true},"inlayHint":{"refreshSupport":true},"diagnostics":{"refreshSupport":true}},"textDocument":{"publishDiagnostics":{"relatedInformation":true,"versionSupport":false,"tagSupport":{"valueSet":[1,2]},"codeDescriptionSupport":true,"dataSupport":true},"synchronization":{"dynamicRegistration":true,"willSave":true,"willSaveWaitUntil":true,"didSave":true},"completion":{"dynamicRegistration":true,"contextSupport":true,"completionItem":{"snippetSupport":true,"commitCharactersSupport":true,"documentationFormat":["markdown","plaintext"],"deprecatedSupport":true,"preselectSupport":true,"tagSupport":{"valueSet":[1]},"insertReplaceSupport":true,"resolveSupport":{"properties":["documentation","detail","additionalTextEdits"]},"insertTextModeSupport":{"valueSet":[1,2]},"labelDetailsSupport":true},"insertTextMode":2,"completionItemKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]},"completionList":{"itemDefaults":["commitCharacters","editRange","insertTextFormat","insertTextMode"]}},"hover":{"dynamicRegistration":true,"contentFormat":["markdown","plaintext"]},"signatureHelp":{"dynamicRegistration":true,"signatureInformation":{"documentationFormat":["markdown","plaintext"],"parameterInformation":{"labelOffsetSupport":true},"activeParameterSupport":true},"contextSupport":true},"definition":{"dynamicRegistration":true,"linkSupport":true},"references":{"dynamicRegistration":true},"documentHighlight":{"dynamicRegistration":true},"documentSymbol":{"dynamicRegistration":true,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},"hierarchicalDocumentSymbolSupport":true,"tagSupport":{"valueSet":[1]},"labelSupport":true},"codeAction":{"dynamicRegistration":true,"isPreferredSupport":true,"disabledSupport":true,"dataSupport":true,"resolveSupport":{"properties":["edit"]},"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}},"honorsChangeAnnotations":false},"codeLens":{"dynamicRegistration":true},"formatting":{"dynamicRegistration":true},"rangeFormatting":{"dynamicRegistration":true},"onTypeFormatting":{"dynamicRegistration":true},"rename":{"dynamicRegistration":true,"prepareSupport":true,"prepareSupportDefaultBehavior":1,"honorsChangeAnnotations":true},"documentLink":{"dynamicRegistration":true,"tooltipSupport":true},"typeDefinition":{"dynamicRegistration":true,"linkSupport":true},"implementation":{"dynamicRegistration":true,"linkSupport":true},"colorProvider":{"dynamicRegistration":true},"foldingRange":{"dynamicRegistration":true,"rangeLimit":5000,"lineFoldingOnly":true,"foldingRangeKind":{"valueSet":["comment","imports","region"]},"foldingRange":{"collapsedText":false}},"declaration":{"dynamicRegistration":true,"linkSupport":true},"selectionRange":{"dynamicRegistration":true},"callHierarchy":{"dynamicRegistration":true},"semanticTokens":{"dynamicRegistration":true,"tokenTypes":["namespace","type","class","enum","interface","struct","typeParameter","parameter","variable","property","enumMember","event","function","method","macro","keyword","modifier","comment","string","number","regexp","operator","decorator"],"tokenModifiers":["declaration","definition","readonly","static","deprecated","abstract","async","modification","documentation","defaultLibrary"],"formats":["relative"],"requests":{"range":true,"full":{"delta":true}},"multilineTokenSupport":false,"overlappingTokenSupport":false,"serverCancelSupport":true,"augmentsSyntaxTokens":true},"linkedEditingRange":{"dynamicRegistration":true},"typeHierarchy":{"dynamicRegistration":true},"inlineValue":{"dynamicRegistration":true},"inlayHint":{"dynamicRegistration":true,"resolveSupport":{"properties":["tooltip","textEdits","label.tooltip","label.location","label.command"]}},"diagnostic":{"dynamicRegistration":true,"relatedDocumentSupport":false}},"window":{"showMessage":{"messageActionItem":{"additionalPropertiesSupport":true}},"showDocument":{"support":true},"workDoneProgress":true},"general":{"staleRequestSupport":{"cancel":true,"retryOnContentModified":["textDocument/semanticTokens/full","textDocument/semanticTokens/range","textDocument/semanticTokens/full/delta"]},"regularExpressions":{"engine":"ECMAScript","version":"ES2020"},"markdown":{"parser":"marked","version":"1.1.0"},"positionEncodings":["utf-16"]},"notebookDocument":{"synchronization":{"dynamicRegistration":true,"executionSummarySupport":true}}},"trace":"off","workspaceFolders":[{"uri":"file:///Users/ahnfelt/Downloads/firefly-boot","name":"firefly-boot"}]}}Content-Length: 52
|
|
4
|
+
|
|
5
|
+
{"jsonrpc":"2.0","method":"initialized","params":{}}Content-Length: 9421
|
|
6
|
+
|
|
7
|
+
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///Users/ahnfelt/Downloads/firefly-boot/lsp/LanguageServer.ff","languageId":"firefly","version":1,"text":"class LanguageServer(\n mutable openFiles: Map[String, String]\n)\n\ndata BadRequestException(reason: String)\n\ncapability Request(\n headers: Map[String, String]\n object: JsValue\n)\n\ncapability RequestMessage(\n id: Option[MessageId] // None when the request is a Notification Message\n method: String\n parameters: Map[String, JsValue]\n)\n\ndata MessageId {\n MessageIdInt(id: Int)\n MessageIdString(id: String)\n}\n\ncapability ResultOrError {\n Result(result: JsValue)\n Error(code: Int, message: String)\n}\n\n\nmain(system: NodeSystem) {\n try {\n mutable input = system.readStream()\n while {True} {\n let requestPair = parseRequest(system, input)\n input = requestPair.second\n let request = requestPair.first\n let message = parseRequestMessage(request.object)\n handleRequestMessage(system.js(), message).each {body =>\n system.writeText(makeResponse(body))\n }\n //system.writeText(makeResponse(makeDiagnoseNotification(system.js())))\n }\n } catch {| BadRequestException(reason), error =>\n system.writeErrorText(reason + \"\\n\")\n } grab()\n}\n \nparseRequest(system: NodeSystem, input: Stream[Buffer]): Pair[Request, Stream[Buffer]] {\n let headersPair = parseRequestHeaders(input)\n let headers = headersPair.first\n let contentLength = headers\n .get(\"content-length\").else {throw(BadRequestException(\"'content-length' header is missing\"))}\n .getInt().else {throw(BadRequestException(\"Value for 'content-length' is not an integer\"))}\n let bodyPair = parseRequestBody(system.js(), contentLength, headersPair.second)\n bodyPair.mapFirst {body => Request(headers, body)}\n}\n\nparseRequestHeaders(input: Stream[Buffer]): Pair[Map[String, String], Stream[Buffer]] {\n let buffers = Stack.make()\n mutable buffer = input.next().else {\n throw(BadRequestException(\"End of input while parsing request headers\"))\n }\n mutable offset = 0\n mutable droppingInitialNewlines = True\n mutable lastWasNewline = False\n mutable done = False\n while {!done} {\n if(offset == buffer.size()) {\n offset = 0\n buffers.push(buffer)\n buffer = input.next().else {\n throw(BadRequestException(\"End of input while parsing request headers\"))\n }\n }\n let byte = buffer.grabUint8(offset)\n if(droppingInitialNewlines && (byte == '\\n'.codeUnit || byte == '\\r'.codeUnit)) {\n // Skip\n } elseIf {byte == '\\n'.codeUnit} {\n if(lastWasNewline) {\n done = True\n } else {\n lastWasNewline = True\n }\n } elseIf {byte != '\\r'.codeUnit && lastWasNewline} {\n lastWasNewline = False\n } else {\n droppingInitialNewlines = False\n }\n offset += 1\n }\n buffers.push(buffer.view(0, offset))\n let headers = Buffer.fromBufferArray(buffers.drain()).toString()\n let map = headers.lines().pairs().filter {_.second.size() != 0}.map {| Pair(i, line) =>\n line.splitFirst(':').else {\n throw(BadRequestException(\"Invalid header at line \" + i + \" '\" + line + \"'\"))\n }.mapFirst {_.lower()} //.mapSecond {_.trim()}\n }.toMap()\n Pair(map, [buffer.view(offset, buffer.size())].toStream().addAll(input))\n}\n\nparseRequestBody(js: JsSystem, contentLength: Int, input: Stream[Buffer]): Pair[JsValue, Stream[Buffer]] {\n let bodyPair = try {\n input.readBytes(contentLength) // Should Stream.readBytes return an option?\n } catchAny {error =>\n throw(BadRequestException(\"End of input while parsing request body\"))\n } grab()\n let body = Buffer.fromBufferArray(bodyPair.first).toString()\n let json = try {\n js.parseJson(body)\n } catchAny {error =>\n throw(BadRequestException(\"Invalid JSON in request body: \" + body))\n } grab()\n Pair(json, bodyPair.second)\n}\n\nparseRequestMessage(object: JsValue): RequestMessage {\n let id = object.getOwn(\"id\").map {id =>\n if(id.isInt()) {\n MessageIdInt(id.grabInt())\n } elseIf {id.isString()} {\n MessageIdString(id.grabString())\n } else {\n throw(BadRequestException(\"Bad JSON-RPC id, int or string expected\"))\n }\n }\n\n let method = object.getOwn(\"method\").{\n | None => throw(BadRequestException(\"Bad JSON-RPC, missing method\"))\n | Some(m) {!m.isString()} => throw(BadRequestException(\"Bad JSON-RPC method, string expected\"))\n | Some(m) => m.grabString()\n }\n\n let parameters = object.getOwn(\"params\").{\n | None => [].toMap()\n | Some(o) {!o.isObject()} => throw(BadRequestException(\"Bad JSON-RPC params, object expected\"))\n | Some(o) => o.grabMap()\n }\n\n RequestMessage(id, method, parameters)\n}\n\nhandleRequestMessage(js: JsSystem, message: RequestMessage): Option[JsValue] {\n message.id.{\n // Notification Message\n | None =>\n message.method.{\n | \"initialized\" =>\n | _ =>\n }\n None\n // Request Message\n | Some(id) =>\n let result = message.method.{\n | \"initialize\" => handleInitialize(js, message.parameters)\n | \"textDocument/diagnostic\" => handleDiagnostic(js, message.parameters)\n | \"hover\" => handleHover(js, message.parameters)\n | _ => handleUnsupported(js)\n }\n Some(makeResponseMessage(js, id, result))\n }\n}\n\nmakeResponse(body: JsValue): String {\n let json = body.toJson(Some(\" \"))\n let length = json.size()\n \"Content-Length: \" + length + \"\\r\\n\" +\n \"\\r\\n\" +\n json\n}\n\nmakeResponseMessage(js: JsSystem, id: MessageId, result: ResultOrError): JsValue {\n let o = js.object()\n o.set(\"jsonrpc\", \"2.0\")\n id.{\n | MessageIdInt(id) => o.set(\"id\", id)\n | MessageIdString(id) => o.set(\"id\", id)\n }\n result.{\n | Result(result) =>\n o.set(\"result\", result)\n | Error(code, message) =>\n let e = js.object()\n e.set(\"code\", code)\n e.set(\"message\", message)\n o.set(\"error\", e)\n }\n o\n}\n\nhandleUnsupported(js: JsSystem): ResultOrError {\n Error(1234, \"Unsupported method\")\n}\n\nhandleInitialize(js: JsSystem, parameters: Map[String, JsValue]): ResultOrError {\n let anyFireflyFile = js.object()\n .with(\"filters\", [\n js.object()\n .with(\"pattern\", js.object()\n .with(\"glob\", \"**/*.ff\")\n .with(\"matches\", \"file\")\n )\n ].toArray())\n\n let o = js.object()\n .with(\"capabilities\", js.object()\n .with(\"textDocumentSync\", js.object()\n .with(\"openClose\", True)\n .with(\"change\", 1 /* TextDocumentSyncKind.Full */)\n )\n .with(\"hoverProvider\", False)\n //.with(\"definitionProvider\", True)\n //.with(\"typeDefinitionProvider\", True)\n .with(\"diagnosticProvider\", js.object()\n .with(\"interFileDependencies\", True)\n .with(\"workspaceDiagnostics\", False)\n )\n /*.with(\"workspace\", js.object()\n .with(\"workspaceFolders\", js.object()\n .with(\"supported\", True)\n .with(\"changeNotifications\", True)\n )\n .with(\"fileOperations\", js.object()\n .with(\"didCreate\", anyFireflyFile)\n .with(\"didRename\", anyFireflyFile)\n .with(\"didDelete\", anyFireflyFile)\n )\n )*/\n )\n .with(\"serverInfo\", js.object()\n .with(\"name\", \"Firefly Language Server\")\n .with(\"version\", \"0.0.0\")\n )\n Result(o)\n}\n\nhandleDiagnostic(js: JsSystem, parameters: Map[String, JsValue]): ResultOrError {\n let diagnostic = js.object()\n .with(\"range\", js.object()\n .with(\"start\", js.object()\n .with(\"line\", 0).with(\"character\", 6)\n )\n .with(\"end\", js.object()\n .with(\"line\", 0).with(\"character\", 20)\n )\n )\n .with(\"severity\", 1 /* Error */)\n .with(\"message\", \"Hurray!\")\n\n let o = js.object()\n .with(\"kind\", \"full\")\n .with(\"items\", [/*diagnostic*/].toArray())\n\n Result(o)\n}\n\nhandleHover(js: JsSystem, parameters: Map[String, JsValue]): ResultOrError {\n let o = js.object().with(\"contents\", \"TODO\")\n Result(o)\n}\n\nmakeNotificationMessage(js: JsSystem, method: String, params: JsValue): JsValue {\n js.object()\n .with(\"jsonrpc\", \"2.0\")\n .with(\"method\", method)\n .with(\"params\", params)\n}\n"}}}Content-Length: 162
|
|
8
|
+
|
|
9
|
+
{"jsonrpc":"2.0","id":1,"method":"textDocument/diagnostic","params":{"textDocument":{"uri":"file:///Users/ahnfelt/Downloads/firefly-boot/lsp/LanguageServer.ff"}}}Content-Length: 44
|
|
10
|
+
|
|
11
|
+
{"jsonrpc":"2.0","id":2,"method":"shutdown"}
|
package/lsp/stdout.txt
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
Content-Length: 500
|
|
2
|
+
|
|
3
|
+
{
|
|
4
|
+
"jsonrpc": "2.0",
|
|
5
|
+
"id": 0,
|
|
6
|
+
"result": {
|
|
7
|
+
"capabilities": {
|
|
8
|
+
"textDocumentSync": {
|
|
9
|
+
"openClose": true,
|
|
10
|
+
"change": 1
|
|
11
|
+
},
|
|
12
|
+
"hoverProvider": false,
|
|
13
|
+
"diagnosticProvider": {
|
|
14
|
+
"interFileDependencies": true,
|
|
15
|
+
"workspaceDiagnostics": false
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"serverInfo": {
|
|
19
|
+
"name": "Firefly Language Server",
|
|
20
|
+
"version": "0.0.0"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}Content-Length: 104
|
|
24
|
+
|
|
25
|
+
{
|
|
26
|
+
"jsonrpc": "2.0",
|
|
27
|
+
"id": 1,
|
|
28
|
+
"result": {
|
|
29
|
+
"kind": "full",
|
|
30
|
+
"items": []
|
|
31
|
+
}
|
|
32
|
+
}Content-Length: 121
|
|
33
|
+
|
|
34
|
+
{
|
|
35
|
+
"jsonrpc": "2.0",
|
|
36
|
+
"id": 2,
|
|
37
|
+
"error": {
|
|
38
|
+
"code": 1234,
|
|
39
|
+
"message": "Unsupported method"
|
|
40
|
+
}
|
|
41
|
+
}
|