(: 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) };