Skip to content

Commit e6720b8

Browse files
authored
misspell: add extra-words (#4401)
1 parent 64492b5 commit e6720b8

File tree

6 files changed

+163
-2
lines changed

6 files changed

+163
-2
lines changed

.golangci.reference.yml

+11
Original file line numberDiff line numberDiff line change
@@ -1361,9 +1361,20 @@ linters-settings:
13611361
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
13621362
# Default is to use a neutral variety of English.
13631363
locale: US
1364+
# Typos to ignore.
1365+
# Should be in lower case.
13641366
# Default: []
13651367
ignore-words:
13661368
- someword
1369+
# Extra word corrections.
1370+
# `typo` and `correction` should only contain letters.
1371+
# The words are case-insensitive.
1372+
# Default: []
1373+
extra-words:
1374+
- typo: "iff"
1375+
correction: "if"
1376+
- typo: "cancelation"
1377+
correction: "cancellation"
13671378
# Mode of the analysis:
13681379
# - default: checks all the file content.
13691380
# - restricted: checks only comments.

pkg/config/linters_settings.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -663,12 +663,18 @@ type MalignedSettings struct {
663663
}
664664

665665
type MisspellSettings struct {
666-
Mode string `mapstructure:"mode"`
667-
Locale string
666+
Mode string `mapstructure:"mode"`
667+
Locale string `mapstructure:"locale"`
668+
ExtraWords []MisspellExtraWords `mapstructure:"extra-words"`
668669
// TODO(ldez): v2 the option must be renamed to `IgnoredRules`.
669670
IgnoreWords []string `mapstructure:"ignore-words"`
670671
}
671672

673+
type MisspellExtraWords struct {
674+
Typo string `mapstructure:"typo"`
675+
Correction string `mapstructure:"correction"`
676+
}
677+
672678
type MustTagSettings struct {
673679
Functions []struct {
674680
Name string `mapstructure:"name"`

pkg/golinters/misspell.go

+33
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"go/token"
66
"strings"
77
"sync"
8+
"unicode"
89

910
"github.com/golangci/misspell"
1011
"golang.org/x/tools/go/analysis"
@@ -95,6 +96,11 @@ func createMisspellReplacer(settings *config.MisspellSettings) (*misspell.Replac
9596
return nil, fmt.Errorf("unknown locale: %q", settings.Locale)
9697
}
9798

99+
err := appendExtraWords(replacer, settings.ExtraWords)
100+
if err != nil {
101+
return nil, fmt.Errorf("process extra words: %w", err)
102+
}
103+
98104
if len(settings.IgnoreWords) != 0 {
99105
replacer.RemoveRule(settings.IgnoreWords)
100106
}
@@ -153,3 +159,30 @@ func runMisspellOnFile(lintCtx *linter.Context, filename string, replacer *missp
153159

154160
return res, nil
155161
}
162+
163+
func appendExtraWords(replacer *misspell.Replacer, extraWords []config.MisspellExtraWords) error {
164+
if len(extraWords) == 0 {
165+
return nil
166+
}
167+
168+
extra := make([]string, 0, len(extraWords)*2)
169+
170+
for _, word := range extraWords {
171+
if word.Typo == "" || word.Correction == "" {
172+
return fmt.Errorf("typo (%q) and correction (%q) fields should not be empty", word.Typo, word.Correction)
173+
}
174+
175+
if strings.ContainsFunc(word.Typo, func(r rune) bool { return !unicode.IsLetter(r) }) {
176+
return fmt.Errorf("the word %q in the 'typo' field should only contain letters", word.Typo)
177+
}
178+
if strings.ContainsFunc(word.Correction, func(r rune) bool { return !unicode.IsLetter(r) }) {
179+
return fmt.Errorf("the word %q in the 'correction' field should only contain letters", word.Correction)
180+
}
181+
182+
extra = append(extra, strings.ToLower(word.Typo), strings.ToLower(word.Correction))
183+
}
184+
185+
replacer.AddRuleList(extra)
186+
187+
return nil
188+
}

pkg/golinters/misspell_test.go

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package golinters
2+
3+
import (
4+
"testing"
5+
6+
"github.com/golangci/misspell"
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
10+
"github.com/golangci/golangci-lint/pkg/config"
11+
)
12+
13+
func Test_appendExtraWords(t *testing.T) {
14+
extraWords := []config.MisspellExtraWords{
15+
{
16+
Typo: "iff",
17+
Correction: "if",
18+
},
19+
{
20+
Typo: "canCELation",
21+
Correction: "canceLLaTION",
22+
},
23+
}
24+
25+
replacer := &misspell.Replacer{}
26+
27+
err := appendExtraWords(replacer, extraWords)
28+
require.NoError(t, err)
29+
30+
expected := []string{"iff", "if", "cancelation", "cancellation"}
31+
32+
assert.Equal(t, replacer.Replacements, expected)
33+
}
34+
35+
func Test_appendExtraWords_error(t *testing.T) {
36+
testCases := []struct {
37+
desc string
38+
extraWords []config.MisspellExtraWords
39+
expected string
40+
}{
41+
{
42+
desc: "empty fields",
43+
extraWords: []config.MisspellExtraWords{{
44+
Typo: "",
45+
Correction: "",
46+
}},
47+
expected: `typo ("") and correction ("") fields should not be empty`,
48+
},
49+
{
50+
desc: "empty typo",
51+
extraWords: []config.MisspellExtraWords{{
52+
Typo: "",
53+
Correction: "if",
54+
}},
55+
expected: `typo ("") and correction ("if") fields should not be empty`,
56+
},
57+
{
58+
desc: "empty correction",
59+
extraWords: []config.MisspellExtraWords{{
60+
Typo: "iff",
61+
Correction: "",
62+
}},
63+
expected: `typo ("iff") and correction ("") fields should not be empty`,
64+
},
65+
{
66+
desc: "invalid characters in typo",
67+
extraWords: []config.MisspellExtraWords{{
68+
Typo: "i'ff",
69+
Correction: "if",
70+
}},
71+
expected: `the word "i'ff" in the 'typo' field should only contain letters`,
72+
},
73+
{
74+
desc: "invalid characters in correction",
75+
extraWords: []config.MisspellExtraWords{{
76+
Typo: "iff",
77+
Correction: "i'f",
78+
}},
79+
expected: `the word "i'f" in the 'correction' field should only contain letters`,
80+
},
81+
}
82+
83+
for _, test := range testCases {
84+
test := test
85+
t.Run(test.desc, func(t *testing.T) {
86+
t.Parallel()
87+
88+
replacer := &misspell.Replacer{}
89+
90+
err := appendExtraWords(replacer, test.extraWords)
91+
require.EqualError(t, err, test.expected)
92+
})
93+
}
94+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
linters-settings:
2+
misspell:
3+
extra-words:
4+
- typo: "iff"
5+
correction: "if"
6+
- typo: "cancelation"
7+
correction: "cancellation"

test/testdata/misspell_custom.go

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//golangcitest:args -Emisspell
2+
//golangcitest:config_path testdata/configs/misspell_custom.yml
3+
package testdata
4+
5+
func Misspell() {
6+
// comment with incorrect spelling: occured // want "`occured` is a misspelling of `occurred`"
7+
}
8+
9+
// the word iff should be reported here // want "\\`iff\\` is a misspelling of \\`if\\`"
10+
// the word cancelation should be reported here // want "\\`cancelation\\` is a misspelling of \\`cancellation\\`"

0 commit comments

Comments
 (0)