diff --git a/docs/explore.xqbk b/docs/explore.xqbk index a52f381..6df7eae 100644 --- a/docs/explore.xqbk +++ b/docs/explore.xqbk @@ -1 +1 @@ -{"cells":[{"kind":2,"language":"xquery","value":"(:<:)\r\n\r\nimport module namespace docs=\"lsp/docs\" at \"/srv/basex/webapp/lsp/docs.xqm\";"},{"kind":2,"language":"xquery","value":"ws:ids()"},{"kind":2,"language":"xquery","value":"let $f:=docs:list(ws:ids())[1]\r\nreturn docs:get(ws:ids(),$f,\"parse\")"}]} \ No newline at end of file +{"cells":[{"kind":2,"language":"xquery","value":"(:<:)\r\n\r\nimport module namespace docs=\"lsp/docs\" at \"/srv/basex/webapp/lsp/docs.xqm\";"},{"kind":2,"language":"xquery","value":"ws:ids()"},{"kind":2,"language":"xquery","value":"let $sock:=foot(ws:ids())\r\nlet $f:=docs:list($sock)\r\nreturn docs:get($sock,$f,\"textDocument\")"}]} \ No newline at end of file diff --git a/webapp/lsp/docs.xqm b/webapp/lsp/docs.xqm index ff334cc..4d1aafe 100644 --- a/webapp/lsp/docs.xqm +++ b/webapp/lsp/docs.xqm @@ -1,35 +1,19 @@ (: Store for XQuery document data , type, text,uri on save parse is created and stored - implementation: data is stored in webSocket + data is stored in webSocket attributes @author Andy Bunce :) module namespace docs="lsp/docs"; import module namespace p="xq4" at "xq4.xqm"; import module namespace pos="lsp/position" at "position.xqm"; - -(: document info :) -declare type docs:property as enum( - "textDocument", - "parse" -); - -(: get $property for $file from session $socket :) -declare function docs:get( - $socket as xs:string, - $file as xs:string, - $property as docs:property -) -{ - let $key:=ws:get($socket,"files")($file)($property) - return ws:get($socket,$key) -}; - -(: save $textDocument data as session $socket properties :) -declare function docs:save( +(: save $textDocument data as session $socket properties +@return uri +:) +declare function docs:open( $socket as xs:string, $params as map(*) -) +) as xs:string { let $text as xs:string:=$params?textDocument?text let $uri:=$params?textDocument?uri @@ -42,13 +26,35 @@ let $files:=if(map:contains($files,$uri)) "textDocument": "file-" || $uuid, "parse": "parse-" || $uuid }) let $keys:=$files($uri) -let $xml:=prof:time(p:parse-Module($text),"⏱️ p:parse-Module ") - return ( ws:set($socket,"files",$files), ws:set($socket,$keys?textDocument,$params?textDocument), - ws:set($socket,$keys?parse,$xml) -) + $uri + ) +}; + +(: change $textDocument data as session $socket properties +@return uri +:) +declare function docs:change( + $socket as xs:string, + $params as map(*) +) as xs:string +{ +let $uri:=$params?textDocument?uri +let $key:=docs:key($socket,$uri,"textDocument") +let $file:=if(exists($key)) + then ws:get($socket,$key) + else error("no file") +let $ver:=$params?textDocument?version +let $text:=if($ver eq 1+ $file?version) + then pos:apply-changes($file?text,$params?contentChanges) + else error("bad ver") +let $file:=$file=>map:put("version",$ver)=>map:put("text",$text) + +return (ws:set($socket,$key,$file), + `{$uri} V{ $ver} text: { $text}` + ) }; (:~ close a file :) @@ -63,9 +69,27 @@ return if(map:contains($files,$uri)) ) else () }; -(:~ list a file :) + +(:~ list of all files :) declare function docs:list($socket as xs:string) as xs:string*{ ws:get($socket,"files",{})=>map:keys() +}; + +(: document info :) +declare type docs:property as enum( + "textDocument", + "parse" +); + +(: get $property key for $file from session $socket :) +declare function docs:key( + $socket as xs:string, + $file as xs:string, + $property as docs:property +) as xs:string? +{ + ws:get($socket,"files")($file)($property) + }; \ No newline at end of file diff --git a/webapp/lsp/lsp-text.xqm b/webapp/lsp/lsp-text.xqm index c116246..1cb29fe 100644 --- a/webapp/lsp/lsp-text.xqm +++ b/webapp/lsp/lsp-text.xqm @@ -2,7 +2,7 @@ : @author andy bunce :) module namespace lsp-text = 'lsp-text'; - +import module namespace docs="lsp/docs" at "docs.xqm"; declare variable $lsp-text:methods:=map{ "textDocument/didOpen": lsp-text:didOpen#1, @@ -55,13 +55,23 @@ declare function lsp-text:didOpen($json as map(*)) as empty-sequence() { + let $uri:=docs:open(ws:id(),$json?params)=>prof:time("⏱️ doc:save ") + + (: + let $xml:=prof:time(p:parse-Module($text),"⏱️ p:parse-Module ") let $x:=job:eval(xs:anyURI("parse.xq"), {"params" : $json?params, "webSocket":ws:id()}, { 'cache': true() } ) - - return () + :) + return ws:send( + {"jsonrpc": "2.0", + "method":"window/logMessage", + "params":{"type":1,"message":"saved " || $uri} + }, + ws:id() +) }; (:~ didChange method response :) @@ -69,13 +79,15 @@ declare function lsp-text:didChange($json as map(*)) as map(*)? { - - let $x:=job:eval(xs:anyURI("parse.xq"), - {"params": $json?params,"webSocket":ws:id()}, - { 'cache': true() } - ) + let $msg:=docs:change(ws:id(),$json?params)=>prof:time("⏱️ doc:change ") - return () + return ws:send( + {"jsonrpc": "2.0", + "method":"window/logMessage", + "params":{"type":1,"message":"changed " || $msg} + }, + ws:id() +) }; diff --git a/webapp/lsp/parse.xq b/webapp/lsp/parse.xq index 9dc8ce4..3fa7eb1 100644 --- a/webapp/lsp/parse.xq +++ b/webapp/lsp/parse.xq @@ -5,7 +5,7 @@ import module namespace docs="lsp/docs" at "docs.xqm"; declare variable $params as map(*) external; declare variable $webSocket as xs:string external; -docs:save( +docs:open( $webSocket, $params )=>prof:time("⏱️ doc:save "),