1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
// 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"
"go/token"
)
func init() {
register(stringssplitFix)
}
var stringssplitFix = fix{
"stringssplit",
"2011-06-28",
stringssplit,
`Restore strings.Split to its original meaning and add strings.SplitN. Bytes too.
http://codereview.appspot.com/4661051
`,
}
func stringssplit(f *ast.File) bool {
if !imports(f, "bytes") && !imports(f, "strings") {
return false
}
fixed := false
walk(f, func(n interface{}) {
call, ok := n.(*ast.CallExpr)
// func Split(s, sep string, n int) []string
// func SplitAfter(s, sep string, n int) []string
if !ok || len(call.Args) != 3 {
return
}
// Is this our function?
switch {
case isPkgDot(call.Fun, "bytes", "Split"):
case isPkgDot(call.Fun, "bytes", "SplitAfter"):
case isPkgDot(call.Fun, "strings", "Split"):
case isPkgDot(call.Fun, "strings", "SplitAfter"):
default:
return
}
sel := call.Fun.(*ast.SelectorExpr)
args := call.Args
fixed = true // We're committed.
// Is the last argument -1? If so, drop the arg.
// (Actually we just look for a negative integer literal.)
// Otherwise, Split->SplitN and keep the arg.
final := args[2]
if unary, ok := final.(*ast.UnaryExpr); ok && unary.Op == token.SUB {
if lit, ok := unary.X.(*ast.BasicLit); ok {
// Is it an integer? If so, it's a negative integer and that's what we're after.
if lit.Kind == token.INT {
// drop the last arg.
call.Args = args[0:2]
return
}
}
}
// If not, rename and keep the argument list.
sel.Sel.Name += "N"
})
return fixed
}
|