[mod] clean up tree walk

This commit is contained in:
Andy Bunce 2025-10-04 16:34:02 +01:00
parent 3465a751bb
commit e38385b593
8 changed files with 66 additions and 89 deletions

View file

@ -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)/*;

View file

@ -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 )

View file

@ -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}}
}
)
};

View file

@ -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(*){
};

View file

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

View file

@ -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]|[À-Ö]|[Ø-ö]|[ø-˿]|[Ͱ-ͽ]|[Ϳ-῿]|[-]|[⁰-↏]|[Ⰰ-⿯]|[、-퟿]|[豈-﷏]|[ﷰ-<2D>]";
declare variable $lsp-text:word-reg:="[A-Z]|_|[a-z]|[À-Ö]|[Ø-ö]|[ø-˿]|[Ͱ-ͽ]|[Ϳ-῿]|[-]|[⁰-↏]|[Ⰰ-⿯]|[、-퟿]|[豈-﷏]|[ﷰ-<2D>]";
(:~ hover :)
declare

View file

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

View file

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