From 0c7b77f50b815617010528291fcce01e5cdedb78 Mon Sep 17 00:00:00 2001 From: rez kamali Date: Mon, 19 Feb 2024 01:59:27 +0100 Subject: [PATCH] add noniljson linter --- .golangci.reference.yml | 2 ++ go.mod | 1 + go.sum | 2 ++ pkg/golinters/noniljson.go | 19 +++++++++++++++++++ pkg/lint/lintersdb/manager.go | 6 ++++++ test/testdata/noniljson.go | 22 ++++++++++++++++++++++ 6 files changed, 52 insertions(+) create mode 100644 pkg/golinters/noniljson.go create mode 100644 test/testdata/noniljson.go diff --git a/.golangci.reference.yml b/.golangci.reference.yml index 35e047a1d059..1a33512dfd74 100644 --- a/.golangci.reference.yml +++ b/.golangci.reference.yml @@ -2557,6 +2557,7 @@ linters: - noctx - nolintlint - nonamedreturns + - noniljson - nosnakecase - nosprintfhostport - paralleltest @@ -2680,6 +2681,7 @@ linters: - noctx - nolintlint - nonamedreturns + - noniljson - nosnakecase - nosprintfhostport - paralleltest diff --git a/go.mod b/go.mod index 0d944a508aa7..dcc0e4ee524c 100644 --- a/go.mod +++ b/go.mod @@ -87,6 +87,7 @@ require ( github.com/nunnatsa/ginkgolinter v0.15.2 github.com/polyfloyd/go-errorlint v1.4.8 github.com/quasilyte/go-ruleguard/dsl v0.3.22 + github.com/rezkam/noniljson v1.0.2 github.com/ryancurrah/gomodguard v1.3.0 github.com/ryanrolds/sqlclosecheck v0.5.1 github.com/sanposhiho/wastedassign/v2 v2.0.7 diff --git a/go.sum b/go.sum index d4d8c2c2f3b0..9a83128959f9 100644 --- a/go.sum +++ b/go.sum @@ -465,6 +465,8 @@ github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= +github.com/rezkam/noniljson v1.0.2 h1:Ftv0ANpDud7D+sQdIhNq6V3BF7WwiIPbf2RrZFs7VZo= +github.com/rezkam/noniljson v1.0.2/go.mod h1:uJL++ig0CSE6XvE16AoxteZXl4AD2Ef2LMMoPjuoSXw= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= diff --git a/pkg/golinters/noniljson.go b/pkg/golinters/noniljson.go new file mode 100644 index 000000000000..a2c3dd1d5452 --- /dev/null +++ b/pkg/golinters/noniljson.go @@ -0,0 +1,19 @@ +package golinters + +import ( + "github.com/rezkam/noniljson" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewNoNilJSON() *goanalysis.Linter { + a := noniljson.Analyzer + + return goanalysis.NewLinter( + a.Name, + "checks that nullable fields in structs used for JSON marshaling use 'omitempty'", + []*analysis.Analyzer{a}, + nil, + ) +} diff --git a/pkg/lint/lintersdb/manager.go b/pkg/lint/lintersdb/manager.go index 977ef0d1c61d..36ac4cb61df2 100644 --- a/pkg/lint/lintersdb/manager.go +++ b/pkg/lint/lintersdb/manager.go @@ -711,6 +711,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { WithPresets(linter.PresetStyle). WithURL("https://github.com/firefart/nonamedreturns"), + linter.NewConfig(golinters.NewNoNilJSON()). + WithSince("v1.57.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetBugs). + WithURL("https://github.com/rezkam/noniljson"), + linter.NewConfig(golinters.NewNoSnakeCase()). WithSince("v1.47.0"). WithPresets(linter.PresetStyle). diff --git a/test/testdata/noniljson.go b/test/testdata/noniljson.go new file mode 100644 index 000000000000..2a4f9ee22f5c --- /dev/null +++ b/test/testdata/noniljson.go @@ -0,0 +1,22 @@ +//golangcitest:args -Enoniljson +package testdata + +type userData struct { + Name *string `json:"name"` // want `nullable field 'Name' in struct 'userData' must include 'omitempty' in its json tag to avoid marshaling as null` + Email string `json:"email,omitempty"` + Address *string `json:"address,omitempty"` + Friends []string `json:"friends"` // want `nullable field 'Friends' in struct 'userData' must include 'omitempty' in its json tag to avoid marshaling as null` + Metadata map[string]string `json:"metadata"` // want `nullable field 'Metadata' in struct 'userData' must include 'omitempty' in its json tag to avoid marshaling as null` +} + +type dynamicData struct { + Data interface{} `json:"data"` // want `nullable field 'Data' in struct 'dynamicData' must include 'omitempty' in its json tag to avoid marshaling as null` +} + +type productData struct { + ID int `json:"id"` + Description *string `json:"description"` // want `nullable field 'Description' in struct 'productData' must include 'omitempty' in its json tag to avoid marshaling as null` + Price float64 `json:"price,omitempty"` + Availability []int `json:"availability"` // want `nullable field 'Availability' in struct 'productData' must include 'omitempty' in its json tag to avoid marshaling as null` + Attributes map[string]interface{} `json:"attributes"` // want `nullable field 'Attributes' in struct 'productData' must include 'omitempty' in its json tag to avoid marshaling as null` +}