Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
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 if i == nil { | |
remyoudompheng
2012/11/17 19:19:59
why not put
case nil: return nil
in the switch?
bradfitz
2012/11/17 22:13:09
Done.
| |
27 return nil | |
28 } | |
29 switch v := i.(type) { | |
30 case *ast.File: | |
31 o := &ast.File{ | |
32 Doc: v.Doc, // shallow | |
33 Package: v.Package, | |
34 Comments: v.Comments, // shallow | |
35 Name: v.Name, | |
36 Scope: v.Scope, | |
37 } | |
38 for _, x := range v.Decls { | |
39 o.Decls = append(o.Decls, clone(x).(ast.Decl)) | |
40 } | |
41 for _, x := range v.Imports { | |
42 o.Imports = append(o.Imports, clone(x).(*ast.ImportSpec) ) | |
43 } | |
44 for _, x := range v.Unresolved { | |
45 o.Unresolved = append(o.Unresolved, x) | |
46 } | |
47 return o | |
48 case *ast.GenDecl: | |
49 o := new(ast.GenDecl) | |
50 *o = *v | |
51 o.Specs = nil | |
52 for _, x := range v.Specs { | |
53 o.Specs = append(o.Specs, clone(x).(ast.Spec)) | |
54 } | |
55 return o | |
56 case *ast.TypeSpec: | |
57 o := new(ast.TypeSpec) | |
58 *o = *v | |
59 o.Type = cloneExpr(v.Type) | |
60 return o | |
61 case *ast.InterfaceType: | |
62 o := new(ast.InterfaceType) | |
63 *o = *v | |
64 o.Methods = clone(v.Methods).(*ast.FieldList) | |
65 return o | |
66 case *ast.FieldList: | |
67 if v == nil { | |
68 return v | |
69 } | |
70 o := new(ast.FieldList) | |
71 *o = *v | |
72 o.List = nil | |
73 for _, x := range v.List { | |
74 o.List = append(o.List, clone(x).(*ast.Field)) | |
75 } | |
76 return o | |
77 case *ast.Field: | |
78 o := &ast.Field{ | |
79 Doc: v.Doc, // shallow | |
80 Type: cloneExpr(v.Type), | |
81 Tag: clone(v.Tag).(*ast.BasicLit), | |
82 Comment: v.Comment, // shallow | |
83 } | |
84 for _, x := range v.Names { | |
85 o.Names = append(o.Names, clone(x).(*ast.Ident)) | |
86 } | |
87 return o | |
88 case *ast.FuncType: | |
89 if v == nil { | |
90 return v | |
91 } | |
92 return &ast.FuncType{ | |
93 Func: v.Func, | |
94 Params: clone(v.Params).(*ast.FieldList), | |
95 Results: clone(v.Results).(*ast.FieldList), | |
96 } | |
97 case *ast.FuncDecl: | |
98 if v == nil { | |
99 return v | |
100 } | |
101 return &ast.FuncDecl{ | |
102 Recv: clone(v.Recv).(*ast.FieldList), | |
103 Name: v.Name, | |
104 Type: clone(v.Type).(*ast.FuncType), | |
105 Body: v.Body, // shallow | |
106 } | |
107 case *ast.ValueSpec: | |
108 if v == nil { | |
109 return v | |
110 } | |
111 o := &ast.ValueSpec{ | |
112 Type: cloneExpr(v.Type), | |
113 } | |
114 for _, x := range v.Names { | |
115 o.Names = append(o.Names, x) | |
116 } | |
117 for _, x := range v.Values { | |
118 o.Values = append(o.Values, cloneExpr(x)) | |
119 } | |
120 return o | |
121 case *ast.CallExpr: | |
122 if v == nil { | |
123 return v | |
124 } | |
125 o := &ast.CallExpr{} | |
126 *o = *v | |
127 o.Args = cloneExprs(v.Args) | |
128 o.Fun = cloneExpr(v.Fun) | |
129 return o | |
130 case *ast.SelectorExpr: | |
131 if v == nil { | |
132 return nil | |
133 } | |
134 return &ast.SelectorExpr{ | |
135 X: cloneExpr(v.X), | |
136 Sel: v.Sel, | |
137 } | |
138 case *ast.ArrayType: | |
139 return &ast.ArrayType{ | |
140 Lbrack: v.Lbrack, | |
141 Len: cloneExpr(v.Len), | |
142 Elt: cloneExpr(v.Elt), | |
143 } | |
144 case *ast.StructType: | |
145 return &ast.StructType{ | |
146 Struct: v.Struct, | |
147 Fields: clone(v.Fields).(*ast.FieldList), | |
148 Incomplete: v.Incomplete, | |
149 } | |
150 case *ast.StarExpr: | |
151 return &ast.StarExpr{ | |
152 Star: v.Star, | |
153 X: cloneExpr(v.X), | |
154 } | |
155 case *ast.CompositeLit: | |
156 return &ast.CompositeLit{ | |
157 Type: cloneExpr(v.Type), | |
158 Lbrace: v.Lbrace, | |
159 Elts: cloneExprs(v.Elts), | |
160 Rbrace: v.Rbrace, | |
161 } | |
162 case *ast.UnaryExpr: | |
163 return &ast.UnaryExpr{ | |
164 OpPos: v.OpPos, | |
165 Op: v.Op, | |
166 X: cloneExpr(v.X), | |
167 } | |
168 case *ast.BinaryExpr: | |
169 return &ast.BinaryExpr{ | |
170 OpPos: v.OpPos, | |
171 Op: v.Op, | |
172 X: cloneExpr(v.X), | |
173 Y: cloneExpr(v.Y), | |
174 } | |
175 case *ast.Ellipsis: | |
176 return &ast.Ellipsis{ | |
177 Ellipsis: v.Ellipsis, | |
178 Elt: cloneExpr(v.Elt), | |
179 } | |
180 case *ast.KeyValueExpr: | |
181 return &ast.KeyValueExpr{ | |
182 Key: cloneExpr(v.Key), | |
183 Colon: v.Colon, | |
184 Value: cloneExpr(v.Value), | |
185 } | |
186 case *ast.FuncLit: | |
187 return &ast.FuncLit{ | |
188 Type: clone(v.Type).(*ast.FuncType), | |
189 Body: v.Body, // shallow | |
190 } | |
191 case *ast.MapType: | |
192 return &ast.MapType{ | |
193 Map: v.Map, | |
194 Key: cloneExpr(v.Key), | |
195 Value: cloneExpr(v.Value), | |
196 } | |
197 case *ast.ParenExpr: | |
198 return &ast.ParenExpr{ | |
199 Lparen: v.Lparen, | |
200 X: cloneExpr(v.X), | |
201 Rparen: v.Rparen, | |
202 } | |
203 case *ast.Ident, *ast.BasicLit: | |
204 return v | |
205 case *ast.ImportSpec: | |
206 return &ast.ImportSpec{ | |
207 Doc: v.Doc, // shallow | |
208 Name: v.Name, | |
209 Path: clone(v.Path).(*ast.BasicLit), | |
210 Comment: v.Comment, // shallow | |
211 EndPos: v.EndPos, | |
212 } | |
213 case *ast.ChanType: | |
214 return &ast.ChanType{ | |
215 Begin: v.Begin, | |
216 Arrow: v.Arrow, | |
217 Dir: v.Dir, | |
218 Value: cloneExpr(v.Value), | |
219 } | |
220 case *ast.TypeAssertExpr: | |
221 return &ast.TypeAssertExpr{ | |
222 X: cloneExpr(v.X), | |
223 Type: cloneExpr(v.Type), | |
224 } | |
225 case *ast.IndexExpr: | |
226 return &ast.IndexExpr{ | |
227 X: cloneExpr(v.X), | |
228 Index: cloneExpr(v.Index), | |
229 Lbrack: v.Lbrack, | |
230 Rbrack: v.Rbrack, | |
231 } | |
232 } | |
233 panic(fmt.Sprintf("Uncloneable type %T", i)) | |
234 } | |
235 | |
236 func cloneExpr(x ast.Expr) ast.Expr { | |
237 if x == nil { | |
238 return nil | |
239 } | |
240 return clone(x).(ast.Expr) | |
241 } | |
242 | |
243 func cloneExprs(x []ast.Expr) []ast.Expr { | |
244 if x == nil { | |
245 return nil | |
246 } | |
247 o := make([]ast.Expr, len(x)) | |
248 for i, x := range x { | |
249 o[i] = cloneExpr(x) | |
250 } | |
251 return o | |
252 } | |
OLD | NEW |