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