Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / internal / lsp / analysis / nonewvars / nonewvars.go
1 // Copyright 2020 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 nonewvars defines an Analyzer that applies suggested fixes
6 // to errors of the type "no new variables on left side of :=".
7 package nonewvars
8
9 import (
10         "bytes"
11         "go/ast"
12         "go/format"
13         "go/token"
14
15         "golang.org/x/tools/go/analysis"
16         "golang.org/x/tools/go/analysis/passes/inspect"
17         "golang.org/x/tools/go/ast/inspector"
18         "golang.org/x/tools/internal/analysisinternal"
19 )
20
21 const Doc = `suggested fixes for "no new vars on left side of :="
22
23 This checker provides suggested fixes for type errors of the
24 type "no new vars on left side of :=". For example:
25         z := 1
26         z := 2
27 will turn into
28         z := 1
29         z = 2
30 `
31
32 var Analyzer = &analysis.Analyzer{
33         Name:             string(analysisinternal.NoNewVars),
34         Doc:              Doc,
35         Requires:         []*analysis.Analyzer{inspect.Analyzer},
36         Run:              run,
37         RunDespiteErrors: true,
38 }
39
40 func run(pass *analysis.Pass) (interface{}, error) {
41         inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
42         errors := analysisinternal.GetTypeErrors(pass)
43
44         nodeFilter := []ast.Node{(*ast.AssignStmt)(nil)}
45         inspect.Preorder(nodeFilter, func(n ast.Node) {
46                 assignStmt, _ := n.(*ast.AssignStmt)
47                 // We only care about ":=".
48                 if assignStmt.Tok != token.DEFINE {
49                         return
50                 }
51
52                 var file *ast.File
53                 for _, f := range pass.Files {
54                         if f.Pos() <= assignStmt.Pos() && assignStmt.Pos() < f.End() {
55                                 file = f
56                                 break
57                         }
58                 }
59                 if file == nil {
60                         return
61                 }
62
63                 for _, err := range errors {
64                         if !FixesError(err.Msg) {
65                                 continue
66                         }
67                         if assignStmt.Pos() > err.Pos || err.Pos >= assignStmt.End() {
68                                 continue
69                         }
70                         var buf bytes.Buffer
71                         if err := format.Node(&buf, pass.Fset, file); err != nil {
72                                 continue
73                         }
74                         pass.Report(analysis.Diagnostic{
75                                 Pos:     err.Pos,
76                                 End:     analysisinternal.TypeErrorEndPos(pass.Fset, buf.Bytes(), err.Pos),
77                                 Message: err.Msg,
78                                 SuggestedFixes: []analysis.SuggestedFix{{
79                                         Message: "Change ':=' to '='",
80                                         TextEdits: []analysis.TextEdit{{
81                                                 Pos: err.Pos,
82                                                 End: err.Pos + 1,
83                                         }},
84                                 }},
85                         })
86                 }
87         })
88         return nil, nil
89 }
90
91 func FixesError(msg string) bool {
92         return msg == "no new variables on left side of :="
93 }