[add] lsp manager

This commit is contained in:
Andy Bunce 2025-10-13 23:07:01 +01:00
parent 38a1909570
commit c4f92f0402
39 changed files with 3481 additions and 25 deletions

View file

@ -0,0 +1,266 @@
{
"new library module": {
"isFileTemplate": true,
"prefix": "library module",
"body": [
"xquery version '3.1';",
"(:~",
"@author: ",
"@date: $CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE",
":)",
"module namespace ${1:prefix} = '${2:http://www.example.com/}';",
""
],
"description": "New library module template"
},
"new main module": {
"isFileTemplate": true,
"prefix": "main module",
"body": [
"xquery version '3.1';",
"(:~",
":)",
"${1:expr}",
""
],
"description": "New main module template"
},
"flowr": {
"prefix": [
"for",
"flowr"
],
"body": [
"for \\$${1:var} at \\$${2:pos} in ${3:expr}",
"let \\$${4:var2} := ${5:expr}",
"where ${6:boolean}",
"order by ${7:expr}",
"return ${8:expr2}"
],
"description": "Full FLOWR expression"
},
"return": {
"prefix": "return",
"body": "return ${1:expr}"
},
"import": {
"prefix": "import",
"body": "import module namespace ${1:ns} = '${2:http://www.example.com/}';",
"description": "Import module"
},
"if": {
"prefix": "if",
"body": [
"if (${1:boolean})",
"then ${2:expr1}",
"else ${3:expr2}"
],
"description": "If then else expression"
},
"module": {
"prefix": "module",
"body": "module namespace ${1:ns} = '${2:http://www.example.com}';"
},
"every": {
"prefix": "every",
"body": "every \\$${1:varname} in ${2:expr} satisfies ${3:expr}"
},
"some": {
"prefix": "some",
"body": "some \\$${1:varname} in ${2:expr} satisfies ${3:expr}"
},
"declare namespace": {
"prefix": [
"declare",
"namespace"
],
"body": [
"declare ${1:prefix}='${2:namespace}';",
""
],
"description": "declare namespace"
},
"declare base-uri": {
"prefix": [
"declare",
"baseuri"
],
"body": [
"declare base-uri '${1:uriliteral}';",
""
],
"description": "declare base-uri"
},
"declare option": {
"prefix": [
"declare",
"option"
],
"body": [
"declare option ${1:eqname} '${2:string}';",
""
],
"description": "declare option"
},
"declare function": {
"prefix": [
"declare",
"function"
],
"body": [
"(:~ ${1:name} :)",
"declare function ${2:ns}:${1:name}()",
"as ${3:type}{",
"${3:expr}",
"};",
""
],
"description": "declare function"
},
"declare variable": {
"prefix": [
"declare",
"variable"
],
"body": [
"(:~ \\$${1:varname} :)",
"declare variable \\$${1:varname} := ${2:expr};",
""
],
"description": "declare variable"
},
"switch": {
"prefix": "switch",
"body": [
"switch(${1:foo})",
"case ${2:foo} return ${3:true}",
"default return ${4:false}"
],
"description": "switch statement"
},
"typeswitch": {
"prefix": "type",
"body": [
"typeswitch(${1:foo})",
"case ${2:foo} return ${3:true}",
"default return ${4:false}"
],
"description": "typeswitch statement"
},
"try": {
"prefix": "try",
"body": [
"try {",
" ${1:expr}",
"} catch ${2:*}",
" { ${3:expr}",
"}"
],
"description": "try catch"
},
"tumbling": {
"prefix": [
"for",
"tumbling",
"window"
],
"body": [
"for tumbling window \\$${1:varname} in ${2:expr}",
"start at \\$${3:start} when ${4:expr}",
"end at \\$${5:end} when ${6:expr}",
"return ${7:expr}"
],
"description": "tumbling window"
},
"sliding": {
"prefix": [
"for",
"sliding",
"window"
],
"body": [
"for sliding window \\$${1:varname} in ${2:expr}",
"start at \\$${3:start} when ${4:expr}",
"end at \\$${5:end} when ${6:expr}",
"return ${7:expr}"
],
"description": "sliding window"
},
"let": {
"prefix": "let",
"body": "let \\$${1:varname} := ${2:expr}"
},
"castable": {
"body": "castable as ${1:atomicType}"
},
"cast": {
"body": "cast as ${1:atomicType}"
},
"update insert": {
"prefix": [
"update",
"insert"
],
"body": "insert node ${1:expr} into ${2:xpath}"
},
"update delete": {
"prefix": ["delete","update"],
"body": "delete node ${1:xpath}"
},
"update replace node": {
"prefix":["update","replace"],
"body": "replace node ${1:xpath} with ${2:expr}"
},
"update replace value": {
"prefix": [ "update",
"replace",
"value"
],
"body": "replace value of node ${1:xpath} with ${2:expr}"
},
"update rename": {
"prefix": [
"update",
"rename"
],
"body": "rename node ${1:xpath} as ${2:eqname}"
},
"copy modify return": {
"prefix": [
"copy",
"modify",
"return"
],
"body": [
"copy \\$${1:varname} := ${2:node}",
"modify ${3:updates}",
"return \\$${1:varname}"
]
},
"transform with": {
"prefix": [
"transform",
"with",
"update"
],
"body": [
"${1:node} transform with {",
" ${2:update}",
"}"
]
},
"transform update": {
"prefix": [
"transform",
"update"
],
"body": [
"${1:node} update {",
"${2:update}",
"}"
]
}
}

