Skip to content

Commit

Permalink
Merge pull request #489 from Jafaral/jrpc
Browse files Browse the repository at this point in the history
ulsp: add a json rpc lib, including  a jrpc test
  • Loading branch information
Don-Ward authored Nov 10, 2024
2 parents 87d5de3 + 127790e commit c90c3be
Show file tree
Hide file tree
Showing 8 changed files with 474 additions and 149 deletions.
11 changes: 7 additions & 4 deletions uni/ulsp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,25 @@ UFLAGS=-s -u
prog=ulsp

SRC=launch-lsp.icn workspace.icn database.icn server.icn completion.icn signature.icn hover.icn \
definition.icn logger.icn
OBJ=launch-lsp.u workspace.u database.u server.u completion.u signature.u hover.u definition.u logger.u
definition.icn jsonrpc.icn logger.icn
OBJ=launch-lsp.u workspace.u database.u server.u completion.u signature.u hover.u definition.u \
jsonrpc.u logger.u

export IPATH=$(UNI)/unidoc

.PHONY: all

all: $(prog)

$(prog): $(OBJ)
$(UC) -o $(prog) $(OBJ)
$(CP) $(prog)$(EXE) ../../bin

jsonrpc-test: jsonrpc-test.u jsonrpc.u
$(UC) -o jsonrpc-test jsonrpc-test.u jsonrpc.u

launch-lsp.u:launch-lsp.icn workspace.u database.u server.u completion.u signature.u hover.u definition.u

server.u:server.icn database.u completion.u workspace.u signature.u hover.u definition.u logger.u
server.u:server.icn database.u completion.u workspace.u signature.u hover.u definition.u jsonrpc.u logger.u
hover.u:hover.icn signature.u
definition.u: definition.icn hover.u

Expand Down
3 changes: 1 addition & 2 deletions uni/ulsp/completion.icn
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ class CompletionHandler(
}
}

results := tojson(results_table)
return results
return results_table
end

method addBuiltInFunctionsCompletionItems(results_table)
Expand Down
6 changes: 3 additions & 3 deletions uni/ulsp/definition.icn
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ class DefinitionHandler(
signatureHandler.handleNewSignature(context)

possibleItems := signatureHandler.getCurrentSigItems()
\possibleItems | return tojson(results_table)
member(item := possibleItems[1], "source") | return tojson(results_table)
\possibleItems | return results_table
member(item := possibleItems[1], "source") | return results_table

if source := open(item["source"]) then {
every line := !source do {
Expand All @@ -58,6 +58,6 @@ class DefinitionHandler(
results_table["uri"] := item["source"]
results_table["range"] := ["start":["line":i;"character":startPos];"end":["line":i;"character":endPos]]

return tojson(results_table)
return results_table
end
end
6 changes: 3 additions & 3 deletions uni/ulsp/hover.icn
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ class HoverHandler(
signatureHandler := SignatureHandler()
signatureHandler.setVariables(workspace)

hover_item := \getHoverItem(desired_line, character) | return tojson(results_table)
_context := \getContext(context) | return tojson(results_table)
hover_item := \getHoverItem(desired_line, character) | return results_table
_context := \getContext(context) | return results_table

if _context == "function" | _context == "built-in-function" | _context == "method" |
_context == "procedure" | _context == "constructor" then {
Expand All @@ -48,7 +48,7 @@ class HoverHandler(
results_table["contents"] := table("kind", "markdown", "value", "(_" || _context || "_) " || hover_item )
}

return tojson(results_table)
return results_table
end

method getContext(context)
Expand Down
107 changes: 107 additions & 0 deletions uni/ulsp/jsonrpc-test.icn
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import ulsp

global work_items

#############################
# JRPC server Calculator
#############################
class JRPC_Calc(jrpc_server)

method start(addr)
local sock, msg
if not (jrpc_server := JRPC_HTTPSocket(addr,"n")) then
write("server open(",addr,") ERROR: ", \&errortext | "Unknown") & fail

repeat {
msg := jrpc_server.get_msg() | next
case msg.get_kind() of {
"request" : thread handle_request(msg)
default:
write("jrpc:msg: " || msg.get_kind(), image(msg.get_content()))
}
}
end

method handle_request(msg)
local id := msg.get_id(),
x := integer(msg.get_params()[1]),
y := integer(msg.get_params()[2])

# uncomment to trigger some test failures
#if x = 9 then fail
case msg.get_method() of {
"+" : {jrpc_server.send_msg(msg.make_result_response(x + y))}
"-" : jrpc_server.send_msg(msg.make_result_response(x - y))
"*" : jrpc_server.send_msg(msg.make_result_response(x * y))
"/" : jrpc_server.send_msg(msg.make_result_response(x / y))
default: write("jrpc:request:unsupported: ", msg.get_method())
}

end
end

###############################
# client
###############################
class JRPC_client(jrpc_client)

method listen(addr)
if not (jrpc_client := JRPC_HTTPSocket(addr,"na")) then
stop("client open(", addr, ") ERROR: ", \&errortext | "Unknown")
end

method test(op, params, answer)
local id
static idx := 0, mtx := mutex()
critical mtx: id := idx +:=1
jrpc_client.send_msg(JRPC_Message().make_request(id, op, params))
work_items[id] := [op, params, answer]
end

method start()
local x := ?9, y := ?8+1
test("+", [x, y], x+y)
test("-", [x, y], x-y)
test("*", [x, y], x*y)
test("/", [x, y], x/y)
end

end

global port
procedure main()
local calc, client, jobset, addr, id, op, x, y, answer,
workers, i, response, job

addr := ":" || 5000 + ?1000
if &features == ("MacOS" | "MS Windows NT") then
addr := "127.0.0.1" || addr

client := JRPC_client()
calc := JRPC_Calc()
thread calc.start(addr)
client.listen(addr)
workers:=[]
work_items := mutex(table())
every !10 do put(workers, thread client.start())
every wait(!workers)
jobset:=set()
every insert(jobset, !*work_items)

every i := !(*work_items*2) do {
if *jobset = 0 then break
if response := client.jrpc_client.get_msg(100) then {
delete(jobset, id:=response.get_id())
job := work_items[id]
op:=job[1]; x:=job[2][1]; y:=job[2][2]; answer := job[3]
write(left(id, 2), ": ", x, " ", op, " ", y, " = ", right(response.get_result(), 3),
" ", if response.get_result()=answer then "Pass" else "Fail")
}
}

every job := work_items[id:=!jobset] do {
op:=job[1]; x:=job[2][1]; y:=job[2][2]
write(left(id, 2), ": ", x, " ", op, " ", y, " = Failed to get a response")
}

end
Loading

0 comments on commit c90c3be

Please sign in to comment.