github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/api/clone.go (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "fmt" 9 "go/ast" 10 "log" 11 "reflect" 12 ) 13 14 const debugClone = false 15 16 // TODO(bradfitz): delete this function (and whole file) once 17 // http://golang.org/issue/4380 is fixed. 18 func clone(i interface{}) (cloned interface{}) { 19 if debugClone { 20 defer func() { 21 if !reflect.DeepEqual(i, cloned) { 22 log.Printf("cloned %T doesn't match: in=%#v out=%#v", i, i, cloned) 23 } 24 }() 25 } 26 switch v := i.(type) { 27 case nil: 28 return nil 29 case *ast.File: 30 o := &ast.File{ 31 Doc: v.Doc, // shallow 32 Package: v.Package, 33 Comments: v.Comments, // shallow 34 Name: v.Name, 35 Scope: v.Scope, 36 } 37 for _, x := range v.Decls { 38 o.Decls = append(o.Decls, clone(x).(ast.Decl)) 39 } 40 for _, x := range v.Imports { 41 o.Imports = append(o.Imports, clone(x).(*ast.ImportSpec)) 42 } 43 for _, x := range v.Unresolved { 44 o.Unresolved = append(o.Unresolved, x) 45 } 46 return o 47 case *ast.GenDecl: 48 o := new(ast.GenDecl) 49 *o = *v 50 o.Specs = nil 51 for _, x := range v.Specs { 52 o.Specs = append(o.Specs, clone(x).(ast.Spec)) 53 } 54 return o 55 case *ast.TypeSpec: 56 o := new(ast.TypeSpec) 57 *o = *v 58 o.Type = cloneExpr(v.Type) 59 return o 60 case *ast.InterfaceType: 61 o := new(ast.InterfaceType) 62 *o = *v 63 o.Methods = clone(v.Methods).(*ast.FieldList) 64 return o 65 case *ast.FieldList: 66 if v == nil { 67 return v 68 } 69 o := new(ast.FieldList) 70 *o = *v 71 o.List = nil 72 for _, x := range v.List { 73 o.List = append(o.List, clone(x).(*ast.Field)) 74 } 75 return o 76 case *ast.Field: 77 o := &ast.Field{ 78 Doc: v.Doc, // shallow 79 Type: cloneExpr(v.Type), 80 Tag: clone(v.Tag).(*ast.BasicLit), 81 Comment: v.Comment, // shallow 82 } 83 for _, x := range v.Names { 84 o.Names = append(o.Names, clone(x).(*ast.Ident)) 85 } 86 return o 87 case *ast.FuncType: 88 if v == nil { 89 return v 90 } 91 return &ast.FuncType{ 92 Func: v.Func, 93 Params: clone(v.Params).(*ast.FieldList), 94 Results: clone(v.Results).(*ast.FieldList), 95 } 96 case *ast.FuncDecl: 97 if v == nil { 98 return v 99 } 100 return &ast.FuncDecl{ 101 Recv: clone(v.Recv).(*ast.FieldList), 102 Name: v.Name, 103 Type: clone(v.Type).(*ast.FuncType), 104 Body: v.Body, // shallow 105 } 106 case *ast.ValueSpec: 107 if v == nil { 108 return v 109 } 110 o := &ast.ValueSpec{ 111 Type: cloneExpr(v.Type), 112 } 113 for _, x := range v.Names { 114 o.Names = append(o.Names, x) 115 } 116 for _, x := range v.Values { 117 o.Values = append(o.Values, cloneExpr(x)) 118 } 119 return o 120 case *ast.CallExpr: 121 if v == nil { 122 return v 123 } 124 o := &ast.CallExpr{} 125 *o = *v 126 o.Args = cloneExprs(v.Args) 127 o.Fun = cloneExpr(v.Fun) 128 return o 129 case *ast.SelectorExpr: 130 if v == nil { 131 return nil 132 } 133 return &ast.SelectorExpr{ 134 X: cloneExpr(v.X), 135 Sel: v.Sel, 136 } 137 case *ast.ArrayType: 138 return &ast.ArrayType{ 139 Lbrack: v.Lbrack, 140 Len: cloneExpr(v.Len), 141 Elt: cloneExpr(v.Elt), 142 } 143 case *ast.StructType: 144 return &ast.StructType{ 145 Struct: v.Struct, 146 Fields: clone(v.Fields).(*ast.FieldList), 147 Incomplete: v.Incomplete, 148 } 149 case *ast.StarExpr: 150 return &ast.StarExpr{ 151 Star: v.Star, 152 X: cloneExpr(v.X), 153 } 154 case *ast.CompositeLit: 155 return &ast.CompositeLit{ 156 Type: cloneExpr(v.Type), 157 Lbrace: v.Lbrace, 158 Elts: cloneExprs(v.Elts), 159 Rbrace: v.Rbrace, 160 } 161 case *ast.UnaryExpr: 162 return &ast.UnaryExpr{ 163 OpPos: v.OpPos, 164 Op: v.Op, 165 X: cloneExpr(v.X), 166 } 167 case *ast.BinaryExpr: 168 return &ast.BinaryExpr{ 169 OpPos: v.OpPos, 170 Op: v.Op, 171 X: cloneExpr(v.X), 172 Y: cloneExpr(v.Y), 173 } 174 case *ast.Ellipsis: 175 return &ast.Ellipsis{ 176 Ellipsis: v.Ellipsis, 177 Elt: cloneExpr(v.Elt), 178 } 179 case *ast.KeyValueExpr: 180 return &ast.KeyValueExpr{ 181 Key: cloneExpr(v.Key), 182 Colon: v.Colon, 183 Value: cloneExpr(v.Value), 184 } 185 case *ast.FuncLit: 186 return &ast.FuncLit{ 187 Type: clone(v.Type).(*ast.FuncType), 188 Body: v.Body, // shallow 189 } 190 case *ast.MapType: 191 return &ast.MapType{ 192 Map: v.Map, 193 Key: cloneExpr(v.Key), 194 Value: cloneExpr(v.Value), 195 } 196 case *ast.ParenExpr: 197 return &ast.ParenExpr{ 198 Lparen: v.Lparen, 199 X: cloneExpr(v.X), 200 Rparen: v.Rparen, 201 } 202 case *ast.Ident, *ast.BasicLit: 203 return v 204 case *ast.ImportSpec: 205 return &ast.ImportSpec{ 206 Doc: v.Doc, // shallow 207 Name: v.Name, 208 Path: clone(v.Path).(*ast.BasicLit), 209 Comment: v.Comment, // shallow 210 EndPos: v.EndPos, 211 } 212 case *ast.ChanType: 213 return &ast.ChanType{ 214 Begin: v.Begin, 215 Arrow: v.Arrow, 216 Dir: v.Dir, 217 Value: cloneExpr(v.Value), 218 } 219 case *ast.TypeAssertExpr: 220 return &ast.TypeAssertExpr{ 221 X: cloneExpr(v.X), 222 Type: cloneExpr(v.Type), 223 } 224 case *ast.IndexExpr: 225 return &ast.IndexExpr{ 226 X: cloneExpr(v.X), 227 Index: cloneExpr(v.Index), 228 Lbrack: v.Lbrack, 229 Rbrack: v.Rbrack, 230 } 231 } 232 panic(fmt.Sprintf("Uncloneable type %T", i)) 233 } 234 235 func cloneExpr(x ast.Expr) ast.Expr { 236 if x == nil { 237 return nil 238 } 239 return clone(x).(ast.Expr) 240 } 241 242 func cloneExprs(x []ast.Expr) []ast.Expr { 243 if x == nil { 244 return nil 245 } 246 o := make([]ast.Expr, len(x)) 247 for i, x := range x { 248 o[i] = cloneExpr(x) 249 } 250 return o 251 }