ollie/tools/lsp/cmd/lsp_symbols/main.go

115 lines
2.7 KiB
Go

// lsp_symbols — List symbols in a file, or search workspace-wide.
package main
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"ollie/tools/lsp/internal/lsp"
"ollie/tools/lsp/internal/cmdutil"
)
func main() {
cmdutil.RunCustom(func() {
var args struct {
Path string `json:"path"`
Query string `json:"query"`
}
if err := json.NewDecoder(os.Stdin).Decode(&args); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
file, _ := filepath.Abs(args.Path)
workspace := args.Query != ""
result, err := lsp.ClientRequest(&lsp.BridgeRequest{
Method: "symbols",
File: file,
Query: args.Query,
Workspace: workspace,
})
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
if result == nil || string(result) == "null" {
fmt.Println("(no symbols found)")
return
}
var docSymbols []documentSymbol
if json.Unmarshal(result, &docSymbols) == nil && len(docSymbols) > 0 {
printDocSymbols(docSymbols, 0)
return
}
var wsSymbols []workspaceSymbol
if json.Unmarshal(result, &wsSymbols) == nil && len(wsSymbols) > 0 {
for _, s := range wsSymbols {
path := lsp.URIToPath(s.Location.URI)
line := s.Location.Range.Start.Line + 1
fmt.Printf("%s:%d %s [%s]\n", path, line, s.Name, symbolKind(s.Kind))
}
return
}
fmt.Println("(no symbols found)")
})
}
func printDocSymbols(symbols []documentSymbol, indent int) {
prefix := ""
for i := 0; i < indent; i++ {
prefix += " "
}
for _, s := range symbols {
line := s.Range.Start.Line + 1
fmt.Printf("%s%s L%d [%s]\n", prefix, s.Name, line, symbolKind(s.Kind))
if len(s.Children) > 0 {
printDocSymbols(s.Children, indent+1)
}
}
}
type documentSymbol struct {
Name string `json:"name"`
Kind int `json:"kind"`
Range rang `json:"range"`
Children []documentSymbol `json:"children"`
}
type workspaceSymbol struct {
Name string `json:"name"`
Kind int `json:"kind"`
Location struct {
URI string `json:"uri"`
Range rang `json:"range"`
} `json:"location"`
}
type rang struct {
Start struct {
Line int `json:"line"`
} `json:"start"`
}
func symbolKind(k int) string {
kinds := map[int]string{
1: "File", 2: "Module", 3: "Namespace", 4: "Package",
5: "Class", 6: "Method", 7: "Property", 8: "Field",
9: "Constructor", 10: "Enum", 11: "Interface", 12: "Function",
13: "Variable", 14: "Constant", 15: "String", 16: "Number",
17: "Boolean", 18: "Array", 19: "Object", 20: "Key",
21: "Null", 22: "EnumMember", 23: "Struct", 24: "Event",
25: "Operator", 26: "TypeParameter",
}
if name, ok := kinds[k]; ok {
return name
}
return fmt.Sprintf("Kind(%d)", k)
}