diff --git a/test/diagnostic.xq b/test/diagnostic.xq index 6056e25..03e98ac 100644 --- a/test/diagnostic.xq +++ b/test/diagnostic.xq @@ -1,4 +1,5 @@ import module namespace hnd="lsp/handlers" at "../webapp/lsp/handlers.xqm"; +import module namespace syms="lsp/symbols" at "../webapp/lsp/providers/documentSymbols.xqm"; declare variable $src:="sample.docs/parse-pdfbox.xml"; declare variable $parse:=doc($src)/*; diff --git a/test/symbols.xq b/test/symbols.xq index 64dc7d1..7491043 100644 --- a/test/symbols.xq +++ b/test/symbols.xq @@ -1,6 +1,6 @@ -import module namespace hnd="lsp/handlers" at "../webapp/lsp/handlers.xqm"; +import module namespace syms="lsp/symbols" at "../webapp/lsp/providers/documentSymbols.xqm"; declare variable $src:="sample.docs/parse-pdfbox.xml"; declare variable $parse:=doc($src)/*; -hnd:symbols($parse ) +syms:list($parse ) diff --git a/webapp/lsp/docs.xqm b/webapp/lsp/docs.xqm index 4234080..9ea5693 100644 --- a/webapp/lsp/docs.xqm +++ b/webapp/lsp/docs.xqm @@ -8,7 +8,7 @@ module namespace docs="lsp/docs"; import module namespace xq4="java:quodatum.parser.xq4"; 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'; +import module namespace lsp-diags = 'lsp-diags' at 'providers/diagnostics.xqm'; (: save $textDocument data as session $socket properties @return uri @@ -120,8 +120,12 @@ declare function docs:parse( { let $text:=docs:get($socket,$file,"textDocument")?text let $xml:= xq4:parseModule($text)=>prof:time("⏱️ p:parse-Module " || $file) + let $diags:=lsp-diags:list($file, $text, $xml)=>prof:time("⏱️ diags " || $file) return ( ws:set($socket,docs:key($socket,$file,"parse"),$xml), - lsp-diags:publish($file, $text, $xml) + {"jsonrpc": "2.0", + "method":"textDocument/publishDiagnostics", + "params":{"uri": $file, "diagnostics": array{$diags}} +} ) }; \ No newline at end of file diff --git a/webapp/lsp/documentSymbols.xqm b/webapp/lsp/documentSymbols.xqm deleted file mode 100644 index a298313..0000000 --- a/webapp/lsp/documentSymbols.xqm +++ /dev/null @@ -1,14 +0,0 @@ -xquery version '4.0'; -(:~ Symbols from XQuery source file :) -module namespace syms="lsp/symbols"; - -import module namespace lspt = 'lsp-typedefs' at "lsp-typedefs.xqm"; -import module namespace pos="lsp/position" at "position.xqm"; - -(:~ symbols :) -declare function syms:list() -as map(*){ - -}; - - diff --git a/webapp/lsp/handlers.xqm b/webapp/lsp/handlers.xqm index be56188..a45e99b 100644 --- a/webapp/lsp/handlers.xqm +++ b/webapp/lsp/handlers.xqm @@ -2,37 +2,20 @@ @author Andy Bunce :) module namespace hnd="lsp/handlers"; -import module namespace lspt = 'lsp-typedefs' at "lsp-typedefs.xqm"; +(:~ structure returned by tree walkers :) declare record hnd:Result( result as item()*, skipchildren? as xs:boolean:=false() ); +declare type hnd:actionFn as fn($parse as element(),$state as hnd:Result ) as hnd:Result; -declare function hnd:handle($el as element(*),$state) -{ - let $f:= function-lookup(xs:QName(name($el)=>trace("SSS")),2) - otherwise fn($el,$state){hnd:Result($state,false())} - return $f($el,$state) -}; - -declare function hnd:diags($parse as element(),$diags:=()) -{ - let $_:=trace((name($parse),$diags),"diags") - let $walk:= hnd:handle($parse,$diags) - - return if($walk?skipchildren) - then $walk?result - else fold-left($parse/*,$diags, - fn($r,$this){ - hnd:diags($this,$r) - }) -}; - +declare type hnd:actionMap as map(xs:string,hnd:actionFn) +; declare function hnd:walk($parse as element(), - $actions as map(*), + $actions as hnd:actionMap, $state as hnd:Result ) as hnd:Result{ @@ -51,37 +34,3 @@ as hnd:Result{ -declare function hnd:symbols($parse as element(),$syms as lspt:DocumentSymbol* :=() ) -{ - let $actions:={ - "ContextValueDecl": hnd:action#2, - "VarDecl": hnd:VarDecl#2, - "FunctionDecl": hnd:FunctionDecl#2, - "ItemTypeDecl": hnd:action#2, - "NamedRecordTypeDecl": hnd:action#2 - } - let $state:= hnd:Result(()) - let $result:= hnd:walk($parse,$actions,$state) - return $result?result -}; - -declare function hnd:action($parse as element(),$state as hnd:Result ) -as hnd:Result{ - hnd:Result($state?result,true()) ,message(name($parse),"ACTION: ") -}; - -declare function hnd:VarDecl($parse as element(VarDecl),$state as hnd:Result ) -as hnd:Result{ - let $name:=$parse/VarNameAndType/EQName - let $range:=lspt:Range(lspt:Position(0,0),lspt:Position(0,3)) - let $sym:=lspt:DocumentSymbol($name,$lspt:SymbolKindMap('Variable'),$range,$range,"TODO") - return ($state?result,$sym)=>hnd:Result(true()) -}; - -declare function hnd:FunctionDecl($parse as element(FunctionDecl),$state as hnd:Result ) -as hnd:Result{ - let $name:=$parse/UnreservedFunctionEQName - let $range:=lspt:Range(lspt:Position(0,0),lspt:Position(0,3)) - let $sym:=lspt:DocumentSymbol($name,$lspt:SymbolKindMap('Method'),$range,$range,"TODO") - return ($state?result,$sym)=>hnd:Result(true()) -}; diff --git a/webapp/lsp/lsp-text.xqm b/webapp/lsp/lsp-text.xqm index 1b2a131..5ba7d30 100644 --- a/webapp/lsp/lsp-text.xqm +++ b/webapp/lsp/lsp-text.xqm @@ -19,7 +19,7 @@ declare variable $lsp-text:methods:=map{ "textDocument/documentSymbol" : lsp-text:symbols#1 }; -declare variable lsp-text:word-reg:="[A-Z]|_|[a-z]|[À-Ö]|[Ø-ö]|[ø-˿]|[Ͱ-ͽ]|[Ϳ-῿]|[‌-‍]|[⁰-↏]|[Ⰰ-⿯]|[、-퟿]|[豈-﷏]|[ﷰ-�]"; +declare variable $lsp-text:word-reg:="[A-Z]|_|[a-z]|[À-Ö]|[Ø-ö]|[ø-˿]|[Ͱ-ͽ]|[Ϳ-῿]|[‌-‍]|[⁰-↏]|[Ⰰ-⿯]|[、-퟿]|[豈-﷏]|[ﷰ-�]"; (:~ hover :) declare diff --git a/webapp/lsp/lsp-diags.xqm b/webapp/lsp/providers/diagnostics.xqm similarity index 85% rename from webapp/lsp/lsp-diags.xqm rename to webapp/lsp/providers/diagnostics.xqm index 26d3e3b..40061bd 100644 --- a/webapp/lsp/lsp-diags.xqm +++ b/webapp/lsp/providers/diagnostics.xqm @@ -9,28 +9,21 @@ message: string The message associated with this diagnostic. renderMessage⁠?: fn(view: EditorView) → Node An optional custom rendering function that displays the message as a DOM node. actions⁠?: readonly Action[] An optional array of actions that can be taken on this diagnostic. :) -import module namespace lspt = 'lsp-typedefs' at "lsp-typedefs.xqm"; -import module namespace pos="lsp/position" at "position.xqm"; +import module namespace lspt = 'lsp-typedefs' at "../lsp-typedefs.xqm"; +import module namespace pos="lsp/position" at "../position.xqm"; declare type lsp-diags:ParseResult as element(Module|ERROR); - - - -declare function lsp-diags:publish( +declare function lsp-diags:list( $uri as xs:string, $text as xs:string, $xml as lsp-diags:ParseResult) -as map(*){ +as map(*)*{ - let $diagnostics:=if($xml/self::ERROR) - then array{lsp-diags:parse-error($text, $xml)} - else array{ lsp-diags:parse-xquery($text,$xml)} + if($xml/self::ERROR) + then lsp-diags:parse-error($text, $xml) + else lsp-diags:parse-xquery($text,$xml) - return {"jsonrpc": "2.0", - "method":"textDocument/publishDiagnostics", - "params":{"uri": $uri, "diagnostics": $diagnostics} -} }; (:~ diff --git a/webapp/lsp/providers/documentSymbols.xqm b/webapp/lsp/providers/documentSymbols.xqm new file mode 100644 index 0000000..96eca9f --- /dev/null +++ b/webapp/lsp/providers/documentSymbols.xqm @@ -0,0 +1,44 @@ +xquery version '4.0'; +(:~ Symbols from walking the parse tree :) +module namespace syms="lsp/symbols"; +import module namespace hnd="lsp/handlers" at "../handlers.xqm"; +import module namespace lspt = 'lsp-typedefs' at "../lsp-typedefs.xqm"; + +declare function syms:list($parse as element(),$syms as lspt:DocumentSymbol* :=() ) +{ + let $actions as hnd:actionMap :={ + "ContextValueDecl": syms:action#2, + "VarDecl": syms:VarDecl#2, + "FunctionDecl": syms:FunctionDecl#2, + "ItemTypeDecl": syms:action#2, + "NamedRecordTypeDecl": syms:action#2 + } + let $state:= hnd:Result(()) + let $result:= hnd:walk($parse,$actions,$state) + return $result?result +}; + +declare function syms:action($parse as element(),$state as hnd:Result ) +as hnd:Result{ + hnd:Result($state?result,true()) ,message(name($parse),"ACTION: ") +}; + +declare function syms:VarDecl($parse as element(VarDecl),$state as hnd:Result ) +as hnd:Result{ + let $name:=$parse/VarNameAndType/EQName + let $length:=string($parse)=>string-length() + let $range:=lspt:Range(lspt:Position(0,0),lspt:Position(0,3)) + let $sym:=lspt:DocumentSymbol($name,$lspt:SymbolKindMap('Variable'),$range,$range,"TODO") + return ($state?result,$sym)=>hnd:Result(true()) +}; + +declare function syms:FunctionDecl($parse as element(FunctionDecl),$state as hnd:Result ) +as hnd:Result{ + let $name:=$parse/UnreservedFunctionEQName + let $range:=lspt:Range(lspt:Position(0,0),lspt:Position(0,3)) + let $sym:=lspt:DocumentSymbol($name,$lspt:SymbolKindMap('Method'),$range,$range,"TODO") + return ($state?result,$sym)=>hnd:Result(true()) +}; + + +