Skip to content

Commit 306816e

Browse files
authored
Revert "Update nolintlint to fix nolint formatting and remove unused nolint statements (#1573)" (#1584)
This reverts commit aeb9830. There are some cases that nolinter fixer wasn't handling properly or expectedly (#1579, #1580, #1581) so we'll fix those in a new attempt.
1 parent 85049e5 commit 306816e

File tree

8 files changed

+38
-240
lines changed

8 files changed

+38
-240
lines changed

pkg/golinters/nolintlint.go

-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ func NewNoLintLint() *goanalysis.Linter {
7272
Pos: i.Position(),
7373
ExpectNoLint: expectNoLint,
7474
ExpectedNoLintLinter: expectedNolintLinter,
75-
Replacement: i.Replacement(),
7675
}
7776
res = append(res, goanalysis.NewIssue(issue, pass))
7877
}

pkg/golinters/nolintlint/nolintlint.go

+14-58
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,16 @@ import (
88
"regexp"
99
"strings"
1010
"unicode"
11-
12-
"github.com/golangci/golangci-lint/pkg/result"
1311
)
1412

1513
type BaseIssue struct {
1614
fullDirective string
1715
directiveWithOptionalLeadingSpace string
1816
position token.Position
19-
replacement *result.Replacement
2017
}
2118

