Skip to content

Commit

Permalink
feat: add extended-rules option
Browse files Browse the repository at this point in the history
  • Loading branch information
ldez committed Dec 8, 2024
1 parent 4e6384a commit 9a47205
Show file tree
Hide file tree
Showing 8 changed files with 326 additions and 103 deletions.
116 changes: 116 additions & 0 deletions converter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package tagliatelle

import (
"fmt"
"strings"

"github.com/ettle/strcase"
)

// https://github.com/dominikh/go-tools/blob/v0.5.1/config/config.go#L167-L175
//
//nolint:gochecknoglobals // For now I'll accept this, but I think will refactor to use a structure.
var staticcheckInitialisms = map[string]bool{
"AMQP": true,
"DB": true,
"GID": true,
"LHS": false,
"RHS": false,
"RTP": true,
"SIP": true,
"TS": true,
}

// Converter is the signature of a case converter.
type Converter func(s string) string

// ConverterCallback allows to abstract `getSimpleConverter` and `ruleToConverter`.
type ConverterCallback func() (Converter, error)

func getSimpleConverter(c string) (Converter, error) {
switch c {
case "camel":
return strcase.ToCamel, nil
case "pascal":
return strcase.ToPascal, nil
case "kebab":
return strcase.ToKebab, nil
case "snake":
return strcase.ToSnake, nil
case "goCamel":
return strcase.ToGoCamel, nil
case "goPascal":
return strcase.ToGoPascal, nil
case "goKebab":
return strcase.ToGoKebab, nil
case "goSnake":
return strcase.ToGoSnake, nil
case "upperSnake":
return strcase.ToSNAKE, nil
case "header":
return toHeader, nil
case "upper":
return strings.ToUpper, nil
case "lower":
return strings.ToLower, nil
default:
return nil, fmt.Errorf("unsupported case: %s", c)
}
}

func toHeader(s string) string {
return strcase.ToCase(s, strcase.TitleCase, '-')
}

func ruleToConverter(rule ExtendedRule) (Converter, error) {
if rule.ExtraInitialisms {
for k, v := range staticcheckInitialisms {
if _, found := rule.InitialismOverrides[k]; found {
continue
}

rule.InitialismOverrides[k] = v
}
}

caser := strcase.NewCaser(strings.HasPrefix(rule.Case, "go"), rule.InitialismOverrides, nil)

switch strings.ToLower(strings.TrimPrefix(rule.Case, "go")) {
case "camel":
return caser.ToCamel, nil

case "pascal":
return caser.ToPascal, nil

case "kebab":
return caser.ToKebab, nil

case "snake":
return caser.ToSnake, nil

case "uppersnake":
return caser.ToSNAKE, nil

case "header":
return toHeaderCase(caser), nil

case "upper":
return func(s string) string {
return caser.ToCase(s, strcase.UpperCase, 0)
}, nil

case "lower":
return func(s string) string {
return caser.ToCase(s, strcase.LowerCase, 0)
}, nil

default:
return nil, fmt.Errorf("unsupported case: %s", rule.Case)
}
}

func toHeaderCase(caser *strcase.Caser) Converter {
return func(s string) string {
return caser.ToCase(s, strcase.TitleCase, '-')
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/ldez/tagliatelle
go 1.22.0

require (
github.com/ettle/strcase v0.2.0
github.com/ettle/strcase v0.2.1-0.20230114185658-e5db6a6becf3
github.com/hashicorp/go-immutable-radix/v2 v2.1.0
golang.org/x/tools v0.27.0
)
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q=
github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A=
github.com/ettle/strcase v0.2.1-0.20230114185658-e5db6a6becf3 h1:UveVPOxnOkBoelw2vLZTm+L0Z7fe/nz5d6JlY+A3QdE=
github.com/ettle/strcase v0.2.1-0.20230114185658-e5db6a6becf3/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/hashicorp/go-immutable-radix/v2 v2.1.0 h1:CUW5RYIcysz+D3B+l1mDeXrQ7fUvGGCwJfdASSzbrfo=
Expand Down
60 changes: 49 additions & 11 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,14 @@ type Foo struct {
}
```

## What this tool is about
## What this linter is about

This tool is about validating tags according to rules you define.
The tool also allows to fix tags according to the rules you defined.
This linter is about validating tags according to rules you define.
The linter also allows to fix tags according to the rules you defined.

This tool is not intended to validate the fact a tag in valid or not.
To do that, you can use `go vet`, or use [golangci-lint](https://golangci-lint.run) ["go vet"](https://golangci-lint.run/usage/linters/#govet) linter.
This linter is not intended to validate the fact a tag in valid or not.

## How to use the tool
## How to use the linter

### As a golangci-lint linter

Expand All @@ -114,9 +113,9 @@ Define the rules, you want via your [golangci-lint](https://golangci-lint.run) c
```yaml
linters-settings:
tagliatelle:
# Check the struct tag name case.
# Checks the struct tag name case.
case:
# Define the association between tag name and case.
# Defines the association between tag name and case.
# Any struct tag name can be used.
# Supported string cases:
# - `camel`
Expand All @@ -142,7 +141,45 @@ linters-settings:
env: upperSnake
envconfig: upperSnake
whatever: snake
# Use the struct field name to check the name of the struct tag.
# Defines the association between tag name and case.
# Important: the `extended-rules` overrides `rules`.
# Default: empty
extended-rules:
json:
# Supported string cases:
# - `camel`
# - `pascal`
# - `kebab`
# - `snake`
# - `upperSnake`
# - `goCamel`
# - `goPascal`
# - `goKebab`
# - `goSnake`
# - `header`
# - `lower`
# - `header`
#
# Required
case: camel
# Adds 'AMQP', 'DB', 'GID', 'RTP', 'SIP', 'TS' to initialisms.
# remove 'LHS', 'RHS' from initialisms.
# Default: true
extra-initialisms: false
# Defines initialism overrides.
# To disable a default initialism,
# You should associate the initialism with `false`.
# Default: empty
initialism-overrides:
AMQP: true
DB: true
GID: true
LHS: false
RHS: false
RTP: true
SIP: true
TS: true
# Uses the struct field name to check the name of the struct tag.
# Default: false
use-field-name: true
# The field names to ignore.
Expand Down Expand Up @@ -171,6 +208,7 @@ linters-settings:
# Ignore the package (takes precedence over all other configurations).
# Default: false
ignore: true

```

#### Examples
Expand Down Expand Up @@ -251,9 +289,9 @@ Here are the default rules for the well known and used tags, when using tagliate

### Custom Rules

The tool is not limited to the tags used in example, you can use it to validate any tag.
The linter is not limited to the tags used in example, **you can use it to validate any tag**.

You can add your own tag, for example `whatever` and tells the tool you want to use `kebab`.
You can add your own tag, for example `whatever` and tells the linter you want to use `kebab`.

This option is only available via [golangci-lint](https://golangci-lint.run).

Expand Down
Loading

0 comments on commit 9a47205

Please sign in to comment.