github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/go/analysis/internal/checker/checker_test.go (about)

     1  // Copyright 2019 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 checker_test
     6  
     7  import (
     8  	"fmt"
     9  	"go/ast"
    10  	"io/ioutil"
    11  	"path/filepath"
    12  	"testing"
    13  
    14  	"github.com/powerman/golang-tools/go/analysis"
    15  	"github.com/powerman/golang-tools/go/analysis/analysistest"
    16  	"github.com/powerman/golang-tools/go/analysis/internal/checker"
    17  	"github.com/powerman/golang-tools/go/analysis/passes/inspect"
    18  	"github.com/powerman/golang-tools/go/ast/inspector"
    19  	"github.com/powerman/golang-tools/internal/testenv"
    20  )
    21  
    22  var from, to string
    23  
    24  func TestApplyFixes(t *testing.T) {
    25  	testenv.NeedsGoPackages(t)
    26  
    27  	from = "bar"
    28  	to = "baz"
    29  
    30  	files := map[string]string{
    31  		"rename/test.go": `package rename
    32  
    33  func Foo() {
    34  	bar := 12
    35  	_ = bar
    36  }
    37  
    38  // the end
    39  `}
    40  	want := `package rename
    41  
    42  func Foo() {
    43  	baz := 12
    44  	_ = baz
    45  }
    46  
    47  // the end
    48  `
    49  
    50  	testdata, cleanup, err := analysistest.WriteFiles(files)
    51  	if err != nil {
    52  		t.Fatal(err)
    53  	}
    54  	path := filepath.Join(testdata, "src/rename/test.go")
    55  	checker.Fix = true
    56  	checker.Run([]string{"file=" + path}, []*analysis.Analyzer{analyzer})
    57  
    58  	contents, err := ioutil.ReadFile(path)
    59  	if err != nil {
    60  		t.Fatal(err)
    61  	}
    62  
    63  	got := string(contents)
    64  	if got != want {
    65  		t.Errorf("contents of rewritten file\ngot: %s\nwant: %s", got, want)
    66  	}
    67  
    68  	defer cleanup()
    69  }
    70  
    71  var analyzer = &analysis.Analyzer{
    72  	Name:     "rename",
    73  	Requires: []*analysis.Analyzer{inspect.Analyzer},
    74  	Run:      run,
    75  }
    76  
    77  func run(pass *analysis.Pass) (interface{}, error) {
    78  	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
    79  	nodeFilter := []ast.Node{(*ast.Ident)(nil)}
    80  	inspect.Preorder(nodeFilter, func(n ast.Node) {
    81  		ident := n.(*ast.Ident)
    82  		if ident.Name == from {
    83  			msg := fmt.Sprintf("renaming %q to %q", from, to)
    84  			pass.Report(analysis.Diagnostic{
    85  				Pos:     ident.Pos(),
    86  				End:     ident.End(),
    87  				Message: msg,
    88  				SuggestedFixes: []analysis.SuggestedFix{{
    89  					Message: msg,
    90  					TextEdits: []analysis.TextEdit{{
    91  						Pos:     ident.Pos(),
    92  						End:     ident.End(),
    93  						NewText: []byte(to),
    94  					}},
    95  				}},
    96  			})
    97  		}
    98  	})
    99  
   100  	return nil, nil
   101  }
   102  
   103  func TestRunDespiteErrors(t *testing.T) {
   104  	testenv.NeedsGoPackages(t)
   105  
   106  	files := map[string]string{
   107  		"rderr/test.go": `package rderr
   108  
   109  // Foo deliberately has a type error
   110  func Foo(s string) int {
   111  	return s + 1
   112  }
   113  `}
   114  
   115  	testdata, cleanup, err := analysistest.WriteFiles(files)
   116  	if err != nil {
   117  		t.Fatal(err)
   118  	}
   119  	path := filepath.Join(testdata, "src/rderr/test.go")
   120  
   121  	// A no-op analyzer that should finish regardless of
   122  	// parse or type errors in the code.
   123  	noop := &analysis.Analyzer{
   124  		Name:     "noop",
   125  		Requires: []*analysis.Analyzer{inspect.Analyzer},
   126  		Run: func(pass *analysis.Pass) (interface{}, error) {
   127  			return nil, nil
   128  		},
   129  		RunDespiteErrors: true,
   130  	}
   131  
   132  	for _, test := range []struct {
   133  		name      string
   134  		pattern   []string
   135  		analyzers []*analysis.Analyzer
   136  		code      int
   137  	}{
   138  		// parse/type errors
   139  		{name: "skip-error", pattern: []string{"file=" + path}, analyzers: []*analysis.Analyzer{analyzer}, code: 1},
   140  		{name: "despite-error", pattern: []string{"file=" + path}, analyzers: []*analysis.Analyzer{noop}, code: 0},
   141  		// combination of parse/type errors and no errors
   142  		{name: "despite-error-and-no-error", pattern: []string{"file=" + path, "sort"}, analyzers: []*analysis.Analyzer{analyzer, noop}, code: 1},
   143  		// non-existing package error
   144  		{name: "no-package", pattern: []string{"xyz"}, analyzers: []*analysis.Analyzer{analyzer}, code: 1},
   145  		{name: "no-package-despite-error", pattern: []string{"abc"}, analyzers: []*analysis.Analyzer{noop}, code: 1},
   146  		{name: "no-multi-package-despite-error", pattern: []string{"xyz", "abc"}, analyzers: []*analysis.Analyzer{noop}, code: 1},
   147  		// combination of type/parsing and different errors
   148  		{name: "different-errors", pattern: []string{"file=" + path, "xyz"}, analyzers: []*analysis.Analyzer{analyzer, noop}, code: 1},
   149  		// non existing dir error
   150  		{name: "no-match-dir", pattern: []string{"file=non/existing/dir"}, analyzers: []*analysis.Analyzer{analyzer, noop}, code: 1},
   151  		// no errors
   152  		{name: "no-errors", pattern: []string{"sort"}, analyzers: []*analysis.Analyzer{analyzer, noop}, code: 0},
   153  	} {
   154  		if got := checker.Run(test.pattern, test.analyzers); got != test.code {
   155  			t.Errorf("got incorrect exit code %d for test %s; want %d", got, test.name, test.code)
   156  		}
   157  	}
   158  
   159  	defer cleanup()
   160  }