103 lines
2.1 KiB
Plaintext
103 lines
2.1 KiB
Plaintext
// JSON-RPC protocol helpers for LSP communication over stdin/stdout.
|
|
// Reads Content-Length framed messages from stdin, writes to stdout.
|
|
|
|
var fd = use('fd')
|
|
var json = use('json')
|
|
|
|
// Read a single JSON-RPC message from stdin.
|
|
// Protocol: "Content-Length: N\r\n\r\n" followed by N bytes of JSON.
|
|
var read_message = function() {
|
|
var header = ""
|
|
var ch = null
|
|
var content_length = null
|
|
var body = null
|
|
var total = 0
|
|
var chunk = null
|
|
|
|
// Read header byte by byte until we hit \r\n\r\n
|
|
while (true) {
|
|
ch = fd.read(0, 1)
|
|
if (ch == null) {
|
|
return null
|
|
}
|
|
header = header + text(ch)
|
|
if (ends_with(header, "\r\n\r\n")) {
|
|
break
|
|
}
|
|
}
|
|
|
|
// Parse Content-Length from header
|
|
var lines = array(header, "\r\n")
|
|
var _i = 0
|
|
while (_i < length(lines)) {
|
|
if (starts_with(lines[_i], "Content-Length:")) {
|
|
content_length = number(trim(text(lines[_i], 16)))
|
|
}
|
|
_i = _i + 1
|
|
}
|
|
|
|
if (content_length == null) {
|
|
return null
|
|
}
|
|
|
|
// Read exactly content_length bytes
|
|
body = ""
|
|
total = 0
|
|
while (total < content_length) {
|
|
chunk = fd.read(0, content_length - total)
|
|
if (chunk == null) {
|
|
return null
|
|
}
|
|
chunk = text(chunk)
|
|
body = body + chunk
|
|
total = total + length(chunk)
|
|
}
|
|
|
|
return json.decode(body)
|
|
}
|
|
|
|
// Send a JSON-RPC message to stdout.
|
|
var send_message = function(msg) {
|
|
var body = json.encode(msg)
|
|
var header = `Content-Length: ${text(length(body))}\r\n\r\n`
|
|
fd.write(1, header + body)
|
|
}
|
|
|
|
// Send a JSON-RPC response for a request.
|
|
var respond = function(id, result) {
|
|
send_message({
|
|
jsonrpc: "2.0",
|
|
id: id,
|
|
result: result
|
|
})
|
|
}
|
|
|
|
// Send a JSON-RPC error response.
|
|
var respond_error = function(id, code, message) {
|
|
send_message({
|
|
jsonrpc: "2.0",
|
|
id: id,
|
|
error: {
|
|
code: code,
|
|
message: message
|
|
}
|
|
})
|
|
}
|
|
|
|
// Send a JSON-RPC notification (no id).
|
|
var notify = function(method, params) {
|
|
send_message({
|
|
jsonrpc: "2.0",
|
|
method: method,
|
|
params: params
|
|
})
|
|
}
|
|
|
|
return {
|
|
read_message: read_message,
|
|
send_message: send_message,
|
|
respond: respond,
|
|
respond_error: respond_error,
|
|
notify: notify
|
|
}
|