module namespace lsp-diags = 'lsp-diags'; import module namespace pos="lsp/position" at "position.xqm"; declare type lsp-diags:ParseResult as element(Module|ERROR); (:~ from: number The start position of the relevant text. to: number The end position. May be equal to from, though actually covering text is preferable. severity: "error" | "hint" | "info" | "warning" The severity of the problem. This will influence how it is displayed. markClass⁠?: string When given, add an extra CSS class to parts of the code that this diagnostic applies to. source⁠?: string An optional source string indicating where the diagnostic is coming from. You can put the name of your linter here, if applicable. 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. :) declare record lsp-diags:nostic( range as pos:Range, severity as xs:integer, (: enum('error', 'hint', 'info', 'warning') :) message as xs:string, code? as xs:string, source as xs:string:="xquery" ); declare variable $lsp-diags:severities:={ 'error':1, 'hint':4, 'info':3, 'warning':2 }; declare function lsp-diags:publish( $uri as xs:string, $text as xs:string, $xml as lsp-diags:ParseResult) as map(*){ let $diagnostics:=if($xml/self::ERROR) then array{lsp-diags:parse-error($text, $xml)} else array{ lsp-diags:parse-xquery($text,$xml)} return {"jsonrpc": "2.0", "method":"textDocument/publishDiagnostics", "params":{"uri": $uri, "diagnostics": $diagnostics} } }; (:~ syntax error, found '}' while expecting [S,'else'] at line 290, column 'XPST0003', 'parse error' 'XQLT0001', 'previous parse error' :) declare function lsp-diags:parse-error($text as xs:string, $xml as element(ERROR)) as map(*)*{ if(string-length($text) gt 0) then let $last:= max((0,string-length($text)-1)) let $dmesg:=$xml/string()=>trace("parse-error") let $dmesg:=translate($dmesg," ",";") let $b:=number($xml/@b)-1 let $e:= number($xml/@e)-1 return ( (: mark error :) lsp-diags:nostic(pos:Range(pos:toPosition($text, $b), pos:toPosition($text, min(($e,$last)))), 1, $dmesg,'XPST0003'), (:mark after error:) if($e ge string-length($text)) then () else lsp-diags:nostic(pos:Range(pos:toPosition($text, $e +1 ), pos:toPosition($text, $last)), 2, "Unparsed due to previous parser error.", "XQLT0001") ) else () }; (: test data :) declare function lsp-diags:parse-xquery($text as xs:string, $xml as element(Module)) as map(*)*{ (: lsp-diags:nostic(pos:Range(pos:Position(0,0), pos:Position(0, 5)), $lsp-diags:severities('error'),"error"), lsp-diags:nostic(pos:Range(pos:Position(1,0), pos:Position(1,5)), $lsp-diags:severities('warning'),"warning"), lsp-diags:nostic(pos:Range(pos:Position(2,0), pos:Position(2, 5)), $lsp-diags:severities('info'),"info"), lsp-diags:nostic(pos:Range(pos:Position(3,0), pos:Position(3, 6)), $lsp-diags:severities('hint'), "hint") :) };