Skip to content

Commit 94eada8

Browse files
authored
Merge pull request #541 from Jafaral/ulsp-refactor
ulsp: code refactoring with error handling improvements
2 parents 8533518 + f978fb3 commit 94eada8

File tree

4 files changed

+111
-34
lines changed

4 files changed

+111
-34
lines changed

uni/lib/jsonrpc.icn

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ class JRPC_Message(msg, kind, json_table)
4343
# Parse the JSON-RPC message and set the kind of the message
4444
method parse_json(s)
4545
msg := s
46-
if json_table := jtou(s) then {
46+
json_table := &null
47+
48+
if json_table := jtous(s) then {
4749
guess_kind()
4850
return self
4951
} else
@@ -52,11 +54,10 @@ class JRPC_Message(msg, kind, json_table)
5254

5355
# Guess the kind of the message based on the JSON-RPC message
5456
method guess_kind()
55-
#if we have a method, the msg is a request
56-
if \json_table["method"] then
57-
kind := if \json_table["id"] then "request" else "notification"
58-
else if \json_table["error"] then
57+
if \json_table["error"] then
5958
kind := "error"
59+
else if \json_table["method"] then
60+
kind := if \json_table["id"] then "request" else "notification"
6061
else if \json_table["result"] then
6162
kind := "response"
6263
else
@@ -100,38 +101,54 @@ class JRPC_Message(msg, kind, json_table)
100101
return msg
101102
end
102103

104+
method to_json()
105+
if msg := tojson(json_table) then
106+
return msg
107+
end
108+
103109
# Initialize the JSON RPC message
104110
method init_msg()
105111
/json_table := ["jsonrpc" : "2.0"]
106112
end
107113

108114
# Set the result of the JSON RPC message
109115
method set_result(result)
116+
init_msg()
110117
json_table["result"] := result
111118
end
112119
# Set the id of the JSON RPC message
113120
method set_id(id)
121+
init_msg()
114122
return json_table["id"] := id
115123
end
116124
# Set the method of the JSON RPC message
117125
method set_method(meth)
118-
return json_table["method"] := meth
126+
init_msg()
127+
json_table["method"] := meth
128+
guess_kind()
129+
return meth
119130
end
120131
# Set the params of the JSON RPC message
121132
method set_params(params)
122-
return json_table["params"] := params
133+
init_msg()
134+
json_table["params"] := params
135+
return params
123136
end
124137

125138
# Make a result response JSON RPC message
126139
method make_result_response(result)
140+
init_msg()
127141
delete(json_table, "method", "params", "error")
128-
json_table["result"] := \result | ""
142+
# JSON-RPC 2.0: result can be null, so preserve null
143+
json_table["result"] := result
144+
guess_kind()
129145
if msg := tojson(json_table) then
130146
return self
131147
end
132148

133149
# Make a request JSON RPC message
134150
method make_request(id, meth, params)
151+
init_msg()
135152
if /json_table then
136153
json_table := [
137154
"id" : id;
@@ -144,6 +161,24 @@ class JRPC_Message(msg, kind, json_table)
144161
json_table["method"] := meth
145162
json_table["params"] := params
146163
}
164+
guess_kind()
165+
if msg := tojson(json_table) then
166+
return self
167+
end
168+
169+
method make_notification(meth, params)
170+
init_msg()
171+
if /json_table then
172+
json_table := [
173+
"method" : meth;
174+
"params" : params
175+
]
176+
else {
177+
delete(json_table, "id", "result", "error")
178+
json_table["method"] := meth
179+
json_table["params"] := params
180+
}
181+
guess_kind()
147182
if msg := tojson(json_table) then
148183
return self
149184
end
@@ -198,12 +233,24 @@ class JRPC_Message(msg, kind, json_table)
198233

199234
# Make an error response JSON RPC message
200235
method make_error_response(err_code, err_msg, err_data)
201-
delete(json_table, "method", "params", "result")
202-
json_table["error"] := [
203-
"code" : err_code;
204-
"message" : err_msg;
205-
"data" : \err_data | ""
206-
]
236+
init_msg()
237+
if /json_table then
238+
json_table := [
239+
"error" : [
240+
"code" : err_code;
241+
"message" : err_msg;
242+
"data" : \err_data | ""
243+
]
244+
]
245+
else {
246+
delete(json_table, "method", "params", "result")
247+
json_table["error"] := [
248+
"code" : err_code;
249+
"message" : err_msg;
250+
"data" : \err_data | ""
251+
]
252+
}
253+
guess_kind()
207254
if msg := tojson(json_table) then
208255
return self
209256
end
@@ -229,7 +276,7 @@ class JRPC_HTTPSocket(sock)
229276
# Wait for a message to arrive, read the header
230277
# assume the min header size is 22, because the shortest jrpc
231278
# msgs will be at least 2 digits, I.e header size >=22
232-
*select(sock, timeout) > 0 | fail
279+
*select(\sock, timeout) > 0 | fail
233280
data ||:= ready(sock, size-*data)
234281
data ~== "" | fail
235282
if *data < size then next

uni/ulsp/completion.icn

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,18 @@ class CompletionHandler(
1313
end
1414

1515
method getResult()
16-
local _context, line, character, results_table, results, desired_line, objectName, context
17-
18-
line := params["position"]["line"] + 1
19-
character := params["position"]["character"] + 1
16+
local _context, line, character, results_table, results, desired_line, objectName, context, position
17+
18+
# Check that params and position exist and are valid
19+
if /params then fail
20+
if not member(params, "position") then fail
21+
# Get position and verify it's not null before accessing its members
22+
if /(position := params["position"]) then fail
23+
if not member(position, "line") then fail
24+
if not member(position, "character") then fail
25+
26+
line := position["line"] + 1
27+
character := position["character"] + 1
2028

2129
context := filehandler.getContext(line, character) | fail
2230
desired_line := context.line

uni/ulsp/launch-lsp.icn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,5 +88,6 @@ procedure main(args)
8888
member(opts, mode := "c") | (mode := "s")
8989

9090
ulsp_server := Server(sock, mode)
91+
ulsp_server.connect()
9192
ulsp_server.run()
9293
end

uni/ulsp/server.icn

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,12 @@ class Server(
221221
uri := request_params["textDocument"]["uri"]
222222
file_contents := request_params["contentChanges"][1]["text"]
223223
filehandler_object := openFiles[\uri]
224+
# If file handler doesn't exist, create it (file might have been changed before didOpen)
225+
if /filehandler_object then {
226+
openFiles[\uri] := FileHandler(fname, lsp_database)
227+
filehandler_object := openFiles[\uri]
228+
filehandler_object.setFile()
229+
}
224230
filehandler_object.updateUniDoc(fname, file_contents)
225231
filehandler_object.updateFileHandler()
226232
end
@@ -232,10 +238,19 @@ class Server(
232238
method completion(msg)
233239
local filehandler_object, result
234240
filehandler_object := openFiles[\msg.get_param_uri()]
241+
if /filehandler_object then {
242+
msg.make_error_response(-32602, "Invalid params", "File not open")
243+
jrpc_handler.send_msg(msg)
244+
return
245+
}
235246
completionHandler.setVariables(filehandler_object, msg.get_params())
236-
result := completionHandler.getResult()
237-
msg.make_result_response(result)
238-
jrpc_handler.send_msg(msg)
247+
if result := completionHandler.getResult() then {
248+
msg.make_result_response(result)
249+
jrpc_handler.send_msg(msg)
250+
} else {
251+
msg.make_error_response(-32602, "Invalid params", "Missing required parameter: position")
252+
jrpc_handler.send_msg(msg)
253+
}
239254
end
240255

241256
########################################################
@@ -358,22 +373,20 @@ class Server(
358373
formattingHandler := FormattingHandler()
359374
end
360375

376+
method connect()
377+
local openopt := "n", mstring
361378

362-
initially
363-
local openopt := "n", mstring := "server"
364-
365-
renewSymbols := 1
366-
cacheSymbols := table()
367379
case mode of {
368-
"s" : { openopt ||:= "a" }
369-
"c" : { mstring := "client" }
370-
default: { write("Unknown mode: " || mode) }
380+
"s" : {
381+
openopt ||:= "a"
382+
mstring := "server"
383+
}
384+
"c" : {
385+
mstring := "client"
386+
}
387+
default: { Logger.error("Unknown mode: " || mode) }
371388
}
372389

373-
\Logger | Logger(7) # default to informational
374-
375-
Logger.info("Loading Database...")
376-
loadDB()
377390
Logger.info("Starting Unicon LSP in ", mstring, " mode at ", port)
378391
every 1 to 5 do {
379392
if sock := open(port, openopt) then
@@ -388,4 +401,12 @@ class Server(
388401
Logger.crit("Failed to establish connection on: ", port)
389402
exit(1)
390403
}
404+
end
405+
406+
initially
407+
renewSymbols := 1
408+
cacheSymbols := table()
409+
\Logger | Logger(7) # default to informational
410+
Logger.info("Loading Database...")
411+
loadDB()
391412
end

0 commit comments

Comments
 (0)