mirror of
https://github.com/mgechev/revive.git
synced 2025-04-13 11:30:36 +02:00
Add extra rule
This commit is contained in:
parent
bd04af7465
commit
b5fc0eaffc
4
fixtures/lint-file-header1.go
Normal file
4
fixtures/lint-file-header1.go
Normal file
@ -0,0 +1,4 @@
|
||||
// baz baz qux
|
||||
// foobar
|
||||
|
||||
package fixtures
|
4
fixtures/lint-file-header2.go
Normal file
4
fixtures/lint-file-header2.go
Normal file
@ -0,0 +1,4 @@
|
||||
/* baz baz qux
|
||||
foobar */
|
||||
|
||||
package fixtures
|
4
fixtures/lint-file-header3.go
Normal file
4
fixtures/lint-file-header3.go
Normal file
@ -0,0 +1,4 @@
|
||||
// baz baz qux
|
||||
// qux foo
|
||||
|
||||
package fixtures // MATCH /the file doesn't have an appropriate header/
|
3
fixtures/lint-file-header4.go
Normal file
3
fixtures/lint-file-header4.go
Normal file
@ -0,0 +1,3 @@
|
||||
// foobar
|
||||
|
||||
package fixtures
|
4
fixtures/lint-file-header5.go
Normal file
4
fixtures/lint-file-header5.go
Normal file
@ -0,0 +1,4 @@
|
||||
// foobaz qux
|
||||
// bar
|
||||
|
||||
package fixtures
|
86
rule/file-header.go
Normal file
86
rule/file-header.go
Normal file
@ -0,0 +1,86 @@
|
||||
package rule
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"regexp"
|
||||
|
||||
"github.com/mgechev/revive/lint"
|
||||
)
|
||||
|
||||
// FileHeaderRule lints given else constructs.
|
||||
type FileHeaderRule struct{}
|
||||
|
||||
// Apply applies the rule to given file.
|
||||
func (r *FileHeaderRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
|
||||
var failures []lint.Failure
|
||||
|
||||
header, ok := arguments[0].(string)
|
||||
if !ok {
|
||||
panic("Invalid argument to the FileHeaderRule")
|
||||
}
|
||||
|
||||
regex, err := regexp.Compile(header)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
fileAst := file.AST
|
||||
walker := lintFileHeader{
|
||||
file: file,
|
||||
fileAst: fileAst,
|
||||
regex: regex,
|
||||
onFailure: func(failure lint.Failure) {
|
||||
failures = append(failures, failure)
|
||||
},
|
||||
}
|
||||
|
||||
ast.Walk(walker, fileAst)
|
||||
|
||||
return failures
|
||||
}
|
||||
|
||||
// Name returns the rule name.
|
||||
func (r *FileHeaderRule) Name() string {
|
||||
return "file-header"
|
||||
}
|
||||
|
||||
type lintFileHeader struct {
|
||||
file *lint.File
|
||||
fileAst *ast.File
|
||||
regex *regexp.Regexp
|
||||
onFailure func(lint.Failure)
|
||||
}
|
||||
|
||||
func (w lintFileHeader) Visit(n ast.Node) ast.Visitor {
|
||||
g := w.fileAst.Comments[0]
|
||||
failure := lint.Failure{
|
||||
Node: w.fileAst,
|
||||
Confidence: 1,
|
||||
Failure: "the file doesn't have an appropriate header",
|
||||
}
|
||||
if g == nil {
|
||||
w.onFailure(failure)
|
||||
return nil
|
||||
}
|
||||
multi := regexp.MustCompile("^/\\*")
|
||||
single := regexp.MustCompile("^//")
|
||||
comment := ""
|
||||
for _, c := range g.List {
|
||||
text := c.Text
|
||||
if multi.Match([]byte(text)) {
|
||||
text = text[2 : len(text)-2]
|
||||
} else if single.Match([]byte(text)) {
|
||||
text = text[2:]
|
||||
}
|
||||
comment += text
|
||||
}
|
||||
|
||||
fmt.Println("#############")
|
||||
fmt.Println(comment)
|
||||
fmt.Println("#############")
|
||||
if !w.regex.Match([]byte(comment)) {
|
||||
w.onFailure(failure)
|
||||
}
|
||||
return nil
|
||||
}
|
17
test/cyclomatic_test.go
Normal file
17
test/cyclomatic_test.go
Normal file
@ -0,0 +1,17 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mgechev/revive/lint"
|
||||
"github.com/mgechev/revive/rule"
|
||||
)
|
||||
|
||||
func TestCyclomatic(t *testing.T) {
|
||||
testRule(t, "cyclomatic", &rule.CyclomaticRule{}, &lint.RuleConfig{
|
||||
Arguments: []interface{}{int64(1)},
|
||||
})
|
||||
testRule(t, "cyclomatic-2", &rule.CyclomaticRule{}, &lint.RuleConfig{
|
||||
Arguments: []interface{}{int64(3)},
|
||||
})
|
||||
}
|
30
test/file-header_test.go
Normal file
30
test/file-header_test.go
Normal file
@ -0,0 +1,30 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mgechev/revive/lint"
|
||||
"github.com/mgechev/revive/rule"
|
||||
)
|
||||
|
||||
func TestLintFileHeader(t *testing.T) {
|
||||
testRule(t, "lint-file-header1", &rule.FileHeaderRule{}, &lint.RuleConfig{
|
||||
Arguments: []interface{}{"foobar"},
|
||||
})
|
||||
|
||||
testRule(t, "lint-file-header2", &rule.FileHeaderRule{}, &lint.RuleConfig{
|
||||
Arguments: []interface{}{"foobar"},
|
||||
})
|
||||
|
||||
testRule(t, "lint-file-header3", &rule.FileHeaderRule{}, &lint.RuleConfig{
|
||||
Arguments: []interface{}{"foobar"},
|
||||
})
|
||||
|
||||
testRule(t, "lint-file-header4", &rule.FileHeaderRule{}, &lint.RuleConfig{
|
||||
Arguments: []interface{}{"^\\sfoobar$"},
|
||||
})
|
||||
|
||||
testRule(t, "lint-file-header5", &rule.FileHeaderRule{}, &lint.RuleConfig{
|
||||
Arguments: []interface{}{"^\\sfoo.*bar$"},
|
||||
})
|
||||
}
|
@ -1,12 +1,4 @@
|
||||
// Copyright (c) 2013 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd.
|
||||
|
||||
// The code contains changes from the original source.
|
||||
|
||||
package testutil
|
||||
package test
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@ -56,21 +48,6 @@ var rules = []lint.Rule{
|
||||
&rule.ContextArgumentsRule{},
|
||||
}
|
||||
|
||||
func TestCyclomatic(t *testing.T) {
|
||||
testRule(t, "cyclomatic", &rule.CyclomaticRule{}, &lint.RuleConfig{
|
||||
Arguments: []interface{}{int64(1)},
|
||||
})
|
||||
testRule(t, "cyclomatic-2", &rule.CyclomaticRule{}, &lint.RuleConfig{
|
||||
Arguments: []interface{}{int64(3)},
|
||||
})
|
||||
}
|
||||
|
||||
func TestMaxPublicStructs(t *testing.T) {
|
||||
testRule(t, "max-public-structs", &rule.MaxPublicStructsRule{}, &lint.RuleConfig{
|
||||
Arguments: []interface{}{int64(1)},
|
||||
})
|
||||
}
|
||||
|
||||
func testRule(t *testing.T, filename string, rule lint.Rule, config ...*lint.RuleConfig) {
|
||||
baseDir := "../fixtures/"
|
||||
filename = filename + ".go"
|
||||
@ -82,17 +59,14 @@ func testRule(t *testing.T, filename string, rule lint.Rule, config ...*lint.Rul
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot get file info for %s: %v", rule.Name(), err)
|
||||
}
|
||||
ins := parseInstructions(t, filename, src)
|
||||
if ins == nil {
|
||||
t.Errorf("Test file %v does not have instructions", filename)
|
||||
return
|
||||
}
|
||||
if config == nil {
|
||||
assertFailures(t, baseDir, stat, src, []lint.Rule{rule}, map[string]lint.RuleConfig{})
|
||||
return
|
||||
}
|
||||
c := map[string]lint.RuleConfig{}
|
||||
c[rule.Name()] = *config[0]
|
||||
if config != nil {
|
||||
c[rule.Name()] = *config[0]
|
||||
}
|
||||
if parseInstructions(t, filename, src) == nil {
|
||||
assertSuccess(t, baseDir, stat, src, []lint.Rule{rule}, c)
|
||||
return
|
||||
}
|
||||
assertFailures(t, baseDir, stat, src, []lint.Rule{rule}, c)
|
||||
}
|
||||
|
||||
@ -103,6 +77,11 @@ func TestAll(t *testing.T) {
|
||||
"cyclomatic.go": true,
|
||||
"cyclomatic-2.go": true,
|
||||
"max-public-structs.go": true,
|
||||
"lint-file-header1.go": true,
|
||||
"lint-file-header2.go": true,
|
||||
"lint-file-header3.go": true,
|
||||
"lint-file-header4.go": true,
|
||||
"lint-file-header5.go": true,
|
||||
}
|
||||
|
||||
rx, err := regexp.Compile(*lintMatch)
|
||||
@ -138,6 +117,28 @@ func TestAll(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func assertSuccess(t *testing.T, baseDir string, fi os.FileInfo, src []byte, rules []lint.Rule, config map[string]lint.RuleConfig) error {
|
||||
l := lint.New(func(file string) ([]byte, error) {
|
||||
return ioutil.ReadFile(baseDir + file)
|
||||
})
|
||||
|
||||
ps, err := l.Lint([]string{fi.Name()}, rules, lint.Config{
|
||||
Rules: config,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
failures := ""
|
||||
for p := range ps {
|
||||
failures += p.Failure
|
||||
}
|
||||
if failures != "" {
|
||||
t.Errorf("Expected the rule to pass but got the following failures: %s", failures)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func assertFailures(t *testing.T, baseDir string, fi os.FileInfo, src []byte, rules []lint.Rule, config map[string]lint.RuleConfig) error {
|
||||
l := lint.New(func(file string) ([]byte, error) {
|
||||
return ioutil.ReadFile(baseDir + file)
|
14
test/max-public-structs_test.go
Normal file
14
test/max-public-structs_test.go
Normal file
@ -0,0 +1,14 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mgechev/revive/lint"
|
||||
"github.com/mgechev/revive/rule"
|
||||
)
|
||||
|
||||
func TestMaxPublicStructs(t *testing.T) {
|
||||
testRule(t, "max-public-structs", &rule.MaxPublicStructsRule{}, &lint.RuleConfig{
|
||||
Arguments: []interface{}{int64(1)},
|
||||
})
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user