fix(lsp): recover from handler panics and decode client uris
This commit is contained in:
+34
-13
@@ -22,12 +22,13 @@ import (
|
||||
"sourcedock.dev/petrbalvin/gasm-devkit/token"
|
||||
)
|
||||
|
||||
// textflagMacros are the flag names defined by textflag.h; they are highlighted
|
||||
// as macros and offered as completions after a TEXT/GLOBL directive.
|
||||
// textflagMacros are the flag names defined by runtime/textflag.h; they are
|
||||
// highlighted as macros and offered as completions after a TEXT/GLOBL
|
||||
// directive.
|
||||
var textflagMacros = map[string]bool{
|
||||
"NOPROFILE": true, "DUPOK": true, "NOSPLIT": true, "RODATA": true,
|
||||
"NOPTR": true, "WRAPPER": true, "NEEDCTXT": true, "TOPFRAME": true,
|
||||
"LEAF": true, "ABI0": true, "REFLECTDATA": true,
|
||||
"NOPROF": true, "DUPOK": true, "NOSPLIT": true, "RODATA": true,
|
||||
"NOPTR": true, "WRAPPER": true, "NEEDCTXT": true, "TLSBSS": true,
|
||||
"NOFRAME": true, "REFLECTMETHOD": true, "TOPFRAME": true, "ABIWRAPPER": true,
|
||||
}
|
||||
|
||||
// completion builds the completion list for a document.
|
||||
@@ -81,13 +82,13 @@ func (s *Server) hover(p hoverParams) *Hover {
|
||||
|
||||
var md string
|
||||
if in, ok := a.Lookup(word); ok {
|
||||
md = "**" + in.Name + "** — " + in.Summary
|
||||
md = "**" + in.Name + "**: " + in.Summary
|
||||
} else if r, ok := a.Register(word); ok {
|
||||
md = "**" + r.Name + "** — " + r.Class.String() + " register. " + r.Desc
|
||||
md = "**" + r.Name + "**: " + r.Class.String() + " register. " + r.Desc
|
||||
} else if desc, ok := arch.PseudoRegDesc(word); ok {
|
||||
md = "**" + strings.ToUpper(word) + "** — pseudo-register. " + desc
|
||||
md = "**" + strings.ToUpper(word) + "**: pseudo-register. " + desc
|
||||
} else if textflagMacros[strings.ToUpper(word)] {
|
||||
md = "**" + strings.ToUpper(word) + "** — textflag.h flag"
|
||||
md = "**" + strings.ToUpper(word) + "**: textflag.h flag"
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@@ -271,7 +272,9 @@ func (s *Server) codeActions(p codeActionParams) []CodeAction {
|
||||
for _, diag := range p.Context.Diagnostics {
|
||||
switch diag.Code {
|
||||
case "missing-ret":
|
||||
// Offer to add RET at the end of the function.
|
||||
// Offer to add RET at the end of the flagged function only: the
|
||||
// diagnostic's range covers the TEXT keyword, so a line match
|
||||
// picks the function the diagnostic belongs to.
|
||||
f, _ := parser.Parse(uriPath(p.TextDocument.URI), text)
|
||||
if f == nil {
|
||||
continue
|
||||
@@ -281,6 +284,9 @@ func (s *Server) codeActions(p codeActionParams) []CodeAction {
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if t.Keyword.Pos.Line-1 != int(diag.Range.Start.Line) {
|
||||
continue
|
||||
}
|
||||
if len(t.Body) == 0 {
|
||||
continue
|
||||
}
|
||||
@@ -298,7 +304,7 @@ func (s *Server) codeActions(p codeActionParams) []CodeAction {
|
||||
endLine := len(lines) - 1
|
||||
endChar := len([]rune(lines[endLine]))
|
||||
actions = append(actions, CodeAction{
|
||||
Title: "Add RET",
|
||||
Title: "Add RET to " + t.Name.Name,
|
||||
Kind: "quickfix",
|
||||
Edit: &WorkspaceEdit{
|
||||
Changes: map[string][]TextEdit{p.TextDocument.URI: {
|
||||
@@ -792,13 +798,28 @@ func textRange(t *ast.Text) Range {
|
||||
|
||||
// diagnosticsFor computes the LSP diagnostics of one document; the push
|
||||
// (publishDiagnostics) and pull (textDocument/diagnostic) paths share it.
|
||||
// Parse errors surface as error-severity diagnostics so a malformed line is
|
||||
// visible in the editor instead of only breaking derived features.
|
||||
func (s *Server) diagnosticsFor(uri string) []Diagnostic {
|
||||
text := s.docs[uri]
|
||||
f, _ := parser.Parse(uriPath(uri), text)
|
||||
f, errs := parser.Parse(uriPath(uri), text)
|
||||
cfg := lint.Config{Arch: arch.FromFilename(uriPath(uri))}
|
||||
diags := lint.File(f, cfg)
|
||||
|
||||
out := make([]Diagnostic, 0, len(diags))
|
||||
out := make([]Diagnostic, 0, len(diags)+len(errs))
|
||||
for _, e := range errs {
|
||||
pos := token.Position{Line: 1, Column: 1}
|
||||
if pe, ok := e.(parser.Error); ok && pe.Pos.IsValid() {
|
||||
pos = pe.Pos
|
||||
}
|
||||
out = append(out, Diagnostic{
|
||||
Range: toRange(pos.Line, pos.Column, token.Position{}),
|
||||
Severity: sevError,
|
||||
Code: "syntax",
|
||||
Source: "gasm",
|
||||
Message: e.Error(),
|
||||
})
|
||||
}
|
||||
for _, d := range diags {
|
||||
out = append(out, Diagnostic{
|
||||
Range: toRange(d.Pos.Line, d.Pos.Column, d.End),
|
||||
|
||||
Reference in New Issue
Block a user