From 15be387a604a3357916b69a3aa2c9562545f5da2 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Wed, 27 Nov 2024 03:39:23 +0100 Subject: [PATCH] chore: update implementation --- .golangci.next.reference.yml | 50 ++++++++++-- jsonschema/golangci.next.jsonschema.json | 80 +++++++++++++++---- pkg/config/linters_settings.go | 22 ++++- pkg/golinters/tagliatelle/tagliatelle.go | 26 ++++-- .../testdata/tagliatelle_ignored_fields.go | 34 ++++++++ .../testdata/tagliatelle_ignored_fields.yml | 7 ++ pkg/lint/lintersdb/builder_linter.go | 1 + 7 files changed, 192 insertions(+), 28 deletions(-) create mode 100644 pkg/golinters/tagliatelle/testdata/tagliatelle_ignored_fields.go create mode 100644 pkg/golinters/tagliatelle/testdata/tagliatelle_ignored_fields.yml diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 5722b7b0ac80..a45ef3279b9e 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -3285,14 +3285,24 @@ linters-settings: tagliatelle: # Check the struct tag name case. case: - # Use the struct field name to check the name of the struct tag. - # Default: false - use-field-name: true # `camel` is used for `json` and `yaml`, and `header` is used for `header` (can be overridden) # Default: {} rules: - # Any struct tag type can be used. - # Support string case: `camel`, `pascal`, `kebab`, `snake`, `upperSnake`, `goCamel`, `goPascal`, `goKebab`, `goSnake`, `upper`, `lower`, `header` + # Define the association between tag name and case. + # Any struct tag name can be used. + # Support string cases: + # - `camel` + # - `pascal` + # - `kebab` + # - `snake` + # - `upperSnake` + # - `goCamel` + # - `goPascal` + # - `goKebab` + # - `goSnake` + # - `upper` + # - `lower` + # - `header` json: camel yaml: camel xml: camel @@ -3302,6 +3312,36 @@ linters-settings: mapstructure: kebab env: upperSnake envconfig: upperSnake + whatever: snake + # Use the struct field name to check the name of the struct tag. + # Default: false + use-field-name: true + # The field names to ignore. + # Default: [] + ignored-fields: + - Bar + - Foo + # Overrides the default/root configuration. + # Default: [] + overrides: + - + # The package path. (uses `/` only as separator) + # Required. + pkg: foo/bar + # Default: empty or the same as the default/root configuration. + rules: + json: snake + xml: pascal + # Default: false (WARNING: it doesn't follow the default/root configuration) + use-field-name: true + # The field names to ignore. + # Default: [] or the same as the default/root configuration. + ignored-fields: + - Bar + - Foo + # Ignore the package (take the precedence over all other configuration). + # Default: false + ignore: true tenv: # The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures. diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index b3a5453dd455..6602309d3e1d 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -305,6 +305,22 @@ "opaque" ] }, + "tagliatelle-cases": { + "enum": [ + "camel", + "pascal", + "kebab", + "snake", + "goCamel", + "goPascal", + "goKebab", + "goSnake", + "upper", + "upperSnake", + "lower", + "header" + ] + }, "linters": { "$comment": "anyOf with enum is used to allow auto completion of non-custom linters", "description": "Linters usable.", @@ -2894,24 +2910,60 @@ "type": "boolean", "default": false }, + "ignored-fields": { + "description": "The field names to ignore.", + "type": "array", + "items": { + "type": "string", + "examples": ["example"] + } + }, "rules": { "type": "object", "patternProperties": { "^.+$": { - "enum": [ - "camel", - "pascal", - "kebab", - "snake", - "goCamel", - "goPascal", - "goKebab", - "goSnake", - "upper", - "upperSnake", - "lower", - "header" - ] + "$ref": "#/definitions/tagliatelle-cases" + } + } + }, + "overrides": { + "description": "Overrides the default/root configuration.", + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["pkg"], + "properties": { + "pkg": { + "description": "A package path.", + "type": "string" + }, + "use-field-name": { + "description": "Use the struct field name to check the name of the struct tag.", + "type": "boolean", + "default": false + }, + "ignored-fields": { + "description": "The field names to ignore.", + "type": "array", + "items": { + "type": "string", + "examples": ["example"] + } + }, + "ignore": { + "description": "Ignore the package (it takes the precedence over all other configuration).", + "type": "boolean", + "default": false + }, + "rules": { + "type": "object", + "patternProperties": { + "^.+$": { + "$ref": "#/definitions/tagliatelle-cases" + } + } + } } } } diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index 51ff661de4fe..98e6bccb313f 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -870,10 +870,24 @@ type TagAlignSettings struct { } type TagliatelleSettings struct { - Case struct { - Rules map[string]string - UseFieldName bool `mapstructure:"use-field-name"` - } + Case TagliatelleCase +} + +type TagliatelleCase struct { + TagliatelleBase `mapstructure:",squash"` + Overrides []TagliatelleOverrides +} + +type TagliatelleOverrides struct { + TagliatelleBase `mapstructure:",squash"` + Package string `mapstructure:"pkg"` + Ignore bool `mapstructure:"ignore"` +} + +type TagliatelleBase struct { + Rules map[string]string `mapstructure:"rules"` + UseFieldName bool `mapstructure:"use-field-name"` + IgnoredFields []string `mapstructure:"ignored-fields"` } type TestifylintSettings struct { diff --git a/pkg/golinters/tagliatelle/tagliatelle.go b/pkg/golinters/tagliatelle/tagliatelle.go index d1674c3e9e28..9e700b49f16c 100644 --- a/pkg/golinters/tagliatelle/tagliatelle.go +++ b/pkg/golinters/tagliatelle/tagliatelle.go @@ -10,10 +10,12 @@ import ( func New(settings *config.TagliatelleSettings) *goanalysis.Linter { cfg := tagliatelle.Config{ - Rules: map[string]string{ - "json": "camel", - "yaml": "camel", - "header": "header", + Base: tagliatelle.Base{ + Rules: map[string]string{ + "json": "camel", + "yaml": "camel", + "header": "header", + }, }, } @@ -21,7 +23,21 @@ func New(settings *config.TagliatelleSettings) *goanalysis.Linter { for k, v := range settings.Case.Rules { cfg.Rules[k] = v } + cfg.UseFieldName = settings.Case.UseFieldName + cfg.IgnoredFields = settings.Case.IgnoredFields + + for _, override := range settings.Case.Overrides { + cfg.Overrides = append(cfg.Overrides, tagliatelle.Overrides{ + Base: tagliatelle.Base{ + Rules: override.Rules, + UseFieldName: override.UseFieldName, + IgnoredFields: override.IgnoredFields, + Ignore: override.Ignore, + }, + Package: override.Package, + }) + } } a := tagliatelle.New(cfg) @@ -31,5 +47,5 @@ func New(settings *config.TagliatelleSettings) *goanalysis.Linter { a.Doc, []*analysis.Analyzer{a}, nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + ).WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/tagliatelle/testdata/tagliatelle_ignored_fields.go b/pkg/golinters/tagliatelle/testdata/tagliatelle_ignored_fields.go new file mode 100644 index 000000000000..cbd326011228 --- /dev/null +++ b/pkg/golinters/tagliatelle/testdata/tagliatelle_ignored_fields.go @@ -0,0 +1,34 @@ +//golangcitest:args -Etagliatelle +//golangcitest:config_path testdata/tagliatelle_ignored_fields.yml +package testdata + +import "time" + +type TglFoo struct { + ID string `json:"ID"` // want `json\(camel\): got 'ID' want 'id'` + UserID string `json:"UserID"` // want `json\(camel\): got 'UserID' want 'userId'` + Name string `json:"name"` + Value time.Duration `json:"value,omitempty"` + Bar TglBar `json:"bar"` + Bur `json:"bur"` +} + +type TglBar struct { + Name string `json:"-"` + Value string `json:"value"` + CommonServiceFooItem *TglBir `json:"CommonServiceItem,omitempty"` +} + +type TglBir struct { + Name string `json:"-"` + Value string `json:"value"` + ReplaceAllowList []string `mapstructure:"replace-allow-list"` +} + +type Bur struct { + Name string + Value string `yaml:"Value"` // want `yaml\(camel\): got 'Value' want 'value'` + More string `json:"-"` + Also string `json:"also,omitempty"` + ReqPerS string `avro:"req_per_s"` +} diff --git a/pkg/golinters/tagliatelle/testdata/tagliatelle_ignored_fields.yml b/pkg/golinters/tagliatelle/testdata/tagliatelle_ignored_fields.yml new file mode 100644 index 000000000000..b80a481674fc --- /dev/null +++ b/pkg/golinters/tagliatelle/testdata/tagliatelle_ignored_fields.yml @@ -0,0 +1,7 @@ +linters-settings: + tagliatelle: + case: + ignored-fields: + - CommonServiceFooItem + + diff --git a/pkg/lint/lintersdb/builder_linter.go b/pkg/lint/lintersdb/builder_linter.go index d2a2dc3d0744..f09fd951ce0e 100644 --- a/pkg/lint/lintersdb/builder_linter.go +++ b/pkg/lint/lintersdb/builder_linter.go @@ -736,6 +736,7 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { linter.NewConfig(tagliatelle.New(&cfg.LintersSettings.Tagliatelle)). WithSince("v1.40.0"). WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). WithURL("https://github.com/ldez/tagliatelle"), linter.NewConfig(tenv.New(&cfg.LintersSettings.Tenv)).