22-
func (b BaseIssue) Position() token.Position { return b.position }
23-
24-
func (b BaseIssue) Replacement() *result.Replacement {
25-
return b.replacement
19+
func (b BaseIssue) Position() token.Position {
20+
return b.position
2621
}
2722

2823
type ExtraLeadingSpace struct {
@@ -90,7 +85,7 @@ type UnusedCandidate struct {
9085
func (i UnusedCandidate) Details() string {
9186
details := fmt.Sprintf("directive `%s` is unused", i.fullDirective)
9287
if i.ExpectedLinter != "" {
93-
details += fmt.Sprintf(" for linter %q", i.ExpectedLinter)
88+
details += fmt.Sprintf(" for linter %s", i.ExpectedLinter)
9489
}
9590
return details
9691
}
@@ -105,7 +100,6 @@ type Issue interface {
105100
Details() string
106101
Position() token.Position
107102
String() string
108-
Replacement() *result.Replacement
109103
}
110104

111105
type Needs uint
@@ -121,7 +115,7 @@ const (
121115
var commentPattern = regexp.MustCompile(`^//\s*(nolint)(:\s*[\w-]+\s*(?:,\s*[\w-]+\s*)*)?\b`)
122116

123117
// matches a complete nolint directive
124-
var fullDirectivePattern = regexp.MustCompile(`^//\s*nolint(?::(\s*[\w-]+\s*(?:,\s*[\w-]+\s*)*))?\s*(//.*)?\s*\n?$`)
118+
var fullDirectivePattern = regexp.MustCompile(`^//\s*nolint(:\s*[\w-]+\s*(?:,\s*[\w-]+\s*)*)?\s*(//.*)?\s*\n?$`)
125119

126120
type Linter struct {
127121
excludes []string // lists individual linters that don't require explanations
@@ -170,34 +164,19 @@ func (l Linter) Run(fset *token.FileSet, nodes ...ast.Node) ([]Issue, error) {
170164
directiveWithOptionalLeadingSpace = "// " + strings.TrimSpace(split[1])
171165
}
172166

173-
pos := fset.Position(comment.Pos())
174-
end := fset.Position(comment.End())
175-
176167
base := BaseIssue{
177168
fullDirective: comment.Text,
178169
directiveWithOptionalLeadingSpace: directiveWithOptionalLeadingSpace,
179-
position: pos,
170+
position: fset.Position(comment.Pos()),
180171
}
181172

182173
// check for, report and eliminate leading spaces so we can check for other issues
183-
if len(leadingSpace) > 0 {
184-
machineReadableReplacement := &result.Replacement{
185-
Inline: &result.InlineFix{
186-
StartCol: pos.Column - 1,
187-
Length: len(leadingSpace) + 2,
188-
NewString: "//",
189-
},
190-
}
174+
if len(leadingSpace) > 1 {
175+
issues = append(issues, ExtraLeadingSpace{BaseIssue: base})
176+
}
191177

192-
if (l.needs & NeedsMachineOnly) != 0 {
193-
issue := NotMachine{BaseIssue: base}
194-
issue.BaseIssue.replacement = machineReadableReplacement
195-
issues = append(issues, issue)
196-
} else if len(leadingSpace) > 1 {
197-
issue := ExtraLeadingSpace{BaseIssue: base}
198-
issue.BaseIssue.replacement = machineReadableReplacement
199-
issues = append(issues, issue)
200-
}
178+
if (l.needs&NeedsMachineOnly) != 0 && len(leadingSpace) > 0 {
179+
issues = append(issues, NotMachine{BaseIssue: base})
201180
}
202181

203182
fullMatches := fullDirectivePattern.FindStringSubmatch(comment.Text)
@@ -209,7 +188,7 @@ func (l Linter) Run(fset *token.FileSet, nodes ...ast.Node) ([]Issue, error) {
209188
lintersText, explanation := fullMatches[1], fullMatches[2]
210189
var linters []string
211190
if len(lintersText) > 0 {
212-
lls := strings.Split(lintersText, ",")
191+
lls := strings.Split(lintersText[1:], ",")
213192
linters = make([]string, 0, len(lls))
214193
for _, ll := range lls {
215194
ll = strings.TrimSpace(ll)
@@ -227,34 +206,11 @@ func (l Linter) Run(fset *token.FileSet, nodes ...ast.Node) ([]Issue, error) {
227206

228207
// when detecting unused directives, we send all the directives through and filter them out in the nolint processor
229208
if (l.needs & NeedsUnused) != 0 {
230-
removeNolintCompletely := &result.Replacement{
231-
Inline: &result.InlineFix{
232-
StartCol: pos.Column - 1,
233-
Length: end.Column - pos.Column,
234-
NewString: "",
235-
},
236-
}
237-
238209
if len(linters) == 0 {
239-
issue := UnusedCandidate{BaseIssue: base}
240-
issue.replacement = removeNolintCompletely
241-
issues = append(issues, issue)
210+
issues = append(issues, UnusedCandidate{BaseIssue: base})
242211
} else {
243-
for i, linter := range linters {
244-
issue := UnusedCandidate{BaseIssue: base, ExpectedLinter: linter}
245-
replacement := removeNolintCompletely
246-
if len(linters) > 1 {
247-
otherLinters := append(append([]string(nil), linters[0:i]...), linters[i+1:]...)
248-
replacement = &result.Replacement{
249-
Inline: &result.InlineFix{
250-
StartCol: (pos.Column - 1) + len("//") + len(leadingSpace) + len("nolint:"),
251-
Length: len(lintersText) - 1,
252-
NewString: strings.Join(otherLinters, ","),
253-
},
254-
}
255-
}
256-
issue.replacement = replacement
257-
issues = append(issues, issue)
212+
for _, linter := range linters {
213+
issues = append(issues, UnusedCandidate{BaseIssue: base, ExpectedLinter: linter})
258214
}
259215
}
260216
}

pkg/golinters/nolintlint/nolintlint_test.go

+20-134
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,16 @@ import (
77

88
"github.com/stretchr/testify/assert"
99
"github.com/stretchr/testify/require"
10-
11-
"github.com/golangci/golangci-lint/pkg/result"
1210
)
1311

1412
//nolint:funlen
1513
func TestNoLintLint(t *testing.T) {
16-
type issueWithReplacement struct {
17-
issue string
18-
replacement *result.Replacement
19-
}
2014
testCases := []struct {
2115
desc string
2216
needs Needs
2317
excludes []string
2418
contents string
25-
expected []issueWithReplacement
19+
expected []string
2620
}{
2721
{
2822
desc: "when no explanation is provided",
@@ -39,11 +33,11 @@ func foo() {
3933
good() //nolint // this is ok
4034
other() //nolintother
4135
}`,
42-
expected: []issueWithReplacement{
43-
{"directive `//nolint` should provide explanation such as `//nolint // this is why` at testing.go:5:1", nil},
44-
{"directive `//nolint` should provide explanation such as `//nolint // this is why` at testing.go:7:9", nil},
45-
{"directive `//nolint //` should provide explanation such as `//nolint // this is why` at testing.go:8:9", nil},
46-
{"directive `//nolint // ` should provide explanation such as `//nolint // this is why` at testing.go:9:9", nil},
36+
expected: []string{
37+
"directive `//nolint` should provide explanation such as `//nolint // this is why` at testing.go:5:1",
38+
"directive `//nolint` should provide explanation such as `//nolint // this is why` at testing.go:7:9",
39+
"directive `//nolint //` should provide explanation such as `//nolint // this is why` at testing.go:8:9",
40+
"directive `//nolint // ` should provide explanation such as `//nolint // this is why` at testing.go:9:9",
4741
},
4842
},
4943
{
@@ -56,8 +50,8 @@ package bar
5650
//nolint // this is ok
5751
//nolint:dupl
5852
func foo() {}`,
59-
expected: []issueWithReplacement{
60-
{"directive `//nolint:dupl` should provide explanation such as `//nolint:dupl // this is why` at testing.go:6:1", nil},
53+
expected: []string{
54+
"directive `//nolint:dupl` should provide explanation such as `//nolint:dupl // this is why` at testing.go:6:1",
6155
},
6256
},
6357
{
@@ -82,9 +76,9 @@ func foo() {
8276
bad() //nolint
8377
bad() // nolint // because
8478
}`,
85-
expected: []issueWithReplacement{
86-
{"directive `//nolint` should mention specific linter such as `//nolint:my-linter` at testing.go:6:9", nil},
87-
{"directive `// nolint // because` should mention specific linter such as `// nolint:my-linter` at testing.go:7:9", nil},
79+
expected: []string{
80+
"directive `//nolint` should mention specific linter such as `//nolint:my-linter` at testing.go:6:9",
81+
"directive `// nolint // because` should mention specific linter such as `// nolint:my-linter` at testing.go:7:9",
8882
},
8983
},
9084
{
@@ -97,17 +91,8 @@ func foo() {
9791
bad() // nolint
9892
good() //nolint
9993
}`,
100-
expected: []issueWithReplacement{
101-
{
102-
"directive `// nolint` should be written without leading space as `//nolint` at testing.go:5:9",
103-
&result.Replacement{
104-
Inline: &result.InlineFix{
105-
StartCol: 8,
106-
Length: 3,
107-
NewString: "//",
108-
},
109-
},
110-
},
94+
expected: []string{
95+
"directive `// nolint` should be written without leading space as `//nolint` at testing.go:5:9",
11196
},
11297
},
11398
{
@@ -119,17 +104,8 @@ func foo() {
119104
bad() // nolint
120105
good() // nolint
121106
}`,
122-
expected: []issueWithReplacement{
123-
{
124-
"directive `// nolint` should not have more than one leading space at testing.go:5:9",
125-
&result.Replacement{
126-
Inline: &result.InlineFix{
127-
StartCol: 8,
128-
Length: 4,
129-
NewString: "//",
130-
},
131-
},
132-
},
107+
expected: []string{
108+
"directive `// nolint` should not have more than one leading space at testing.go:5:9",
133109
},
134110
},
135111
{
@@ -143,8 +119,8 @@ func foo() {
143119
good() // nolint: linter1,linter2
144120
good() // nolint: linter1, linter2
145121
}`,
146-
expected: []issueWithReplacement{
147-
{"directive `// nolint:linter1 linter2` should match `// nolint[:<comma-separated-linters>] [// <explanation>]` at testing.go:6:9", nil}, //nolint:lll // this is a string
122+
expected: []string{
123+
"directive `// nolint:linter1 linter2` should match `// nolint[:<comma-separated-linters>] [// <explanation>]` at testing.go:6:9", //nolint:lll // this is a string
148124
},
149125
},
150126
{
@@ -157,92 +133,6 @@ func foo() {
157133
// something else
158134
}`,
159135
},
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-
"directive `//nolint` is unused at testing.go:5:9",
172-
&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-
"directive `//nolint:somelinter` is unused for linter \"somelinter\" at testing.go:5:9",
194-
&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 linter generates replacement for each linter",
206-
needs: NeedsUnused,
207-
contents: `
208-
package bar
209-
210-
func foo() {
211-
bad() //nolint:linter1,linter2,linter3
212-
}`,
213-
expected: []issueWithReplacement{
214-
{
215-
"directive `//nolint:linter1,linter2,linter3` is unused for linter \"linter1\" at testing.go:5:9",
216-
&result.Replacement{
217-
Inline: &result.InlineFix{
218-
StartCol: 17,
219-
Length: 22,
220-
NewString: "linter2,linter3",
221-
},
222-
},
223-
},
224-
{
225-
"directive `//nolint:linter1,linter2,linter3` is unused for linter \"linter2\" at testing.go:5:9",
226-
&result.Replacement{
227-
Inline: &result.InlineFix{
228-
StartCol: 17,
229-
Length: 22,
230-
NewString: "linter1,linter3",
231-
},
232-
},
233-
},
234-
{
235-
"directive `//nolint:linter1,linter2,linter3` is unused for linter \"linter3\" at testing.go:5:9",
236-
&result.Replacement{
237-
Inline: &result.InlineFix{
238-
StartCol: 17,
239-
Length: 22,
240-
NewString: "linter1,linter2",
241-
},
242-
},
243-
},
244-
},
245-
},
246136
}
247137

248138
for _, test := range testCases {
@@ -259,16 +149,12 @@ func foo() {
259149
actualIssues, err := linter.Run(fset, expr)
260150
require.NoError(t, err)
261151

262-
actualIssuesWithReplacements := make([]issueWithReplacement, 0, len(actualIssues))
152+
actualIssueStrs := make([]string, 0, len(actualIssues))
263153
for _, i := range actualIssues {
264-
actualIssuesWithReplacements = append(actualIssuesWithReplacements, issueWithReplacement{
265-
issue: i.String(),
266-
replacement: i.Replacement(),
267-
})
154+
actualIssueStrs = append(actualIssueStrs, i.String())
268155
}
269156

270-
assert.ElementsMatch(t, test.expected, actualIssuesWithReplacements,
271-
"expected %s \nbut got %s", test.expected, actualIssuesWithReplacements)
157+
assert.ElementsMatch(t, test.expected, actualIssueStrs, "expected %s \nbut got %s", test.expected, actualIssues)
272158
})
273159
}
274160
}

pkg/result/issue.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ type Range struct {
1414

1515
type Replacement struct {
1616
NeedOnlyDelete bool // need to delete all lines of the issue without replacement with new lines
17-
NewLines []string // if NeedDelete is false it's the replacement lines
17+
NewLines []string // is NeedDelete is false it's the replacement lines
1818
Inline *InlineFix
1919
}
2020

0 commit comments

Comments
 (0)