From 1430f052f3b9631c5e2a14b86cfe51f71859377b Mon Sep 17 00:00:00 2001 From: Oliver Eikemeier Date: Sun, 8 Jun 2025 14:29:28 +0200 Subject: [PATCH] Add ptrequality linter ptrequality is a Go linter (static analysis tool) that detects comparisons against the address of newly created values, such as ptr == &MyStruct{} or ptr == new(MyStruct). https://github.com/fillmore-labs/ptrequality Signed-off-by: Oliver Eikemeier --- go.mod | 2 ++ go.sum | 4 ++++ jsonschema/golangci.next.jsonschema.json | 15 +++++++++++++ pkg/config/linters_settings.go | 8 +++++++ pkg/golinters/ptrequality/ptrequality.go | 16 ++++++++++++++ .../ptrequality_integration_test.go | 11 ++++++++++ .../ptrequality/testdata/ptrequality.go | 22 +++++++++++++++++++ .../ptrequality/testdata/ptrequality.yml | 6 +++++ pkg/lint/lintersdb/builder_linter.go | 6 +++++ 9 files changed, 90 insertions(+) create mode 100644 pkg/golinters/ptrequality/ptrequality.go create mode 100644 pkg/golinters/ptrequality/ptrequality_integration_test.go create mode 100644 pkg/golinters/ptrequality/testdata/ptrequality.go create mode 100644 pkg/golinters/ptrequality/testdata/ptrequality.yml diff --git a/go.mod b/go.mod index 72dd9208d831..24e21a10f18a 100644 --- a/go.mod +++ b/go.mod @@ -38,6 +38,7 @@ require ( github.com/daixiang0/gci v0.13.6 github.com/denis-tingaikin/go-header v0.5.0 github.com/fatih/color v1.18.0 + github.com/fillmore-labs/ptrequality v0.0.1 github.com/firefart/nonamedreturns v1.0.6 github.com/fzipp/gocyclo v0.6.0 github.com/ghostiam/protogetter v0.3.15 @@ -143,6 +144,7 @@ require ( require ( codeberg.org/chavacava/garif v0.2.0 // indirect + fillmore-labs.com/cmplint v0.0.3 // indirect github.com/Masterminds/semver/v3 v3.3.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect diff --git a/go.sum b/go.sum index 8cde5e69bf0e..b56e9d06fb38 100644 --- a/go.sum +++ b/go.sum @@ -37,6 +37,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 codeberg.org/chavacava/garif v0.2.0 h1:F0tVjhYbuOCnvNcU3YSpO6b3Waw6Bimy4K0mM8y6MfY= codeberg.org/chavacava/garif v0.2.0/go.mod h1:P2BPbVbT4QcvLZrORc2T29szK3xEOlnl0GiPTJmEqBQ= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +fillmore-labs.com/cmplint v0.0.3 h1:YW+NLyXMNYAmwr9v0ofFVKHLOPWDrvCqfvrZGEP2oiU= +fillmore-labs.com/cmplint v0.0.3/go.mod h1:WX9w3G+sErDzIKbUlzZ3+4nvn411/4nqlgI+8xUYphw= github.com/4meepo/tagalign v1.4.2 h1:0hcLHPGMjDyM1gHG58cS73aQF8J4TdVR96TZViorO9E= github.com/4meepo/tagalign v1.4.2/go.mod h1:+p4aMyFM+ra7nb41CnFG6aSDXqRxU/w1VQqScKqDARI= github.com/Abirdcfly/dupword v0.1.6 h1:qeL6u0442RPRe3mcaLcbaCi2/Y/hOcdtw6DE9odjz9c= @@ -164,6 +166,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= +github.com/fillmore-labs/ptrequality v0.0.1 h1:b+GCdFN/ORdsgjgW8Ggb51WeiMeMEaRM5dYLd6CcHIE= +github.com/fillmore-labs/ptrequality v0.0.1/go.mod h1:7EBFsehWCO2/yMWxaT0e9ATxLdAE7nHRN1DAzSCxX/o= github.com/firefart/nonamedreturns v1.0.6 h1:vmiBcKV/3EqKY3ZiPxCINmpS431OcE1S47AQUwhrg8E= github.com/firefart/nonamedreturns v1.0.6/go.mod h1:R8NisJnSIpvPWheCq0mNRXJok6D8h7fagJTF8EMEwCo= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index a12cb912b569..30668cf008c4 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -804,6 +804,7 @@ "predeclared", "promlinter", "protogetter", + "ptrequality", "reassign", "recvcheck", "revive", @@ -2881,6 +2882,17 @@ } } }, + "ptrequalitySettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "check-is": { + "description": "Suppress check for errors with \"Is\" method", + "type": "boolean", + "default": true + } + } + }, "reviveSettings": { "type": "object", "additionalProperties": false, @@ -4530,6 +4542,9 @@ "protogetter": { "$ref": "#/definitions/settings/definitions/protogetterSettings" }, + "ptrequality": { + "$ref": "#/definitions/settings/definitions/ptrequalitySettings" + }, "revive": { "$ref": "#/definitions/settings/definitions/reviveSettings" }, diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index e2838d808acb..cf2711b2d5b1 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -137,6 +137,9 @@ var defaultLintersSettings = LintersSettings{ Predeclared: PredeclaredSettings{ Qualified: false, }, + PtrEquality: PtrEqualitySettings{ + CheckIs: true, + }, SlogLint: SlogLintSettings{ NoMixedArgs: true, KVOnly: false, @@ -263,6 +266,7 @@ type LintersSettings struct { Predeclared PredeclaredSettings `mapstructure:"predeclared"` Promlinter PromlinterSettings `mapstructure:"promlinter"` ProtoGetter ProtoGetterSettings `mapstructure:"protogetter"` + PtrEquality PtrEqualitySettings `mapstructure:"ptrequality"` Reassign ReassignSettings `mapstructure:"reassign"` Recvcheck RecvcheckSettings `mapstructure:"recvcheck"` Revive ReviveSettings `mapstructure:"revive"` @@ -761,6 +765,10 @@ type ProtoGetterSettings struct { ReplaceFirstArgInAppend bool `mapstructure:"replace-first-arg-in-append"` } +type PtrEqualitySettings struct { + CheckIs bool `mapstructure:"check-is"` +} + type ReassignSettings struct { Patterns []string `mapstructure:"patterns"` } diff --git a/pkg/golinters/ptrequality/ptrequality.go b/pkg/golinters/ptrequality/ptrequality.go new file mode 100644 index 000000000000..c9bd2d22d2d2 --- /dev/null +++ b/pkg/golinters/ptrequality/ptrequality.go @@ -0,0 +1,16 @@ +package ptrequality + +import ( + "github.com/fillmore-labs/ptrequality" + + "github.com/golangci/golangci-lint/v2/pkg/config" + "github.com/golangci/golangci-lint/v2/pkg/goanalysis" +) + +func New(settings *config.PtrEqualitySettings) *goanalysis.Linter { + return goanalysis.NewLinterFromAnalyzer(ptrequality.Analyzer). + WithConfig(map[string]any{ + "check-is": settings.CheckIs, + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/pkg/golinters/ptrequality/ptrequality_integration_test.go b/pkg/golinters/ptrequality/ptrequality_integration_test.go new file mode 100644 index 000000000000..bf91596ad696 --- /dev/null +++ b/pkg/golinters/ptrequality/ptrequality_integration_test.go @@ -0,0 +1,11 @@ +package ptrequality + +import ( + "testing" + + "github.com/golangci/golangci-lint/v2/test/testshared/integration" +) + +func TestFromTestdata(t *testing.T) { + integration.RunTestdata(t) +} diff --git a/pkg/golinters/ptrequality/testdata/ptrequality.go b/pkg/golinters/ptrequality/testdata/ptrequality.go new file mode 100644 index 000000000000..b880ffbc9cc5 --- /dev/null +++ b/pkg/golinters/ptrequality/testdata/ptrequality.go @@ -0,0 +1,22 @@ +//golangcitest:args -Eptrequality +//golangcitest:config_path testdata/ptrequality.yml +package main + +import ( + "errors" + "log" + "net/url" +) + +func main() { + _, err := url.Parse("://example.com") + + if errors.Is(err, &url.Error{}) { // want "is always false" + log.Fatal("Cannot parse URL") + } + + var urlErr *url.Error + if errors.As(err, &urlErr) { + log.Fatalf("Cannot parse URL: %v", urlErr) + } +} diff --git a/pkg/golinters/ptrequality/testdata/ptrequality.yml b/pkg/golinters/ptrequality/testdata/ptrequality.yml new file mode 100644 index 000000000000..6e5fbf01adbc --- /dev/null +++ b/pkg/golinters/ptrequality/testdata/ptrequality.yml @@ -0,0 +1,6 @@ +version: "2" + +linters: + settings: + ptrequality: + check-is: false diff --git a/pkg/lint/lintersdb/builder_linter.go b/pkg/lint/lintersdb/builder_linter.go index 734aab63cd1c..1d16606a6f49 100644 --- a/pkg/lint/lintersdb/builder_linter.go +++ b/pkg/lint/lintersdb/builder_linter.go @@ -89,6 +89,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/predeclared" "github.com/golangci/golangci-lint/v2/pkg/golinters/promlinter" "github.com/golangci/golangci-lint/v2/pkg/golinters/protogetter" + "github.com/golangci/golangci-lint/v2/pkg/golinters/ptrequality" "github.com/golangci/golangci-lint/v2/pkg/golinters/reassign" "github.com/golangci/golangci-lint/v2/pkg/golinters/recvcheck" "github.com/golangci/golangci-lint/v2/pkg/golinters/revive" @@ -555,6 +556,11 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithAutoFix(). WithURL("https://github.com/ghostiam/protogetter"), + linter.NewConfig(ptrequality.New(&cfg.Linters.Settings.PtrEquality)). + WithSince("v2.2.0"). + WithLoadForGoAnalysis(). + WithURL("https://github.com/fillmore-labs/ptrequality"), + linter.NewConfig(reassign.New(&cfg.Linters.Settings.Reassign)). WithSince("v1.49.0"). WithLoadForGoAnalysis().