1
2
3
4
5
6
7 package analysisutil
8
9 import (
10 "bytes"
11 "go/ast"
12 "go/printer"
13 "go/token"
14 "go/types"
15 "os"
16
17 "golang.org/x/tools/go/analysis"
18 "golang.org/x/tools/internal/aliases"
19 "golang.org/x/tools/internal/analysisinternal"
20 )
21
22
23 func Format(fset *token.FileSet, x ast.Expr) string {
24 var b bytes.Buffer
25 printer.Fprint(&b, fset, x)
26 return b.String()
27 }
28
29
30 func HasSideEffects(info *types.Info, e ast.Expr) bool {
31 safe := true
32 ast.Inspect(e, func(node ast.Node) bool {
33 switch n := node.(type) {
34 case *ast.CallExpr:
35 typVal := info.Types[n.Fun]
36 switch {
37 case typVal.IsType():
38
39 case typVal.IsBuiltin():
40
41
42 safe = false
43 return false
44 default:
45
46
47
48 safe = false
49 return false
50 }
51 case *ast.UnaryExpr:
52 if n.Op == token.ARROW {
53 safe = false
54 return false
55 }
56 }
57 return true
58 })
59 return !safe
60 }
61
62
63
64 func ReadFile(pass *analysis.Pass, filename string) ([]byte, *token.File, error) {
65 readFile := pass.ReadFile
66 if readFile == nil {
67 readFile = os.ReadFile
68 }
69 content, err := readFile(filename)
70 if err != nil {
71 return nil, nil, err
72 }
73 tf := pass.Fset.AddFile(filename, -1, len(content))
74 tf.SetLinesForContent(content)
75 return content, tf, nil
76 }
77
78
79
80 func LineStart(f *token.File, line int) token.Pos {
81
82
83
84
85
86
87 min := 0
88 max := f.Size()
89 for {
90 offset := (min + max) / 2
91 pos := f.Pos(offset)
92 posn := f.Position(pos)
93 if posn.Line == line {
94 return pos - (token.Pos(posn.Column) - 1)
95 }
96
97 if min+1 >= max {
98 return token.NoPos
99 }
100
101 if posn.Line < line {
102 min = offset
103 } else {
104 max = offset
105 }
106 }
107 }
108
109
110 func Imports(pkg *types.Package, path string) bool {
111 for _, imp := range pkg.Imports() {
112 if imp.Path() == path {
113 return true
114 }
115 }
116 return false
117 }
118
119
120
121
122
123 func IsNamedType(t types.Type, pkgPath string, names ...string) bool {
124 n, ok := aliases.Unalias(t).(*types.Named)
125 if !ok {
126 return false
127 }
128 obj := n.Obj()
129 if obj == nil || obj.Pkg() == nil || obj.Pkg().Path() != pkgPath {
130 return false
131 }
132 name := obj.Name()
133 for _, n := range names {
134 if name == n {
135 return true
136 }
137 }
138 return false
139 }
140
141
142
143
144 func IsFunctionNamed(f *types.Func, pkgPath string, names ...string) bool {
145 if f == nil {
146 return false
147 }
148 if f.Pkg() == nil || f.Pkg().Path() != pkgPath {
149 return false
150 }
151 if f.Type().(*types.Signature).Recv() != nil {
152 return false
153 }
154 for _, n := range names {
155 if f.Name() == n {
156 return true
157 }
158 }
159 return false
160 }
161
162 var MustExtractDoc = analysisinternal.MustExtractDoc
163
View as plain text