From 6481ba19f86959dd8f9b154df34f523e14e98adb Mon Sep 17 00:00:00 2001 From: Adrien CABARBAYE Date: Wed, 8 Jan 2025 15:02:52 +0000 Subject: [PATCH 1/2] :sparkles: `[collection]` add helpers easier to use with slices --- changes/20250108150125.feature | 1 + utils/collection/modify.go | 5 ++++ utils/collection/search.go | 41 +++++++++++++++++++++++++++++++++ utils/collection/search_test.go | 39 +++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 changes/20250108150125.feature diff --git a/changes/20250108150125.feature b/changes/20250108150125.feature new file mode 100644 index 0000000000..6e0ae8c127 --- /dev/null +++ b/changes/20250108150125.feature @@ -0,0 +1 @@ +:sparkles: `[collection]` add helpers easier to use with slices diff --git a/utils/collection/modify.go b/utils/collection/modify.go index fba08dbe01..d1da6053c9 100644 --- a/utils/collection/modify.go +++ b/utils/collection/modify.go @@ -4,6 +4,8 @@ */ package collection +import "slices" + // Remove looks for elements in a slice. If they're found, it will // remove them. func Remove(slice []string, val ...string) []string { @@ -16,6 +18,9 @@ func GenericRemove(equal func(string, string) bool, slice []string, val ...strin if len(val) == 0 { return slice } + if len(val) == 1 { + return slices.DeleteFunc(slice, func(v string) bool { return equal(v, val[0]) }) + } list := make([]string, 0, len(slice)) found := make([]bool, len(val)) diff --git a/utils/collection/search.go b/utils/collection/search.go index e47c33404b..33b2ce8ca1 100644 --- a/utils/collection/search.go +++ b/utils/collection/search.go @@ -5,6 +5,7 @@ package collection import ( + "slices" "strings" mapset "github.com/deckarep/golang-set/v2" @@ -25,6 +26,10 @@ func FindInSlice(strict bool, slice []string, val ...string) (int, bool) { if len(val) == 0 || len(slice) == 0 { return -1, false } + if strict && len(val) == 1 { + idx := slices.Index(slice, val[0]) + return idx, idx >= 0 + } inSlice := make(map[string]int, len(slice)) for i := range slice { @@ -59,6 +64,9 @@ func UniqueEntries[T comparable](slice []T) []T { // Any returns true if there is at least one element of the slice which is true. func Any(slice []bool) bool { + if len(slice) == 0 { + return false + } for i := range slice { if slice[i] { return true @@ -67,6 +75,21 @@ func Any(slice []bool) bool { return false } +// AnyTrue returns whether there is a value set to true +func AnyTrue(values ...bool) bool { + return Any(values) +} + +// AnyFunc returns whether there is at least one element of slice s for which f() returns true. +func AnyFunc[S ~[]E, E any](s S, f func(E) bool) bool { + all := make([]bool, 0, len(s)) + for i := range s { + all = append(all, f(s[i])) + + } + return Any(all) +} + // AnyEmpty returns whether there is one entry in the slice which is empty. // If strict, then whitespaces are considered as empty strings func AnyEmpty(strict bool, slice []string) bool { @@ -76,6 +99,9 @@ func AnyEmpty(strict bool, slice []string) bool { // All returns true if all items of the slice are true. func All(slice []bool) bool { + if len(slice) == 0 { + return false + } for i := range slice { if !slice[i] { return false @@ -84,6 +110,21 @@ func All(slice []bool) bool { return true } +// AllTrue returns whether all values are true. +func AllTrue(values ...bool) bool { + return All(values) +} + +// AllFunc returns whether f returns true for all the elements of slice s. +func AllFunc[S ~[]E, E any](s S, f func(E) bool) bool { + all := make([]bool, 0, len(s)) + for i := range s { + all = append(all, f(s[i])) + + } + return All(all) +} + // AllNotEmpty returns whether all elements of the slice are not empty. // If strict, then whitespaces are considered as empty strings func AllNotEmpty(strict bool, slice []string) bool { diff --git a/utils/collection/search_test.go b/utils/collection/search_test.go index 7cc0b6984e..115fe8fb53 100644 --- a/utils/collection/search_test.go +++ b/utils/collection/search_test.go @@ -58,19 +58,58 @@ func TestFindInSlice(t *testing.T) { } func TestAny(t *testing.T) { + assert.False(t, Any([]bool{})) assert.True(t, Any([]bool{false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false})) assert.False(t, Any([]bool{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false})) assert.True(t, Any([]bool{true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true})) assert.True(t, Any([]bool{true, true, true, true, true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true})) } +func TestAnyTrue(t *testing.T) { + assert.False(t, AnyTrue()) + assert.True(t, AnyTrue(false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false)) + assert.False(t, AnyTrue(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false)) + assert.True(t, AnyTrue(true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true)) + assert.True(t, AnyTrue(true, true, true, true, true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true)) +} + +func TestAnyFunc(t *testing.T) { + f := func(v bool) bool { + return v + } + assert.False(t, AnyFunc([]bool{}, f)) + assert.True(t, AnyFunc([]bool{false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false}, f)) + assert.False(t, AnyFunc([]bool{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, f)) + assert.True(t, AnyFunc([]bool{true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true}, f)) + assert.True(t, AnyFunc([]bool{true, true, true, true, true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true}, f)) +} + func TestAll(t *testing.T) { + assert.False(t, All([]bool{})) assert.False(t, All([]bool{false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false})) assert.False(t, All([]bool{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false})) assert.True(t, All([]bool{true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true})) assert.False(t, All([]bool{true, true, true, true, true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true})) } +func TestAllTrue(t *testing.T) { + assert.False(t, AllTrue(false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false)) + assert.False(t, AllTrue(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false)) + assert.True(t, AllTrue(true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true)) + assert.False(t, AllTrue(true, true, true, true, true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true)) +} + +func TestAllFunc(t *testing.T) { + f := func(v bool) bool { + return v + } + assert.False(t, AllFunc([]bool{}, f)) + assert.False(t, AllFunc([]bool{false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false}, f)) + assert.False(t, AllFunc([]bool{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, f)) + assert.True(t, AllFunc([]bool{true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true}, f)) + assert.False(t, AllFunc([]bool{true, true, true, true, true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true}, f)) +} + func TestAnyEmpty(t *testing.T) { assert.True(t, AnyEmpty(false, []string{faker.Username(), faker.Name(), faker.Sentence(), ""})) assert.False(t, AnyEmpty(false, []string{faker.Username(), " ", faker.Name(), faker.Sentence()})) From 8555a382632ffab0131b34b4dea6acad338713f5 Mon Sep 17 00:00:00 2001 From: Adrien CABARBAYE Date: Wed, 8 Jan 2025 18:02:12 +0000 Subject: [PATCH 2/2] :gear: disable incorrect linting --- utils/filesystem/limits_test.go | 4 ++-- utils/git/config_test.go | 2 +- utils/git/limits_test.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/utils/filesystem/limits_test.go b/utils/filesystem/limits_test.go index 649d5dbe23..48369a1342 100644 --- a/utils/filesystem/limits_test.go +++ b/utils/filesystem/limits_test.go @@ -8,8 +8,8 @@ import ( ) func TestNewLimits(t *testing.T) { - require.NoError(t, NoLimits().Validate()) - require.NoError(t, DefaultLimits().Validate()) + require.NoError(t, NoLimits().Validate()) //nolint:typecheck + require.NoError(t, DefaultLimits().Validate()) //nolint:typecheck assert.True(t, DefaultLimits().Apply()) assert.False(t, NoLimits().Apply()) } diff --git a/utils/git/config_test.go b/utils/git/config_test.go index 48b1de7355..7dd5cab1e9 100644 --- a/utils/git/config_test.go +++ b/utils/git/config_test.go @@ -7,5 +7,5 @@ import ( ) func TestNewConfig(t *testing.T) { - require.NoError(t, DefaultLimits().Validate()) + require.NoError(t, DefaultLimits().Validate()) //nolint:typecheck } diff --git a/utils/git/limits_test.go b/utils/git/limits_test.go index 763f3663df..8346a74ed9 100644 --- a/utils/git/limits_test.go +++ b/utils/git/limits_test.go @@ -8,8 +8,8 @@ import ( ) func TestNewLimits(t *testing.T) { - require.NoError(t, NoLimits().Validate()) - require.NoError(t, DefaultLimits().Validate()) + require.NoError(t, NoLimits().Validate()) //nolint:typecheck + require.NoError(t, DefaultLimits().Validate()) //nolint:typecheck assert.True(t, DefaultLimits().Apply()) assert.False(t, NoLimits().Apply()) }