From c53d46816f9e37ba40d730a95024e603f97e1f6c Mon Sep 17 00:00:00 2001 From: Ruidy Date: Mon, 1 Sep 2025 23:08:10 -0400 Subject: [PATCH] refactor: migrate to Go 1.22 slices/cmp, update linters Replace usage of golang.org/x/exp/constraints with Go 1.22 cmp/slices. Update .golangci.yml to new v2 format and enable gofmt/goimports. Refactor imports and type constraints across codebase for consistency. --- .golangci.yml | 58 ++++++++++++++++++++++++++------------------ any.go | 9 +++---- drop_test.go | 1 - find_test.go | 3 ++- flatmap_test.go | 3 ++- intersection_test.go | 4 +-- join.go | 14 +++++------ join_test.go | 29 ++++++++++++---------- max.go | 4 +-- min.go | 4 +-- pipe.go | 6 ++--- result.go | 2 +- slices.go | 7 +++--- sum.go | 8 +++--- 14 files changed, 83 insertions(+), 69 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 0cdfa63..ccdfeec 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,42 +1,54 @@ -skip-dirs-use-default: true - -run: - timeout: 5m - +version: "2" linters: enable: - bodyclose - - deadcode - depguard - dogsled - - errcheck - errorlint - - exportloopref - gocritic - gocyclo - - gofmt - - goimports - goprintffuncname - - gosimple - gosec - - govet - - ineffassign - misspell - noctx - nolintlint - prealloc - rowserrcheck - staticcheck - - structcheck - - stylecheck - - typecheck - unconvert - unparam - - unused - - varcheck - whitespace - fast: true - -linters-settings: - goimports: - local-prefixes: github.com/rjNemo/underscore \ No newline at end of file + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ + settings: + depguard: + rules: + main: + list-mode: lax + files: + - $all + allow: + - $gostd + - github.com/rjNemo/underscore + - github.com/rjNemo/underscore/... + - github.com/stretchr/testify/... + - golang.org/x/exp/constraints +formatters: + enable: + - gofmt + - goimports + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/any.go b/any.go index e74934b..32bb95e 100644 --- a/any.go +++ b/any.go @@ -1,12 +1,9 @@ package underscore +import "slices" + // Any returns true if any of the values in the slice pass the predicate truth test. // Short-circuits and stops traversing the slice if a true element is found. func Any[T any](values []T, predicate func(T) bool) bool { - for _, v := range values { - if predicate(v) { - return true - } - } - return false + return slices.ContainsFunc(values, predicate) } diff --git a/drop_test.go b/drop_test.go index 97a187d..ccd5240 100644 --- a/drop_test.go +++ b/drop_test.go @@ -9,7 +9,6 @@ import ( ) func TestDrop(t *testing.T) { - nums := []int{1, 9, 2, 8, 3, 7, 4, 6, 5} want := []int{1, 9, 2, 3, 7, 4, 6, 5} diff --git a/find_test.go b/find_test.go index 7a07a9e..1be791c 100644 --- a/find_test.go +++ b/find_test.go @@ -3,8 +3,9 @@ package underscore_test import ( "testing" - u "github.com/rjNemo/underscore" "github.com/stretchr/testify/assert" + + u "github.com/rjNemo/underscore" ) func TestFind(t *testing.T) { diff --git a/flatmap_test.go b/flatmap_test.go index 29fdb10..ff5ca41 100644 --- a/flatmap_test.go +++ b/flatmap_test.go @@ -3,8 +3,9 @@ package underscore_test import ( "testing" - u "github.com/rjNemo/underscore" "github.com/stretchr/testify/assert" + + u "github.com/rjNemo/underscore" ) func TestFlatmap(t *testing.T) { diff --git a/intersection_test.go b/intersection_test.go index c9f353b..839b58d 100644 --- a/intersection_test.go +++ b/intersection_test.go @@ -3,9 +3,9 @@ package underscore_test import ( "testing" - u "github.com/rjNemo/underscore" - "github.com/stretchr/testify/assert" + + u "github.com/rjNemo/underscore" ) func TestIntersection(t *testing.T) { diff --git a/join.go b/join.go index fdb3208..9dab6b0 100644 --- a/join.go +++ b/join.go @@ -6,12 +6,12 @@ func Join[T, P any, S comparable]( left []T, right []P, leftSelector func(T) S, - rightSelector func(P) S) []Tuple[T, []P] { - - var results = make([]Tuple[T, []P], 0, len(left)) + rightSelector func(P) S, +) []Tuple[T, []P] { + results := make([]Tuple[T, []P], 0, len(left)) for _, l := range left { - var matches = Filter(right, func(r P) bool { return leftSelector(l) == rightSelector(r) }) - var tuple = Tuple[T, []P]{Left: l, Right: matches} + matches := Filter(right, func(r P) bool { return leftSelector(l) == rightSelector(r) }) + tuple := Tuple[T, []P]{Left: l, Right: matches} results = append(results, tuple) } @@ -28,8 +28,8 @@ func JoinProject[L, R, O any, S comparable]( right []R, leftSelector func(L) S, rightSelector func(R) S, - projection func(Tuple[L, []R]) O) (results []O) { - + projection func(Tuple[L, []R]) O, +) (results []O) { for _, x := range Join(left, right, leftSelector, rightSelector) { results = append(results, projection(x)) } diff --git a/join_test.go b/join_test.go index 1159af5..8cf322a 100644 --- a/join_test.go +++ b/join_test.go @@ -3,23 +3,26 @@ package underscore_test import ( "testing" - u "github.com/rjNemo/underscore" "github.com/stretchr/testify/assert" + + u "github.com/rjNemo/underscore" ) -var zero = u.Tuple[int, string]{Left: 0, Right: "Zero"} -var one = u.Tuple[int, string]{Left: 1, Right: "One"} -var two = u.Tuple[int, string]{Left: 2, Right: "Two"} -var three = u.Tuple[int, string]{Left: 3, Right: "Three"} +var ( + zero = u.Tuple[int, string]{Left: 0, Right: "Zero"} + one = u.Tuple[int, string]{Left: 1, Right: "One"} + two = u.Tuple[int, string]{Left: 2, Right: "Two"} + three = u.Tuple[int, string]{Left: 3, Right: "Three"} +) func Test_Join_Can_Join_Two_Slices_Together(t *testing.T) { - var left = []u.Tuple[int, string]{zero, one, two, three} - var right = []u.Tuple[int, string]{one, three, two, three, two, three} + left := []u.Tuple[int, string]{zero, one, two, three} + right := []u.Tuple[int, string]{one, three, two, three, two, three} selector := func(x u.Tuple[int, string]) int { return x.Left } - var joined = u.Join(left, right, selector, selector) - var want = []u.Tuple[u.Tuple[int, string], []u.Tuple[int, string]]{ + joined := u.Join(left, right, selector, selector) + want := []u.Tuple[u.Tuple[int, string], []u.Tuple[int, string]]{ {Left: zero, Right: nil}, {Left: one, Right: []u.Tuple[int, string]{one}}, {Left: two, Right: []u.Tuple[int, string]{two, two}}, @@ -30,16 +33,16 @@ func Test_Join_Can_Join_Two_Slices_Together(t *testing.T) { } func Test_Join_Can_Join_and_Project_Two_Slices_Together(t *testing.T) { - var left = []u.Tuple[int, string]{zero, one, two, three} - var right = []u.Tuple[int, string]{one, three, two, three, two, three} + left := []u.Tuple[int, string]{zero, one, two, three} + right := []u.Tuple[int, string]{one, three, two, three, two, three} selector := func(x u.Tuple[int, string]) int { return x.Left } project := func(x u.Tuple[u.Tuple[int, string], []u.Tuple[int, string]]) int { return len(x.Right) // projecting to a could of how many } - var joined = u.JoinProject(left, right, selector, selector, project) - var want = []int{0, 1, 2, 3} + joined := u.JoinProject(left, right, selector, selector, project) + want := []int{0, 1, 2, 3} assert.Equal(t, want, joined) } diff --git a/max.go b/max.go index 0799e0b..be74b3c 100644 --- a/max.go +++ b/max.go @@ -1,11 +1,11 @@ package underscore -import "golang.org/x/exp/constraints" +import "cmp" // Max returns the maximum value in the slice. // This function can currently only compare numbers reliably. // This function uses operator <. -func Max[T constraints.Ordered](values []T) T { +func Max[T cmp.Ordered](values []T) T { max := values[0] for _, v := range values { if v > max { diff --git a/min.go b/min.go index 7789583..35c42a0 100644 --- a/min.go +++ b/min.go @@ -1,11 +1,11 @@ package underscore -import "golang.org/x/exp/constraints" +import "cmp" // Min returns the minimum value in the slice. // This function can currently only compare numbers reliably. // This function uses operator <. -func Min[T constraints.Ordered](values []T) T { +func Min[T cmp.Ordered](values []T) T { min := values[0] for _, v := range values { if v < min { diff --git a/pipe.go b/pipe.go index 7fde98a..7223ada 100644 --- a/pipe.go +++ b/pipe.go @@ -1,10 +1,10 @@ package underscore import ( - "golang.org/x/exp/constraints" + "cmp" ) -type Pipe[T constraints.Ordered] struct { +type Pipe[T cmp.Ordered] struct { Value []T } @@ -12,7 +12,7 @@ type Pipe[T constraints.Ordered] struct { // call Value to retrieve the final value. // // Methods not returning a slice such as Reduce, All, Any, will break the Pipe and return Value instantly. -func NewPipe[T constraints.Ordered](value []T) Pipe[T] { +func NewPipe[T cmp.Ordered](value []T) Pipe[T] { return Pipe[T]{Value: value} } diff --git a/result.go b/result.go index d6463f4..f20c378 100644 --- a/result.go +++ b/result.go @@ -2,7 +2,7 @@ package underscore // Result represent the outcome of an operation where failure is possible type Result[T any] interface { - isResult() //to seal the Result interface + isResult() // to seal the Result interface ToValue() (*T, error) IsSuccess() bool } diff --git a/slices.go b/slices.go index ad2f462..8b73940 100644 --- a/slices.go +++ b/slices.go @@ -1,20 +1,19 @@ package underscore import ( + "cmp" "sort" - - "golang.org/x/exp/constraints" ) // SortSliceASC sorts any slice ASCENDING -func SortSliceASC[T constraints.Ordered](s []T) { +func SortSliceASC[T cmp.Ordered](s []T) { sort.SliceStable(s, func(i, j int) bool { return s[i] < s[j] }) } // SortSliceDESC sorts any slice DESCENDING -func SortSliceDESC[T constraints.Ordered](s []T) { +func SortSliceDESC[T cmp.Ordered](s []T) { sort.SliceStable(s, func(i, j int) bool { return s[i] > s[j] }) diff --git a/sum.go b/sum.go index bd18a35..9d7178e 100644 --- a/sum.go +++ b/sum.go @@ -1,9 +1,11 @@ package underscore -import "golang.org/x/exp/constraints" +import ( + "cmp" +) // Sum adds elements of the slice. -func Sum[T constraints.Ordered](values []T) (sum T) { +func Sum[T cmp.Ordered](values []T) (sum T) { for _, v := range values { sum += v } @@ -12,7 +14,7 @@ func Sum[T constraints.Ordered](values []T) (sum T) { // SumMap sums the values you select from your struct, basically a sort cut instead of // having to perform a [Map] followed by a [Sum]. -func SumMap[T any, R constraints.Ordered](list []T, selector func(T) R) (sum R) { +func SumMap[T any, R cmp.Ordered](list []T, selector func(T) R) (sum R) { for _, v := range list { sum += selector(v) }