From c59edb71a2cea866a7d8db77dfe97da7eaff35a1 Mon Sep 17 00:00:00 2001 From: Andy Bunce Date: Sat, 26 Jul 2025 14:21:07 +0100 Subject: [PATCH] [fix] sending messages --- README.md | 2 ++ webapp/lsp/jsonrpc.xqm | 59 +++++++++++++++++++++++++++++++++++ webapp/lsp/lsp-ws.xqm | 23 +++++++------- webapp/static/ace/esm.html | 41 ++++++++++++++++++++++++ webapp/static/ace/script.js | 2 +- webapp/static/ace/socket.html | 33 ++++++++++++++++++++ 6 files changed, 147 insertions(+), 13 deletions(-) create mode 100644 webapp/lsp/jsonrpc.xqm create mode 100644 webapp/static/ace/esm.html create mode 100644 webapp/static/ace/socket.html diff --git a/README.md b/README.md index 91e1cee..da7886e 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ An attempt to write a language protocol server using BaseX features... * https://github.com/mkslanc/ace-linters https://mkslanc.github.io/ace-linters/ * I needed `set NODE_OPTIONS=--max_old_space_size=8192` for build to complete +* or `node --max-old-space-size=8192 node_modules/webpack-dev-serve +r/bin/webpack-dev-server.js` ## notes Using https://github.com/mkslanc/ace-linters https://mkslanc.github.io/ace-linters/ diff --git a/webapp/lsp/jsonrpc.xqm b/webapp/lsp/jsonrpc.xqm new file mode 100644 index 0000000..729574e --- /dev/null +++ b/webapp/lsp/jsonrpc.xqm @@ -0,0 +1,59 @@ +(:~ + : jsonrpc + : @author andy bunce + :) +module namespace lsprpc = 'lsprpc'; + +declare variable $lsprpc:methods:=map{ + "initialize" : lsprpc:method-initialize#1, + "initialized" : lsprpc:method-unknown#1, + "workspace/didChangeConfiguration" :lsprpc:method-unknown#1, + "textDocument/didOpen": lsprpc:method-unknown#1, + "textDocument/didClose" : lsprpc:method-unknown#1 +}; + +(:~ return map if $msg is jsonrpc else empty :) +declare +function lsprpc:parse($msg as xs:string) +as map(*)? +{ + try { + let $json:=parse-json($msg) + return if($json?jsonrpc="2.0" and exists($json?method)) + then $json + else () + } catch *{ + () + } + +}; + +(:~ send replay to $json :) +declare +function lsprpc:reply($json as map(*)) +as empty-sequence() { + let $method := $json?method + let $f :=$lsprpc:methods?($method) + let $response := $f!.($json) + return if(exists($response)) then ws:send($response=>trace("REPLY: "),ws:id()) +}; + +(:~ canned initialize response :) +declare +function lsprpc:method-initialize($json as map(*)) +as map(*)? +{ + ``[{"jsonrpc":"2.0","id":0, +"result":{"capabilities":{"textDocumentSync":2,"completionProvider":{"resolveProvider":false,"triggerCharacters":["\"",":"]},"hoverProvider":true,"documentSymbolProvider":true,"documentRangeFormattingProvider":false,"colorProvider":{},"foldingRangeProvider":true,"selectionRangeProvider":true,"documentLinkProvider":{}}}}]`` + =>parse-json() +}; + +(:~ unknown method response :) +declare +function lsprpc:method-unknown($json as map(*)) +as map(*)? +{ + let $_:=trace($json?method,"unknown") + return () +}; + diff --git a/webapp/lsp/lsp-ws.xqm b/webapp/lsp/lsp-ws.xqm index fced4e4..6c7812b 100644 --- a/webapp/lsp/lsp-ws.xqm +++ b/webapp/lsp/lsp-ws.xqm @@ -1,9 +1,10 @@ (:~ - : Simple WebSocket chat. WebSocket functions. - : @author BaseX Team, BSD License + : WebSocket LSP + : @author Andy Bunce :) module namespace lsp-ws = 'lsp-ws'; +import module namespace lsprpc = 'lsprpc' at 'jsonrpc.xqm'; import module namespace chat-util = 'chat/util' at 'lsp-util.xqm'; declare @@ -18,9 +19,8 @@ function lsp-ws:error($error) { declare %ws:connect('/lsp') function lsp-ws:connect() as empty-sequence() { - let $_:=ws:id()=>trace("CONNECT2: ") - let $_:=session:get($chat-util:id)=>trace("CONNECTx: ") - return ws:set(ws:id()=>trace("CONNECT: "), $chat-util:id, "session:get($chat-util:id)") + + ws:set(ws:id()=>trace("CONNECT: "), $chat-util:id, "session:get($chat-util:id)") (: ,chat-util:users() :) }; @@ -33,15 +33,14 @@ declare function lsp-ws:message( $message as xs:string ) as empty-sequence() { - let $json := parse-json($message=>trace("MSG ")) - let $type := $json?type - return if($type = 'message') then ( - chat-util:message($json?text, $json?to) - ) else if($type = 'ping') then( - (: do nothing :) - ) else error() + + let $json := lsprpc:parse($message=>trace("MSG ")) + return if(exists($json)) + then lsprpc:reply($json) + else message($message,"bad RPC: ") }; + (:~ : Closes a WebSocket connection. Unregisters the user and notifies all clients. :) diff --git a/webapp/static/ace/esm.html b/webapp/static/ace/esm.html new file mode 100644 index 0000000..1f7ea6d --- /dev/null +++ b/webapp/static/ace/esm.html @@ -0,0 +1,41 @@ + + + + + + + BaseX LSP + + + + +
somethingdba
+
some text
+ + + + + + \ No newline at end of file diff --git a/webapp/static/ace/script.js b/webapp/static/ace/script.js index 36f7201..efd045d 100644 --- a/webapp/static/ace/script.js +++ b/webapp/static/ace/script.js @@ -32,7 +32,7 @@ const serverData = { module: () => import("https://www.unpkg.com/ace-linters@latest/build/language-client"), modes: "json|json5", type: "socket", - socket: new WebSocket("ws://127.0.0.1:3000/exampleServer"), // your websocket server address + socket: new WebSocket("ws://127.0.0.1:3000/ws/lsp"), // your websocket server address } function opts(editor) { diff --git a/webapp/static/ace/socket.html b/webapp/static/ace/socket.html new file mode 100644 index 0000000..8d75280 --- /dev/null +++ b/webapp/static/ace/socket.html @@ -0,0 +1,33 @@ + + + + + + + BaseX LSP + + + + +
Socket dba
+ + + + \ No newline at end of file