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