1
0
mirror of https://github.com/mgechev/revive.git synced 2025-11-23 22:04:49 +02:00

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
This commit is contained in:
Jameel Al-Aziz
2024-02-26 02:58:31 -08:00
committed by GitHub
parent b3a6cfe0cd
commit 17a0393326
7 changed files with 466 additions and 5 deletions

View File

@@ -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, 世界")
}
}

View File

@@ -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, 世界")
}
}

View File

@@ -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, 世界")
}
}

160
testdata/enforce-slice-style-nil.go vendored Normal file
View File

@@ -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, 世界")
}
}