diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..dae727f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + + { + "type": "jdk", + "request": "launch", + "name": "Launch Java App" + } + ] +} \ No newline at end of file diff --git a/bundles/grammar/rex.xq b/bundles/grammar/rex.xq index 1b88b7b..de45642 100644 --- a/bundles/grammar/rex.xq +++ b/bundles/grammar/rex.xq @@ -1,5 +1,5 @@ (: parse xq and save result:) -import module namespace p="xq4" at "C:\Users\mrwhe\git\quodatum\basex-lsp\webapp\lsp\xq4.xqm"; +import module namespace p="xq4" at "C:\Users\mrwhe\git\quodatum\basex-lsp\webapp\lsp\ast\xq4.xqm"; declare variable $generator.xpath :="https://raw.githubusercontent.com/dnovatchev/Articles/refs/heads/main/Generators/Code/generator.xq"; declare variable $pdfbox-good.xqm :="../../test/sample.docs/pdfbox.xqm"; diff --git a/bundles/grammar/test-xquery.xq b/bundles/grammar/test-xquery.xq index 137cd70..82071fc 100644 --- a/bundles/grammar/test-xquery.xq +++ b/bundles/grammar/test-xquery.xq @@ -1,3 +1,3 @@ -import module namespace p="xq4" at "C:\Users\mrwhe\git\quodatum\basex-lsp\webapp\lsp\xq4.xqm"; +import module namespace p="xq4" at "C:\Users\mrwhe\git\quodatum\basex-lsp\webapp\lsp\ast\xq4.xqm"; let $t:=fetch:text("https://raw.githubusercontent.com/dnovatchev/Articles/refs/heads/main/Generators/Code/generator.xq")=>lazy:cache() return p:parse-Module($t) \ No newline at end of file diff --git a/webapp/lsp/ast/ast.xqm b/webapp/lsp/ast/ast.xqm new file mode 100644 index 0000000..ac85a17 --- /dev/null +++ b/webapp/lsp/ast/ast.xqm @@ -0,0 +1,56 @@ +(: Abstract syntax tree +@author Andy Bunce +:) +module namespace ast="lsp/ast"; +(: import module namespace p="xq4" at "xq4.xqm"; :) +import module namespace xq4="java:quodatum.parser.xq4"; + +(:~ build :) +declare function ast:build($text as xs:string,$uri as xs:string:="") +as element(*){ + let $xml:= xq4:parseModule($text)=>prof:time("⏱️ p:parse-Module " || $uri) + return ($xml, + message(ast:report($xml),"REP"), + message(ast:report(ast:flatten($xml)),"flat") + ) +}; + +(:~ + :concrete to abstract: simplify by omitting elements with only one child +:) +declare function ast:flatten($input as element()) as element() { + if (1=count($input/*)) then ast:flatten($input/*) + else element {node-name($input) } + {$input/@*, + for $child in $input/node() + return + if ($child instance of element()) + then ast:flatten($child) + else $child + } +}; + +(:-------------------------------------------:) + +declare function ast:report($el as element(*)) { + + {count($el//element())} + {ast:max-node-depth($el)} + +}; + +declare function ast:max-depth($nodes as node()*) as xs:integer { + if (empty($nodes)) then 0 + else + max(( + for $node in $nodes + return + if ($node instance of element()) + then ast:max-depth($node/node()) + 1 + else ast:max-depth($node/node()) + )) +}; + +declare function ast:max-node-depth($root as node()) as xs:integer { + ast:max-depth($root) +}; diff --git a/webapp/lsp/xq4.xqm b/webapp/lsp/ast/xq4.xqm similarity index 100% rename from webapp/lsp/xq4.xqm rename to webapp/lsp/ast/xq4.xqm diff --git a/webapp/lsp/docs.xqm b/webapp/lsp/docs.xqm index 72f4c66..249f00d 100644 --- a/webapp/lsp/docs.xqm +++ b/webapp/lsp/docs.xqm @@ -4,11 +4,10 @@ @author Andy Bunce :) module namespace docs="lsp/docs"; -(: import module namespace p="xq4" at "xq4.xqm"; :) -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 'providers/diagnostics.xqm'; +import module namespace ast = 'lsp/ast' at 'ast/ast.xqm'; (: save $textDocument data as session $socket properties @return uri @@ -119,7 +118,7 @@ declare function docs:parse( )as map(*)? { let $text:=docs:get($socket,$file,"textDocument")?text - let $xml:= xq4:parseModule($text)=>prof:time("⏱️ p:parse-Module " || $file) + let $xml:= ast:build($text, $file) let $diags:=lsp-diags:list($file, $text, $xml)=>prof:time("⏱️ diags " || $file) return ( ws:set($socket,docs:key($socket,$file,"parse"),$xml), diff --git a/webapp/lsp/providers/documentSymbols.xqm b/webapp/lsp/providers/documentSymbols.xqm index 4c136f4..7f48006 100644 --- a/webapp/lsp/providers/documentSymbols.xqm +++ b/webapp/lsp/providers/documentSymbols.xqm @@ -50,6 +50,7 @@ as hnd:Result{ declare function syms:FunctionDecl($parse as element(FunctionDecl),$state as hnd:Result ) as hnd:Result{ let $name:=syms:localName($parse/UnreservedFunctionEQName) + let $prev:=$state?result[$name eq ?name] let $range:=lspt:Range(lspt:Position(0,0),lspt:Position(0,3)) let $sym:=lspt:DocumentSymbol($name,$lspt:SymbolKindMap('Method'),$range,$range,"FUN") return ($state?result,$sym)=>hnd:Result(true()) diff --git a/webapp/static/clients/codemirror/grail.html b/webapp/static/clients/codemirror/grail.html index bb83247..d24d46e 100644 --- a/webapp/static/clients/codemirror/grail.html +++ b/webapp/static/clients/codemirror/grail.html @@ -8,8 +8,8 @@ - - + + diff --git a/webapp/static/clients/codemirror/script.js b/webapp/static/clients/codemirror/script.js index df30a57..089fa00 100644 --- a/webapp/static/clients/codemirror/script.js +++ b/webapp/static/clients/codemirror/script.js @@ -119,7 +119,8 @@ $("load").onchange = e => { }); $("load").value = ""; }; -$("tConnect").addEventListener('quiet-change', event => { +$("tConnect").addEventListener('quiet-change', e => { + e.preventDefault(); $("popConnect").showPopover() }); $("msgIcon").onclick = e => {