Skip to content
Open
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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,16 @@ arguments = [["ID"], ["VM"]]

This way, revive will not warn for an identifier called `customId` but will warn that `customVm` should be called `customVM`.

You can also enforce custom package naming conventions using a regex pattern:

```toml
[rule.var-naming]
arguments = [[], [], [{ "packageNamePattern" = "^[a-z][a-zA-Z0-9]*$" }]]
```

This enforces that package names must start with a lowercase letter followed by any combination of letters and digits
(allowing camelCase but disallowing underscores). When a regex pattern is set, it takes precedence over the default package naming checks.

## Available Formatters

This section lists all the available formatters and provides a screenshot for each one.
Expand Down
14 changes: 13 additions & 1 deletion RULES_DESCRIPTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1852,8 +1852,12 @@ When `skipPackageNameCollisionWithGoStd`
(`skippackagenamecollisionwithgostd`, `skip-package-name-collision-with-go-std`)
is set to true, the rule disables checks on package names that collide
with Go standard library packages.
You can also add a string parameter `packageNamePattern` to enforce custom package naming
conventions using a regex pattern. When set, the regex pattern takes precedence over the default package naming checks (including bad
package names and stdlib conflicts).

By default, the rule behaves exactly as the alternative in `golint` but optionally, you can relax it (see [golint/lint/issues/89](https://github.com/golang/lint/issues/89)).
By default, the rule behaves exactly as the alternative in `golint` but
optionally, you can relax it (see [golint/lint/issues/89](https://github.com/golang/lint/issues/89)).

Configuration examples:

Expand Down Expand Up @@ -1902,6 +1906,14 @@ arguments = [[], [], [{ extra-bad-package-names = ["helpers", "models"] }]]
arguments = [[], [], [{ skip-package-name-collision-with-go-std = true }]]
```

Enforce custom package naming with regex (allows camelCase, disallows
underscores):

```toml
[rule.var-naming]
arguments = [[], [], [{ "packageNamePattern" = "^[a-z][a-zA-Z0-9]*$" }]]
```

## waitgroup-by-value

_Description_: Function parameters that are passed by value, are in fact a copy of the original argument.
Expand Down
22 changes: 22 additions & 0 deletions rule/var_naming.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"go/ast"
"go/token"
"path/filepath"
"regexp"
"strings"
"sync"

Expand Down Expand Up @@ -49,6 +50,7 @@ type VarNamingRule struct {
skipPackageNameChecks bool // if true - disable check for meaningless and user-defined bad package names
extraBadPackageNames map[string]struct{} // inactive if skipPackageNameChecks is false
pkgNameAlreadyChecked syncSet // set of packages names already checked
validPackageNameRegex *regexp.Regexp // if set, package names must match this regex pattern

skipPackageNameCollisionWithGoStd bool // if true - disable checks for collisions with Go standard library package names
// stdPackageNames holds the names of standard library packages excluding internal and vendor.
Expand Down Expand Up @@ -118,6 +120,16 @@ func (r *VarNamingRule) Configure(arguments lint.Arguments) error {
}
case isRuleOption(k, "skipPackageNameCollisionWithGoStd"):
r.skipPackageNameCollisionWithGoStd = fmt.Sprint(v) == "true"
case isRuleOption(k, "packageNamePattern"):
pattern, ok := v.(string)
if !ok {
return fmt.Errorf("invalid argument to the var-naming rule. Expecting packageNamePattern to be a string regex pattern, but got %T", v)
}
regex, err := regexp.Compile(pattern)
if err != nil {
return fmt.Errorf("invalid packageNamePattern regex pattern %q: %w", pattern, err)
}
r.validPackageNameRegex = regex
}
}
}
Expand Down Expand Up @@ -199,6 +211,16 @@ func (r *VarNamingRule) applyPackageCheckRules(file *lint.File, onFailure func(f
pkgName := pkgNameNode.Name
pkgNameLower := strings.ToLower(pkgName)

// Check against custom regex pattern if configured
if r.validPackageNameRegex != nil && !r.validPackageNameRegex.MatchString(pkgName) {
onFailure(r.pkgNameFailure(pkgNameNode, "package name %q does not match the required pattern %q", pkgName, r.validPackageNameRegex.String()))
}

// If regex is configured, skip other checks as the regex is the primary validator
if r.validPackageNameRegex != nil {
return
}

// Check if top level package
if pkgNameLower == "pkg" && filepath.Base(fileDir) != pkgName {
onFailure(r.pkgNameFailure(pkgNameNode, "should not have a root level package called pkg"))
Expand Down
14 changes: 14 additions & 0 deletions test/var_naming_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,20 @@ func TestVarNaming(t *testing.T) {
[]any{map[string]any{"skip-package-name-collision-with-go-std": true}},
},
})
testRule(t, "var_naming_valid_package_name_by_regex", &rule.VarNamingRule{}, &lint.RuleConfig{
Arguments: []any{
[]any{},
[]any{},
[]any{map[string]any{"packageNamePattern": "^[a-z][a-zA-Z0-9]*$"}}, // regex pattern to allow camel case package names
},
})
testRule(t, "var_naming_invalid_package_name_by_regex", &rule.VarNamingRule{}, &lint.RuleConfig{
Arguments: []any{
[]any{},
[]any{},
[]any{map[string]any{"packageNamePattern": "^[a-z][a-zA-Z0-9]*$"}}, // tests that the pattern rejects names with underscores
},
})
}

func BenchmarkUpperCaseConstTrue(b *testing.B) {
Expand Down
1 change: 1 addition & 0 deletions testdata/var_naming_invalid_package_name_by_regex.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package bad_package_name // MATCH /package name "bad_package_name" does not match the required pattern "^[a-z][a-zA-Z0-9]*$"/
1 change: 1 addition & 0 deletions testdata/var_naming_valid_package_name_by_regex.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package goodPackageName