basex-lsp/webapp/lsp/docs.xqm
2025-08-04 12:34:23 +01:00

81 lines
No EOL
2 KiB
Text

(: Store for XQuery document data , type, text,uri
on save parse is created and stored
implementation: data is stored in webSocket
@author Andy Bunce
:)
module namespace docs="lsp/docs";
import module namespace p="xq4" at "xq4.xqm";
declare record docs:Position(
(: Line position in a document (zero-based). :)
line as xs:integer,
(: Character offset on a line in a document (zero-based). :)
character as xs:integer
);
(: 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(
$socket as xs:string,
$textDocument as map(*)
)
{
let $text as xs:string:=$textDocument?text
let $uri:=$textDocument?uri
let $files:=ws:get($socket,"files",{})
let $files:=if(map:contains($files,$uri))
then $files
else map:put($files,$uri,{
"textDocument":random:uuid(),
"parse":random:uuid() })
let $keys:=$files($uri)
let $xml:=p:parse-Module($text)
return (
ws:set($socket,"files",$files),
ws:set($socket,$keys?textDocument,$textDocument),
ws:set($socket,$keys?parse,$xml)
)
};
declare function docs:resolvePosition(text as xs:string, pos as docs:Position)
as xs:integer
{
let line = 0, off = 0
while (line < pos.line) {
let next = text.indexOf("\n", off)
if (!next) throw new RangeError("Position out of bounds")
off = next + 1
line++
}
off += pos.character
if (off > string-length($text)) throw new RangeError("Position out of bounds")
return off
}
declare function docs:toPosition($text as xs:string, $pos as xs:integer)
as docs:Position {
for (let off = 0, line = 0;;) {
let next = text.indexOf("\n", off)
if (next < 0 || next >= pos) return {line, character: pos - off}
off = next + 1
line++
}
}