github.com/elek/golangci-lint@v1.42.2-0.20211208090441-c05b7fcb3a9a/pkg/golinters/nolintlint/nolintlint_test.go (about)

     1  package nolintlint
     2  
     3  import (
     4  	"go/parser"
     5  	"go/token"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/elek/golangci-lint/pkg/result"
    12  )
    13  
    14  //nolint:funlen
    15  func TestNoLintLint(t *testing.T) {
    16  	type issueWithReplacement struct {
    17  		issue       string
    18  		replacement *result.Replacement
    19  	}
    20  	testCases := []struct {
    21  		desc     string
    22  		needs    Needs
    23  		excludes []string
    24  		contents string
    25  		expected []issueWithReplacement
    26  	}{
    27  		{
    28  			desc:  "when no explanation is provided",
    29  			needs: NeedsExplanation,
    30  			contents: `
    31  package bar
    32  
    33  // example
    34  //nolint
    35  func foo() {
    36    bad() //nolint
    37    bad() //nolint //
    38    bad() //nolint // 
    39    good() //nolint // this is ok
    40  	other() //nolintother
    41  }`,
    42  			expected: []issueWithReplacement{
    43  				{issue: "directive `//nolint` should provide explanation such as `//nolint // this is why` at testing.go:5:1"},
    44  				{issue: "directive `//nolint` should provide explanation such as `//nolint // this is why` at testing.go:7:9"},
    45  				{issue: "directive `//nolint //` should provide explanation such as `//nolint // this is why` at testing.go:8:9"},
    46  				{issue: "directive `//nolint // ` should provide explanation such as `//nolint // this is why` at testing.go:9:9"},
    47  			},
    48  		},
    49  		{
    50  			desc:  "when multiple directives on multiple lines",
    51  			needs: NeedsExplanation,
    52  			contents: `
    53  package bar
    54  
    55  // example
    56  //nolint // this is ok
    57  //nolint:dupl
    58  func foo() {}`,
    59  			expected: []issueWithReplacement{
    60  				{issue: "directive `//nolint:dupl` should provide explanation such as `//nolint:dupl // this is why` at testing.go:6:1"},
    61  			},
    62  		},
    63  		{
    64  			desc:     "when no explanation is needed for a specific linter",
    65  			needs:    NeedsExplanation,
    66  			excludes: []string{"lll"},
    67  			contents: `
    68  package bar
    69  
    70  func foo() {
    71  	thisIsAReallyLongLine() //nolint:lll
    72  }`,
    73  		},
    74  		{
    75  			desc:  "when no specific linter is mentioned",
    76  			needs: NeedsSpecific,
    77  			contents: `
    78  package bar
    79  
    80  func foo() {
    81    good() //nolint:my-linter
    82    bad() //nolint
    83    bad() // nolint // because
    84  }`,
    85  			expected: []issueWithReplacement{
    86  				{issue: "directive `//nolint` should mention specific linter such as `//nolint:my-linter` at testing.go:6:9"},
    87  				{issue: "directive `// nolint // because` should mention specific linter such as `// nolint:my-linter` at testing.go:7:9"},
    88  			},
    89  		},
    90  		{
    91  			desc:  "when machine-readable style isn't used",
    92  			needs: NeedsMachineOnly,
    93  			contents: `
    94  package bar
    95  
    96  func foo() {
    97    bad() // nolint
    98    good() //nolint
    99  }`,
   100  			expected: []issueWithReplacement{
   101  				{
   102  					issue: "directive `// nolint` should be written without leading space as `//nolint` at testing.go:5:9",
   103  					replacement: &result.Replacement{
   104  						Inline: &result.InlineFix{
   105  							StartCol:  10,
   106  							Length:    1,
   107  							NewString: "",
   108  						},
   109  					},
   110  				},
   111  			},
   112  		},
   113  		{
   114  			desc: "extra spaces in front of directive are reported",
   115  			contents: `
   116  package bar
   117  
   118  func foo() {
   119    bad() //  nolint
   120    good() // nolint
   121  }`,
   122  			expected: []issueWithReplacement{
   123  				{
   124  					issue: "directive `//  nolint` should not have more than one leading space at testing.go:5:9",
   125  					replacement: &result.Replacement{
   126  						Inline: &result.InlineFix{
   127  							StartCol:  10,
   128  							Length:    2,
   129  							NewString: " ",
   130  						},
   131  					},
   132  				},
   133  			},
   134  		},
   135  		{
   136  			desc: "spaces are allowed in comma-separated list of linters",
   137  			contents: `
   138  package bar
   139  
   140  func foo() {
   141    good() // nolint:linter1,linter-two
   142    bad() // nolint:linter1 linter2
   143    good() // nolint: linter1,linter2
   144    good() // nolint: linter1, linter2
   145  }`,
   146  			expected: []issueWithReplacement{
   147  				{issue: "directive `// nolint:linter1 linter2` should match `// nolint[:<comma-separated-linters>] [// <explanation>]` at testing.go:6:9"}, //nolint:lll // this is a string
   148  			},
   149  		},
   150  		{
   151  			desc: "multi-line comments don't confuse parser",
   152  			contents: `
   153  package bar
   154  
   155  func foo() {
   156    //nolint:test
   157    // something else
   158  }`,
   159  		},
   160  		{
   161  			desc:  "needs unused without specific linter generates replacement",
   162  			needs: NeedsUnused,
   163  			contents: `
   164  package bar
   165  
   166  func foo() {
   167    bad() //nolint
   168  }`,
   169  			expected: []issueWithReplacement{
   170  				{
   171  					issue: "directive `//nolint` is unused at testing.go:5:9",
   172  					replacement: &result.Replacement{
   173  						Inline: &result.InlineFix{
   174  							StartCol:  8,
   175  							Length:    8,
   176  							NewString: "",
   177  						},
   178  					},
   179  				},
   180  			},
   181  		},
   182  		{
   183  			desc:  "needs unused with one specific linter generates replacement",
   184  			needs: NeedsUnused,
   185  			contents: `
   186  package bar
   187  
   188  func foo() {
   189    bad() //nolint:somelinter
   190  }`,
   191  			expected: []issueWithReplacement{
   192  				{
   193  					issue: "directive `//nolint:somelinter` is unused for linter \"somelinter\" at testing.go:5:9",
   194  					replacement: &result.Replacement{
   195  						Inline: &result.InlineFix{
   196  							StartCol:  8,
   197  							Length:    19,
   198  							NewString: "",
   199  						},
   200  					},
   201  				},
   202  			},
   203  		},
   204  		{
   205  			desc:  "needs unused with multiple specific linters does not generate replacements",
   206  			needs: NeedsUnused,
   207  			contents: `
   208  package bar
   209  
   210  func foo() {
   211    bad() //nolint:linter1,linter2
   212  }`,
   213  			expected: []issueWithReplacement{
   214  				{
   215  					issue: "directive `//nolint:linter1,linter2` is unused for linter \"linter1\" at testing.go:5:9",
   216  				},
   217  				{
   218  					issue: "directive `//nolint:linter1,linter2` is unused for linter \"linter2\" at testing.go:5:9",
   219  				},
   220  			},
   221  		},
   222  	}
   223  
   224  	for _, test := range testCases {
   225  		test := test
   226  		t.Run(test.desc, func(t *testing.T) {
   227  			t.Parallel()
   228  
   229  			linter, _ := NewLinter(test.needs, test.excludes)
   230  
   231  			fset := token.NewFileSet()
   232  			expr, err := parser.ParseFile(fset, "testing.go", test.contents, parser.ParseComments)
   233  			require.NoError(t, err)
   234  
   235  			actualIssues, err := linter.Run(fset, expr)
   236  			require.NoError(t, err)
   237  
   238  			actualIssuesWithReplacements := make([]issueWithReplacement, 0, len(actualIssues))
   239  			for _, i := range actualIssues {
   240  				actualIssuesWithReplacements = append(actualIssuesWithReplacements, issueWithReplacement{
   241  					issue:       i.String(),
   242  					replacement: i.Replacement(),
   243  				})
   244  			}
   245  
   246  			assert.ElementsMatch(t, test.expected, actualIssuesWithReplacements,
   247  				"expected %s \nbut got %s", test.expected, actualIssuesWithReplacements)
   248  		})
   249  	}
   250  }