112 lines
3.1 KiB
Go
112 lines
3.1 KiB
Go
// Package astfmt implements `ast.Node` formatting with fmt-like API.
|
|
package astfmt
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"go/ast"
|
|
"go/printer"
|
|
"go/token"
|
|
"io"
|
|
)
|
|
|
|
// Println calls fmt.Println with additional support of %s format
|
|
// for ast.Node arguments.
|
|
//
|
|
// Uses empty file set for AST printing.
|
|
func Println(args ...interface{}) error {
|
|
return defaultPrinter.Println(args...)
|
|
}
|
|
|
|
// Fprintf calls fmt.Fprintf with additional support of %s format
|
|
// for ast.Node arguments.
|
|
//
|
|
// Uses empty file set for AST printing.
|
|
func Fprintf(w io.Writer, format string, args ...interface{}) error {
|
|
return defaultPrinter.Fprintf(w, format, args...)
|
|
}
|
|
|
|
// Sprintf calls fmt.Sprintf with additional support of %s format
|
|
// for ast.Node arguments.
|
|
//
|
|
// Uses empty file set for AST printing.
|
|
func Sprintf(format string, args ...interface{}) string {
|
|
return defaultPrinter.Sprintf(format, args...)
|
|
}
|
|
|
|
// Sprint calls fmt.Sprint with additional support of %s format
|
|
// for ast.Node arguments.
|
|
//
|
|
// Uses empty file set for AST printing.
|
|
func Sprint(args ...interface{}) string {
|
|
return defaultPrinter.Sprint(args...)
|
|
}
|
|
|
|
// NewPrinter returns printer that uses bound file set when printing AST nodes.
|
|
func NewPrinter(fset *token.FileSet) *Printer {
|
|
return &Printer{fset: fset}
|
|
}
|
|
|
|
// Printer provides API close to fmt package for printing AST nodes.
|
|
// Unlike freestanding functions from this package, it makes it possible
|
|
// to associate appropriate file set for better output.
|
|
type Printer struct {
|
|
fset *token.FileSet
|
|
}
|
|
|
|
// Println printer method is like Println function, but uses bound file set when printing.
|
|
func (p *Printer) Println(args ...interface{}) error {
|
|
_, err := fmt.Println(wrapArgs(p.fset, args)...)
|
|
return err
|
|
}
|
|
|
|
// Fprintf printer method is like Fprintf function, but uses bound file set when printing.
|
|
func (p *Printer) Fprintf(w io.Writer, format string, args ...interface{}) error {
|
|
_, err := fmt.Fprintf(w, format, wrapArgs(p.fset, args)...)
|
|
return err
|
|
}
|
|
|
|
// Sprintf printer method is like Sprintf function, but uses bound file set when printing.
|
|
func (p *Printer) Sprintf(format string, args ...interface{}) string {
|
|
return fmt.Sprintf(format, wrapArgs(p.fset, args)...)
|
|
}
|
|
|
|
// Sprint printer method is like Sprint function, but uses bound file set when printing.
|
|
func (p *Printer) Sprint(args ...interface{}) string {
|
|
return fmt.Sprint(wrapArgs(p.fset, args)...)
|
|
}
|
|
|
|
// defaultPrinter is used in printing functions like Println.
|
|
// Uses empty file set.
|
|
var defaultPrinter = NewPrinter(token.NewFileSet())
|
|
|
|
// wrapArgs returns arguments slice with every ast.Node element
|
|
// replaced with fmtNode wrapper that supports additional formatting.
|
|
func wrapArgs(fset *token.FileSet, args []interface{}) []interface{} {
|
|
for i := range args {
|
|
if x, ok := args[i].(ast.Node); ok {
|
|
args[i] = fmtNode{fset: fset, node: x}
|
|
}
|
|
}
|
|
return args
|
|
}
|
|
|
|
type fmtNode struct {
|
|
fset *token.FileSet
|
|
node ast.Node
|
|
}
|
|
|
|
func (n fmtNode) String() string {
|
|
var buf bytes.Buffer
|
|
if err := printer.Fprint(&buf, n.fset, n.node); err != nil {
|
|
return fmt.Sprintf("%%!s(ast.Node=%s)", err)
|
|
}
|
|
return buf.String()
|
|
}
|
|
|
|
func (n fmtNode) GoString() string {
|
|
var buf bytes.Buffer
|
|
fmt.Fprintf(&buf, "%#v", n.node)
|
|
return buf.String()
|
|
}
|