blob: e364cd9616797afd0827504ab6a8a6e4f07ca3ec [file] [log] [blame]
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package render
import (
"fmt"
"go/ast"
"go/token"
"strings"
)
// shortOneLineNodeDepth returns a heavily-truncated, one-line summary of the
// given node. It will only accept an *ast.FuncDecl when not called recursively.
// The depth specifies the current depth when traversing the AST and the
// function will stop traversing once it reaches maxSynopsisNodeDepth.
func shortOneLineNodeDepth(fset *token.FileSet, node ast.Node, depth int) (string, error) {
if _, ok := node.(*ast.FuncDecl); !ok && depth == 0 {
return "", fmt.Errorf("only *ast.FuncDecl nodes are supported at top level")
}
const dotDotDot = "..."
if depth == maxSynopsisNodeDepth {
return dotDotDot, nil
}
depth++
switch n := node.(type) {
case *ast.FuncDecl:
// Formats func declarations.
name := n.Name.Name
recv, err := shortOneLineNodeDepth(fset, n.Recv, depth)
if err != nil {
return "", err
}
if len(recv) > 0 {
recv = "(" + recv + ") "
}
fnc, err := shortOneLineNodeDepth(fset, n.Type, depth)
if err != nil {
return "", err
}
fnc = strings.TrimPrefix(fnc, "func")
return recv + name + fnc, nil
case *ast.FuncType:
var params []string
if n.Params != nil {
for _, field := range n.Params.List {
f, err := shortOneLineField(fset, field, depth)
if err != nil {
return "", err
}
params = append(params, f)
}
}
return fmt.Sprintf("func(%s)", joinStrings(params)), nil
case *ast.FieldList:
if n == nil || len(n.List) == 0 {
return "", nil
}
if len(n.List) == 1 {
return shortOneLineField(fset, n.List[0], depth)
}
return dotDotDot, nil
default:
return "", nil
}
}
// shortOneLineField returns a heavily-truncated, one-line summary of the field.
// Notably, it omits the field types in its result.
func shortOneLineField(fset *token.FileSet, field *ast.Field, depth int) (string, error) {
if len(field.Names) == 0 {
return shortOneLineNodeDepth(fset, field.Type, depth)
}
var names []string
for _, name := range field.Names {
names = append(names, name.Name)
}
s, err := shortOneLineNodeDepth(fset, field.Type, depth)
if err != nil {
return "", err
}
return joinStrings(names) + s, nil
}