Source file src/pkg/cmd/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go
     1	
     2	
     3	
     4	
     5	package astutil
     6	
     7	import (
     8		"fmt"
     9		"go/ast"
    10		"reflect"
    11		"sort"
    12	)
    13	
    14	
    15	
    16	
    17	
    18	
    19	
    20	type ApplyFunc func(*Cursor) bool
    21	
    22	
    23	
    24	
    25	
    26	
    27	
    28	
    29	
    30	
    31	
    32	
    33	
    34	
    35	
    36	
    37	
    38	
    39	
    40	
    41	
    42	
    43	func Apply(root ast.Node, pre, post ApplyFunc) (result ast.Node) {
    44		parent := &struct{ ast.Node }{root}
    45		defer func() {
    46			if r := recover(); r != nil && r != abort {
    47				panic(r)
    48			}
    49			result = parent.Node
    50		}()
    51		a := &application{pre: pre, post: post}
    52		a.apply(parent, "Node", nil, root)
    53		return
    54	}
    55	
    56	var abort = new(int) 
    57	
    58	
    59	
    60	
    61	
    62	
    63	
    64	
    65	
    66	
    67	
    68	
    69	
    70	
    71	type Cursor struct {
    72		parent ast.Node
    73		name   string
    74		iter   *iterator 
    75		node   ast.Node
    76	}
    77	
    78	
    79	func (c *Cursor) Node() ast.Node { return c.node }
    80	
    81	
    82	func (c *Cursor) Parent() ast.Node { return c.parent }
    83	
    84	
    85	
    86	
    87	func (c *Cursor) Name() string { return c.name }
    88	
    89	
    90	
    91	
    92	
    93	func (c *Cursor) Index() int {
    94		if c.iter != nil {
    95			return c.iter.index
    96		}
    97		return -1
    98	}
    99	
   100	
   101	func (c *Cursor) field() reflect.Value {
   102		return reflect.Indirect(reflect.ValueOf(c.parent)).FieldByName(c.name)
   103	}
   104	
   105	
   106	
   107	func (c *Cursor) Replace(n ast.Node) {
   108		if _, ok := c.node.(*ast.File); ok {
   109			file, ok := n.(*ast.File)
   110			if !ok {
   111				panic("attempt to replace *ast.File with non-*ast.File")
   112			}
   113			c.parent.(*ast.Package).Files[c.name] = file
   114			return
   115		}
   116	
   117		v := c.field()
   118		if i := c.Index(); i >= 0 {
   119			v = v.Index(i)
   120		}
   121		v.Set(reflect.ValueOf(n))
   122	}
   123	
   124	
   125	
   126	
   127	
   128	func (c *Cursor) Delete() {
   129		if _, ok := c.node.(*ast.File); ok {
   130			delete(c.parent.(*ast.Package).Files, c.name)
   131			return
   132		}
   133	
   134		i := c.Index()
   135		if i < 0 {
   136			panic("Delete node not contained in slice")
   137		}
   138		v := c.field()
   139		l := v.Len()
   140		reflect.Copy(v.Slice(i, l), v.Slice(i+1, l))
   141		v.Index(l - 1).Set(reflect.Zero(v.Type().Elem()))
   142		v.SetLen(l - 1)
   143		c.iter.step--
   144	}
   145	
   146	
   147	
   148	
   149	func (c *Cursor) InsertAfter(n ast.Node) {
   150		i := c.Index()
   151		if i < 0 {
   152			panic("InsertAfter node not contained in slice")
   153		}
   154		v := c.field()
   155		v.Set(reflect.Append(v, reflect.Zero(v.Type().Elem())))
   156		l := v.Len()
   157		reflect.Copy(v.Slice(i+2, l), v.Slice(i+1, l))
   158		v.Index(i + 1).Set(reflect.ValueOf(n))
   159		c.iter.step++
   160	}
   161	
   162	
   163	
   164	
   165	func (c *Cursor) InsertBefore(n ast.Node) {
   166		i := c.Index()
   167		if i < 0 {
   168			panic("InsertBefore node not contained in slice")
   169		}
   170		v := c.field()
   171		v.Set(reflect.Append(v, reflect.Zero(v.Type().Elem())))
   172		l := v.Len()
   173		reflect.Copy(v.Slice(i+1, l), v.Slice(i, l))
   174		v.Index(i).Set(reflect.ValueOf(n))
   175		c.iter.index++
   176	}
   177	
   178	
   179	type application struct {
   180		pre, post ApplyFunc
   181		cursor    Cursor
   182		iter      iterator
   183	}
   184	
   185	func (a *application) apply(parent ast.Node, name string, iter *iterator, n ast.Node) {
   186		
   187		if v := reflect.ValueOf(n); v.Kind() == reflect.Ptr && v.IsNil() {
   188			n = nil
   189		}
   190	
   191		
   192		saved := a.cursor
   193		a.cursor.parent = parent
   194		a.cursor.name = name
   195		a.cursor.iter = iter
   196		a.cursor.node = n
   197	
   198		if a.pre != nil && !a.pre(&a.cursor) {
   199			a.cursor = saved
   200			return
   201		}
   202	
   203		
   204		
   205		switch n := n.(type) {
   206		case nil:
   207			
   208	
   209		
   210		case *ast.Comment:
   211			
   212	
   213		case *ast.CommentGroup:
   214			if n != nil {
   215				a.applyList(n, "List")
   216			}
   217	
   218		case *ast.Field:
   219			a.apply(n, "Doc", nil, n.Doc)
   220			a.applyList(n, "Names")
   221			a.apply(n, "Type", nil, n.Type)
   222			a.apply(n, "Tag", nil, n.Tag)
   223			a.apply(n, "Comment", nil, n.Comment)
   224	
   225		case *ast.FieldList:
   226			a.applyList(n, "List")
   227	
   228		
   229		case *ast.BadExpr, *ast.Ident, *ast.BasicLit:
   230			
   231	
   232		case *ast.Ellipsis:
   233			a.apply(n, "Elt", nil, n.Elt)
   234	
   235		case *ast.FuncLit:
   236			a.apply(n, "Type", nil, n.Type)
   237			a.apply(n, "Body", nil, n.Body)
   238	
   239		case *ast.CompositeLit:
   240			a.apply(n, "Type", nil, n.Type)
   241			a.applyList(n, "Elts")
   242	
   243		case *ast.ParenExpr:
   244			a.apply(n, "X", nil, n.X)
   245	
   246		case *ast.SelectorExpr:
   247			a.apply(n, "X", nil, n.X)
   248			a.apply(n, "Sel", nil, n.Sel)
   249	
   250		case *ast.IndexExpr:
   251			a.apply(n, "X", nil, n.X)
   252			a.apply(n, "Index", nil, n.Index)
   253	
   254		case *ast.SliceExpr:
   255			a.apply(n, "X", nil, n.X)
   256			a.apply(n, "Low", nil, n.Low)
   257			a.apply(n, "High", nil, n.High)
   258			a.apply(n, "Max", nil, n.Max)
   259	
   260		case *ast.TypeAssertExpr:
   261			a.apply(n, "X", nil, n.X)
   262			a.apply(n, "Type", nil, n.Type)
   263	
   264		case *ast.CallExpr:
   265			a.apply(n, "Fun", nil, n.Fun)
   266			a.applyList(n, "Args")
   267	
   268		case *ast.StarExpr:
   269			a.apply(n, "X", nil, n.X)
   270	
   271		case *ast.UnaryExpr:
   272			a.apply(n, "X", nil, n.X)
   273	
   274		case *ast.BinaryExpr:
   275			a.apply(n, "X", nil, n.X)
   276			a.apply(n, "Y", nil, n.Y)
   277	
   278		case *ast.KeyValueExpr:
   279			a.apply(n, "Key", nil, n.Key)
   280			a.apply(n, "Value", nil, n.Value)
   281	
   282		
   283		case *ast.ArrayType:
   284			a.apply(n, "Len", nil, n.Len)
   285			a.apply(n, "Elt", nil, n.Elt)
   286	
   287		case *ast.StructType:
   288			a.apply(n, "Fields", nil, n.Fields)
   289	
   290		case *ast.FuncType:
   291			a.apply(n, "Params", nil, n.Params)
   292			a.apply(n, "Results", nil, n.Results)
   293	
   294		case *ast.InterfaceType:
   295			a.apply(n, "Methods", nil, n.Methods)
   296	
   297		case *ast.MapType:
   298			a.apply(n, "Key", nil, n.Key)
   299			a.apply(n, "Value", nil, n.Value)
   300	
   301		case *ast.ChanType:
   302			a.apply(n, "Value", nil, n.Value)
   303	
   304		
   305		case *ast.BadStmt:
   306			
   307	
   308		case *ast.DeclStmt:
   309			a.apply(n, "Decl", nil, n.Decl)
   310	
   311		case *ast.EmptyStmt:
   312			
   313	
   314		case *ast.LabeledStmt:
   315			a.apply(n, "Label", nil, n.Label)
   316			a.apply(n, "Stmt", nil, n.Stmt)
   317	
   318		case *ast.ExprStmt:
   319			a.apply(n, "X", nil, n.X)
   320	
   321		case *ast.SendStmt:
   322			a.apply(n, "Chan", nil, n.Chan)
   323			a.apply(n, "Value", nil, n.Value)
   324	
   325		case *ast.IncDecStmt:
   326			a.apply(n, "X", nil, n.X)
   327	
   328		case *ast.AssignStmt:
   329			a.applyList(n, "Lhs")
   330			a.applyList(n, "Rhs")
   331	
   332		case *ast.GoStmt:
   333			a.apply(n, "Call", nil, n.Call)
   334	
   335		case *ast.DeferStmt:
   336			a.apply(n, "Call", nil, n.Call)
   337	
   338		case *ast.ReturnStmt:
   339			a.applyList(n, "Results")
   340	
   341		case *ast.BranchStmt:
   342			a.apply(n, "Label", nil, n.Label)
   343	
   344		case *ast.BlockStmt:
   345			a.applyList(n, "List")
   346	
   347		case *ast.IfStmt:
   348			a.apply(n, "Init", nil, n.Init)
   349			a.apply(n, "Cond", nil, n.Cond)
   350			a.apply(n, "Body", nil, n.Body)
   351			a.apply(n, "Else", nil, n.Else)
   352	
   353		case *ast.CaseClause:
   354			a.applyList(n, "List")
   355			a.applyList(n, "Body")
   356	
   357		case *ast.SwitchStmt:
   358			a.apply(n, "Init", nil, n.Init)
   359			a.apply(n, "Tag", nil, n.Tag)
   360			a.apply(n, "Body", nil, n.Body)
   361	
   362		case *ast.TypeSwitchStmt:
   363			a.apply(n, "Init", nil, n.Init)
   364			a.apply(n, "Assign", nil, n.Assign)
   365			a.apply(n, "Body", nil, n.Body)
   366	
   367		case *ast.CommClause:
   368			a.apply(n, "Comm", nil, n.Comm)
   369			a.applyList(n, "Body")
   370	
   371		case *ast.SelectStmt:
   372			a.apply(n, "Body", nil, n.Body)
   373	
   374		case *ast.ForStmt:
   375			a.apply(n, "Init", nil, n.Init)
   376			a.apply(n, "Cond", nil, n.Cond)
   377			a.apply(n, "Post", nil, n.Post)
   378			a.apply(n, "Body", nil, n.Body)
   379	
   380		case *ast.RangeStmt:
   381			a.apply(n, "Key", nil, n.Key)
   382			a.apply(n, "Value", nil, n.Value)
   383			a.apply(n, "X", nil, n.X)
   384			a.apply(n, "Body", nil, n.Body)
   385	
   386		
   387		case *ast.ImportSpec:
   388			a.apply(n, "Doc", nil, n.Doc)
   389			a.apply(n, "Name", nil, n.Name)
   390			a.apply(n, "Path", nil, n.Path)
   391			a.apply(n, "Comment", nil, n.Comment)
   392	
   393		case *ast.ValueSpec:
   394			a.apply(n, "Doc", nil, n.Doc)
   395			a.applyList(n, "Names")
   396			a.apply(n, "Type", nil, n.Type)
   397			a.applyList(n, "Values")
   398			a.apply(n, "Comment", nil, n.Comment)
   399	
   400		case *ast.TypeSpec:
   401			a.apply(n, "Doc", nil, n.Doc)
   402			a.apply(n, "Name", nil, n.Name)
   403			a.apply(n, "Type", nil, n.Type)
   404			a.apply(n, "Comment", nil, n.Comment)
   405	
   406		case *ast.BadDecl:
   407			
   408	
   409		case *ast.GenDecl:
   410			a.apply(n, "Doc", nil, n.Doc)
   411			a.applyList(n, "Specs")
   412	
   413		case *ast.FuncDecl:
   414			a.apply(n, "Doc", nil, n.Doc)
   415			a.apply(n, "Recv", nil, n.Recv)
   416			a.apply(n, "Name", nil, n.Name)
   417			a.apply(n, "Type", nil, n.Type)
   418			a.apply(n, "Body", nil, n.Body)
   419	
   420		
   421		case *ast.File:
   422			a.apply(n, "Doc", nil, n.Doc)
   423			a.apply(n, "Name", nil, n.Name)
   424			a.applyList(n, "Decls")
   425			
   426			
   427	
   428		case *ast.Package:
   429			
   430			var names []string
   431			for name := range n.Files {
   432				names = append(names, name)
   433			}
   434			sort.Strings(names)
   435			for _, name := range names {
   436				a.apply(n, name, nil, n.Files[name])
   437			}
   438	
   439		default:
   440			panic(fmt.Sprintf("Apply: unexpected node type %T", n))
   441		}
   442	
   443		if a.post != nil && !a.post(&a.cursor) {
   444			panic(abort)
   445		}
   446	
   447		a.cursor = saved
   448	}
   449	
   450	
   451	type iterator struct {
   452		index, step int
   453	}
   454	
   455	func (a *application) applyList(parent ast.Node, name string) {
   456		
   457		saved := a.iter
   458		a.iter.index = 0
   459		for {
   460			
   461			v := reflect.Indirect(reflect.ValueOf(parent)).FieldByName(name)
   462			if a.iter.index >= v.Len() {
   463				break
   464			}
   465	
   466			
   467			var x ast.Node
   468			if e := v.Index(a.iter.index); e.IsValid() {
   469				x = e.Interface().(ast.Node)
   470			}
   471	
   472			a.iter.step = 1
   473			a.apply(parent, name, &a.iter, x)
   474			a.iter.index += a.iter.step
   475		}
   476		a.iter = saved
   477	}
   478	
View as plain text