From f479a923fa9c1c6887e8dbc9ddd16156548af800 Mon Sep 17 00:00:00 2001 From: Sergey Vilgelm Date: Tue, 8 Sep 2020 10:06:40 -0500 Subject: [PATCH 1/2] Add stringintconv and ifaceassert to govet Add new linters: * stringintconv, enabled by default * ifaceassert is additional linter Move govet tests to a dedicated folder --- pkg/golinters/govet.go | 5 +++++ test/testdata/{govet.go => govet/default.go} | 17 +++++++++++------ test/testdata/govet/ifaceassert.go | 14 ++++++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) rename test/testdata/{govet.go => govet/default.go} (65%) create mode 100644 test/testdata/govet/ifaceassert.go diff --git a/pkg/golinters/govet.go b/pkg/golinters/govet.go index 7ea1f094e641..4e79c980b8ff 100644 --- a/pkg/golinters/govet.go +++ b/pkg/golinters/govet.go @@ -17,6 +17,7 @@ import ( "golang.org/x/tools/go/analysis/passes/errorsas" "golang.org/x/tools/go/analysis/passes/findcall" "golang.org/x/tools/go/analysis/passes/httpresponse" + "golang.org/x/tools/go/analysis/passes/ifaceassert" _ "golang.org/x/tools/go/analysis/passes/inspect" // unused internal analyzer "golang.org/x/tools/go/analysis/passes/loopclosure" "golang.org/x/tools/go/analysis/passes/lostcancel" @@ -28,6 +29,7 @@ import ( "golang.org/x/tools/go/analysis/passes/shift" "golang.org/x/tools/go/analysis/passes/sortslice" "golang.org/x/tools/go/analysis/passes/stdmethods" + "golang.org/x/tools/go/analysis/passes/stringintconv" "golang.org/x/tools/go/analysis/passes/structtag" "golang.org/x/tools/go/analysis/passes/testinggoroutine" "golang.org/x/tools/go/analysis/passes/tests" @@ -55,6 +57,7 @@ var ( errorsas.Analyzer, findcall.Analyzer, httpresponse.Analyzer, + ifaceassert.Analyzer, loopclosure.Analyzer, lostcancel.Analyzer, nilfunc.Analyzer, @@ -64,6 +67,7 @@ var ( shift.Analyzer, sortslice.Analyzer, stdmethods.Analyzer, + stringintconv.Analyzer, structtag.Analyzer, testinggoroutine.Analyzer, tests.Analyzer, @@ -90,6 +94,7 @@ var ( printf.Analyzer, shift.Analyzer, stdmethods.Analyzer, + stringintconv.Analyzer, structtag.Analyzer, tests.Analyzer, unmarshal.Analyzer, diff --git a/test/testdata/govet.go b/test/testdata/govet/default.go similarity index 65% rename from test/testdata/govet.go rename to test/testdata/govet/default.go index 2843521e46d9..f23df4ab1640 100644 --- a/test/testdata/govet.go +++ b/test/testdata/govet/default.go @@ -1,6 +1,6 @@ //args: -Egovet //config: linters-settings.govet.check-shadowing=true -package testdata +package govet import ( "fmt" @@ -8,11 +8,11 @@ import ( "os" ) -func Govet() error { +func Composites() error { return &os.PathError{"first", "path", os.ErrNotExist} // ERROR "composites: \\`(os|io/fs)\\.PathError\\` composite literal uses unkeyed fields" } -func GovetShadow(f io.Reader, buf []byte) (err error) { +func Shadow(f io.Reader, buf []byte) (err error) { if f != nil { _, err := f.Read(buf) // ERROR `shadow: declaration of .err. shadows declaration at line \d+` if err != nil { @@ -24,15 +24,20 @@ func GovetShadow(f io.Reader, buf []byte) (err error) { return } -func GovetNolintVet() error { +func NolintVet() error { return &os.PathError{"first", "path", os.ErrNotExist} //nolint:vet } -func GovetNolintVetShadow() error { +func NolintVetShadow() error { return &os.PathError{"first", "path", os.ErrNotExist} //nolint:vetshadow } -func GovetPrintf() { +func Printf() { x := "dummy" fmt.Printf("%d", x) // ERROR "printf: Printf format %d has arg x of wrong type string" } + +func StringIntConv() { + i := 42 + fmt.Println("i = " + string(i)) // ERROR "stringintconv: conversion from int to string yields a string of one rune, not a string of digits (did you mean fmt.Sprint(x)?)" +} diff --git a/test/testdata/govet/ifaceassert.go b/test/testdata/govet/ifaceassert.go new file mode 100644 index 000000000000..c00535c226e8 --- /dev/null +++ b/test/testdata/govet/ifaceassert.go @@ -0,0 +1,14 @@ +//args: -Egovet +//config: linters-settings.govet.enable=["ifaceassert"] +package govet + +import ( + "io" +) + +func IfaceAssert() { + var v interface { + Read() + } + _ = v.(io.Reader) // ERROR "composites: `os.PathError` composite literal uses unkeyed fields" +} From d3ec33e7a14fa30f18aaa7cc74e5f667047356b2 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Thu, 18 Feb 2021 01:36:08 +0100 Subject: [PATCH 2/2] fix: tests --- test/testdata/{govet/default.go => govet.go} | 16 ++++++++-------- test/testdata/govet/ifaceassert.go | 14 -------------- test/testdata/govet_ifaceassert.go | 14 ++++++++++++++ 3 files changed, 22 insertions(+), 22 deletions(-) rename test/testdata/{govet/default.go => govet.go} (75%) delete mode 100644 test/testdata/govet/ifaceassert.go create mode 100644 test/testdata/govet_ifaceassert.go diff --git a/test/testdata/govet/default.go b/test/testdata/govet.go similarity index 75% rename from test/testdata/govet/default.go rename to test/testdata/govet.go index f23df4ab1640..b97980352046 100644 --- a/test/testdata/govet/default.go +++ b/test/testdata/govet.go @@ -1,6 +1,6 @@ //args: -Egovet //config: linters-settings.govet.check-shadowing=true -package govet +package testdata import ( "fmt" @@ -8,11 +8,11 @@ import ( "os" ) -func Composites() error { +func GovetComposites() error { return &os.PathError{"first", "path", os.ErrNotExist} // ERROR "composites: \\`(os|io/fs)\\.PathError\\` composite literal uses unkeyed fields" } -func Shadow(f io.Reader, buf []byte) (err error) { +func GovetShadow(f io.Reader, buf []byte) (err error) { if f != nil { _, err := f.Read(buf) // ERROR `shadow: declaration of .err. shadows declaration at line \d+` if err != nil { @@ -24,20 +24,20 @@ func Shadow(f io.Reader, buf []byte) (err error) { return } -func NolintVet() error { +func GovetNolintVet() error { return &os.PathError{"first", "path", os.ErrNotExist} //nolint:vet } -func NolintVetShadow() error { +func GovetNolintVetShadow() error { return &os.PathError{"first", "path", os.ErrNotExist} //nolint:vetshadow } -func Printf() { +func GovetPrintf() { x := "dummy" fmt.Printf("%d", x) // ERROR "printf: Printf format %d has arg x of wrong type string" } -func StringIntConv() { +func GovetStringIntConv() { i := 42 - fmt.Println("i = " + string(i)) // ERROR "stringintconv: conversion from int to string yields a string of one rune, not a string of digits (did you mean fmt.Sprint(x)?)" + fmt.Println("i = " + string(i)) // ERROR "stringintconv: conversion from int to string yields a string of one rune, not a string of digits \\(did you mean fmt.Sprint\\(x\\)\\?\\)" } diff --git a/test/testdata/govet/ifaceassert.go b/test/testdata/govet/ifaceassert.go deleted file mode 100644 index c00535c226e8..000000000000 --- a/test/testdata/govet/ifaceassert.go +++ /dev/null @@ -1,14 +0,0 @@ -//args: -Egovet -//config: linters-settings.govet.enable=["ifaceassert"] -package govet - -import ( - "io" -) - -func IfaceAssert() { - var v interface { - Read() - } - _ = v.(io.Reader) // ERROR "composites: `os.PathError` composite literal uses unkeyed fields" -} diff --git a/test/testdata/govet_ifaceassert.go b/test/testdata/govet_ifaceassert.go new file mode 100644 index 000000000000..9a4253aa0465 --- /dev/null +++ b/test/testdata/govet_ifaceassert.go @@ -0,0 +1,14 @@ +//args: -Egovet +//config: linters-settings.govet.enable=ifaceassert +package testdata + +import ( + "io" +) + +func GovetIfaceAssert() { + var v interface { + Read() + } + _ = v.(io.Reader) // ERROR "impossible type assertion: no type can implement both interface\\{Read\\(\\)\\} and io\\.Reader \\(conflicting types for Read method\\)" +}