// 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) }