| // Copyright 2011 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" |
| |
| func init() { |
| register(mapdeleteFix) |
| } |
| |
| var mapdeleteFix = fix{ |
| "mapdelete", |
| "2011-10-18", |
| mapdelete, |
| `Use delete(m, k) instead of m[k] = 0, false. |
| |
| http://codereview.appspot.com/5272045 |
| `, |
| } |
| |
| func mapdelete(f *ast.File) bool { |
| fixed := false |
| walk(f, func(n interface{}) { |
| stmt, ok := n.(*ast.Stmt) |
| if !ok { |
| return |
| } |
| as, ok := (*stmt).(*ast.AssignStmt) |
| if !ok || len(as.Lhs) != 1 || len(as.Rhs) != 2 { |
| return |
| } |
| ix, ok := as.Lhs[0].(*ast.IndexExpr) |
| if !ok { |
| return |
| } |
| if !isTopName(as.Rhs[1], "false") { |
| warn(as.Pos(), "two-element map assignment with non-false second value") |
| return |
| } |
| if !canDrop(as.Rhs[0]) { |
| warn(as.Pos(), "two-element map assignment with non-trivial first value") |
| return |
| } |
| *stmt = &ast.ExprStmt{ |
| X: &ast.CallExpr{ |
| Fun: &ast.Ident{ |
| NamePos: as.Pos(), |
| Name: "delete", |
| }, |
| Args: []ast.Expr{ix.X, ix.Index}, |
| }, |
| } |
| fixed = true |
| }) |
| return fixed |
| } |
| |
| // canDrop reports whether it is safe to drop the |
| // evaluation of n from the program. |
| // It is very conservative. |
| func canDrop(n ast.Expr) bool { |
| switch n := n.(type) { |
| case *ast.Ident, *ast.BasicLit: |
| return true |
| case *ast.ParenExpr: |
| return canDrop(n.X) |
| case *ast.SelectorExpr: |
| return canDrop(n.X) |
| case *ast.CompositeLit: |
| if !canDrop(n.Type) { |
| return false |
| } |
| for _, e := range n.Elts { |
| if !canDrop(e) { |
| return false |
| } |
| } |
| return true |
| case *ast.StarExpr: |
| // Dropping *x is questionable, |
| // but we have to be able to drop (*T)(nil). |
| return canDrop(n.X) |
| case *ast.ArrayType, *ast.ChanType, *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.StructType: |
| return true |
| } |
| return false |
| } |