Skip to content

Commit

Permalink
misspell: add extra-words (#4401)
Browse files Browse the repository at this point in the history
  • Loading branch information
ldez authored Feb 20, 2024
1 parent 64492b5 commit e6720b8
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 2 deletions.
11 changes: 11 additions & 0 deletions .golangci.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1361,9 +1361,20 @@ linters-settings:
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
# Default is to use a neutral variety of English.
locale: US
# Typos to ignore.
# Should be in lower case.
# Default: []
ignore-words:
- 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:
# - default: checks all the file content.
# - restricted: checks only comments.
Expand Down
10 changes: 8 additions & 2 deletions pkg/config/linters_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -663,12 +663,18 @@ type MalignedSettings struct {
}

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

type MisspellExtraWords struct {
Typo string `mapstructure:"typo"`
Correction string `mapstructure:"correction"`
}

type MustTagSettings struct {
Functions []struct {
Name string `mapstructure:"name"`
Expand Down
33 changes: 33 additions & 0 deletions pkg/golinters/misspell.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"go/token"
"strings"
"sync"
"unicode"

"github.com/golangci/misspell"
"golang.org/x/tools/go/analysis"
Expand Down Expand Up @@ -95,6 +96,11 @@ func createMisspellReplacer(settings *config.MisspellSettings) (*misspell.Replac
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 {
replacer.RemoveRule(settings.IgnoreWords)
}
Expand Down Expand Up @@ -153,3 +159,30 @@ func runMisspellOnFile(lintCtx *linter.Context, filename string, replacer *missp

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 changes: 94 additions & 0 deletions pkg/golinters/misspell_test.go
Original file line number Diff line number Diff line change
@@ -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 changes: 7 additions & 0 deletions test/testdata/configs/misspell_custom.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
linters-settings:
misspell:
extra-words:
- typo: "iff"
correction: "if"
- typo: "cancelation"
correction: "cancellation"
10 changes: 10 additions & 0 deletions test/testdata/misspell_custom.go
Original file line number Diff line number Diff line change
@@ -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\\`"

0 comments on commit e6720b8

Please sign in to comment.