86 lines
No EOL
2.2 KiB
Text
86 lines
No EOL
2.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";
|
|
|
|
(:~
|
|
@param line Line position in a document (zero-based).
|
|
@param character Character offset on a line in a document (zero-based).
|
|
:)
|
|
declare record docs:Position(
|
|
line as xs:integer,
|
|
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,
|
|
$params as map(*)
|
|
)
|
|
{
|
|
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)
|
|
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)
|
|
)
|
|
};
|
|
|
|
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 :)
|
|
0
|
|
};
|
|
|
|
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++
|
|
} :)
|
|
docs:Position(0,0)
|
|
}; |