Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add checkdeprecated linter #3808

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .golangci.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@ linters-settings:
first-strong-isolate: false
pop-directional-isolate: false

checkdeprecated:
# report malformed deprecated comments. The proper format is `Deprecated: <text>`.
# Default: false
check-comment: true
# Custom Deprecated comment header.
patterns:
- "MyDeprecated"

cyclop:
# The maximal code complexity to report.
# Default: 10
Expand Down Expand Up @@ -2062,6 +2070,7 @@ linters:
- asciicheck
- bidichk
- bodyclose
- checkdeprecated
- containedctx
- contextcheck
- cyclop
Expand Down Expand Up @@ -2175,6 +2184,7 @@ linters:
- asciicheck
- bidichk
- bodyclose
- checkdeprecated
- containedctx
- contextcheck
- cyclop
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ require (
github.com/ashanbrown/forbidigo v1.5.1
github.com/ashanbrown/makezero v1.1.1
github.com/bkielbasa/cyclop v1.2.0
github.com/black-06/check-deprecated v0.1.1
github.com/blizzy78/varnamelen v0.8.0
github.com/bombsimon/wsl/v3 v3.4.0
github.com/breml/bidichk v0.2.4
Expand Down
2 changes: 2 additions & 0 deletions go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions pkg/config/linters_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ var defaultLintersSettings = LintersSettings{
type LintersSettings struct {
Asasalint AsasalintSettings
BiDiChk BiDiChkSettings
CheckDeprecated CheckDeprecated
Cyclop Cyclop
Decorder DecorderSettings
Depguard DepGuardSettings
Expand Down Expand Up @@ -246,6 +247,11 @@ type BiDiChkSettings struct {
PopDirectionalIsolate bool `mapstructure:"pop-directional-isolate"`
}

type CheckDeprecated struct {
CheckComment bool `mapstructure:"check-comment"`
Patterns []string `mapstructure:"patterns"`
}

type Cyclop struct {
MaxComplexity int `mapstructure:"max-complexity"`
PackageAverage float64 `mapstructure:"package-average"`
Expand Down
28 changes: 28 additions & 0 deletions pkg/golinters/checkdeprecated.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package golinters

import (
checkdeprecated "github.com/black-06/check-deprecated"
"golang.org/x/tools/go/analysis"

"github.com/golangci/golangci-lint/pkg/config"
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
)

func NewCheckDeprecated(settings *config.CheckDeprecated) *goanalysis.Linter {
if settings == nil {
settings = &config.CheckDeprecated{}
}
analyzers := []*analysis.Analyzer{
checkdeprecated.NewCheckDeprecatedAnalyzer(settings.Patterns...),
}
if settings.CheckComment {
analyzers = append(analyzers, checkdeprecated.NewCheckDeprecatedCommentAnalyzer(settings.Patterns...))
}

return goanalysis.NewLinter(
"checkdeprecated",
"check for using a deprecated function, variable, constant or field",
analyzers,
nil,
).WithLoadMode(goanalysis.LoadModeTypesInfo)
}
8 changes: 8 additions & 0 deletions pkg/lint/lintersdb/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
var (
asasalintCfg *config.AsasalintSettings
bidichkCfg *config.BiDiChkSettings
checkDeprecatedCfg *config.CheckDeprecated
cyclopCfg *config.Cyclop
decorderCfg *config.DecorderSettings
depGuardCfg *config.DepGuardSettings
Expand Down Expand Up @@ -183,6 +184,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
if m.cfg != nil {
asasalintCfg = &m.cfg.LintersSettings.Asasalint
bidichkCfg = &m.cfg.LintersSettings.BiDiChk
checkDeprecatedCfg = &m.cfg.LintersSettings.CheckDeprecated
cyclopCfg = &m.cfg.LintersSettings.Cyclop
decorderCfg = &m.cfg.LintersSettings.Decorder
depGuardCfg = &m.cfg.LintersSettings.Depguard
Expand Down Expand Up @@ -320,6 +322,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithLoadForGoAnalysis().
WithURL("https://github.com/kkHAIKE/contextcheck"),

linter.NewConfig(golinters.NewCheckDeprecated(checkDeprecatedCfg)).
WithSince("v1.53.0").
WithLoadForGoAnalysis().
WithPresets(linter.PresetComment, linter.PresetStyle).
WithURL("https://github.com/black-06/check-deprecated"),

linter.NewConfig(golinters.NewCyclop(cyclopCfg)).
WithSince("v1.37.0").
WithLoadForGoAnalysis().
Expand Down
122 changes: 122 additions & 0 deletions test/testdata/checkdeprecated.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
//golangcitest:args -Echeckdeprecated
package testdata

import (
"fmt"
"io/ioutil"
)

func Caller() {
ioutil.ReadAll(nil) // want "using deprecated: As of Go 1.16, this function simply calls io.ReadAll."
fmt.Println(VarDeprecated) // want "using deprecated: VarDeprecated by GenDecl ValueSpec"
var (
_ = VarDeprecated // want "using deprecated: VarDeprecated by GenDecl ValueSpec"
_ = VarDeprecated + "..." // want "using deprecated: VarDeprecated by GenDecl ValueSpec"
_ = vars1 // want "using deprecated: vars1 by ValueSpec"
_ = vars2 // want "using deprecated: vars1/2/3 by GenDecl ValueSpec"
_ = vars3 // want "using deprecated: vars1/2/3 by GenDecl ValueSpec"
_ = ConstDeprecated // want "using deprecated: ConstDeprecated by GenDecl ValueSpec"
_ = consts1 // want "using deprecated: consts1 by ValueSpec"
_ = consts2 // want "using deprecated: consts 1/2/3 by GenDecl ValueSpec"
_ = consts3 // want "using deprecated: consts 1/2/3 by GenDecl ValueSpec"
)
FuncDeprecated() // want "using deprecated: don't use FuncDeprecated by FuncDecl"
var (
_ = StructDeprecated{} // want "using deprecated: use s3 instead of StructDeprecated, by GenDecl TypeSpec"
_ = StructDeprecated2{} // want "using deprecated: \\(no comment\\)"
s = Struct{}
_ = struct1{} // want "using deprecated: struct1 by TypeSpec"
s2 = struct2{} // want "using deprecated: struct 1/2/3 by GenDecl TypeSpec"
_ = s2.F2 // want "using deprecated: F2 by Field"
s3 = struct3{} // want "using deprecated: struct 1/2/3 by GenDecl TypeSpec"
)
s.StructFun() // want "using deprecated: don't use it"
s3.fun1()
s3.fun2() // want "using deprecated: fun2 by FuncDecl"

var (
_ InterfaceDeprecated // want "using deprecated: InterfaceDeprecated by GenDecl TypeSpec"
_ interface1 // want "using deprecated: interface1 by TypeSpec"
_ interface2 // want "using deprecated: interface 1/2/3 by GenDecl TypeSpec"
i3 interface3 // want "using deprecated: interface 1/2/3 by GenDecl TypeSpec"
)
i3.fun2() // want "using deprecated: interface3 fun2 by Field"
}

// Deprecated: VarDeprecated by GenDecl ValueSpec
var VarDeprecated = ""

// DEPRECATED: vars1/2/3 by GenDecl ValueSpec
var (
// deprecated. vars1 by ValueSpec
vars1 = ""
vars2 = ""
vars3 = ""
)

// ConstDeprecated
// it's deprecated. ConstDeprecated by GenDecl ValueSpec
const ConstDeprecated = ""

// NOTE: deprecated. consts 1/2/3 by GenDecl ValueSpec
const (
// deprecated, consts1 by ValueSpec
consts1 = iota
consts2
consts3
)

// FuncDeprecated
//
// Deprecated: don't use FuncDeprecated by FuncDecl
func FuncDeprecated() {
}

type Struct struct{}

// Deprecated, don't use it
func (p Struct) StructFun() {}

// Deprecated: use s3 instead of StructDeprecated, by GenDecl TypeSpec
type StructDeprecated struct{}

func (p StructDeprecated) Fun() {} // want "using deprecated: use s3 instead of StructDeprecated, by GenDecl TypeSpec"

// Deprecated.
type StructDeprecated2 struct{}

// InterfaceDeprecated
//
// Deprecated, InterfaceDeprecated by GenDecl TypeSpec
type InterfaceDeprecated interface{}

// Deprecated struct 1/2/3 by GenDecl TypeSpec
type (
// Deprecated struct1 by TypeSpec
struct1 struct{}
struct2 struct {
F1 string
// Deprecated F2 by Field
F2 string
}
struct3 struct{}
)

func (s struct3) fun1() {} // want "using deprecated: struct 1/2/3 by GenDecl TypeSpec"

// Deprecated fun2 by FuncDecl
func (s struct3) fun2() {} // want "using deprecated: struct 1/2/3 by GenDecl TypeSpec"

// Deprecated interface 1/2/3
// by GenDecl TypeSpec
type (
// Deprecated interface1 by TypeSpec
interface1 interface{}
interface2 interface {
}
interface3 interface {
fun1()
// deprecated. interface3 fun2 by Field
fun2()
}
)
81 changes: 81 additions & 0 deletions test/testdata/checkdeprecated_comment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//golangcitest:args -Echeckdeprecated
//golangcitest:config_path testdata/configs/checkdeprecated.yml
package testdata

// Deprecated: VarDeprecatedComment by GenDecl ValueSpec
var VarDeprecateComment = ""

// DEPRECATED: vars1/2/3 by GenDecl ValueSpec
var (
// deprecated. vars1 by ValueSpec
vars1Comment = "" // want "malformed deprecated header: the proper format is `Deprecated: <text>`"
vars2Comment = "" // want "malformed deprecated header: use `Deprecated: ` \\(note the casing\\) instead of `DEPRECATED: `"
vars3Comment = "" // want "malformed deprecated header: use `Deprecated: ` \\(note the casing\\) instead of `DEPRECATED: `"
)

// ConstDeprecated
// it's deprecated. ConstDeprecated by GenDecl ValueSpec
const ConstDeprecatedComment = "" // want "malformed deprecated header: the proper format is `Deprecated: <text>`"

// NOTE: deprecated. consts 1/2/3 by GenDecl ValueSpec
const (
// deprecated, consts1 by ValueSpec
consts1Comment = iota // want "malformed deprecated header: the proper format is `Deprecated: <text>`"
consts2Comment // want "malformed deprecated header: the proper format is `Deprecated: <text>`"
consts3Comment // want "malformed deprecated header: the proper format is `Deprecated: <text>`"
)

// FuncDeprecated
//
// Deprecated: don't use FuncDeprecated by FuncDecl
func FuncDeprecatedComment() {
}

type StructComment struct{}

// Deprecated, don't use it
func (p StructComment) StructFun() {} // want "malformed deprecated header: the proper format is `Deprecated: <text>`"

// Deprecated: use s3 instead of StructDeprecated, by GenDecl TypeSpec
type StructDeprecatedComment struct{}

func (p StructDeprecatedComment) Fun() {} // want "using deprecated: use s3 instead of StructDeprecated, by GenDecl TypeSpec"

// Deprecated.
type StructDeprecated2Comment struct{} // want "malformed deprecated header: the proper format is `Deprecated: <text>`"

// InterfaceDeprecated
//
// Deprecated, InterfaceDeprecated by GenDecl TypeSpec
type InterfaceDeprecatedComment interface{} // want "malformed deprecated header: the proper format is `Deprecated: <text>`"

// Deprecated struct 1/2/3 by GenDecl TypeSpec
type (
// Deprecated struct1 by TypeSpec
struct1Comment struct{} // want "malformed deprecated header: the proper format is `Deprecated: <text>`"
struct2Comment struct { // want "malformed deprecated header: the proper format is `Deprecated: <text>`"
F1 string
// Deprecated F2 by Field
F2 string // want "malformed deprecated header: the proper format is `Deprecated: <text>`"
}
struct3Comment struct{} // want "malformed deprecated header: the proper format is `Deprecated: <text>`"
)

func (s struct3Comment) fun1() {} // want "using deprecated: struct 1/2/3 by GenDecl TypeSpec"

// Deprecated fun2 by FuncDecl
func (s struct3Comment) fun2() {} // want "using deprecated: struct 1/2/3 by GenDecl TypeSpec"

// Deprecated interface 1/2/3
// by GenDecl TypeSpec
type (
// Deprecated interface1 by TypeSpec
interface1Comment interface{} // want "malformed deprecated header: the proper format is `Deprecated: <text>`"
interface2Comment interface { // want "malformed deprecated header: the proper format is `Deprecated: <text>`"
}
interface3Comment interface { // want "malformed deprecated header: the proper format is `Deprecated: <text>`"
fun1()
// deprecated. interface3 fun2 by Field
fun2() // want "malformed deprecated header: the proper format is `Deprecated: <text>`"
}
)
5 changes: 5 additions & 0 deletions test/testdata/configs/checkdeprecated.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
linters-settings:
checkdeprecated:
check-comment: true
patterns:
- "MyDeprecated"