diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f8cb730..9214437 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,8 @@ jobs: runs-on: ubuntu-latest env: GO_VERSION: stable - GOLANGCI_LINT_VERSION: v1.55.2 + GOLANGCI_LINT_VERSION: v1.56.2 + CGO_ENABLED: 0 steps: @@ -25,7 +26,7 @@ jobs: # https://github.com/marketplace/actions/setup-go-environment - name: Set up Go ${{ env.GO_VERSION }} - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} diff --git a/.github/workflows/go-cross.yml b/.github/workflows/go-cross.yml index 4682daf..f232db9 100644 --- a/.github/workflows/go-cross.yml +++ b/.github/workflows/go-cross.yml @@ -26,7 +26,7 @@ jobs: # https://github.com/marketplace/actions/setup-go-environment - name: Set up Go ${{ matrix.go-version }} - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5d440aa..a223796 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,7 +22,7 @@ jobs: # https://github.com/marketplace/actions/setup-go-environment - name: Set up Go ${{ env.GO_VERSION }} - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} diff --git a/.golangci.yml b/.golangci.yml index 31c566e..db2d7c7 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -7,7 +7,6 @@ linters-settings: enable-all: true disable: - fieldalignment - - shadow # FIXME(ldez) must be fixed gocyclo: min-complexity: 16 goconst: diff --git a/Dockerfile b/Dockerfile index 788ce3a..c85cd68 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.19-alpine +FROM golang:1.22-alpine # cache buster RUN echo 4 diff --git a/cmd/misspell/main.go b/cmd/misspell/main.go index feb9c8b..6dd6012 100644 --- a/cmd/misspell/main.go +++ b/cmd/misspell/main.go @@ -159,7 +159,7 @@ func main() { // // Stuff to ignore // - if len(*ignores) > 0 { + if *ignores != "" { r.RemoveRule(strings.Split(*ignores, ",")) } @@ -188,7 +188,7 @@ func main() { defaultWrite = tmpl defaultRead = tmpl stdout.Println(sqliteHeader) - case len(*format) > 0: + case *format != "": t, err := template.New("custom").Parse(*format) if err != nil { log.Fatalf("Unable to compile log format: %s", err) diff --git a/go.mod b/go.mod index b417491..b4b425d 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ module github.com/golangci/misspell -go 1.19 +go 1.21 require github.com/gobwas/glob v0.2.3 diff --git a/ignore/glob.go b/ignore/glob.go index fe62152..c95d5f2 100644 --- a/ignore/glob.go +++ b/ignore/glob.go @@ -89,7 +89,7 @@ func NewBaseGlobMatch(arg string, truth bool) (*GlobMatch, error) { // Arg true should be set to false if the output is inverted. func NewPathGlobMatch(arg string, truth bool) (*GlobMatch, error) { // if starts with "/" then glob only applies to top level - if len(arg) > 0 && arg[0] == '/' { + if arg != "" && arg[0] == '/' { arg = arg[1:] } diff --git a/mime.go b/mime.go index 76a96cf..19d49e0 100644 --- a/mime.go +++ b/mime.go @@ -7,6 +7,7 @@ import ( "net/http" "os" "path/filepath" + "slices" "strings" ) @@ -77,13 +78,12 @@ func isSCMPath(s string) bool { if strings.Contains(filepath.Base(s), "EDITMSG") { return false } + parts := strings.Split(filepath.Clean(s), string(filepath.Separator)) - for _, dir := range parts { - if scm[dir] { - return true - } - } - return false + + return slices.ContainsFunc(parts, func(dir string) bool { + return scm[dir] + }) } var magicHeaders = [][]byte{ @@ -174,7 +174,8 @@ func ReadTextFile(filename string) (string, error) { // if not-text, then exit isText := false if fstat.Size() > 50000 { - fin, err := os.Open(filename) + var fin *os.File + fin, err = os.Open(filename) if err != nil { return "", fmt.Errorf("unable to open large file %q: %w", filename, err) } diff --git a/notwords.go b/notwords.go index a250cf7..3e3a4cc 100644 --- a/notwords.go +++ b/notwords.go @@ -20,7 +20,7 @@ var ( func RemovePath(s string) string { out := bytes.Buffer{} var idx int - for len(s) > 0 { + for s != "" { if idx = strings.IndexByte(s, '/'); idx == -1 { out.WriteString(s) break diff --git a/replace.go b/replace.go index bcfcf8d..b51dfa8 100644 --- a/replace.go +++ b/replace.go @@ -5,6 +5,7 @@ import ( "bytes" "io" "regexp" + "slices" "strings" "text/scanner" ) @@ -17,12 +18,9 @@ func max(x, y int) int { } func inArray(haystack []string, needle string) bool { - for _, word := range haystack { - if strings.EqualFold(needle, word) { - return true - } - } - return false + return slices.ContainsFunc(haystack, func(word string) bool { + return strings.EqualFold(needle, word) + }) } var wordRegexp = regexp.MustCompile(`[a-zA-Z0-9']+`) @@ -192,7 +190,7 @@ Loop: return buf.String(), diffs } -// Replace is corrects misspellings in input, returning corrected version along with a list of diffs. +// Replace is correcting misspellings in input, returning corrected version along with a list of diffs. func (r *Replacer) Replace(input string) (string, []Diff) { output := r.engine.Replace(input) if input == output { diff --git a/stringreplacer.go b/stringreplacer.go index d3d2778..46cb6c4 100644 --- a/stringreplacer.go +++ b/stringreplacer.go @@ -102,7 +102,6 @@ func (t *trieNode) add(key, val string, priority int, r *genericReplacer) { return } - //nolint:nestif // TODO(ldez) must be fixed. if t.prefix != "" { // Need to split the prefix among multiple nodes. var n int // length of the longest common prefix @@ -111,9 +110,10 @@ func (t *trieNode) add(key, val string, priority int, r *genericReplacer) { break } } - if n == len(t.prefix) { + switch n { + case len(t.prefix): t.next.add(key[n:], val, priority, r) - } else if n == 0 { + case 0: // First byte differs, start a new lookup table here. Looking up // what is currently t.prefix[0] will lead to prefixNode, and // looking up key[0] will lead to keyNode. @@ -133,7 +133,7 @@ func (t *trieNode) add(key, val string, priority int, r *genericReplacer) { t.prefix = "" t.next = nil keyNode.add(key[1:], val, priority, r) - } else { + default: // Insert new node after the common section of the prefix. next := &trieNode{ prefix: t.prefix[n:], @@ -143,18 +143,22 @@ func (t *trieNode) add(key, val string, priority int, r *genericReplacer) { t.next = next next.add(key[n:], val, priority, r) } - } else if t.table != nil { + return + } + + if t.table != nil { // Insert into existing table. m := r.mapping[key[0]] if t.table[m] == nil { t.table[m] = new(trieNode) } t.table[m].add(key[1:], val, priority, r) - } else { - t.prefix = key - t.next = new(trieNode) - t.next.add("", val, priority, r) + return } + + t.prefix = key + t.next = new(trieNode) + t.next.add("", val, priority, r) } // genericReplacer is the fully generic algorithm. diff --git a/words_test.go b/words_test.go index 31fcf28..7f7cde1 100644 --- a/words_test.go +++ b/words_test.go @@ -19,14 +19,16 @@ func (a sortByLen) Less(i, j int) bool { return len(a[i]) > len(a[j]) } -func TestWordSort(t *testing.T) { +func Test_wordSort(t *testing.T) { if len(DictMain)%2 == 1 { t.Errorf("Dictionary is a not a multiple of 2") } + words := make([]string, 0, len(DictMain)/2) for i := 0; i < len(DictMain); i += 2 { words = append(words, DictMain[i]) } + if !sort.IsSorted(sortByLen(words)) { t.Errorf("Words not sorted by len, by alpha!") t.Errorf("Words.go is autogenerated -- do not edit.")