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  }