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 }