GoPLS Viewer

Home|gopls/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.
7package analysisutil
8
9import (
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.
19func Format(fset *token.FileSetx ast.Exprstring {
20    var b bytes.Buffer
21    printer.Fprint(&bfsetx)
22    return b.String()
23}
24
25// HasSideEffects reports whether evaluation of e has side effects.
26func HasSideEffects(info *types.Infoe ast.Exprbool {
27    safe := true
28    ast.Inspect(e, func(node ast.Nodebool {
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.
59func Unparen(e ast.Exprast.Expr {
60    for {
61        pok := 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.
71func ReadFile(fset *token.FileSetfilename string) ([]byte, *token.Fileerror) {
72    contenterr := ioutil.ReadFile(filename)
73    if err != nil {
74        return nilnilerr
75    }
76    tf := fset.AddFile(filename, -1len(content))
77    tf.SetLinesForContent(content)
78    return contenttfnil
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.
83func LineStart(f *token.Fileline inttoken.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.
113func Imports(pkg *types.Packagepath stringbool {
114    for _imp := range pkg.Imports() {
115        if imp.Path() == path {
116            return true
117        }
118    }
119    return false
120}
121
MembersX
LineStart.f
LineStart.line
Unparen
Format
Format.fset
HasSideEffects.e
LineStart.BlockStmt.posn
Imports
Imports.RangeStmt_2747.imp
types
printer
HasSideEffects.info
bytes
Format.x
ReadFile.filename
LineStart
LineStart.min
LineStart.BlockStmt.pos
ioutil
ReadFile.err
HasSideEffects.safe
Unparen.e
Imports.path
Format.b
ReadFile.fset
ReadFile.content
ReadFile.tf
HasSideEffects
token
ReadFile
LineStart.max
Imports.pkg
ast
Members
X