// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package main import ( "go/ast" "go/token" "reflect" ) type simplifier struct{} func (s *simplifier) Visit(node ast.Node) ast.Visitor { switch n := node.(type) { case *ast.CompositeLit: // array, slice, and map composite literals may be simplified outer := n var eltType ast.Expr switch typ := outer.Type.(type) { case *ast.ArrayType: eltType = typ.Elt case *ast.MapType: eltType = typ.Value } if eltType != nil { typ := reflect.ValueOf(eltType) for i, x := range outer.Elts { px := &outer.Elts[i] // look at value of indexed/named elements if t, ok := x.(*ast.KeyValueExpr); ok { x = t.Value px = &t.Value } simplify(x) // if the element is a composite literal and its literal type // matches the outer literal's element type exactly, the inner // literal type may be omitted if inner, ok := x.(*ast.CompositeLit); ok { if match(nil, typ, reflect.ValueOf(inner.Type)) { inner.Type = nil } } // if the outer literal's element type is a pointer type *T // and the element is & of a composite literal of type T, // the inner &T may be omitted. if ptr, ok := eltType.(*ast.StarExpr); ok { if addr, ok := x.(*ast.UnaryExpr); ok && addr.Op == token.AND { if inner, ok := addr.X.(*ast.CompositeLit); ok { if match(nil, reflect.ValueOf(ptr.X), reflect.ValueOf(inner.Type)) { inner.Type = nil // drop T *px = inner // drop & } } } } } // node was simplified - stop walk (there are no subnodes to simplify) return nil } case *ast.RangeStmt: // range of the form: for x, _ = range v {...} // can be simplified to: for x = range v {...} if n.Value != nil { if ident, ok := n.Value.(*ast.Ident); ok && ident.Name == "_" { n.Value = nil } } } return s } func simplify(node ast.Node) { var s simplifier ast.Walk(&s, node) }