sa1024.go raw
1 package sa1024
2
3 import (
4 "go/constant"
5 "sort"
6
7 "honnef.co/go/tools/analysis/callcheck"
8 "honnef.co/go/tools/analysis/lint"
9 "honnef.co/go/tools/internal/passes/buildir"
10
11 "golang.org/x/tools/go/analysis"
12 )
13
14 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
15 Analyzer: &analysis.Analyzer{
16 Name: "SA1024",
17 Requires: []*analysis.Analyzer{buildir.Analyzer},
18 Run: callcheck.Analyzer(rules),
19 },
20 Doc: &lint.RawDocumentation{
21 Title: `A string cutset contains duplicate characters`,
22 Text: `The \'strings.TrimLeft\' and \'strings.TrimRight\' functions take cutsets, not
23 prefixes. A cutset is treated as a set of characters to remove from a
24 string. For example,
25
26 strings.TrimLeft("42133word", "1234")
27
28 will result in the string \'"word"\' – any characters that are 1, 2, 3 or
29 4 are cut from the left of the string.
30
31 In order to remove one string from another, use \'strings.TrimPrefix\' instead.`,
32 Since: "2017.1",
33 Severity: lint.SeverityWarning,
34 MergeIf: lint.MergeIfAny,
35 },
36 })
37
38 var Analyzer = SCAnalyzer.Analyzer
39
40 var rules = map[string]callcheck.Check{
41 "strings.Trim": check,
42 "strings.TrimLeft": check,
43 "strings.TrimRight": check,
44 }
45
46 func check(call *callcheck.Call) {
47 arg := call.Args[1]
48 if !isUniqueStringCutset(arg.Value) {
49 const MsgNonUniqueCutset = "cutset contains duplicate characters"
50 arg.Invalid(MsgNonUniqueCutset)
51 }
52 }
53
54 func isUniqueStringCutset(v callcheck.Value) bool {
55 if c := callcheck.ExtractConstExpectKind(v, constant.String); c != nil {
56 s := constant.StringVal(c.Value)
57 rs := runeSlice(s)
58 if len(rs) < 2 {
59 return true
60 }
61 sort.Sort(rs)
62 for i, r := range rs[1:] {
63 if rs[i] == r {
64 return false
65 }
66 }
67 }
68 return true
69 }
70
71 type runeSlice []rune
72
73 func (rs runeSlice) Len() int { return len(rs) }
74 func (rs runeSlice) Less(i int, j int) bool { return rs[i] < rs[j] }
75 func (rs runeSlice) Swap(i int, j int) { rs[i], rs[j] = rs[j], rs[i] }
76