Categorygithub.com/sirkon/dst
modulepackage
0.26.4
Repository: https://github.com/sirkon/dst.git
Documentation: pkg.go.dev

# README

Build Status Documentation codecov stability-stable Sourcegraph

Decorated Syntax Tree

The dst package enables manipulation of a Go syntax tree with high fidelity. Decorations (e.g. comments and line spacing) remain attached to the correct nodes as the tree is modified.

Where does go/ast break?

The go/ast package wasn't created with source manipulation as an intended use-case. Comments are stored by their byte offset instead of attached to nodes, so re-arranging nodes breaks the output. See this Go issue for more information.

Consider this example where we want to reverse the order of the two statements. As you can see the comments don't remain attached to the correct nodes:

code := `package a

func main(){
	var a int    // foo
	var b string // bar
}
`
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "", code, parser.ParseComments)
if err != nil {
	panic(err)
}

list := f.Decls[0].(*ast.FuncDecl).Body.List
list[0], list[1] = list[1], list[0]

if err := format.Node(os.Stdout, fset, f); err != nil {
	panic(err)
}

//Output:
//package a
//
//func main() {
//	// foo
//	var b string
//	var a int
//	// bar
//}

Here's the same example using dst:

code := `package a

func main(){
	var a int    // foo
	var b string // bar
}
`
f, err := decorator.Parse(code)
if err != nil {
	panic(err)
}

list := f.Decls[0].(*dst.FuncDecl).Body.List
list[0], list[1] = list[1], list[0]

if err := decorator.Print(f); err != nil {
	panic(err)
}

//Output:
//package a
//
//func main() {
//	var b string // bar
//	var a int    // foo
//}

Usage

Parsing a source file to dst and printing the results after modification can be accomplished with several Parse and Print convenience functions in the decorator package.

For more fine-grained control you can use Decorator to convert from ast to dst, and Restorer to convert back again.

Comments

Comments are added at decoration attachment points. See here for a full list of these points, along with demonstration code of where they are rendered in the output.

The decoration attachment points have convenience functions Append, Prepend, Replace, Clear and All to accomplish common tasks. Use the full text of your comment including the // or /**/ markers. When adding a line comment, a newline is automatically rendered.

code := `package main

func main() {
	println("Hello World!")
}`
f, err := decorator.Parse(code)
if err != nil {
	panic(err)
}

call := f.Decls[0].(*dst.FuncDecl).Body.List[0].(*dst.ExprStmt).X.(*dst.CallExpr)

call.Decs.Start.Append("// you can add comments at the start...")
call.Decs.Fun.Append("/* ...in the middle... */")
call.Decs.End.Append("// or at the end.")

if err := decorator.Print(f); err != nil {
	panic(err)
}

//Output:
//package main
//
//func main() {
//	// you can add comments at the start...
//	println /* ...in the middle... */ ("Hello World!") // or at the end.
//}

Spacing

The Before property marks the node as having a line space (new line or empty line) before the node. These spaces are rendered before any decorations attached to the Start decoration point. The After property is similar but rendered after the node (and after any End decorations).

code := `package main

func main() {
	println(a, b, c)
}`
f, err := decorator.Parse(code)
if err != nil {
	panic(err)
}

call := f.Decls[0].(*dst.FuncDecl).Body.List[0].(*dst.ExprStmt).X.(*dst.CallExpr)

call.Decs.Before = dst.EmptyLine
call.Decs.After = dst.EmptyLine

for _, v := range call.Args {
	v := v.(*dst.Ident)
	v.Decs.Before = dst.NewLine
	v.Decs.After = dst.NewLine
}

if err := decorator.Print(f); err != nil {
	panic(err)
}

//Output:
//package main
//
//func main() {
//
//	println(
//		a,
//		b,
//		c,
//	)
//
//}

Decorations

The common decoration properties (Start, End, Before and After) occur on all nodes, and can be accessed with the Decorations() method on the Node interface:

code := `package main

func main() {
	var i int
	i++
	println(i)
}`
f, err := decorator.Parse(code)
if err != nil {
	panic(err)
}

list := f.Decls[0].(*dst.FuncDecl).Body.List

list[0].Decorations().Before = dst.EmptyLine
list[0].Decorations().End.Append("// the Decorations method allows access to the common")
list[1].Decorations().End.Append("// decoration properties (Before, Start, End and After)")
list[2].Decorations().End.Append("// for all nodes.")
list[2].Decorations().After = dst.EmptyLine

