feat(lsp): resolve symbols across workspace files
Assisted-by: GLM 5.3 Flash
This commit is contained in:
+25
-27
@@ -127,8 +127,8 @@ func (s *Server) openASTs() []openAST {
|
||||
|
||||
// definition returns the location of the named label or function: a local
|
||||
// label in the current document wins, then the TEXT functions of every open
|
||||
// document are searched, so a `CALL ·helper(SB)` jumps to its definition in
|
||||
// another file.
|
||||
// document and indexed workspace file are searched, so a `CALL ·helper(SB)`
|
||||
// jumps to its definition even when the defining file was never opened.
|
||||
func (s *Server) definition(p definitionParams) []Location {
|
||||
text := s.docs[p.TextDocument.URI]
|
||||
word, _ := wordAt(text, p.Position)
|
||||
@@ -156,15 +156,15 @@ func (s *Server) definition(p definitionParams) []Location {
|
||||
}
|
||||
}
|
||||
|
||||
// Function definitions across the open workspace.
|
||||
for _, of := range s.openASTs() {
|
||||
for _, d := range of.file.Decls {
|
||||
// Function definitions across the workspace.
|
||||
for _, u := range s.scanUnits() {
|
||||
for _, d := range u.file.Decls {
|
||||
t, ok := d.(*ast.Text)
|
||||
if !ok || !realSymbol(t.Name) {
|
||||
continue
|
||||
}
|
||||
if t.Name.Name == name {
|
||||
return []Location{{URI: of.uri, Range: clientRange(s.docs[of.uri], symRange(t.Name))}}
|
||||
return []Location{{URI: u.uri, Range: clientRange(u.text, symRange(t.Name))}}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -172,10 +172,11 @@ func (s *Server) definition(p definitionParams) []Location {
|
||||
}
|
||||
|
||||
// references returns all locations where the symbol under the cursor appears
|
||||
// across every open document. The current document matches labels and any
|
||||
// operand name, as before; other documents only match SB-qualified operand
|
||||
// references and the definition itself, because a bare name is a
|
||||
// function-local label whose repeats in other files are unrelated.
|
||||
// across every open document and indexed workspace file. The current
|
||||
// document matches labels and any operand name, as before; every other
|
||||
// source only matches SB-qualified operand references and the definition
|
||||
// itself, because a bare name is a function-local label whose repeats in
|
||||
// other files are unrelated.
|
||||
func (s *Server) references(p referenceParams) []Location {
|
||||
text := s.docs[p.TextDocument.URI]
|
||||
word, _ := wordAt(text, p.Position)
|
||||
@@ -186,22 +187,22 @@ func (s *Server) references(p referenceParams) []Location {
|
||||
uri := p.TextDocument.URI
|
||||
|
||||
var out []Location
|
||||
for _, of := range s.openASTs() {
|
||||
sameDoc := of.uri == uri
|
||||
for _, d := range of.file.Decls {
|
||||
for _, u := range s.scanUnits() {
|
||||
sameDoc := u.uri == uri
|
||||
for _, d := range u.file.Decls {
|
||||
t, ok := d.(*ast.Text)
|
||||
if !ok || !realSymbol(t.Name) {
|
||||
continue
|
||||
}
|
||||
// Include the definition if requested.
|
||||
if p.Context.IncludeDeclaration && t.Name.Name == name {
|
||||
out = append(out, Location{URI: of.uri, Range: clientRange(s.docs[of.uri], symRange(t.Name))})
|
||||
out = append(out, Location{URI: u.uri, Range: clientRange(u.text, symRange(t.Name))})
|
||||
}
|
||||
for _, stmt := range t.Body {
|
||||
switch st := stmt.(type) {
|
||||
case *ast.Label:
|
||||
if sameDoc && st.Name.Text == name {
|
||||
out = append(out, Location{URI: of.uri, Range: clientRange(s.docs[of.uri], tokenRange(st.Name))})
|
||||
out = append(out, Location{URI: u.uri, Range: clientRange(u.text, tokenRange(st.Name))})
|
||||
}
|
||||
case *ast.Instr:
|
||||
for _, op := range st.Operands {
|
||||
@@ -215,8 +216,8 @@ func (s *Server) references(p referenceParams) []Location {
|
||||
// identifier, `·`/package prefix included, so a
|
||||
// rename replaces the whole spelling.
|
||||
out = append(out, Location{
|
||||
URI: of.uri,
|
||||
Range: clientRange(s.docs[of.uri], Range{
|
||||
URI: u.uri,
|
||||
Range: clientRange(u.text, Range{
|
||||
Start: Position{Line: op.Pos.Line - 1, Character: op.Pos.Column - 1},
|
||||
End: Position{Line: op.Pos.Line - 1, Character: op.Pos.Column - 1 + symIdentLen(op.Addr.Sym)},
|
||||
}),
|
||||
@@ -510,19 +511,16 @@ func (s *Server) documentHighlights(p documentHighlightParams) []DocumentHighlig
|
||||
return out
|
||||
}
|
||||
|
||||
// workspaceSymbols searches all open documents for symbols matching the query.
|
||||
// workspaceSymbols searches all open documents and indexed workspace files
|
||||
// for symbols matching the query.
|
||||
func (s *Server) workspaceSymbols(p workspaceSymbolParams) []WorkspaceSymbol {
|
||||
if p.Query == "" {
|
||||
return nil
|
||||
}
|
||||
query := strings.ToLower(p.Query)
|
||||
var out []WorkspaceSymbol
|
||||
for uri, text := range s.docs {
|
||||
f, _ := parser.Parse(uriPath(uri), text)
|
||||
if f == nil {
|
||||
continue
|
||||
}
|
||||
for _, d := range f.Decls {
|
||||
for _, u := range s.scanUnits() {
|
||||
for _, d := range u.file.Decls {
|
||||
switch dd := d.(type) {
|
||||
case *ast.Text:
|
||||
// A malformed TEXT line is kept in the tree under a "?"
|
||||
@@ -535,7 +533,7 @@ func (s *Server) workspaceSymbols(p workspaceSymbolParams) []WorkspaceSymbol {
|
||||
out = append(out, WorkspaceSymbol{
|
||||
Name: dd.Name.Name,
|
||||
Kind: symFunction,
|
||||
Location: Location{URI: uri, Range: clientRange(text, symRange(dd.Name))},
|
||||
Location: Location{URI: u.uri, Range: clientRange(u.text, symRange(dd.Name))},
|
||||
})
|
||||
}
|
||||
case *ast.Globl:
|
||||
@@ -543,7 +541,7 @@ func (s *Server) workspaceSymbols(p workspaceSymbolParams) []WorkspaceSymbol {
|
||||
out = append(out, WorkspaceSymbol{
|
||||
Name: dd.Name.Name,
|
||||
Kind: symConstant,
|
||||
Location: Location{URI: uri, Range: clientRange(text, symRange(dd.Name))},
|
||||
Location: Location{URI: u.uri, Range: clientRange(u.text, symRange(dd.Name))},
|
||||
})
|
||||
}
|
||||
case *ast.Data:
|
||||
@@ -551,7 +549,7 @@ func (s *Server) workspaceSymbols(p workspaceSymbolParams) []WorkspaceSymbol {
|
||||
out = append(out, WorkspaceSymbol{
|
||||
Name: dd.Name.Name,
|
||||
Kind: symConstant,
|
||||
Location: Location{URI: uri, Range: clientRange(text, symRange(dd.Name))},
|
||||
Location: Location{URI: u.uri, Range: clientRange(u.text, symRange(dd.Name))},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user