From 17a03933269677761cc1c82ef1fb81946468c3e7 Mon Sep 17 00:00:00 2001 From: Jameel Al-Aziz <247849+jalaziz@users.noreply.github.com> Date: Mon, 26 Feb 2024 02:58:31 -0800 Subject: [PATCH] enforce-slice-style: Support nil declaration enforcement (#974) * enforce-slice-style: Support nil declaration enforcement Add support for enforcing nil slice declarations as recommended by both the Go Code Review and Uber style guides. This initial version is quite strict in that it also prevents using empty literal and make-style slices in struct assignments and as function arguments. * Add more tests * docs --- RULES_DESCRIPTIONS.md | 3 +- rule/enforce-slice-style.go | 29 ++++- test/enforce-slice-style_test.go | 6 + testdata/enforce-slice-style-any.go | 91 ++++++++++++++ testdata/enforce-slice-style-literal.go | 91 ++++++++++++++ testdata/enforce-slice-style-make.go | 91 ++++++++++++++ testdata/enforce-slice-style-nil.go | 160 ++++++++++++++++++++++++ 7 files changed, 466 insertions(+), 5 deletions(-) create mode 100644 testdata/enforce-slice-style-nil.go diff --git a/RULES_DESCRIPTIONS.md b/RULES_DESCRIPTIONS.md index 73b0ee3..8657524 100644 --- a/RULES_DESCRIPTIONS.md +++ b/RULES_DESCRIPTIONS.md @@ -427,7 +427,7 @@ arguments = [ { funcArgStyle = "full", funcRetValStyle = "short" } ] ## enforce-slice-style -_Description_: This rule enforces consistent usage of `make([]type, 0)` or `[]type{}` for slice initialization. +_Description_: This rule enforces consistent usage of `make([]type, 0)`, `[]type{}`, or `var []type` for slice initialization. It does not affect `make([]type, non_zero_len, or_non_zero_cap)` constructions as well as `[]type{v1}`. Nil slices are always permitted. @@ -435,6 +435,7 @@ _Configuration_: (string) Specifies the enforced style for slice initialization. - "any": No enforcement (default). - "make": Enforces the usage of `make([]type, 0)`. - "literal": Enforces the usage of `[]type{}`. +- "nil": Enforces the usage of `var []type`. Example: diff --git a/rule/enforce-slice-style.go b/rule/enforce-slice-style.go index abaf20b..60d8ac0 100644 --- a/rule/enforce-slice-style.go +++ b/rule/enforce-slice-style.go @@ -14,6 +14,7 @@ const ( enforceSliceStyleTypeAny enforceSliceStyleType = "any" enforceSliceStyleTypeMake enforceSliceStyleType = "make" enforceSliceStyleTypeLiteral enforceSliceStyleType = "literal" + enforceSliceStyleTypeNil enforceSliceStyleType = "nil" ) func sliceStyleFromString(s string) (enforceSliceStyleType, error) { @@ -24,6 +25,8 @@ func sliceStyleFromString(s string) (enforceSliceStyleType, error) { return enforceSliceStyleTypeMake, nil case string(enforceSliceStyleTypeLiteral): return enforceSliceStyleTypeLiteral, nil + case string(enforceSliceStyleTypeNil): + return enforceSliceStyleTypeNil, nil default: return enforceSliceStyleTypeAny, fmt.Errorf( "invalid slice style: %s (expecting one of %v)", @@ -32,6 +35,7 @@ func sliceStyleFromString(s string) (enforceSliceStyleType, error) { enforceSliceStyleTypeAny, enforceSliceStyleTypeMake, enforceSliceStyleTypeLiteral, + enforceSliceStyleTypeNil, }, ) } @@ -86,7 +90,10 @@ func (r *EnforceSliceStyleRule) Apply(file *lint.File, arguments lint.Arguments) ast.Inspect(astFile, func(n ast.Node) bool { switch v := n.(type) { case *ast.CompositeLit: - if r.enforceSliceStyle != enforceSliceStyleTypeMake { + switch r.enforceSliceStyle { + case enforceSliceStyleTypeMake, enforceSliceStyleTypeNil: + // continue + default: return true } @@ -99,14 +106,22 @@ func (r *EnforceSliceStyleRule) Apply(file *lint.File, arguments lint.Arguments) return true } + var failureMessage string + if r.enforceSliceStyle == enforceSliceStyleTypeNil { + failureMessage = "use nil slice declaration (e.g. var args []type) instead of []type{}" + } else { + failureMessage = "use make([]type) instead of []type{} (or declare nil slice)" + } failures = append(failures, lint.Failure{ Confidence: 1, Node: v, Category: "style", - Failure: "use make([]type) instead of []type{} (or declare nil slice)", + Failure: failureMessage, }) case *ast.CallExpr: - if r.enforceSliceStyle != enforceSliceStyleTypeLiteral { + switch r.enforceSliceStyle { + case enforceSliceStyleTypeLiteral, enforceSliceStyleTypeNil: + default: // skip any function calls, even if it's make([]type) // we don't want to report it if literals are not enforced return true @@ -151,11 +166,17 @@ func (r *EnforceSliceStyleRule) Apply(file *lint.File, arguments lint.Arguments) } } + var failureMessage string + if r.enforceSliceStyle == enforceSliceStyleTypeNil { + failureMessage = "use nil slice declaration (e.g. var args []type) instead of make([]type, 0)" + } else { + failureMessage = "use []type{} instead of make([]type, 0) (or declare nil slice)" + } failures = append(failures, lint.Failure{ Confidence: 1, Node: v.Args[0], Category: "style", - Failure: "use []type{} instead of make([]type, 0) (or declare nil slice)", + Failure: failureMessage, }) } return true diff --git a/test/enforce-slice-style_test.go b/test/enforce-slice-style_test.go index 928690d..55d0c11 100644 --- a/test/enforce-slice-style_test.go +++ b/test/enforce-slice-style_test.go @@ -22,3 +22,9 @@ func TestEnforceSliceStyle_literal(t *testing.T) { Arguments: []any{"literal"}, }) } + +func TestEnforceSliceStyle_nil(t *testing.T) { + testRule(t, "enforce-slice-style-nil", &rule.EnforceSliceStyleRule{}, &lint.RuleConfig{ + Arguments: []any{"nil"}, + }) +} diff --git a/testdata/enforce-slice-style-any.go b/testdata/enforce-slice-style-any.go index 77bd4f3..98060c3 100644 --- a/testdata/enforce-slice-style-any.go +++ b/testdata/enforce-slice-style-any.go @@ -1,5 +1,7 @@ package fixtures +import "fmt" + func somefn() { m0 := make([]string, 10) m1 := make([]string, 0, 10) @@ -9,6 +11,17 @@ func somefn() { m5 := []string{"v1", "v2"} m6 := [8]string{} m7 := [...]string{} + var m8 []string + var m9 []string = make([]string, 0) + var m10 = make([]string, 0) + m11 := []string(nil) + var m12 []string = []string{} + var m13 = []string{} + var m14 = []string(nil) + var m15 []string = nil + var m16 []string + m16 = make([]string, 0) + m16 = []string{} _ = m0 _ = m1 @@ -18,6 +31,15 @@ func somefn() { _ = m5 _ = m6 _ = m7 + _ = m8 + _ = m9 + _ = m10 + _ = m11 + _ = m12 + _ = m13 + _ = m14 + _ = m15 + _ = m16 } type Slice []string @@ -29,6 +51,17 @@ func somefn2() { m3 := make(Slice, 0, 0) m4 := Slice{} m5 := Slice{"v1", "v2"} + var m6 Slice + var m7 Slice = make(Slice, 0) + var m8 = make(Slice, 0) + m9 := Slice(nil) + var m10 Slice = Slice{} + var m11 = Slice{} + var m12 = Slice(nil) + var m13 Slice = nil + var m14 Slice + m14 = make(Slice, 0) + m14 = Slice{} _ = m0 _ = m1 @@ -36,6 +69,15 @@ func somefn2() { _ = m3 _ = m4 _ = m5 + _ = m6 + _ = m7 + _ = m8 + _ = m9 + _ = m10 + _ = m11 + _ = m12 + _ = m13 + _ = m14 } type SliceSlice Slice @@ -47,6 +89,17 @@ func somefn3() { m3 := make(SliceSlice, 0, 0) m4 := SliceSlice{} m5 := SliceSlice{"v1", "v2"} + var m6 SliceSlice + var m7 SliceSlice = make(SliceSlice, 0) + var m8 = make(SliceSlice, 0) + m9 := SliceSlice(nil) + var m10 SliceSlice = SliceSlice{} + var m11 = SliceSlice{} + var m12 = SliceSlice(nil) + var m13 SliceSlice = nil + var m14 SliceSlice + m14 = make(SliceSlice, 0) + m14 = SliceSlice{} _ = m0 _ = m1 @@ -54,6 +107,15 @@ func somefn3() { _ = m3 _ = m4 _ = m5 + _ = m6 + _ = m7 + _ = m8 + _ = m9 + _ = m10 + _ = m11 + _ = m12 + _ = m13 + _ = m14 } func somefn4() { @@ -64,6 +126,35 @@ func somefn4() { m1["el3"] = make([]string, 0, 0) m1["el4"] = []string{} m1["el5"] = []string{"v1", "v2"} + m1["el6"] = nil _ = m1 } + +func somefn5() { + afunc([]string{}) + afunc(make([]string, 0)) + afunc([]string(nil)) +} + +func somefn6() { + type s struct { + a []string + } + s1 = s{a: []string{}} + s2 = s{a: make([]string, 0)} + s3 = s{} + s4 = s{a: nil} +} + +func somefn7() { + if m := []string(nil); len(m) == 0 { + fmt.Println("Hello, 世界") + } + if m := make([]string, 0); len(m) == 0 { + fmt.Println("Hello, 世界") + } + if m := []string{}; len(m) == 0 { + fmt.Println("Hello, 世界") + } +} diff --git a/testdata/enforce-slice-style-literal.go b/testdata/enforce-slice-style-literal.go index 636cd4f..3a92368 100644 --- a/testdata/enforce-slice-style-literal.go +++ b/testdata/enforce-slice-style-literal.go @@ -1,5 +1,7 @@ package fixtures +import "fmt" + func somefn() { m0 := make([]string, 10) m1 := make([]string, 0, 10) @@ -9,6 +11,17 @@ func somefn() { m5 := []string{"v1", "v2"} m6 := [8]string{} m7 := [...]string{} + var m8 []string + var m9 []string = make([]string, 0) // MATCH /use []type{} instead of make([]type, 0) (or declare nil slice)/ + var m10 = make([]string, 0) // MATCH /use []type{} instead of make([]type, 0) (or declare nil slice)/ + m11 := []string(nil) + var m12 []string = []string{} + var m13 = []string{} + var m14 = []string(nil) + var m15 []string = nil + var m16 []string + m16 = make([]string, 0) // MATCH /use []type{} instead of make([]type, 0) (or declare nil slice)/ + m16 = []string{} _ = m0 _ = m1 @@ -18,6 +31,15 @@ func somefn() { _ = m5 _ = m6 _ = m7 + _ = m8 + _ = m9 + _ = m10 + _ = m11 + _ = m12 + _ = m13 + _ = m14 + _ = m15 + _ = m16 } type Slice []string @@ -29,6 +51,17 @@ func somefn2() { m3 := make(Slice, 0, 0) // MATCH /use []type{} instead of make([]type, 0) (or declare nil slice)/ m4 := Slice{} m5 := Slice{"v1", "v2"} + var m6 Slice + var m7 Slice = make(Slice, 0) // MATCH /use []type{} instead of make([]type, 0) (or declare nil slice)/ + var m8 = make(Slice, 0) // MATCH /use []type{} instead of make([]type, 0) (or declare nil slice)/ + m9 := Slice(nil) + var m10 Slice = Slice{} + var m11 = Slice{} + var m12 = Slice(nil) + var m13 Slice = nil + var m14 Slice + m14 = make(Slice, 0) // MATCH /use []type{} instead of make([]type, 0) (or declare nil slice)/ + m14 = Slice{} _ = m0 _ = m1 @@ -36,6 +69,15 @@ func somefn2() { _ = m3 _ = m4 _ = m5 + _ = m6 + _ = m7 + _ = m8 + _ = m9 + _ = m10 + _ = m11 + _ = m12 + _ = m13 + _ = m14 } type SliceSlice Slice @@ -47,6 +89,17 @@ func somefn3() { m3 := make(SliceSlice, 0, 0) // MATCH /use []type{} instead of make([]type, 0) (or declare nil slice)/ m4 := SliceSlice{} m5 := SliceSlice{"v1", "v2"} + var m6 SliceSlice + var m7 SliceSlice = make(SliceSlice, 0) // MATCH /use []type{} instead of make([]type, 0) (or declare nil slice)/ + var m8 = make(SliceSlice, 0) // MATCH /use []type{} instead of make([]type, 0) (or declare nil slice)/ + m9 := SliceSlice(nil) + var m10 SliceSlice = SliceSlice{} + var m11 = SliceSlice{} + var m12 = SliceSlice(nil) + var m13 SliceSlice = nil + var m14 SliceSlice + m14 = make(SliceSlice, 0) // MATCH /use []type{} instead of make([]type, 0) (or declare nil slice)/ + m14 = SliceSlice{} _ = m0 _ = m1 @@ -54,6 +107,15 @@ func somefn3() { _ = m3 _ = m4 _ = m5 + _ = m6 + _ = m7 + _ = m8 + _ = m9 + _ = m10 + _ = m11 + _ = m12 + _ = m13 + _ = m14 } func somefn4() { @@ -64,6 +126,35 @@ func somefn4() { m1["el3"] = make([]string, 0, 0) // MATCH /use []type{} instead of make([]type, 0) (or declare nil slice)/ m1["el4"] = []string{} m1["el5"] = []string{"v1", "v2"} + m1["el6"] = nil _ = m1 } + +func somefn5() { + afunc([]string{}) + afunc(make([]string, 0)) // MATCH /use []type{} instead of make([]type, 0) (or declare nil slice)/ + afunc([]string(nil)) +} + +func somefn6() { + type s struct { + a []string + } + s1 = s{a: []string{}} + s2 = s{a: make([]string, 0)} // MATCH /use []type{} instead of make([]type, 0) (or declare nil slice)/ + s3 = s{} + s4 = s{a: nil} +} + +func somefn7() { + if m := []string(nil); len(m) == 0 { + fmt.Println("Hello, 世界") + } + if m := make([]string, 0); len(m) == 0 { // MATCH /use []type{} instead of make([]type, 0) (or declare nil slice)/ + fmt.Println("Hello, 世界") + } + if m := []string{}; len(m) == 0 { + fmt.Println("Hello, 世界") + } +} diff --git a/testdata/enforce-slice-style-make.go b/testdata/enforce-slice-style-make.go index 5bee16a..a42bc0b 100644 --- a/testdata/enforce-slice-style-make.go +++ b/testdata/enforce-slice-style-make.go @@ -1,5 +1,7 @@ package fixtures +import "fmt" + func somefn() { m0 := make([]string, 10) m1 := make([]string, 0, 10) @@ -9,6 +11,17 @@ func somefn() { m5 := []string{"v1", "v2"} m6 := [8]string{} m7 := [...]string{} + var m8 []string + var m9 []string = make([]string, 0) + var m10 = make([]string, 0) + m11 := []string(nil) + var m12 []string = []string{} // MATCH /use make([]type) instead of []type{} (or declare nil slice)/ + var m13 = []string{} // MATCH /use make([]type) instead of []type{} (or declare nil slice)/ + var m14 = []string(nil) + var m15 []string = nil + var m16 []string + m16 = make([]string, 0) + m16 = []string{} // MATCH /use make([]type) instead of []type{} (or declare nil slice)/ _ = m0 _ = m1 @@ -18,6 +31,15 @@ func somefn() { _ = m5 _ = m6 _ = m7 + _ = m8 + _ = m9 + _ = m10 + _ = m11 + _ = m12 + _ = m13 + _ = m14 + _ = m15 + _ = m16 } type Slice []string @@ -29,6 +51,17 @@ func somefn2() { m3 := make(Slice, 0, 0) m4 := Slice{} // MATCH /use make([]type) instead of []type{} (or declare nil slice)/ m5 := Slice{"v1", "v2"} + var m6 Slice + var m7 Slice = make(Slice, 0) + var m8 = make(Slice, 0) + m9 := Slice(nil) + var m10 Slice = Slice{} // MATCH /use make([]type) instead of []type{} (or declare nil slice)/ + var m11 = Slice{} // MATCH /use make([]type) instead of []type{} (or declare nil slice)/ + var m12 = Slice(nil) + var m13 Slice = nil + var m14 Slice + m14 = make(Slice, 0) + m14 = Slice{} // MATCH /use make([]type) instead of []type{} (or declare nil slice)/ _ = m0 _ = m1 @@ -36,6 +69,15 @@ func somefn2() { _ = m3 _ = m4 _ = m5 + _ = m6 + _ = m7 + _ = m8 + _ = m9 + _ = m10 + _ = m11 + _ = m12 + _ = m13 + _ = m14 } type SliceSlice Slice @@ -47,6 +89,17 @@ func somefn3() { m3 := make(SliceSlice, 0, 0) m4 := SliceSlice{} // MATCH /use make([]type) instead of []type{} (or declare nil slice)/ m5 := SliceSlice{"v1", "v2"} + var m6 SliceSlice + var m7 SliceSlice = make(SliceSlice, 0) + var m8 = make(SliceSlice, 0) + m9 := SliceSlice(nil) + var m10 SliceSlice = SliceSlice{} // MATCH /use make([]type) instead of []type{} (or declare nil slice)/ + var m11 = SliceSlice{} // MATCH /use make([]type) instead of []type{} (or declare nil slice)/ + var m12 = SliceSlice(nil) + var m13 SliceSlice = nil + var m14 SliceSlice + m14 = make(SliceSlice, 0) + m14 = SliceSlice{} // MATCH /use make([]type) instead of []type{} (or declare nil slice)/ _ = m0 _ = m1 @@ -54,6 +107,15 @@ func somefn3() { _ = m3 _ = m4 _ = m5 + _ = m6 + _ = m7 + _ = m8 + _ = m9 + _ = m10 + _ = m11 + _ = m12 + _ = m13 + _ = m14 } func somefn4() { @@ -64,6 +126,35 @@ func somefn4() { m1["el3"] = make([]string, 0, 0) m1["el4"] = []string{} // MATCH /use make([]type) instead of []type{} (or declare nil slice)/ m1["el5"] = []string{"v1", "v2"} + m1["el6"] = nil _ = m1 } + +func somefn5() { + afunc([]string{}) // MATCH /use make([]type) instead of []type{} (or declare nil slice)/ + afunc(make([]string, 0)) + afunc([]string(nil)) +} + +func somefn6() { + type s struct { + a []string + } + s1 = s{a: []string{}} // MATCH /use make([]type) instead of []type{} (or declare nil slice)/ + s2 = s{a: make([]string, 0)} + s3 = s{} + s4 = s{a: nil} +} + +func somefn7() { + if m := []string(nil); len(m) == 0 { + fmt.Println("Hello, 世界") + } + if m := make([]string, 0); len(m) == 0 { + fmt.Println("Hello, 世界") + } + if m := []string{}; len(m) == 0 { // MATCH /use make([]type) instead of []type{} (or declare nil slice)/ + fmt.Println("Hello, 世界") + } +} diff --git a/testdata/enforce-slice-style-nil.go b/testdata/enforce-slice-style-nil.go new file mode 100644 index 0000000..dad8915 --- /dev/null +++ b/testdata/enforce-slice-style-nil.go @@ -0,0 +1,160 @@ +package fixtures + +import "fmt" + +func somefn() { + m0 := make([]string, 10) + m1 := make([]string, 0, 10) + m2 := make([]string, 0) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + m3 := make([]string, 0, 0) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + m4 := []string{} // MATCH /use nil slice declaration (e.g. var args []type) instead of []type{}/ + m5 := []string{"v1", "v2"} + m6 := [8]string{} + m7 := [...]string{} + var m8 []string + var m9 []string = make([]string, 0) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + var m10 = make([]string, 0) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + m11 := []string(nil) + var m12 []string = []string{} // MATCH /use nil slice declaration (e.g. var args []type) instead of []type{}/ + var m13 = []string{} // MATCH /use nil slice declaration (e.g. var args []type) instead of []type{}/ + var m14 = []string(nil) + var m15 []string = nil + var m16 []string + m16 = make([]string, 0) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + m16 = []string{} // MATCH /use nil slice declaration (e.g. var args []type) instead of []type{}/ + + _ = m0 + _ = m1 + _ = m2 + _ = m3 + _ = m4 + _ = m5 + _ = m6 + _ = m7 + _ = m8 + _ = m9 + _ = m10 + _ = m11 + _ = m12 + _ = m13 + _ = m14 + _ = m15 + _ = m16 +} + +type Slice []string + +func somefn2() { + m0 := make(Slice, 10) + m1 := make(Slice, 0, 10) + m2 := make(Slice, 0) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + m3 := make(Slice, 0, 0) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + m4 := Slice{} // MATCH /use nil slice declaration (e.g. var args []type) instead of []type{}/ + m5 := Slice{"v1", "v2"} + var m6 Slice + var m7 Slice = make(Slice, 0) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + var m8 = make(Slice, 0) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + m9 := Slice(nil) + var m10 Slice = Slice{} // MATCH /use nil slice declaration (e.g. var args []type) instead of []type{}/ + var m11 = Slice{} // MATCH /use nil slice declaration (e.g. var args []type) instead of []type{}/ + var m12 = Slice(nil) + var m13 Slice = nil + var m14 Slice + m14 = make(Slice, 0) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + m14 = Slice{} // MATCH /use nil slice declaration (e.g. var args []type) instead of []type{}/ + + _ = m0 + _ = m1 + _ = m2 + _ = m3 + _ = m4 + _ = m5 + _ = m6 + _ = m7 + _ = m8 + _ = m9 + _ = m10 + _ = m11 + _ = m12 + _ = m13 + _ = m14 +} + +type SliceSlice Slice + +func somefn3() { + m0 := make(SliceSlice, 10) + m1 := make(SliceSlice, 0, 10) + m2 := make(SliceSlice, 0) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + m3 := make(SliceSlice, 0, 0) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + m4 := SliceSlice{} // MATCH /use nil slice declaration (e.g. var args []type) instead of []type{}/ + m5 := SliceSlice{"v1", "v2"} + var m6 SliceSlice + var m7 SliceSlice = make(SliceSlice, 0) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + var m8 = make(SliceSlice, 0) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + m9 := SliceSlice(nil) + var m10 SliceSlice = SliceSlice{} // MATCH /use nil slice declaration (e.g. var args []type) instead of []type{}/ + var m11 = SliceSlice{} // MATCH /use nil slice declaration (e.g. var args []type) instead of []type{}/ + var m12 = SliceSlice(nil) + var m13 SliceSlice = nil + var m14 SliceSlice + m14 = make(SliceSlice, 0) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + m14 = SliceSlice{} // MATCH /use nil slice declaration (e.g. var args []type) instead of []type{}/ + + _ = m0 + _ = m1 + _ = m2 + _ = m3 + _ = m4 + _ = m5 + _ = m6 + _ = m7 + _ = m8 + _ = m9 + _ = m10 + _ = m11 + _ = m12 + _ = m13 + _ = m14 +} + +func somefn4() { + m1 := [][]string{} // MATCH /use nil slice declaration (e.g. var args []type) instead of []type{}/ + m1["el0"] = make([]string, 10) + m1["el1"] = make([]string, 0, 10) + m1["el2"] = make([]string, 0) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + m1["el3"] = make([]string, 0, 0) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + m1["el4"] = []string{} // MATCH /use nil slice declaration (e.g. var args []type) instead of []type{}/ + m1["el5"] = []string{"v1", "v2"} + m1["el6"] = nil + + _ = m1 +} + +func somefn5() { + afunc([]string{}) // MATCH /use nil slice declaration (e.g. var args []type) instead of []type{}/ + afunc(make([]string, 0)) // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + afunc([]string(nil)) +} + +func somefn6() { + type s struct { + a []string + } + s1 = s{a: []string{}} // MATCH /use nil slice declaration (e.g. var args []type) instead of []type{}/ + s2 = s{a: make([]string, 0)} // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + s3 = s{} + s4 = s{a: nil} +} + +func somefn7() { + if m := []string(nil); len(m) == 0 { + fmt.Println("Hello, 世界") + } + if m := make([]string, 0); len(m) == 0 { // MATCH /use nil slice declaration (e.g. var args []type) instead of make([]type, 0)/ + fmt.Println("Hello, 世界") + } + if m := []string{}; len(m) == 0 { // MATCH /use nil slice declaration (e.g. var args []type) instead of []type{}/ + fmt.Println("Hello, 世界") + } +}