github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/internal/lsp/analysis/noresultvalues/noresultvalues.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 noresultvalues defines an Analyzer that applies suggested fixes 6 // to errors of the type "no result values expected". 7 package noresultvalues 8 9 import ( 10 "bytes" 11 "go/ast" 12 "go/format" 13 "strings" 14 15 "github.com/powerman/golang-tools/go/analysis" 16 "github.com/powerman/golang-tools/go/analysis/passes/inspect" 17 "github.com/powerman/golang-tools/go/ast/inspector" 18 "github.com/powerman/golang-tools/internal/analysisinternal" 19 ) 20 21 const Doc = `suggested fixes for unexpected return values 22 23 This checker provides suggested fixes for type errors of the 24 type "no result values expected" or "too many return values". 25 For example: 26 func z() { return nil } 27 will turn into 28 func z() { return } 29 ` 30 31 var Analyzer = &analysis.Analyzer{ 32 Name: string(analysisinternal.NoResultValues), 33 Doc: Doc, 34 Requires: []*analysis.Analyzer{inspect.Analyzer}, 35 Run: run, 36 RunDespiteErrors: true, 37 } 38 39 func run(pass *analysis.Pass) (interface{}, error) { 40 inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) 41 errors := analysisinternal.GetTypeErrors(pass) 42 43 nodeFilter := []ast.Node{(*ast.ReturnStmt)(nil)} 44 inspect.Preorder(nodeFilter, func(n ast.Node) { 45 retStmt, _ := n.(*ast.ReturnStmt) 46 47 var file *ast.File 48 for _, f := range pass.Files { 49 if f.Pos() <= retStmt.Pos() && retStmt.Pos() < f.End() { 50 file = f 51 break 52 } 53 } 54 if file == nil { 55 return 56 } 57 58 for _, err := range errors { 59 if !FixesError(err.Msg) { 60 continue 61 } 62 if retStmt.Pos() >= err.Pos || err.Pos >= retStmt.End() { 63 continue 64 } 65 var buf bytes.Buffer 66 if err := format.Node(&buf, pass.Fset, file); err != nil { 67 continue 68 } 69 pass.Report(analysis.Diagnostic{ 70 Pos: err.Pos, 71 End: analysisinternal.TypeErrorEndPos(pass.Fset, buf.Bytes(), err.Pos), 72 Message: err.Msg, 73 SuggestedFixes: []analysis.SuggestedFix{{ 74 Message: "Delete return values", 75 TextEdits: []analysis.TextEdit{{ 76 Pos: retStmt.Pos(), 77 End: retStmt.End(), 78 NewText: []byte("return"), 79 }}, 80 }}, 81 }) 82 } 83 }) 84 return nil, nil 85 } 86 87 func FixesError(msg string) bool { 88 return msg == "no result values expected" || 89 strings.HasPrefix(msg, "too many return values") && strings.Contains(msg, "want ()") 90 }