// transformItem takes a reflect.Value representing a variable of type ast.Node // transforms its child elements recursively with apply, and then transforms the // actual element if it contains an expression. func (tr *Transformer) transformItem(rv reflect.Value) (reflect.Value, bool, map[string]ast.Expr) { … } // Transform applies the transformation to the specified parsed file, // whose type information is supplied in info, and returns the number // of replacements that were made. // // It mutates the AST in place (the identity of the root node is // unchanged), and may add nodes for which no type information is // available in info. // // Derived from rewriteFile in $GOROOT/src/cmd/gofmt/rewrite.go. func (tr *Transformer) Transform(info *types.Info, pkg *types.Package, file *ast.File) int { … } // setValue is a wrapper for x.SetValue(y); it protects // the caller from panics if x cannot be changed to y. func setValue(x, y reflect.Value) { … } var objectPtrNil … var scopePtrNil … var identType … var selectorExprType … var objectPtrType … var statementType … var positionType … var scopePtrType … // apply replaces each AST field x in val with f(x), returning val. // To avoid extra conversions, f operates on the reflect.Value form. // f takes a reflect.Value representing the variable to modify of type ast.Node. // It returns a reflect.Value containing the transformed value of type ast.Node, // whether any change was made, and a map of identifiers to ast.Expr (so we can // do contextually correct substitutions in the parent statements). func (tr *Transformer) apply(f func(reflect.Value) (reflect.Value, bool, map[string]ast.Expr), val reflect.Value) (reflect.Value, bool, map[string]ast.Expr) { … } // subst returns a copy of (replacement) pattern with values from env // substituted in place of wildcards and pos used as the position of // tokens from the pattern. if env == nil, subst returns a copy of // pattern and doesn't change the line number information. func (tr *Transformer) subst(env map[string]ast.Expr, pattern, pos reflect.Value) reflect.Value { … } func rvToExpr(rv reflect.Value) ast.Expr { … } // updateTypeInfo duplicates type information for the existing AST old // so that it also applies to duplicated AST new. func updateTypeInfo(info *types.Info, new, old ast.Expr) { … }