Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / go / analysis / passes / internal / analysisutil / util.go
1 // Package analysisutil defines various helper functions
2 // used by two or more packages beneath go/analysis.
3 package analysisutil
4
5 import (
6         "bytes"
7         "go/ast"
8         "go/printer"
9         "go/token"
10         "go/types"
11         "io/ioutil"
12 )
13
14 // Format returns a string representation of the expression.
15 func Format(fset *token.FileSet, x ast.Expr) string {
16         var b bytes.Buffer
17         printer.Fprint(&b, fset, x)
18         return b.String()
19 }
20
21 // HasSideEffects reports whether evaluation of e has side effects.
22 func HasSideEffects(info *types.Info, e ast.Expr) bool {
23         safe := true
24         ast.Inspect(e, func(node ast.Node) bool {
25                 switch n := node.(type) {
26                 case *ast.CallExpr:
27                         typVal := info.Types[n.Fun]
28                         switch {
29                         case typVal.IsType():
30                                 // Type conversion, which is safe.
31                         case typVal.IsBuiltin():
32                                 // Builtin func, conservatively assumed to not
33                                 // be safe for now.
34                                 safe = false
35                                 return false
36                         default:
37                                 // A non-builtin func or method call.
38                                 // Conservatively assume that all of them have
39                                 // side effects for now.
40                                 safe = false
41                                 return false
42                         }
43                 case *ast.UnaryExpr:
44                         if n.Op == token.ARROW {
45                                 safe = false
46                                 return false
47                         }
48                 }
49                 return true
50         })
51         return !safe
52 }
53
54 // Unparen returns e with any enclosing parentheses stripped.
55 func Unparen(e ast.Expr) ast.Expr {
56         for {
57                 p, ok := e.(*ast.ParenExpr)
58                 if !ok {
59                         return e
60                 }
61                 e = p.X
62         }
63 }
64
65 // ReadFile reads a file and adds it to the FileSet
66 // so that we can report errors against it using lineStart.
67 func ReadFile(fset *token.FileSet, filename string) ([]byte, *token.File, error) {
68         content, err := ioutil.ReadFile(filename)
69         if err != nil {
70                 return nil, nil, err
71         }
72         tf := fset.AddFile(filename, -1, len(content))
73         tf.SetLinesForContent(content)
74         return content, tf, nil
75 }
76
77 // LineStart returns the position of the start of the specified line
78 // within file f, or NoPos if there is no line of that number.
79 func LineStart(f *token.File, line int) token.Pos {
80         // Use binary search to find the start offset of this line.
81         //
82         // TODO(adonovan): eventually replace this function with the
83         // simpler and more efficient (*go/token.File).LineStart, added
84         // in go1.12.
85
86         min := 0        // inclusive
87         max := f.Size() // exclusive
88         for {
89                 offset := (min + max) / 2
90                 pos := f.Pos(offset)
91                 posn := f.Position(pos)
92                 if posn.Line == line {
93                         return pos - (token.Pos(posn.Column) - 1)
94                 }
95
96                 if min+1 >= max {
97                         return token.NoPos
98                 }
99
100                 if posn.Line < line {
101                         min = offset
102                 } else {
103                         max = offset
104                 }
105         }
106 }
107
108 // Imports returns true if path is imported by pkg.
109 func Imports(pkg *types.Package, path string) bool {
110         for _, imp := range pkg.Imports() {
111                 if imp.Path() == path {
112                         return true
113                 }
114         }
115         return false
116 }