126 lines
No EOL
3.3 KiB
Text
126 lines
No EOL
3.3 KiB
Text
(: Store for XQuery document data , type, text,uri
|
|
on save parse is created and stored
|
|
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";
|
|
import module namespace rpc = 'rpc' at 'jsonrpc.xqm';
|
|
import module namespace lsp-diags = 'lsp-diags' at 'lsp-diags.xqm';
|
|
|
|
(: 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
|
|
let $files:=ws:get($socket,"files",{})
|
|
let $files:=if(map:contains($files,$uri))
|
|
then $files
|
|
else
|
|
let $uuid:=random:uuid()
|
|
return map:put($files,$uri,{
|
|
"textDocument": "file-" || $uuid,
|
|
"parse": "parse-" || $uuid })
|
|
let $keys:=$files($uri)
|
|
return (
|
|
ws:set($socket,"files",$files),
|
|
ws:set($socket,$keys?textDocument,$params?textDocument),
|
|
$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(xs:QName("docs:change"), "no file" || $uri)
|
|
|
|
let $ver:=$params?textDocument?version
|
|
let $IGNORE_VER:=true()
|
|
let $text:=if($IGNORE_VER or $ver eq 1+ $file?version)
|
|
then pos:apply-changes($file?text,$params?contentChanges)
|
|
else error(xs:QName("docs:change"),`badver got {$ver} expecting: {1+ $file?version}`)
|
|
|
|
let $file:=$file=>map:put("version",$ver)=>map:put("text",$text)
|
|
|
|
return ( ws:set($socket,$key,$file)
|
|
, $uri)
|
|
|
|
};
|
|
|
|
(:~ close a file :)
|
|
declare function docs:close($socket as xs:string,$uri as xs:string)
|
|
as map(*){
|
|
let $files:=ws:get($socket,"files",{})
|
|
return if(map:contains($files,$uri))
|
|
then let $props:=$files($uri)
|
|
return (
|
|
map:items($props)!ws:delete($socket,.),
|
|
ws:set($socket,"files",map:remove($files,$uri))
|
|
)
|
|
else ()
|
|
};
|
|
|
|
(:~ 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)
|
|
};
|
|
|
|
(: get $property key for $file from session $socket :)
|
|
declare function docs:get(
|
|
$socket as xs:string,
|
|
$file as xs:string,
|
|
$property as docs:Property
|
|
) as item()?
|
|
{
|
|
ws:get($socket,
|
|
docs:key($socket,$file,$property)
|
|
)
|
|
};
|
|
|
|
(:~ generate XML parse, save it and publish diagnostics :)
|
|
declare function docs:parse(
|
|
$socket as xs:string,
|
|
$file as xs:string
|
|
)as map(*)?
|
|
{
|
|
let $text:=docs:get($socket,$file,"textDocument")?text
|
|
let $xml:= p:parse-Module($text)=>prof:time("⏱️ p:parse-Module " || $file)
|
|
return (
|
|
ws:set($socket,docs:key($socket,$file,"parse"),$xml),
|
|
lsp-diags:publish($file, $text, $xml)
|
|
)
|
|
}; |