golang.org/x/tools/gopls@v0.15.3/internal/analysis/nonewvars/nonewvars.go (about) 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 _ "embed" 12 "go/ast" 13 "go/format" 14 "go/token" 15 16 "golang.org/x/tools/go/analysis" 17 "golang.org/x/tools/go/analysis/passes/inspect" 18 "golang.org/x/tools/go/ast/inspector" 19 "golang.org/x/tools/internal/analysisinternal" 20 ) 21 22 //go:embed doc.go 23 var doc string 24 25 var Analyzer = &analysis.Analyzer{ 26 Name: "nonewvars", 27 Doc: analysisinternal.MustExtractDoc(doc, "nonewvars"), 28 Requires: []*analysis.Analyzer{inspect.Analyzer}, 29 Run: run, 30 RunDespiteErrors: true, 31 URL: "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/nonewvars", 32 } 33 34 func run(pass *analysis.Pass) (interface{}, error) { 35 inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) 36 if len(pass.TypeErrors) == 0 { 37 return nil, nil 38 } 39 40 nodeFilter := []ast.Node{(*ast.AssignStmt)(nil)} 41 inspect.Preorder(nodeFilter, func(n ast.Node) { 42 assignStmt, _ := n.(*ast.AssignStmt) 43 // We only care about ":=". 44 if assignStmt.Tok != token.DEFINE { 45 return 46 } 47 48 var file *ast.File 49 for _, f := range pass.Files { 50 if f.Pos() <= assignStmt.Pos() && assignStmt.Pos() < f.End() { 51 file = f 52 break 53 } 54 } 55 if file == nil { 56 return 57 } 58 59 for _, err := range pass.TypeErrors { 60 if !FixesError(err.Msg) { 61 continue 62 } 63 if assignStmt.Pos() > err.Pos || err.Pos >= assignStmt.End() { 64 continue 65 } 66 var buf bytes.Buffer 67 if err := format.Node(&buf, pass.Fset, file); err != nil { 68 continue 69 } 70 pass.Report(analysis.Diagnostic{ 71 Pos: err.Pos, 72 End: analysisinternal.TypeErrorEndPos(pass.Fset, buf.Bytes(), err.Pos), 73 Message: err.Msg, 74 SuggestedFixes: []analysis.SuggestedFix{{ 75 Message: "Change ':=' to '='", 76 TextEdits: []analysis.TextEdit{{ 77 Pos: err.Pos, 78 End: err.Pos + 1, 79 }}, 80 }}, 81 }) 82 } 83 }) 84 return nil, nil 85 } 86 87 func FixesError(msg string) bool { 88 return msg == "no new variables on left side of :=" 89 }