if err := decorator.Print(f); err != nil {
	panic(err)
}

//Output:
//package main
//
//func main() {
//
//	var i int  // the Decorations method allows access to the common
//	i++        // decoration properties (Before, Start, End and After)
//	println(i) // for all nodes.
//
//}

dstutil.Decorations

While debugging, it is often useful to have a list of all decorations attached to a node. The dstutil package provides a helper function Decorations which returns a list of the attachment points and all decorations for any node:

code := `package main

// main comment
// is multi line
func main() {

	if true {

		// foo
		println( /* foo inline */ "foo")
	} else if false {
		println /* bar inline */ ("bar")

		// bar after

	} else {
		// empty block
	}
}`

f, err := decorator.Parse(code)
if err != nil {
	panic(err)
}

dst.Inspect(f, func(node dst.Node) bool {
	if node == nil {
		return false
	}
	before, after, points := dstutil.Decorations(node)
	var info string
	if before != dst.None {
		info += fmt.Sprintf("- Before: %s\n", before)
	}
	for _, point := range points {
		if len(point.Decs) == 0 {
			continue
		}
		info += fmt.Sprintf("- %s: [", point.Name)
		for i, dec := range point.Decs {
			if i > 0 {
				info += ", "
			}
			info += fmt.Sprintf("%q", dec)
		}
		info += "]\n"
	}
	if after != dst.None {
		info += fmt.Sprintf("- After: %s\n", after)
	}
	if info != "" {
		fmt.Printf("%T\n%s\n", node, info)
	}
	return true
})

//Output:
//*dst.FuncDecl
//- Before: NewLine
//- Start: ["// main comment", "// is multi line"]
//
//*dst.IfStmt
//- Before: NewLine
//- After: NewLine
//
//*dst.ExprStmt
//- Before: NewLine
//- Start: ["// foo"]
//- After: NewLine
//
//*dst.CallExpr
//- Lparen: ["/* foo inline */"]
//
//*dst.ExprStmt
//- Before: NewLine
//- End: ["\n", "\n", "// bar after"]
//- After: NewLine
//
//*dst.CallExpr
//- Fun: ["/* bar inline */"]
//
//*dst.BlockStmt
//- Lbrace: ["\n", "// empty block"]

Newlines

The Before and After properties cover the majority of cases, but occasionally a newline needs to be rendered inside a node. Simply add a \n decoration to accomplish this.

Clone

Re-using an existing node elsewhere in the tree will panic when the tree is restored to ast. Instead, use the Clone function to make a deep copy of the node before re-use:

code := `package main

var i /* a */ int`

f, err := decorator.Parse(code)
if err != nil {
	panic(err)
}

cloned := dst.Clone(f.Decls[0]).(*dst.GenDecl)

cloned.Decs.Before = dst.NewLine
cloned.Specs[0].(*dst.ValueSpec).Names[0].Name = "j"
cloned.Specs[0].(*dst.ValueSpec).Names[0].Decs.End.Replace("/* b */")

f.Decls = append(f.Decls, cloned)

if err := decorator.Print(f); err != nil {
	panic(err)
}

//Output:
//package main
//
//var i /* a */ int
//var j /* b */ int

Apply

The dstutil package is a fork of golang.org/x/tools/go/ast/astutil, and provides the Apply function with similar semantics.

Imports

The decorator can automatically manage the import block, which is a non-trivial task.

Use NewDecoratorWithImports and NewRestorerWithImports to create an import aware decorator / restorer.

During decoration, remote identifiers are normalised - *ast.SelectorExpr nodes that represent qualified identifiers are replaced with *dst.Ident nodes with the Path field set to the path of the imported package.

When adding a qualified identifier node, there is no need to use *dst.SelectorExpr - just add a *dst.Ident and set Path to the imported package path. The restorer will wrap it in a *ast.SelectorExpr where appropriate when converting back to ast, and also update the import block.

To enable import management, the decorator must be able to resolve the imported package for selector expressions and identifiers, and the restorer must be able to resolve the name of a package given it's path. Several implementations for these resolvers are provided, and the best method will depend on the environment. See below for more details.

Load

The Load convenience function uses go/packages to load packages and decorate all loaded ast files, with import management enabled:

