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"; import module namespace pos="lsp/position" at "../position.xqm"; declare variable $syms:actions as hnd:actionMap :={ "ContextValueDecl": syms:action#2, "VarDecl": syms:VarDecl#2, "FunctionDecl": syms:FunctionDecl#2, "ItemTypeDecl": syms:action#2, "NamedRecordTypeDecl": syms:NamedRecordTypeDecl#2 }; declare function syms:list($parse as element(),$text as xs:string) as lspt:DocumentSymbol*{ let $state:= hnd:State((),false(),{"text":$text}) let $state:= hnd:walk($parse,$syms:actions,$state) return $state?result }; (: for testing only:) declare function syms:dummy($parse as element(),$text as xs:string ) as lspt:DocumentSymbol*{ let $fr:=(pos:full-range($text),message("dummy")) (: dummy data :) let $nameRange:=$fr return map:for-each($lspt:SymbolKindMap, fn($k,$v){ lspt:DocumentSymbol($k,$v,$fr,$nameRange,`{$k} v:{$v}`) }) }; (:~ just trace :) declare function syms:action($parse as element(),$state as hnd:State ) as hnd:State{ $state ,message(name($parse),"ACTION: ") }; declare function syms:VarDecl($parse as element(VarDecl),$state as hnd:State ) as hnd:State{ let $name:=syms:localName($parse/VarNameAndType/EQName) let $length:=string($parse)=>string-length() let $range:=pos:range-from-ast($parse/VarNameAndType/EQName,$state?extras?text) let $full-range:=pos:range-from-ast($parse,$state?extras?text) let $sym:=lspt:DocumentSymbol($name,$lspt:SymbolKindMap('Variable'),$range,$full-range,"VAR") return $state =>map:put("result",($state?result,$sym)) =>map:put("skipchildren",true()) }; declare function syms:FunctionDecl($parse as element(FunctionDecl),$state as hnd:State ) as hnd:State{ let $name:=syms:localName($parse/UnreservedFunctionEQName) let $prev:=$state?result[$name eq ?name] let $range:=pos:range-from-ast($parse/UnreservedFunctionEQName,$state?extras?text) let $full-range:=pos:range-from-ast($parse,$state?extras?text) let $sym:=lspt:DocumentSymbol($name,$lspt:SymbolKindMap('Method'),$range,$full-range,"FUN") return $state =>map:put("result",($state?result,$sym)) =>map:put("skipchildren",true()) }; declare function syms:NamedRecordTypeDecl($parse as element(NamedRecordTypeDecl), $state as hnd:State ) as hnd:State{ let $name:=syms:localName($parse/EQName) let $range:=pos:range-from-ast($parse/EQName,$state?extras?text) let $full-range:=pos:range-from-ast($parse,$state?extras?text) let $sym:=lspt:DocumentSymbol($name,$lspt:SymbolKindMap('TypeParameter'),$range,$full-range,"--RECORD") =>trace("RECORD") return $state =>map:put("result",($state?result,$sym)) =>map:put("skipchildren",true()) }; declare function syms:localName($name as xs:string ) as xs:string{ if(starts-with($name,"Q{")) then substring-after($name,"}") else if(contains($name,":")) then substring-after($name,":") else $name };