misspell: add extra-words (#4401)
This commit is contained in:
parent
64492b5e59
commit
e6720b809f
@ -1361,9 +1361,20 @@ linters-settings:
|
|||||||
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
||||||
# Default is to use a neutral variety of English.
|
# Default is to use a neutral variety of English.
|
||||||
locale: US
|
locale: US
|
||||||
|
# Typos to ignore.
|
||||||
|
# Should be in lower case.
|
||||||
# Default: []
|
# Default: []
|
||||||
ignore-words:
|
ignore-words:
|
||||||
- someword
|
- someword
|
||||||
|
# Extra word corrections.
|
||||||
|
# `typo` and `correction` should only contain letters.
|
||||||
|
# The words are case-insensitive.
|
||||||
|
# Default: []
|
||||||
|
extra-words:
|
||||||
|
- typo: "iff"
|
||||||
|
correction: "if"
|
||||||
|
- typo: "cancelation"
|
||||||
|
correction: "cancellation"
|
||||||
# Mode of the analysis:
|
# Mode of the analysis:
|
||||||
# - default: checks all the file content.
|
# - default: checks all the file content.
|
||||||
# - restricted: checks only comments.
|
# - restricted: checks only comments.
|
||||||
|
@ -664,11 +664,17 @@ type MalignedSettings struct {
|
|||||||
|
|
||||||
type MisspellSettings struct {
|
type MisspellSettings struct {
|
||||||
Mode string `mapstructure:"mode"`
|
Mode string `mapstructure:"mode"`
|
||||||
Locale string
|
Locale string `mapstructure:"locale"`
|
||||||
|
ExtraWords []MisspellExtraWords `mapstructure:"extra-words"`
|
||||||
// TODO(ldez): v2 the option must be renamed to `IgnoredRules`.
|
// TODO(ldez): v2 the option must be renamed to `IgnoredRules`.
|
||||||
IgnoreWords []string `mapstructure:"ignore-words"`
|
IgnoreWords []string `mapstructure:"ignore-words"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MisspellExtraWords struct {
|
||||||
|
Typo string `mapstructure:"typo"`
|
||||||
|
Correction string `mapstructure:"correction"`
|
||||||
|
}
|
||||||
|
|
||||||
type MustTagSettings struct {
|
type MustTagSettings struct {
|
||||||
Functions []struct {
|
Functions []struct {
|
||||||
Name string `mapstructure:"name"`
|
Name string `mapstructure:"name"`
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"go/token"
|
"go/token"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"github.com/golangci/misspell"
|
"github.com/golangci/misspell"
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
@ -95,6 +96,11 @@ func createMisspellReplacer(settings *config.MisspellSettings) (*misspell.Replac
|
|||||||
return nil, fmt.Errorf("unknown locale: %q", settings.Locale)
|
return nil, fmt.Errorf("unknown locale: %q", settings.Locale)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err := appendExtraWords(replacer, settings.ExtraWords)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("process extra words: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
if len(settings.IgnoreWords) != 0 {
|
if len(settings.IgnoreWords) != 0 {
|
||||||
replacer.RemoveRule(settings.IgnoreWords)
|
replacer.RemoveRule(settings.IgnoreWords)
|
||||||
}
|
}
|
||||||
@ -153,3 +159,30 @@ func runMisspellOnFile(lintCtx *linter.Context, filename string, replacer *missp
|
|||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func appendExtraWords(replacer *misspell.Replacer, extraWords []config.MisspellExtraWords) error {
|
||||||
|
if len(extraWords) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
extra := make([]string, 0, len(extraWords)*2)
|
||||||
|
|
||||||
|
for _, word := range extraWords {
|
||||||
|
if word.Typo == "" || word.Correction == "" {
|
||||||
|
return fmt.Errorf("typo (%q) and correction (%q) fields should not be empty", word.Typo, word.Correction)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.ContainsFunc(word.Typo, func(r rune) bool { return !unicode.IsLetter(r) }) {
|
||||||
|
return fmt.Errorf("the word %q in the 'typo' field should only contain letters", word.Typo)
|
||||||
|
}
|
||||||
|
if strings.ContainsFunc(word.Correction, func(r rune) bool { return !unicode.IsLetter(r) }) {
|
||||||
|
return fmt.Errorf("the word %q in the 'correction' field should only contain letters", word.Correction)
|
||||||
|
}
|
||||||
|
|
||||||
|
extra = append(extra, strings.ToLower(word.Typo), strings.ToLower(word.Correction))
|
||||||
|
}
|
||||||
|
|
||||||
|
replacer.AddRuleList(extra)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
94
pkg/golinters/misspell_test.go
Normal file
94
pkg/golinters/misspell_test.go
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package golinters
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/golangci/misspell"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/golangci/golangci-lint/pkg/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_appendExtraWords(t *testing.T) {
|
||||||
|
extraWords := []config.MisspellExtraWords{
|
||||||
|
{
|
||||||
|
Typo: "iff",
|
||||||
|
Correction: "if",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Typo: "canCELation",
|
||||||
|
Correction: "canceLLaTION",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
replacer := &misspell.Replacer{}
|
||||||
|
|
||||||
|
err := appendExtraWords(replacer, extraWords)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
expected := []string{"iff", "if", "cancelation", "cancellation"}
|
||||||
|
|
||||||
|
assert.Equal(t, replacer.Replacements, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_appendExtraWords_error(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
extraWords []config.MisspellExtraWords
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "empty fields",
|
||||||
|
extraWords: []config.MisspellExtraWords{{
|
||||||
|
Typo: "",
|
||||||
|
Correction: "",
|
||||||
|
}},
|
||||||
|
expected: `typo ("") and correction ("") fields should not be empty`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "empty typo",
|
||||||
|
extraWords: []config.MisspellExtraWords{{
|
||||||
|
Typo: "",
|
||||||
|
Correction: "if",
|
||||||
|
}},
|
||||||
|
expected: `typo ("") and correction ("if") fields should not be empty`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "empty correction",
|
||||||
|
extraWords: []config.MisspellExtraWords{{
|
||||||
|
Typo: "iff",
|
||||||
|
Correction: "",
|
||||||
|
}},
|
||||||
|
expected: `typo ("iff") and correction ("") fields should not be empty`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "invalid characters in typo",
|
||||||
|
extraWords: []config.MisspellExtraWords{{
|
||||||
|
Typo: "i'ff",
|
||||||
|
Correction: "if",
|
||||||
|
}},
|
||||||
|
expected: `the word "i'ff" in the 'typo' field should only contain letters`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "invalid characters in correction",
|
||||||
|
extraWords: []config.MisspellExtraWords{{
|
||||||
|
Typo: "iff",
|
||||||
|
Correction: "i'f",
|
||||||
|
}},
|
||||||
|
expected: `the word "i'f" in the 'correction' field should only contain letters`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
test := test
|
||||||
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
replacer := &misspell.Replacer{}
|
||||||
|
|
||||||
|
err := appendExtraWords(replacer, test.extraWords)
|
||||||
|
require.EqualError(t, err, test.expected)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
7
test/testdata/configs/misspell_custom.yml
vendored
Normal file
7
test/testdata/configs/misspell_custom.yml
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
linters-settings:
|
||||||
|
misspell:
|
||||||
|
extra-words:
|
||||||
|
- typo: "iff"
|
||||||
|
correction: "if"
|
||||||
|
- typo: "cancelation"
|
||||||
|
correction: "cancellation"
|
10
test/testdata/misspell_custom.go
vendored
Normal file
10
test/testdata/misspell_custom.go
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
//golangcitest:args -Emisspell
|
||||||
|
//golangcitest:config_path testdata/configs/misspell_custom.yml
|
||||||
|
package testdata
|
||||||
|
|
||||||
|
func Misspell() {
|
||||||
|
// comment with incorrect spelling: occured // want "`occured` is a misspelling of `occurred`"
|
||||||
|
}
|
||||||
|
|
||||||
|
// the word iff should be reported here // want "\\`iff\\` is a misspelling of \\`if\\`"
|
||||||
|
// the word cancelation should be reported here // want "\\`cancelation\\` is a misspelling of \\`cancellation\\`"
|
Loading…
x
Reference in New Issue
Block a user