// Create a simple module in a temporary directory
dir, err := tempDir(map[string]string{
	"go.mod":	"module root",
	"main.go":	"package main \n\n func main() {}",
})
defer os.RemoveAll(dir)
if err != nil {
	panic(err)
}

// Use the Load convenience function that calls go/packages to load the package. All loaded
// ast files are decorated to dst.
pkgs, err := decorator.Load(&packages.Config{Dir: dir, Mode: packages.LoadSyntax}, "root")
if err != nil {
	panic(err)
}
p := pkgs[0]
f := p.Syntax[0]

// Add a call expression. Note we don't have to use a SelectorExpr - just adding an Ident with
// the imported package path will do. The restorer will add SelectorExpr where appropriate when
// converting back to ast. Note the new Path field on *dst.Ident. Set this to the package path
// of the imported package, and the restorer will automatically add the import to the import
// block.
b := f.Decls[0].(*dst.FuncDecl).Body
b.List = append(b.List, &dst.ExprStmt{
	X: &dst.CallExpr{
		Fun:	&dst.Ident{Path: "fmt", Name: "Println"},
		Args: []dst.Expr{
			&dst.BasicLit{Kind: token.STRING, Value: strconv.Quote("Hello, World!")},
		},
	},
})

// Create a restorer with the import manager enabled, and print the result. As you can see, the
// import block is automatically managed, and the Println ident is converted to a SelectorExpr:
r := decorator.NewRestorerWithImports("root", gopackages.New(dir))
if err := r.Print(p.Syntax[0]); err != nil {
	panic(err)
}

//Output:
//package main
//
//import "fmt"
//
//func main() { fmt.Println("Hello, World!") }

Mappings

The decorator exposes Dst.Nodes and Ast.Nodes which map between ast.Node and dst.Node. This enables systems that refer to ast nodes (such as go/types) to be used:

code := `package main

func main() {
	var i int
	i++
	println(i)
}`

// Parse the code to AST
fset := token.NewFileSet()
astFile, err := parser.ParseFile(fset, "", code, parser.ParseComments)
if err != nil {
	panic(err)
}

// Invoke the type checker using AST as input
typesInfo := types.Info{
	Defs:	make(map[*ast.Ident]types.Object),
	Uses:	make(map[*ast.Ident]types.Object),
}
conf := &types.Config{}
if _, err := conf.Check("", fset, []*ast.File{astFile}, &typesInfo); err != nil {
	panic(err)
}

// Create a new decorator, which will track the mapping between ast and dst nodes
dec := decorator.NewDecorator(fset)

// Decorate the *ast.File to give us a *dst.File
f, err := dec.DecorateFile(astFile)
if err != nil {
	panic(err)
}

// Find the *dst.Ident for the definition of "i"
dstDef := f.Decls[0].(*dst.FuncDecl).Body.List[0].(*dst.DeclStmt).Decl.(*dst.GenDecl).Specs[0].(*dst.ValueSpec).Names[0]

// Find the *ast.Ident using the Ast.Nodes mapping
astDef := dec.Ast.Nodes[dstDef].(*ast.Ident)

// Find the types.Object corresponding to "i"
obj := typesInfo.Defs[astDef]

// Find all the uses of that object
var astUses []*ast.Ident
for id, ob := range typesInfo.Uses {
	if ob != obj {
		continue
	}
	astUses = append(astUses, id)
}

// Find each *dst.Ident in the Dst.Nodes mapping
var dstUses []*dst.Ident
for _, id := range astUses {
	dstUses = append(dstUses, dec.Dst.Nodes[id].(*dst.Ident))
}

// Change the name of the original definition and all uses
dstDef.Name = "foo"
for _, id := range dstUses {
	id.Name = "foo"
}

// Print the DST
if err := decorator.Print(f); err != nil {
	panic(err)
}

//Output:
//package main
//
//func main() {
//	var foo int
//	foo++
//	println(foo)
//}

Resolvers

There are two separate interfaces defined by the resolver package which allow the decorator and restorer to automatically manage the imports block.

The decorator uses a DecoratorResolver which resolves the package path of any *ast.Ident. This is complicated by dot-import syntax (see below).

The restorer uses a RestorerResolver which resolves the name of any package given the path. This is complicated by vendoring and Go modules.

When Resolver is set on Decorator or Restorer, the Path property must be set to the local package path.

Several implementations of both interfaces that are suitable for different environments are provided:

DecoratorResolver

gotypes

The gotypes package provides a DecoratorResolver with full dot-import compatibility. However it requires full export data for all imported packages, so the Uses map from go/types.Info is required. There are several methods of generating go/types.Info. Using golang.org/x/tools/go/packages.Load is recommended for full Go modules compatibility. See the decorator.Load convenience function to automate this.

goast

The goast package provides a simplified DecoratorResolver that only needs to scan a single ast file. This is unable to resolve identifiers from dot-imported packages, so will panic if a dot-import is encountered in the import block. It uses the provided RestorerResolver to resolve the names of all imported packages. If no RestorerResolver is provided, the guess implementation is used.

RestorerResolver

gopackages

The gopackages package provides a RestorerResolver with full compatibility with Go modules. It uses golang.org/x/tools/go/packages to load the package data. This may be very slow, and uses the go command line tool to query package data, so may not be compatible with some environments.

gobuild

The gobuild package provides an alternative RestorerResolver that uses the legacy go/build system to load the imported package data. This may be needed in some circumstances and provides better performance than go/packages. However, this is not Go modules aware.

guess and simple

The guess and simple packages provide simple RestorerResolver implementations that may be useful in certain circumstances, or where performance is critical. simple resolves paths only if they occur in a provided map. guess guesses the package name based on the last part of the path.

Example

Here's an example of supplying resolvers for the decorator and restorer:

code := `package main

	import "fmt"

	func main() {
		fmt.Println("a")
	}`

dec := decorator.NewDecoratorWithImports(token.NewFileSet(), "main", goast.New())

f, err := dec.Parse(code)
if err != nil {
	panic(err)
}

f.Decls[1].(*dst.FuncDecl).Body.List[0].(*dst.ExprStmt).X.(*dst.CallExpr).Args = []dst.Expr{
	&dst.CallExpr{
		Fun: &dst.Ident{Name: "A", Path: "foo.bar/baz"},
	},
}

res := decorator.NewRestorerWithImports("main", guess.New())
if err := res.Print(f); err != nil {
	panic(err)
}

//Output:
//package main
//
//import (
//	"fmt"
//
//	"foo.bar/baz"
//)
//
//func main() {
//	fmt.Println(baz.A())
//}

Alias

To control the alias of imports, use a FileRestorer:

code := `package main

	import "fmt"

	func main() {
		fmt.Println("a")
	}`

dec := decorator.NewDecoratorWithImports(token.NewFileSet(), "main", goast.New())

f, err := dec.Parse(code)
if err != nil {
	panic(err)
}

res := decorator.NewRestorerWithImports("main", guess.New())

fr := res.FileRestorer()
fr.Alias["fmt"] = "fmt1"

if err := fr.Print(f); err != nil {
	panic(err)
}

//Output:
//package main
//
//import fmt1 "fmt"
//
//func main() {
//	fmt1.Println("a")
//}

Details

For more information on exactly how the imports block is managed, read through the test cases.

Dot-imports

Consider this file...

package main

import (
	. "a"
)

func main() {
	B()
	C()
}

B and C could be local identifiers from a different file in this package, or from the imported package a. If only one is from a and it is removed, we should remove the import when we restore to ast. Thus the resolver needs to be able to resolve the package using the full info from go/types.

Status

This package is well tested and used in many projects. The API should be considered stable going forward.

Chat?

Feel free to create an issue or chat in the #dst Gophers Slack channel.

# Packages

No description provided by the author
No description provided by the author
No description provided by the author

# Functions

Clone returns a deep copy of the node, ready to be re-used elsewhere in the tree.
CloneObject returns nil: After cloning a node, it should not be attached to the same object / scope.
CloneScope returns nil: After cloning a node, it should not be attached to the same object / scope.
Fprint prints the (sub-)tree starting at AST node x to w.
Inspect traverses an AST in depth-first order: It starts by calling f(node); node must not be nil.
IsExported reports whether name is an exported Go symbol (that is, whether it begins with an upper-case letter).
NewIdent creates a new Ident without position.
NewObj creates a new object of a given kind and name.
NewPackage creates a new Package node from a set of File nodes.
NewScope creates a new scope nested in the outer scope.
NotNilFilter returns true for field values that are not nil; it returns false otherwise.
Print prints x to standard output, skipping nil fields.
Walk traverses an AST in depth-first order: It starts by calling v.Visit(node); node must not be nil.

# Constants

for error handling.
constant.
EmptyLine is a double "\n".
function or method.
label.
NewLine is a single "\n".
None means no extra spacing.
package.
No description provided by the author
No description provided by the author
type.
variable.

# Structs

A type is represented by a tree consisting of one or more of the following type-specific expression nodes.
ArrayTypeDecorations holds decorations for ArrayType: type R /*Start*/ [ /*Lbrack*/ 1] /*Len*/ int /*End*/ .
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
AssignStmtDecorations holds decorations for AssignStmt: /*Start*/ i = /*Tok*/ 1 /*End*/ .
A declaration is represented by one of the following declaration nodes.
BadDeclDecorations holds decorations for BadDecl: .
An expression is represented by a tree consisting of one or more of the following concrete expression nodes.
BadExprDecorations holds decorations for BadExpr: .
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
BadStmtDecorations holds decorations for BadStmt: .
An expression is represented by a tree consisting of one or more of the following concrete expression nodes.
BasicLitDecorations holds decorations for BasicLit: .
An expression is represented by a tree consisting of one or more of the following concrete expression nodes.
BinaryExprDecorations holds decorations for BinaryExpr: var P = /*Start*/ 1 /*X*/ & /*Op*/ 2 /*End*/ .
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
BlockStmtDecorations holds decorations for BlockStmt: if true /*Start*/ { /*Lbrace*/ i++ } /*End*/ func() /*Start*/ { /*Lbrace*/ i++ } /*End*/ () .
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
BranchStmtDecorations holds decorations for BranchStmt: /*Start*/ goto /*Tok*/ A /*End*/ .
An expression is represented by a tree consisting of one or more of the following concrete expression nodes.
CallExprDecorations holds decorations for CallExpr: var L = /*Start*/ C /*Fun*/ ( /*Lparen*/ 0, []int{}..
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
CaseClauseDecorations holds decorations for CaseClause: switch i { /*Start*/ case /*Case*/ 1: /*Colon*/ i++ /*End*/ } .
A type is represented by a tree consisting of one or more of the following type-specific expression nodes.
ChanTypeDecorations holds decorations for ChanType: type W /*Start*/ chan /*Begin*/ int /*End*/ type X /*Start*/ <-chan /*Begin*/ int /*End*/ type Y /*Start*/ chan /*Begin*/ <- /*Arrow*/ int /*End*/ .
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
CommClauseDecorations holds decorations for CommClause: select { /*Start*/ case /*Case*/ a := <-c /*Comm*/ : /*Colon*/ print(a) /*End*/ } .
An expression is represented by a tree consisting of one or more of the following concrete expression nodes.
CompositeLitDecorations holds decorations for CompositeLit: var D = /*Start*/ A /*Type*/ { /*Lbrace*/ A: 0} /*End*/ .
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
DeclStmtDecorations holds decorations for DeclStmt: .
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
DeferStmtDecorations holds decorations for DeferStmt: /*Start*/ defer /*Defer*/ func() {}() /*End*/ .
An expression is represented by a tree consisting of one or more of the following concrete expression nodes.
EllipsisDecorations holds decorations for Ellipsis: func B(a /*Start*/ ..
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
EmptyStmtDecorations holds decorations for EmptyStmt: .
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
ExprStmtDecorations holds decorations for ExprStmt: .
A Field represents a Field declaration list in a struct type, a method list in an interface type, or a parameter/result declaration in a signature.
FieldDecorations holds decorations for Field: type A struct { /*Start*/ A int /*Type*/ `a:"a"` /*End*/ } .
A FieldList represents a list of Fields, enclosed by parentheses or braces.
FieldListDecorations holds decorations for FieldList: type A1 struct /*Start*/ { /*Opening*/ a, b int c string } /*End*/ .
A File node represents a Go source file.
FileDecorations holds decorations for File: /*Start*/ package /*Package*/ data /*Name*/ .
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
ForStmtDecorations holds decorations for ForStmt: /*Start*/ for /*For*/ { i++ } /*End*/ /*Start*/ for /*For*/ i < 1 /*Cond*/ { i++ } /*End*/ /*Start*/ for /*For*/ i = 0; /*Init*/ i < 10; /*Cond*/ i++ /*Post*/ { i++ } /*End*/ .
A declaration is represented by one of the following declaration nodes.
FuncDeclDecorations holds decorations for FuncDecl: /*Start*/ func /*Func*/ d /*Name*/ (d, e int) /*Params*/ { return } /*End*/ /*Start*/ func /*Func*/ (a *A) /*Recv*/ e /*Name*/ (d, e int) /*Params*/ { return } /*End*/ /*Start*/ func /*Func*/ (a *A) /*Recv*/ f /*Name*/ (d, e int) /*Params*/ (f, g int) /*Results*/ { return } /*End*/ .
An expression is represented by a tree consisting of one or more of the following concrete expression nodes.
FuncLitDecorations holds decorations for FuncLit: var C = /*Start*/ func(a int, b ...int) (c int) /*Type*/ { return 0 } /*End*/ .
A type is represented by a tree consisting of one or more of the following type-specific expression nodes.
FuncTypeDecorations holds decorations for FuncType: type T /*Start*/ func /*Func*/ (a int) /*Params*/ (b int) /*End*/ .
A declaration is represented by one of the following declaration nodes.
GenDeclDecorations holds decorations for GenDecl: /*Start*/ const /*Tok*/ ( /*Lparen*/ a, b = 1, 2 c = 3 ) /*End*/ /*Start*/ const /*Tok*/ d = 1 /*End*/ .
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
GoStmtDecorations holds decorations for GoStmt: /*Start*/ go /*Go*/ func() {}() /*End*/ .
An expression is represented by a tree consisting of one or more of the following concrete expression nodes.
IdentDecorations holds decorations for Ident: /*Start*/ i /*End*/ ++ /*Start*/ fmt.
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
IfStmtDecorations holds decorations for IfStmt: /*Start*/ if /*If*/ a := b; /*Init*/ a /*Cond*/ { i++ } else /*Else*/ { i++ } /*End*/ .
A Spec node represents a single (non-parenthesized) import, constant, type, or variable declaration.
ImportSpecDecorations holds decorations for ImportSpec: import ( /*Start*/ fmt /*Name*/ "fmt" /*End*/ ) .
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
IncDecStmtDecorations holds decorations for IncDecStmt: /*Start*/ i /*X*/ ++ /*End*/ .
An expression is represented by a tree consisting of one or more of the following concrete expression nodes.
IndexExprDecorations holds decorations for IndexExpr: var G = /*Start*/ []int{0} /*X*/ [ /*Lbrack*/ 0 /*Index*/] /*End*/ .
An expression is represented by a tree consisting of one or more of the following concrete expression nodes.
IndexListExprDecorations holds decorations for IndexListExpr: .
A type is represented by a tree consisting of one or more of the following type-specific expression nodes.
InterfaceTypeDecorations holds decorations for InterfaceType: type U /*Start*/ interface /*Interface*/ { A() } /*End*/ .
An expression is represented by a tree consisting of one or more of the following concrete expression nodes.
KeyValueExprDecorations holds decorations for KeyValueExpr: var Q = map[string]string{ /*Start*/ "a" /*Key*/ : /*Colon*/ "a", /*End*/ } .
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
LabeledStmtDecorations holds decorations for LabeledStmt: /*Start*/ A /*Label*/ : /*Colon*/ print("Stmt") /*End*/ .
A type is represented by a tree consisting of one or more of the following type-specific expression nodes.
MapTypeDecorations holds decorations for MapType: type V /*Start*/ map[ /*Map*/ int] /*Key*/ int /*End*/ .
NodeDecs holds the decorations that are common to all nodes (except Package).
An Object describes a named language entity such as a package, constant, type, variable, function (incl.
A Package node represents a set of source files collectively building a Go package.
PackageDecorations holds decorations for Package: .
An expression is represented by a tree consisting of one or more of the following concrete expression nodes.
ParenExprDecorations holds decorations for ParenExpr: var E = /*Start*/ ( /*Lparen*/ 1 + 1 /*X*/) /*End*/ / 2 .
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
RangeStmtDecorations holds decorations for RangeStmt: /*Start*/ for range /*Range*/ a /*X*/ { } /*End*/ /*Start*/ for /*For*/ k /*Key*/ := range /*Range*/ a /*X*/ { print(k) } /*End*/ /*Start*/ for /*For*/ k /*Key*/, v /*Value*/ := range /*Range*/ a /*X*/ { print(k, v) } /*End*/ .
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
ReturnStmtDecorations holds decorations for ReturnStmt: func() int { /*Start*/ return /*Return*/ 1 /*End*/ }() .
A Scope maintains the set of named language entities declared in the scope and a link to the immediately surrounding (outer) scope.
An expression is represented by a tree consisting of one or more of the following concrete expression nodes.
SelectorExprDecorations holds decorations for SelectorExpr: var F = /*Start*/ tt.
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
SelectStmtDecorations holds decorations for SelectStmt: /*Start*/ select /*Select*/ { } /*End*/ .
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
SendStmtDecorations holds decorations for SendStmt: /*Start*/ c /*Chan*/ <- /*Arrow*/ 0 /*End*/ .
An expression is represented by a tree consisting of one or more of the following concrete expression nodes.
SliceExprDecorations holds decorations for SliceExpr: var H = /*Start*/ []int{0, 1, 2} /*X*/ [ /*Lbrack*/ 1: /*Low*/ 2: /*High*/ 3 /*Max*/] /*End*/ var H1 = /*Start*/ []int{0, 1, 2} /*X*/ [ /*Lbrack*/ 1: /*Low*/ 2 /*High*/] /*End*/ var H2 = /*Start*/ []int{0} /*X*/ [: /*Low*/] /*End*/ var H3 = /*Start*/ []int{0} /*X*/ [ /*Lbrack*/ 1: /*Low*/] /*End*/ var H4 = /*Start*/ []int{0, 1, 2} /*X*/ [: /*Low*/ 2 /*High*/] /*End*/ var H5 = /*Start*/ []int{0, 1, 2} /*X*/ [: /*Low*/ 2: /*High*/ 3 /*Max*/] /*End*/ .
An expression is represented by a tree consisting of one or more of the following concrete expression nodes.
StarExprDecorations holds decorations for StarExpr: var N = /*Start*/ * /*Star*/ p /*End*/ .
A type is represented by a tree consisting of one or more of the following type-specific expression nodes.
StructTypeDecorations holds decorations for StructType: type S /*Start*/ struct /*Struct*/ { A int } /*End*/ .
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
SwitchStmtDecorations holds decorations for SwitchStmt: /*Start*/ switch /*Switch*/ i /*Tag*/ { } /*End*/ /*Start*/ switch /*Switch*/ a := i; /*Init*/ a /*Tag*/ { } /*End*/ .
An expression is represented by a tree consisting of one or more of the following concrete expression nodes.
TypeAssertExprDecorations holds decorations for TypeAssertExpr: var J = /*Start*/ f.
A Spec node represents a single (non-parenthesized) import, constant, type, or variable declaration.
TypeSpecDecorations holds decorations for TypeSpec: type ( /*Start*/ T1 /*Name*/ []int /*End*/ ) type ( /*Start*/ T2 = /*Name*/ T1 /*End*/ ) .
A statement is represented by a tree consisting of one or more of the following concrete statement nodes.
TypeSwitchStmtDecorations holds decorations for TypeSwitchStmt: /*Start*/ switch /*Switch*/ f.(type) /*Assign*/ { } /*End*/ /*Start*/ switch /*Switch*/ g := f.(type) /*Assign*/ { case int: print(g) } /*End*/ /*Start*/ switch /*Switch*/ g := f; /*Init*/ g := g.(type) /*Assign*/ { case int: print(g) } /*End*/ .
An expression is represented by a tree consisting of one or more of the following concrete expression nodes.
UnaryExprDecorations holds decorations for UnaryExpr: var O = /*Start*/ ^ /*Op*/ 1 /*End*/ .
A Spec node represents a single (non-parenthesized) import, constant, type, or variable declaration.
ValueSpecDecorations holds decorations for ValueSpec: var ( /*Start*/ j = /*Assign*/ 1 /*End*/ ) var ( /*Start*/ k, l = /*Assign*/ 1, 2 /*End*/ ) var ( /*Start*/ m, n int = /*Assign*/ 1, 2 /*End*/ ) .

# Interfaces

All declaration nodes implement the Decl interface.
All expression nodes implement the Expr interface.
Node is satisfied by all nodes types.
A Spec node represents a single (non-parenthesized) import, constant, type, or variable declaration.
All statement nodes implement the Stmt interface.
A Visitor's Visit method is invoked for each node encountered by Walk.

# Type aliases

The direction of a channel type is indicated by a bit mask including one or both of the following constants.
Decorations is a slice of strings which are rendered with the node.
A FieldFilter may be provided to Fprint to control the output.
An Importer resolves import paths to package Objects.
ObjKind describes what an object represents.
SpaceType represents the line spacing before or after a node.