View file

@ -50,9 +50,9 @@ declare
function lsp-text:completion($json as map(*))
as map(*)?
{
let $doc:=$json?params?textDocument?uri
let $uri:=$json?params?textDocument?uri
let $context:=$json?params?context (:{"triggerCharacter":":","triggerKind":2.0e0}:)
let $result:=comp:list($context)
let $result:=comp:list($context)=>prof:time("⏱️ completions " || $uri)
return rpc:result($json,array:build($result))
};

View file

@ -2,13 +2,15 @@ module namespace comp = 'lsp-completions';
import module namespace lspt = 'lsp-typedefs' at "../lsp-typedefs.xqm";
import module namespace ctx="lsp/context" at "../context.xqm";
declare variable $comp:snippet-source:="../etc/snippets.json";
declare variable $comp:snippets:=json:doc($comp:snippet-source,{"format":"w3"});
(: (:{"triggerCharacter":":","triggerKind":2.0e0}:):)
declare function comp:list($context as map(*))
as lspt:CompletionItem*
{
message($context,"context: "),
ctx:functions("fn")!ctx:map(.)=>trace("aaa")
ctx:functions("fn")!ctx:map(.)
};
declare function comp:dummy($context as map(*))

View file

@ -5,17 +5,18 @@ 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 function syms:list($parse as element(),$text as xs:string)
as lspt:DocumentSymbol*{
let $actions as hnd:actionMap :={
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:action#2
}
"NamedRecordTypeDecl": syms:NamedRecordTypeDecl#2
};
declare function syms:list($parse as element(),$text as xs:string)
as lspt:DocumentSymbol*{
let $state:= hnd:Result(())
let $result:= hnd:walk($parse,$actions,$state)
let $result:= hnd:walk($parse,$syms:actions,$state)
return $result?result
};
@ -42,7 +43,7 @@ as hnd:Result{
let $name:=syms:localName($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")
let $sym:=lspt:DocumentSymbol($name,$lspt:SymbolKindMap('Variable'),$range,$range,"VAR")
return ($state?result,$sym)=>hnd:Result(true())
};
@ -50,7 +51,16 @@ declare function syms:FunctionDecl($parse as element(FunctionDecl),$state as hn
as hnd:Result{
let $name:=syms:localName($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")
let $sym:=lspt:DocumentSymbol($name,$lspt:SymbolKindMap('Method'),$range,$range,"FUN")
return ($state?result,$sym)=>hnd:Result(true())
};
declare function syms:NamedRecordTypeDecl($parse as element(NamedRecordTypeDecl), $state as hnd:Result )
as hnd:Result{
let $name:=syms:localName($parse/EQName)
let $range:=lspt:Range(lspt:Position(0,0),lspt:Position(0,3))
let $sym:=lspt:DocumentSymbol($name,$lspt:SymbolKindMap('TypeParameter'),$range,$range,"--RECORD")
=>trace("RECORD")
return ($state?result,$sym)=>hnd:Result(true())
};