[mod] commit
This commit is contained in:
parent
30f913906d
commit
2d0ae19026
8 changed files with 128 additions and 23 deletions
24
test/ast.xq
24
test/ast.xq
|
|
@ -1,10 +1,20 @@
|
||||||
import module namespace syms="lsp/symbols" at "../webapp/lsp/ast/ast.xqm";
|
import module namespace ast="lsp/ast" at "../webapp/lsp/ast/ast.xqm";
|
||||||
|
|
||||||
declare $file:="C:\Users\mrwhe\git\quodatum\basex-lsp\test\sample.docs\pdfbox.xqm";
|
(: declare variable $file:="sample.docs/pdfbox.xqm"; :)
|
||||||
|
declare variable $file:="sample.docs/simple.xq";
|
||||||
|
|
||||||
declare variable $A:=doc("C:\Users\mrwhe\git\quodatum\basex-lsp\test\sample.docs\parse-pdfbox.xml");
|
declare variable $A:=doc("sample.docs/parse-pdfbox.xml");
|
||||||
$A update{
|
|
||||||
for $e in .//element()
|
|
||||||
|
unparsed-text($file)
|
||||||
|
|
||||||
|
=>ast:build()
|
||||||
|
|
||||||
|
update{
|
||||||
|
for $e in descendant-or-self::element()
|
||||||
let $len:=string-length($e)
|
let $len:=string-length($e)
|
||||||
return insert node attribute len { $len } into $e
|
let $before:=$e/preceding-sibling::node()/string-length()=>sum()
|
||||||
}
|
return (insert node attribute len { $len } into $e,
|
||||||
|
insert node attribute before { $before } into $e
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
||||||
6
test/sample.docs/simple.xq
Normal file
6
test/sample.docs/simple.xq
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
(: simple parse test :)
|
||||||
|
declare function local:print($src as xs:string, $dest as xs:string)
|
||||||
|
{
|
||||||
|
concat($src,"->", $dest)
|
||||||
|
};
|
||||||
|
local:print("sss","bbb")
|
||||||
|
|
@ -5,14 +5,23 @@ module namespace ast="lsp/ast";
|
||||||
(: import module namespace p="xq4" at "xq4.xqm"; :)
|
(: import module namespace p="xq4" at "xq4.xqm"; :)
|
||||||
import module namespace xq4="java:quodatum.parser.xq4";
|
import module namespace xq4="java:quodatum.parser.xq4";
|
||||||
|
|
||||||
(:~ build :)
|
(:~ build
|
||||||
declare function ast:build($text as xs:string,$uri as xs:string:="")
|
$opts uri,
|
||||||
|
abstract:true(),
|
||||||
|
position: true()
|
||||||
|
:)
|
||||||
|
declare function ast:build($text as xs:string,$opts as map(*):={})
|
||||||
as element(*){
|
as element(*){
|
||||||
let $xml:= xq4:parseModule($text)=>prof:time("⏱️ p:parse-Module " || $uri)
|
let $xml:= xq4:parseModule($text)=>prof:time("⏱️ parseModule " || $opts?uri)
|
||||||
return ($xml,
|
let $res:= if($opts?abstract)
|
||||||
message(ast:report($xml),"REP"),
|
then ast:flatten($xml)=>prof:time("⏱️ abstract ")
|
||||||
message(ast:report(ast:flatten($xml)),"flat")
|
else $xml
|
||||||
)
|
|
||||||
|
let $res:=if($opts?position)
|
||||||
|
then ast:annotate-with-positions($res)=>prof:time("⏱️ position ")
|
||||||
|
else $res
|
||||||
|
|
||||||
|
return $res
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~
|
(:~
|
||||||
|
|
@ -31,7 +40,82 @@ declare function ast:flatten($input as element()) as element() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
(:-------------------------------------------:)
|
declare function ast:add-positions($nodes as node()*, $start-pos as xs:integer) as item()+ {
|
||||||
|
if (empty($nodes)) then (
|
||||||
|
$start-pos, ()
|
||||||
|
) else (
|
||||||
|
let $head := $nodes[1]
|
||||||
|
let $tail := $nodes[position() > 1]
|
||||||
|
return
|
||||||
|
typeswitch($head)
|
||||||
|
case element() return
|
||||||
|
let $children := $head/node()
|
||||||
|
let $child-result := ast:add-positions($children, $start-pos)
|
||||||
|
let $child-end-pos := $child-result[1]
|
||||||
|
let $processed-children := subsequence($child-result, 2)
|
||||||
|
let $element-text := string-join($processed-children ! string(.), "")
|
||||||
|
let $element-length := string-length($element-text)
|
||||||
|
let $element-end-pos :=
|
||||||
|
if ($element-length > 0) then $start-pos + $element-length - 1
|
||||||
|
else $start-pos
|
||||||
|
let $tail-result :=
|
||||||
|
if (exists($tail)) then
|
||||||
|
ast:add-positions($tail, $element-end-pos + 1)
|
||||||
|
else (
|
||||||
|
$element-end-pos + 1, ()
|
||||||
|
)
|
||||||
|
let $final-end-pos := $tail-result[1]
|
||||||
|
let $processed-tail := subsequence($tail-result, 2)
|
||||||
|
return (
|
||||||
|
$final-end-pos,
|
||||||
|
element {node-name($head)} {
|
||||||
|
attribute start {$start-pos},
|
||||||
|
attribute end {$element-end-pos},
|
||||||
|
$processed-children
|
||||||
|
},
|
||||||
|
$processed-tail
|
||||||
|
)
|
||||||
|
case text() return
|
||||||
|
let $text-length := string-length($head)
|
||||||
|
let $text-end-pos :=
|
||||||
|
if ($text-length > 0) then $start-pos + $text-length - 1
|
||||||
|
else $start-pos
|
||||||
|
let $tail-result :=
|
||||||
|
if (exists($tail)) then
|
||||||
|
ast:add-positions($tail, $text-end-pos + 1)
|
||||||
|
else (
|
||||||
|
$text-end-pos + 1, ()
|
||||||
|
)
|
||||||
|
let $final-end-pos := $tail-result[1]
|
||||||
|
let $processed-tail := subsequence($tail-result, 2)
|
||||||
|
return (
|
||||||
|
$final-end-pos,
|
||||||
|
$head,
|
||||||
|
$processed-tail
|
||||||
|
)
|
||||||
|
default return
|
||||||
|
let $tail-result :=
|
||||||
|
if (exists($tail)) then
|
||||||
|
ast:add-positions($tail, $start-pos)
|
||||||
|
else (
|
||||||
|
$start-pos, ()
|
||||||
|
)
|
||||||
|
let $final-end-pos := $tail-result[1]
|
||||||
|
let $processed-tail := subsequence($tail-result, 2)
|
||||||
|
return (
|
||||||
|
$final-end-pos,
|
||||||
|
$head,
|
||||||
|
$processed-tail
|
||||||
|
)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
declare function ast:annotate-with-positions($xml as element()) as element() {
|
||||||
|
let $result := ast:add-positions($xml, 1)
|
||||||
|
return $result[2]
|
||||||
|
};
|
||||||
|
|
||||||
|
(:-------reporting------------------------------------:)
|
||||||
|
|
||||||
declare function ast:report($el as element(*)) {
|
declare function ast:report($el as element(*)) {
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ declare function docs:parse(
|
||||||
)as map(*)?
|
)as map(*)?
|
||||||
{
|
{
|
||||||
let $text:=docs:get($socket,$file,"textDocument")?text
|
let $text:=docs:get($socket,$file,"textDocument")?text
|
||||||
let $xml:= ast:build($text, $file)
|
let $xml:= ast:build($text, {"uri": $file, "abstract":false(), "position":true()})
|
||||||
let $diags:=lsp-diags:list($file, $text, $xml)=>prof:time("⏱️ diags " || $file)
|
let $diags:=lsp-diags:list($file, $text, $xml)=>prof:time("⏱️ diags " || $file)
|
||||||
return (
|
return (
|
||||||
ws:set($socket,docs:key($socket,$file,"parse"),$xml),
|
ws:set($socket,docs:key($socket,$file,"parse"),$xml),
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,14 @@ module namespace hnd="lsp/handlers";
|
||||||
(:~ structure returned by tree walkers :)
|
(:~ structure returned by tree walkers :)
|
||||||
declare record hnd:Result(
|
declare record hnd:Result(
|
||||||
result as item()*,
|
result as item()*,
|
||||||
skipchildren? as xs:boolean:=false()
|
skipchildren? as xs:boolean:=false(),
|
||||||
|
extras?
|
||||||
);
|
);
|
||||||
|
|
||||||
declare type hnd:actionFn as fn($parse as element(),$state as hnd:Result ) as hnd:Result;
|
declare type hnd:actionFn as fn(
|
||||||
|
$parse as element(),
|
||||||
|
$state as hnd:Result
|
||||||
|
) as hnd:Result;
|
||||||
|
|
||||||
declare type hnd:actionMap as map(xs:string,hnd:actionFn);
|
declare type hnd:actionMap as map(xs:string,hnd:actionFn);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ function lsp-ws:message(
|
||||||
$message as xs:string
|
$message as xs:string
|
||||||
) as empty-sequence() {
|
) as empty-sequence() {
|
||||||
|
|
||||||
let $json := rpc:parse($message)
|
let $json := rpc:parse($message=>trace("IN: "))
|
||||||
return if(exists($json))
|
return if(exists($json))
|
||||||
then rpc:reply($json)
|
then rpc:reply($json)
|
||||||
else message($message,"bad RPC: ")
|
else message($message,"bad RPC: ")
|
||||||
|
|
|
||||||
|
|
@ -87,8 +87,8 @@ as lspt:Range{
|
||||||
|
|
||||||
(:~ range for $text from indices:)
|
(:~ range for $text from indices:)
|
||||||
declare function pos:range-from-ast(
|
declare function pos:range-from-ast(
|
||||||
$text as xs:string,
|
$ast as element(*),
|
||||||
$ast as element(*))
|
$text as xs:string)
|
||||||
as lspt:Range{
|
as lspt:Range{
|
||||||
lspt:Range(
|
lspt:Range(
|
||||||
pos:toPosition($text,number($ast/@start)),
|
pos:toPosition($text,number($ast/@start)),
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,9 @@ declare function syms:FunctionDecl($parse as element(FunctionDecl),$state as hn
|
||||||
as hnd:Result{
|
as hnd:Result{
|
||||||
let $name:=syms:localName($parse/UnreservedFunctionEQName)
|
let $name:=syms:localName($parse/UnreservedFunctionEQName)
|
||||||
let $prev:=$state?result[$name eq ?name]
|
let $prev:=$state?result[$name eq ?name]
|
||||||
let $range:=lspt:Range(lspt:Position(0,0),lspt:Position(0,3))
|
let $range:=pos:range-from-ast($parse,$state?context?text)=>trace("POSSSS")
|
||||||
let $sym:=lspt:DocumentSymbol($name,$lspt:SymbolKindMap('Method'),$range,$range,"FUN")
|
let $full-range:=$range
|
||||||
|
let $sym:=lspt:DocumentSymbol($name,$lspt:SymbolKindMap('Method'),$range,$full-range,"FUN")
|
||||||
return ($state?result,$sym)=>hnd:Result(true())
|
return ($state?result,$sym)=>hnd:Result(true())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue