mirror of
https://github.com/mgechev/revive.git
synced 2024-11-21 17:16:40 +02:00
adds filename-format rule (#1092)
This commit is contained in:
parent
511e4e65ff
commit
eb18252088
@ -548,6 +548,7 @@ List of all available rules. The rules ported from `golint` are left unchanged a
|
||||
| [`max-control-nesting`](./RULES_DESCRIPTIONS.md#max-control-nesting) | int (defaults to 5) | Sets restriction for maximum nesting of control structures. | no | no |
|
||||
| [`comments-density`](./RULES_DESCRIPTIONS.md#comments-density) | int (defaults to 0) | Enforces a minimum comment / code relation | no | no |
|
||||
| [`file-length-limit`](./RULES_DESCRIPTIONS.md#file-length-limit) | map (optional)| Enforces a maximum number of lines per file | no | no |
|
||||
| [`filename-format`](./RULES_DESCRIPTIONS.md#filename-format) | regular expression (optional) | Enforces the formatting of filenames | no | no |
|
||||
|
||||
## Configurable rules
|
||||
|
||||
|
@ -39,6 +39,7 @@ List of all available rules.
|
||||
- [exported](#exported)
|
||||
- [file-header](#file-header)
|
||||
- [file-length-limit](#file-length-limit)
|
||||
- [filename-format](#filename-format)
|
||||
- [flag-parameter](#flag-parameter)
|
||||
- [function-length](#function-length)
|
||||
- [function-result-limit](#function-result-limit)
|
||||
@ -519,6 +520,18 @@ Example:
|
||||
arguments = [{max=100,skipComments=true,skipBlankLines=true}]
|
||||
```
|
||||
|
||||
## filename-format
|
||||
_Description_: enforces conventions on source file names. By default, the rule enforces filenames of the form `^[_A-Za-z0-9][_A-Za-z0-9-]*.go$`: Optionally, the rule can be configured to enforce other forms.
|
||||
|
||||
_Configuration_: (string) regular expression for source filenames.
|
||||
|
||||
Example:
|
||||
|
||||
```toml
|
||||
[rule.filename-format]
|
||||
arguments=["^[_a-z][_a-z0-9]*.go$"]
|
||||
```
|
||||
|
||||
## flag-parameter
|
||||
|
||||
_Description_: If a function controls the flow of another by passing it information on what to do, both functions are said to be [control-coupled](https://en.wikipedia.org/wiki/Coupling_(computer_programming)#Procedural_programming).
|
||||
|
@ -97,6 +97,7 @@ var allRules = append([]lint.Rule{
|
||||
&rule.MaxControlNestingRule{},
|
||||
&rule.CommentsDensityRule{},
|
||||
&rule.FileLengthLimitRule{},
|
||||
&rule.FilenameFormatRule{},
|
||||
}, defaultRules...)
|
||||
|
||||
var allFormatters = []lint.Formatter{
|
||||
|
87
rule/filename-format.go
Normal file
87
rule/filename-format.go
Normal file
@ -0,0 +1,87 @@
|
||||
package rule
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sync"
|
||||
"unicode"
|
||||
|
||||
"github.com/mgechev/revive/lint"
|
||||
)
|
||||
|
||||
// FilenameFormatRule lints source filenames according to a set of regular expressions given as arguments
|
||||
type FilenameFormatRule struct {
|
||||
format *regexp.Regexp
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// Apply applies the rule to the given file.
|
||||
func (r *FilenameFormatRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
|
||||
r.configure(arguments)
|
||||
|
||||
filename := filepath.Base(file.Name)
|
||||
if r.format.MatchString(filename) {
|
||||
return nil
|
||||
}
|
||||
|
||||
failureMsg := fmt.Sprintf("Filename %s is not of the format %s.%s", filename, r.format.String(), r.getMsgForNonAsciiChars(filename))
|
||||
return []lint.Failure{{
|
||||
Confidence: 1,
|
||||
Failure: failureMsg,
|
||||
RuleName: r.Name(),
|
||||
Node: file.AST.Name,
|
||||
}}
|
||||
}
|
||||
|
||||
func (r *FilenameFormatRule) getMsgForNonAsciiChars(str string) string {
|
||||
result := ""
|
||||
for _, c := range str {
|
||||
if c <= unicode.MaxASCII {
|
||||
continue
|
||||
}
|
||||
|
||||
result += fmt.Sprintf(" Non ASCII character %c (%U) found.", c, c)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Name returns the rule name.
|
||||
func (*FilenameFormatRule) Name() string {
|
||||
return "filename-format"
|
||||
}
|
||||
|
||||
var defaultFormat = regexp.MustCompile("^[_A-Za-z0-9][_A-Za-z0-9-]*.go$")
|
||||
|
||||
func (r *FilenameFormatRule) configure(arguments lint.Arguments) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
if r.format != nil {
|
||||
return
|
||||
}
|
||||
|
||||
argsCount := len(arguments)
|
||||
if argsCount == 0 {
|
||||
r.format = defaultFormat
|
||||
return
|
||||
}
|
||||
|
||||
if argsCount > 1 {
|
||||
panic(fmt.Sprintf("rule %q expects only one argument, got %d %v", r.Name(), argsCount, arguments))
|
||||
}
|
||||
|
||||
arg := arguments[0]
|
||||
str, ok := arg.(string)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("rule %q expects a string argument, got %v of type %T", r.Name(), arg, arg))
|
||||
}
|
||||
|
||||
format, err := regexp.Compile(str)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("rule %q expects a valid regexp argument, got %v for %s", r.Name(), err, arg))
|
||||
}
|
||||
|
||||
r.format = format
|
||||
}
|
16
test/filename-format_test.go
Normal file
16
test/filename-format_test.go
Normal file
@ -0,0 +1,16 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mgechev/revive/lint"
|
||||
"github.com/mgechev/revive/rule"
|
||||
)
|
||||
|
||||
func TestLintFilenameFormat(t *testing.T) {
|
||||
testRule(t, "filename-ok-default", &rule.FilenameFormatRule{}, &lint.RuleConfig{})
|
||||
|
||||
testRule(t, "filenamе-with-non-ascii-char", &rule.FilenameFormatRule{}, &lint.RuleConfig{})
|
||||
|
||||
testRule(t, "filename_with_underscores", &rule.FilenameFormatRule{}, &lint.RuleConfig{Arguments: []any{"^[A-Za-z][A-Za-z0-9]*.go$"}})
|
||||
}
|
1
testdata/filename-ok-default.go
vendored
Normal file
1
testdata/filename-ok-default.go
vendored
Normal file
@ -0,0 +1 @@
|
||||
package main
|
3
testdata/filename_with_underscores.go
vendored
Normal file
3
testdata/filename_with_underscores.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
package main
|
||||
|
||||
// MATCH:1 /Filename filename_with_underscores.go is not of the format ^[A-Za-z][A-Za-z0-9]*.go$./
|
3
testdata/filenamе-with-non-ascii-char.go
vendored
Normal file
3
testdata/filenamе-with-non-ascii-char.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
package main
|
||||
|
||||
// MATCH:1 /Filename filenamе-with-non-ascii-char.go is not of the format ^[_A-Za-z0-9][_A-Za-z0-9-]*.go$. Non ASCII character е (U+0435) found./
|
Loading…
Reference in New Issue
Block a user