[mod] improve logging
This commit is contained in:
parent
279b1ee189
commit
00aed821e1
12 changed files with 89 additions and 48 deletions
12
README.md
12
README.md
|
@ -1,12 +1,14 @@
|
|||
Work in progress.
|
||||
|
||||
An attempt to write a [Language Server Protocol](https://en.wikipedia.org/wiki/Language_Server_Protocol) server for and in XQuery 4.0. It uses the [BaseX websocket](https://docs.basex.org/main/WebSockets) feature.
|
||||
An attempt to write a [Language Server Protocol](https://en.wikipedia.org/wiki/Language_Server_Protocol) server for and in XQuery 4.0. It tracks the draft specifications at https://qt4cg.org/
|
||||
It written for BaseX 12.0 and uses the [BaseX websocket](https://docs.basex.org/main/WebSockets) feature.
|
||||
|
||||
# Demo
|
||||
1. Requires `Docker` or `Podman` on the local machine.
|
||||
2. Clone this repo
|
||||
3. Run `docker compose up -d` The LSP server shall now running on port 3000 (edit `compose.yaml` to change port)
|
||||
4. In a browser navigate to `http://localhost:3000/static/clients/codemirror/` to see the CodeMirror 6 demo.
|
||||
The demos expect `Docker` or `Podman` on the local machine. This is only a requirement for the demos.
|
||||
|
||||
1 Clone this repo
|
||||
2. Run `docker compose up -d` The LSP server shall now running on port 3000 (edit `compose.yaml` to change port)
|
||||
3. In a browser navigate to `http://localhost:3000/static/clients/codemirror/` to see the CodeMirror 6 demo.
|
||||
|
||||
In principle, the LSP can be used in any environment that can make use of a LSP server accessed via a websocket.
|
||||
## LSP Server
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
xquery version '4.0';
|
||||
(:~ Symbols from XQuery source file :)
|
||||
module namespace syms="lsp/symbols";
|
||||
|
||||
import module namespace lspt = 'lsp-typedefs' at "lsp-typedefs.xqm";
|
||||
import module namespace pos="lsp/position" at "position.xqm";
|
||||
|
||||
(:~ symbols :)
|
||||
declare function syms:list()
|
||||
as map(*){
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -39,9 +39,17 @@ as map(*)?
|
|||
declare
|
||||
function rpc:reply($json as map(*))
|
||||
as empty-sequence() {
|
||||
let $f :=$rpc:Methods?($json?method)
|
||||
let $f :=(void(trace($json,"➡️")),$rpc:Methods?($json?method))
|
||||
let $response := $f!.($json)
|
||||
return $response!ws:send(.=>trace("REPLY: "),ws:id())
|
||||
return $response!rpc:send(.)
|
||||
};
|
||||
|
||||
(:~ send with logging :)
|
||||
declare
|
||||
function rpc:send($msg as map(*))
|
||||
as empty-sequence()
|
||||
{
|
||||
ws:send($msg =>trace("⬅️"),ws:id())
|
||||
};
|
||||
|
||||
(:~ canned initialize response :)
|
||||
|
@ -59,6 +67,7 @@ function rpc:method-initialized($json as map(*))
|
|||
as empty-sequence()
|
||||
{
|
||||
ws:set(ws:id(),"initialized", true())
|
||||
(: ,rpc:later(5000,"rpc:show-message","This is a test async message 5secs after initialized",ws:id()) :)
|
||||
};
|
||||
|
||||
(:~ unknown method response :)
|
||||
|
@ -105,4 +114,31 @@ declare function rpc:error($message as xs:string,$json as map(*))
|
|||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
(:~ window/showMessage :)
|
||||
declare function rpc:show-message($msg as xs:string)
|
||||
as map(*)
|
||||
{
|
||||
{"jsonrpc": "2.0",
|
||||
"method":"window/showMessage",
|
||||
"params":{"type":3, "message": $msg}
|
||||
}
|
||||
};
|
||||
|
||||
(:~ send message after delay :)
|
||||
declare function rpc:later($msdelay as xs:integer,$fn as xs:string ,$arg, $wsid as xs:string)
|
||||
{
|
||||
let $xq:=`import module namespace rpc = 'rpc' at 'jsonrpc.xqm';
|
||||
declare variable $msdelay external;
|
||||
declare variable $fn external;
|
||||
declare variable $arg external;
|
||||
declare variable $wsid external;
|
||||
|
||||
prof:sleep($msdelay),
|
||||
ws:send(function-lookup(xs:QName($fn),1)($arg),$wsid)
|
||||
`
|
||||
let $bindings:={"msdelay": $msdelay,"wsid": $wsid, "fn": $fn,"arg":$arg}
|
||||
let $opts:={"cache": true(),"base-uri": static-base-uri()}
|
||||
return job:eval($xq, $bindings,$opts)=>void()
|
||||
};
|
2
webapp/lsp/later.xq
Normal file
2
webapp/lsp/later.xq
Normal file
|
@ -0,0 +1,2 @@
|
|||
import module namespace rpc = 'rpc' at 'jsonrpc.xqm';
|
||||
rpc:later(1000,"rpc:show-message","Hello","sock")
|
|
@ -1,10 +1,5 @@
|
|||
module namespace lsp-diags = 'lsp-diags';
|
||||
|
||||
import module namespace lspt = 'lsp-typedefs' at "lsp-typedefs.xqm";
|
||||
import module namespace pos="lsp/position" at "position.xqm";
|
||||
|
||||
declare type lsp-diags:ParseResult as element(Module|ERROR);
|
||||
(:~
|
||||
(:~ codemirror
|
||||
from: number The start position of the relevant text.
|
||||
to: number The end position. May be equal to from, though actually covering text is preferable.
|
||||
severity: "error" | "hint" | "info" | "warning" The severity of the problem. This will influence how it is displayed.
|
||||
|
@ -13,21 +8,14 @@ source?: string An optional source string indicating where the diagnostic is
|
|||
message: string The message associated with this diagnostic.
|
||||
renderMessage?: fn(view: EditorView) → Node An optional custom rendering function that displays the message as a DOM node.
|
||||
actions?: readonly Action[] An optional array of actions that can be taken on this diagnostic.
|
||||
:)
|
||||
declare record lsp-diags:nostic(
|
||||
range as lspt:Range,
|
||||
severity as xs:integer, (: enum('error', 'hint', 'info', 'warning') :)
|
||||
message as xs:string,
|
||||
code? as xs:string,
|
||||
source as xs:string:="xquery"
|
||||
);
|
||||
:)
|
||||
import module namespace lspt = 'lsp-typedefs' at "lsp-typedefs.xqm";
|
||||
import module namespace pos="lsp/position" at "position.xqm";
|
||||
|
||||
declare type lsp-diags:ParseResult as element(Module|ERROR);
|
||||
|
||||
|
||||
|
||||
declare variable $lsp-diags:severities:={
|
||||
'error':1,
|
||||
'hint':4,
|
||||
'info':3,
|
||||
'warning':2
|
||||
};
|
||||
|
||||
declare function lsp-diags:publish(
|
||||
$uri as xs:string,
|
||||
|
@ -60,7 +48,7 @@ as map(*)*{
|
|||
let $e:= number($xml/@e)-1
|
||||
return (
|
||||
(: mark error :)
|
||||
lsp-diags:nostic(lspt:Range(pos:toPosition($text, $b),
|
||||
lspt:diagnostic(lspt:Range(pos:toPosition($text, $b),
|
||||
pos:toPosition($text, $e)),
|
||||
1,
|
||||
$dmesg,'XPST0003'),
|
||||
|
@ -68,7 +56,7 @@ as map(*)*{
|
|||
(:mark after error:)
|
||||
if($e ge string-length($text))
|
||||
then ()
|
||||
else lsp-diags:nostic(lspt:Range(pos:toPosition($text, $e +1 ),
|
||||
else lspt:diagnostic(lspt:Range(pos:toPosition($text, $e +1 ),
|
||||
pos:toPosition($text, $last)),
|
||||
2,
|
||||
"Unparsed due to previous parser error.",
|
||||
|
|
|
@ -23,13 +23,8 @@ function lsp-text:hover($json as map(*))
|
|||
as map(*)
|
||||
{
|
||||
let $r:= [
|
||||
`markdown here, this is **bold**.
|
||||
|
||||
A [link](http://google.com)
|
||||
|
||||
The last line.`
|
||||
,
|
||||
`A hover at { pos:ln-col($json?params?position) } uri: {$json?params?textDocument?uri} `
|
||||
`At { pos:ln-col($json?params?position) }, uri: {$json?params?textDocument?uri},
|
||||
[path](https://quodatum.github.io/basex-xqparse/i-BaseX.xhtml#EQName)`
|
||||
]
|
||||
return rpc:result({"contents":$r},$json)
|
||||
};
|
||||
|
|
|
@ -94,4 +94,19 @@ declare variable $lspt:SymbolKindMap :={
|
|||
'TypeParameter': 26
|
||||
};
|
||||
|
||||
declare variable $lspt:DiagnosticSeverityKinds:={
|
||||
'error':1,
|
||||
'warning':2,
|
||||
'info':3,
|
||||
'hint':4
|
||||
};
|
||||
|
||||
declare record lspt:diagnostic(
|
||||
range as lspt:Range,
|
||||
severity as xs:integer, (: enum('error', 'hint', 'info', 'warning') :)
|
||||
message as xs:string,
|
||||
code? as xs:string,
|
||||
source as xs:string:="xquery"
|
||||
);
|
||||
|
||||
declare type lspt:TraceValue as enum( 'off' , 'messages' , 'verbose');
|
||||
|
|
|
@ -13,9 +13,7 @@ function lsp-ws:error($error) {
|
|||
trace($error,"ERR ")
|
||||
};
|
||||
|
||||
(:~
|
||||
: Creates a WebSocket connection. Registers the user and notifies all clients.
|
||||
:)
|
||||
(:~ Creates a WebSocket connection. :)
|
||||
declare
|
||||
%ws:connect('/lsp')
|
||||
function lsp-ws:connect() as empty-sequence() {
|
||||
|
|
|
@ -14,6 +14,7 @@ as lspt:num
|
|||
let $off:=if($pos?line eq 0)
|
||||
then 0
|
||||
else $nl[$pos?line]
|
||||
let $_:=substring($text,$off+1,1)=>string-to-codepoints()=>trace("LF? ")
|
||||
return $off+$pos?character
|
||||
};
|
||||
|
||||
|
@ -22,7 +23,7 @@ declare function pos:toPosition($text as xs:string,
|
|||
$index as lspt:num
|
||||
)
|
||||
as lspt:Position {
|
||||
let $nl:= if($index=>trace("IN ") gt string-length($text)=>trace("L "))
|
||||
let $nl:= if($index gt string-length($text))
|
||||
then error(xs:QName("pos:range"),`out of range: index={$index},length={string-length($text)}`)
|
||||
else index-of(string-to-codepoints($text),10)
|
||||
let $line:=pos:lineAt($nl,$index)
|
||||
|
|
|
@ -22,19 +22,16 @@ body {
|
|||
grid-template-rows: min-content min-content 1fr min-content;
|
||||
gap: 1px;
|
||||
|
||||
* {
|
||||
padding: 0px 0px;
|
||||
}
|
||||
|
||||
.nav-item{
|
||||
padding: 0px 9px;
|
||||
margin: 0px 3px;
|
||||
.navbar * {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
/* Set editor dimensions */
|
||||
#editor {
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
height:80cqh;
|
||||
height:75cqh;
|
||||
}
|
||||
|
||||
/* Stretch editor to fit inside its containing div */
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue