1
2
3
4
5 package modernize
6
7 import (
8 _ "embed"
9 "go/ast"
10 "go/constant"
11 "go/format"
12 "go/token"
13 "go/types"
14 "iter"
15 "regexp"
16 "strings"
17
18 "golang.org/x/tools/go/analysis"
19 "golang.org/x/tools/go/analysis/passes/inspect"
20 "golang.org/x/tools/go/ast/edge"
21 "golang.org/x/tools/go/ast/inspector"
22 "golang.org/x/tools/internal/analysis/analyzerutil"
23 "golang.org/x/tools/internal/astutil"
24 "golang.org/x/tools/internal/moreiters"
25 "golang.org/x/tools/internal/packagepath"
26 "golang.org/x/tools/internal/stdlib"
27 "golang.org/x/tools/internal/typesinternal"
28 )
29
30
31 var doc string
32
33
34 var Suite = []*analysis.Analyzer{
35 AnyAnalyzer,
36
37
38 FmtAppendfAnalyzer,
39 ForVarAnalyzer,
40 MapsLoopAnalyzer,
41 MinMaxAnalyzer,
42 NewExprAnalyzer,
43 OmitZeroAnalyzer,
44 plusBuildAnalyzer,
45 RangeIntAnalyzer,
46 ReflectTypeForAnalyzer,
47 SlicesContainsAnalyzer,
48
49 SlicesSortAnalyzer,
50 stditeratorsAnalyzer,
51 stringscutAnalyzer,
52 StringsCutPrefixAnalyzer,
53 StringsSeqAnalyzer,
54 StringsBuilderAnalyzer,
55 TestingContextAnalyzer,
56 WaitGroupAnalyzer,
57 }
58
59
60
61
62 func formatExprs(fset *token.FileSet, exprs []ast.Expr) string {
63 var buf strings.Builder
64 for i, e := range exprs {
65 if i > 0 {
66 buf.WriteString(", ")
67 }
68 format.Node(&buf, fset, e)
69 }
70 return buf.String()
71 }
72
73
74 func isZeroIntConst(info *types.Info, e ast.Expr) bool {
75 return isIntLiteral(info, e, 0)
76 }
77
78
79 func isIntLiteral(info *types.Info, e ast.Expr, n int64) bool {
80 return info.Types[e].Value == constant.MakeInt64(n)
81 }
82
83
84
85
86
87
88
89
90
91
92 func filesUsingGoVersion(pass *analysis.Pass, version string) iter.Seq[inspector.Cursor] {
93 inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
94
95 return func(yield func(inspector.Cursor) bool) {
96 for curFile := range inspect.Root().Children() {
97 file := curFile.Node().(*ast.File)
98 if analyzerutil.FileUsesGoVersion(pass, file, version) && !yield(curFile) {
99 break
100 }
101 }
102 }
103 }
104
105
106
107 func within(pass *analysis.Pass, pkgs ...string) bool {
108 path := pass.Pkg.Path()
109 return packagepath.IsStdPackage(path) &&
110 moreiters.Contains(stdlib.Dependencies(pkgs...), path)
111 }
112
113
114
115 func unparenEnclosing(cur inspector.Cursor) inspector.Cursor {
116 for astutil.IsChildOf(cur, edge.ParenExpr_X) {
117 cur = cur.Parent()
118 }
119 return cur
120 }
121
122 var (
123 builtinAny = types.Universe.Lookup("any")
124 builtinAppend = types.Universe.Lookup("append")
125 builtinBool = types.Universe.Lookup("bool")
126 builtinInt = types.Universe.Lookup("int")
127 builtinFalse = types.Universe.Lookup("false")
128 builtinLen = types.Universe.Lookup("len")
129 builtinMake = types.Universe.Lookup("make")
130 builtinNew = types.Universe.Lookup("new")
131 builtinNil = types.Universe.Lookup("nil")
132 builtinString = types.Universe.Lookup("string")
133 builtinTrue = types.Universe.Lookup("true")
134 byteSliceType = types.NewSlice(types.Typ[types.Byte])
135 omitemptyRegex = regexp.MustCompile(`(?:^json| json):"[^"]*(,omitempty)(?:"|,[^"]*")\s?`)
136 )
137
138
139 func lookup(info *types.Info, cur inspector.Cursor, name string) types.Object {
140 scope := typesinternal.EnclosingScope(info, cur)
141 _, obj := scope.LookupParent(name, cur.Node().Pos())
142 return obj
143 }
144
View as plain text