mirror of
https://github.com/golang/go
synced 2024-11-18 11:04:42 -07:00
internal/lsp: group document symbols and add more detail
This change uses go/types information to get the types for the different symbols. It also groups the symbols according to their kinds, though this doesn't seem to be reflected in the actual VSCode UI... Updates golang/go#30915 Change-Id: I2caefe01f9834aaad6b9e81cd391d461405ef725 Reviewed-on: https://go-review.googlesource.com/c/tools/+/169438 Reviewed-by: Ian Cottrell <iancottrell@google.com>
This commit is contained in:
parent
3ad05305c9
commit
c02eab13f0
@ -5,11 +5,11 @@
|
||||
package source
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/format"
|
||||
"go/token"
|
||||
"go/types"
|
||||
|
||||
"golang.org/x/tools/internal/span"
|
||||
)
|
||||
@ -26,31 +26,34 @@ const (
|
||||
)
|
||||
|
||||
type Symbol struct {
|
||||
Name string
|
||||
Detail string
|
||||
Span span.Span
|
||||
Kind SymbolKind
|
||||
Children []Symbol
|
||||
Name string
|
||||
Detail string
|
||||
Span span.Span
|
||||
SelectionSpan span.Span
|
||||
Kind SymbolKind
|
||||
Children []Symbol
|
||||
}
|
||||
|
||||
func DocumentSymbols(ctx context.Context, f File) []Symbol {
|
||||
var symbols []Symbol
|
||||
fset := f.GetFileSet(ctx)
|
||||
astFile := f.GetAST(ctx)
|
||||
for _, decl := range astFile.Decls {
|
||||
file := f.GetAST(ctx)
|
||||
pkg := f.GetPackage(ctx)
|
||||
info := pkg.GetTypesInfo()
|
||||
q := qualifier(file, pkg.GetTypes(), info)
|
||||
|
||||
var symbols []Symbol
|
||||
for _, decl := range file.Decls {
|
||||
switch decl := decl.(type) {
|
||||
case *ast.FuncDecl:
|
||||
symbols = append(symbols, funcSymbol(decl, fset))
|
||||
symbols = append(symbols, funcSymbol(decl, info.ObjectOf(decl.Name), fset, q))
|
||||
case *ast.GenDecl:
|
||||
for _, spec := range decl.Specs {
|
||||
switch spec := spec.(type) {
|
||||
case *ast.ImportSpec:
|
||||
symbols = append(symbols, importSymbol(spec, fset))
|
||||
case *ast.TypeSpec:
|
||||
symbols = append(symbols, typeSymbol(spec, fset))
|
||||
symbols = append(symbols, typeSymbol(spec, info.ObjectOf(spec.Name), fset, q))
|
||||
case *ast.ValueSpec:
|
||||
for _, name := range spec.Names {
|
||||
symbols = append(symbols, varSymbol(decl, name, fset))
|
||||
symbols = append(symbols, varSymbol(decl, name, info.ObjectOf(name), fset, q))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -59,67 +62,66 @@ func DocumentSymbols(ctx context.Context, f File) []Symbol {
|
||||
return symbols
|
||||
}
|
||||
|
||||
func funcSymbol(decl *ast.FuncDecl, fset *token.FileSet) Symbol {
|
||||
func funcSymbol(decl *ast.FuncDecl, obj types.Object, fset *token.FileSet, q types.Qualifier) Symbol {
|
||||
s := Symbol{
|
||||
Name: decl.Name.String(),
|
||||
Name: obj.Name(),
|
||||
Kind: FunctionSymbol,
|
||||
}
|
||||
|
||||
if decl.Recv != nil {
|
||||
s.Kind = MethodSymbol
|
||||
}
|
||||
|
||||
span, err := nodeSpan(decl, fset)
|
||||
if err == nil {
|
||||
if span, err := nodeSpan(decl, fset); err == nil {
|
||||
s.Span = span
|
||||
}
|
||||
buf := &bytes.Buffer{}
|
||||
if err := format.Node(buf, fset, decl); err == nil {
|
||||
s.Detail = buf.String()
|
||||
if span, err := nodeSpan(decl.Name, fset); err == nil {
|
||||
s.SelectionSpan = span
|
||||
}
|
||||
sig, _ := obj.Type().(*types.Signature)
|
||||
if sig != nil {
|
||||
if sig.Recv() != nil {
|
||||
s.Kind = MethodSymbol
|
||||
}
|
||||
s.Detail += "("
|
||||
for i := 0; i < sig.Params().Len(); i++ {
|
||||
if i > 0 {
|
||||
s.Detail += ", "
|
||||
}
|
||||
param := sig.Params().At(i)
|
||||
label := types.TypeString(param.Type(), q)
|
||||
if param.Name() != "" {
|
||||
label = fmt.Sprintf("%s %s", param.Name(), label)
|
||||
}
|
||||
s.Detail += label
|
||||
}
|
||||
s.Detail += ")"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func importSymbol(spec *ast.ImportSpec, fset *token.FileSet) Symbol {
|
||||
func typeSymbol(spec *ast.TypeSpec, obj types.Object, fset *token.FileSet, q types.Qualifier) Symbol {
|
||||
s := Symbol{
|
||||
Name: spec.Path.Value,
|
||||
Kind: PackageSymbol,
|
||||
Detail: "import " + spec.Path.Value,
|
||||
}
|
||||
span, err := nodeSpan(spec, fset)
|
||||
if err == nil {
|
||||
s.Span = span
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func typeSymbol(spec *ast.TypeSpec, fset *token.FileSet) Symbol {
|
||||
s := Symbol{
|
||||
Name: spec.Name.String(),
|
||||
Name: obj.Name(),
|
||||
Kind: StructSymbol,
|
||||
}
|
||||
span, err := nodeSpan(spec, fset)
|
||||
if err == nil {
|
||||
if span, err := nodeSpan(spec, fset); err == nil {
|
||||
s.Span = span
|
||||
}
|
||||
if span, err := nodeSpan(spec.Name, fset); err == nil {
|
||||
s.SelectionSpan = span
|
||||
}
|
||||
s.Detail, _ = formatType(obj.Type(), q)
|
||||
return s
|
||||
}
|
||||
|
||||
func varSymbol(decl *ast.GenDecl, name *ast.Ident, fset *token.FileSet) Symbol {
|
||||
func varSymbol(decl ast.Node, name *ast.Ident, obj types.Object, fset *token.FileSet, q types.Qualifier) Symbol {
|
||||
s := Symbol{
|
||||
Name: name.Name,
|
||||
Name: obj.Name(),
|
||||
Kind: VariableSymbol,
|
||||
}
|
||||
|
||||
if decl.Tok == token.CONST {
|
||||
s.Kind = ConstantSymbol
|
||||
}
|
||||
|
||||
span, err := nodeSpan(name, fset)
|
||||
if err == nil {
|
||||
if span, err := nodeSpan(decl, fset); err == nil {
|
||||
s.Span = span
|
||||
}
|
||||
|
||||
if span, err := nodeSpan(name, fset); err == nil {
|
||||
s.SelectionSpan = span
|
||||
}
|
||||
s.Detail = types.TypeString(obj.Type(), q)
|
||||
return s
|
||||
}
|
||||
|
||||
|
@ -5,9 +5,8 @@
|
||||
package lsp
|
||||
|
||||
import (
|
||||
"golang.org/x/tools/internal/lsp/source"
|
||||
|
||||
"golang.org/x/tools/internal/lsp/protocol"
|
||||
"golang.org/x/tools/internal/lsp/source"
|
||||
)
|
||||
|
||||
func toProtocolDocumentSymbols(m *protocol.ColumnMapper, symbols []source.Symbol) []protocol.DocumentSymbol {
|
||||
@ -21,6 +20,8 @@ func toProtocolDocumentSymbols(m *protocol.ColumnMapper, symbols []source.Symbol
|
||||
}
|
||||
if r, err := m.Range(s.Span); err == nil {
|
||||
ps.Range = r
|
||||
}
|
||||
if r, err := m.Range(s.SelectionSpan); err == nil {
|
||||
ps.SelectionRange = r
|
||||
}
|
||||
result = append(result, ps)
|
||||
|
Loading…
Reference in New Issue
Block a user