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
|
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.
|
// documentSymbols returns functions and their labels, plus global symbols.
|
||||||
func (s *Server) documentSymbols(p documentSymbolParams) []DocumentSymbol {
|
func (s *Server) documentSymbols(p documentSymbolParams) []DocumentSymbol {
|
||||||
text := s.docs[p.TextDocument.URI]
|
text := s.docs[p.TextDocument.URI]
|
||||||
|
|||||||
@@ -312,6 +312,7 @@ type ServerCapabilities struct {
|
|||||||
DocumentHighlightProvider bool `json:"documentHighlightProvider,omitempty"`
|
DocumentHighlightProvider bool `json:"documentHighlightProvider,omitempty"`
|
||||||
CodeActionProvider bool `json:"codeActionProvider,omitempty"`
|
CodeActionProvider bool `json:"codeActionProvider,omitempty"`
|
||||||
SignatureHelpProvider map[string]any `json:"signatureHelpProvider,omitempty"`
|
SignatureHelpProvider map[string]any `json:"signatureHelpProvider,omitempty"`
|
||||||
|
WorkspaceSymbolProvider bool `json:"workspaceSymbolProvider,omitempty"`
|
||||||
SemanticTokensProvider map[string]any `json:"semanticTokensProvider,omitempty"`
|
SemanticTokensProvider map[string]any `json:"semanticTokensProvider,omitempty"`
|
||||||
InlayHintProvider bool `json:"inlayHintProvider,omitempty"`
|
InlayHintProvider bool `json:"inlayHintProvider,omitempty"`
|
||||||
DiagnosticProvider map[string]any `json:"diagnosticProvider,omitempty"`
|
DiagnosticProvider map[string]any `json:"diagnosticProvider,omitempty"`
|
||||||
@@ -378,6 +379,19 @@ const (
|
|||||||
highlightWrite = 2
|
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 {
|
type initializeResult struct {
|
||||||
Capabilities ServerCapabilities `json:"capabilities"`
|
Capabilities ServerCapabilities `json:"capabilities"`
|
||||||
ServerInfo map[string]string `json:"serverInfo,omitempty"`
|
ServerInfo map[string]string `json:"serverInfo,omitempty"`
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ func (s *Server) dispatch(msg *rpcMessage) (exit bool) {
|
|||||||
DocumentHighlightProvider: true,
|
DocumentHighlightProvider: true,
|
||||||
CodeActionProvider: true,
|
CodeActionProvider: true,
|
||||||
SignatureHelpProvider: map[string]any{"triggerCharacters": []string{"("}},
|
SignatureHelpProvider: map[string]any{"triggerCharacters": []string{"("}},
|
||||||
|
WorkspaceSymbolProvider: true,
|
||||||
},
|
},
|
||||||
ServerInfo: map[string]string{"name": "gasm", "version": "0.31.1"},
|
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)
|
json.Unmarshal(msg.Params, &p)
|
||||||
s.respond(msg.ID, s.semanticTokens(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":
|
case "shutdown":
|
||||||
s.respond(msg.ID, nil)
|
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) {
|
func TestMethodNotFound(t *testing.T) {
|
||||||
in := frame(9, "bogus/method", map[string]any{}) + frame(nil, "exit", nil)
|
in := frame(9, "bogus/method", map[string]any{}) + frame(nil, "exit", nil)
|
||||||
msgs := run(t, in)
|
msgs := run(t, in)
|
||||||
|
|||||||
Reference in New Issue
Block a user