feat(lsp): add workspace symbol search
Assisted-by: MiMo V2.5 Pro
This commit is contained in:
@@ -452,6 +452,50 @@ func (s *Server) documentHighlights(p documentHighlightParams) []DocumentHighlig
|
||||
return out
|
||||
}
|
||||
|
||||
// workspaceSymbols searches all open documents 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 {
|
||||
switch dd := d.(type) {
|
||||
case *ast.Text:
|
||||
if strings.Contains(strings.ToLower(dd.Name.Name), query) {
|
||||
out = append(out, WorkspaceSymbol{
|
||||
Name: dd.Name.Name,
|
||||
Kind: symFunction,
|
||||
Location: Location{URI: uri, Range: symRange(dd.Name)},
|
||||
})
|
||||
}
|
||||
case *ast.Globl:
|
||||
if dd.Name != nil && strings.Contains(strings.ToLower(dd.Name.Name), query) {
|
||||
out = append(out, WorkspaceSymbol{
|
||||
Name: dd.Name.Name,
|
||||
Kind: symConstant,
|
||||
Location: Location{URI: uri, Range: symRange(dd.Name)},
|
||||
})
|
||||
}
|
||||
case *ast.Data:
|
||||
if dd.Name != nil && strings.Contains(strings.ToLower(dd.Name.Name), query) {
|
||||
out = append(out, WorkspaceSymbol{
|
||||
Name: dd.Name.Name,
|
||||
Kind: symConstant,
|
||||
Location: Location{URI: uri, Range: symRange(dd.Name)},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// documentSymbols returns functions and their labels, plus global symbols.
|
||||
func (s *Server) documentSymbols(p documentSymbolParams) []DocumentSymbol {
|
||||
text := s.docs[p.TextDocument.URI]
|
||||
|
||||
@@ -312,6 +312,7 @@ type ServerCapabilities struct {
|
||||
DocumentHighlightProvider bool `json:"documentHighlightProvider,omitempty"`
|
||||
CodeActionProvider bool `json:"codeActionProvider,omitempty"`
|
||||
SignatureHelpProvider map[string]any `json:"signatureHelpProvider,omitempty"`
|
||||
WorkspaceSymbolProvider bool `json:"workspaceSymbolProvider,omitempty"`
|
||||
SemanticTokensProvider map[string]any `json:"semanticTokensProvider,omitempty"`
|
||||
InlayHintProvider bool `json:"inlayHintProvider,omitempty"`
|
||||
DiagnosticProvider map[string]any `json:"diagnosticProvider,omitempty"`
|
||||
@@ -378,6 +379,19 @@ const (
|
||||
highlightWrite = 2
|
||||
)
|
||||
|
||||
// --- workspace symbols -------------------------------------------------------
|
||||
|
||||
type workspaceSymbolParams struct {
|
||||
Query string `json:"query"`
|
||||
}
|
||||
|
||||
// WorkspaceSymbol represents a symbol found across the workspace.
|
||||
type WorkspaceSymbol struct {
|
||||
Name string `json:"name"`
|
||||
Kind int `json:"kind"`
|
||||
Location Location `json:"location"`
|
||||
}
|
||||
|
||||
type initializeResult struct {
|
||||
Capabilities ServerCapabilities `json:"capabilities"`
|
||||
ServerInfo map[string]string `json:"serverInfo,omitempty"`
|
||||
|
||||
@@ -135,6 +135,7 @@ func (s *Server) dispatch(msg *rpcMessage) (exit bool) {
|
||||
DocumentHighlightProvider: true,
|
||||
CodeActionProvider: true,
|
||||
SignatureHelpProvider: map[string]any{"triggerCharacters": []string{"("}},
|
||||
WorkspaceSymbolProvider: true,
|
||||
},
|
||||
ServerInfo: map[string]string{"name": "gasm", "version": "0.31.1"},
|
||||
})
|
||||
@@ -228,6 +229,11 @@ func (s *Server) dispatch(msg *rpcMessage) (exit bool) {
|
||||
json.Unmarshal(msg.Params, &p)
|
||||
s.respond(msg.ID, s.semanticTokens(p))
|
||||
|
||||
case "workspace/symbol":
|
||||
var p workspaceSymbolParams
|
||||
json.Unmarshal(msg.Params, &p)
|
||||
s.respond(msg.ID, s.workspaceSymbols(p))
|
||||
|
||||
case "shutdown":
|
||||
s.respond(msg.ID, nil)
|
||||
|
||||
|
||||
@@ -450,6 +450,31 @@ func TestDocumentHighlights(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorkspaceSymbols(t *testing.T) {
|
||||
in := session("file:///f_amd64.s", cleanDoc) +
|
||||
frame(13, "workspace/symbol", map[string]any{
|
||||
"query": "foo",
|
||||
}) + frame(nil, "exit", nil)
|
||||
msgs := run(t, in)
|
||||
resp := findByID(msgs, 13)
|
||||
if resp == nil {
|
||||
t.Fatal("no workspace/symbol response")
|
||||
}
|
||||
var syms []WorkspaceSymbol
|
||||
if err := json.Unmarshal(mustResult(t, resp), &syms); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
found := false
|
||||
for _, s := range syms {
|
||||
if s.Name == "foo" {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("want symbol foo in results, got %+v", syms)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMethodNotFound(t *testing.T) {
|
||||
in := frame(9, "bogus/method", map[string]any{}) + frame(nil, "exit", nil)
|
||||
msgs := run(t, in)
|
||||
|
||||
Reference in New Issue
Block a user