From 1858f4f7c20c16d6846df5cb9d22992d4d3c66c9 Mon Sep 17 00:00:00 2001 From: mgechev Date: Sun, 26 Nov 2017 19:06:02 -0800 Subject: [PATCH] Add rule --- defaultrule/blank-imports.go | 2 +- defaultrule/imports.go | 54 +++++++++++++++++++++++++++++++ defaultrule/imports_test.go | 61 ++++++++++++++++++++++++++++++++++++ testutil/testutil.go | 9 ++++-- 4 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 defaultrule/imports.go create mode 100644 defaultrule/imports_test.go diff --git a/defaultrule/blank-imports.go b/defaultrule/blank-imports.go index 2444a8f..62a98f9 100644 --- a/defaultrule/blank-imports.go +++ b/defaultrule/blank-imports.go @@ -30,7 +30,7 @@ func (r *BlankImportsRule) Apply(file *file.File, arguments rule.Arguments) []ru // Name returns the rule name. func (r *BlankImportsRule) Name() string { - return "argument-limit" + return "blank-imports" } type lintBlankImports struct { diff --git a/defaultrule/imports.go b/defaultrule/imports.go new file mode 100644 index 0000000..66e8649 --- /dev/null +++ b/defaultrule/imports.go @@ -0,0 +1,54 @@ +package defaultrule + +import ( + "go/ast" + + "github.com/mgechev/revive/file" + "github.com/mgechev/revive/rule" +) + +// ImportsRule lints given else constructs. +type ImportsRule struct{} + +// Apply applies the rule to given file. +func (r *ImportsRule) Apply(file *file.File, arguments rule.Arguments) []rule.Failure { + var failures []rule.Failure + + fileAst := file.GetAST() + walker := lintImports{ + file: file, + fileAst: fileAst, + onFailure: func(failure rule.Failure) { + failures = append(failures, failure) + }, + } + + ast.Walk(walker, fileAst) + + return failures +} + +// Name returns the rule name. +func (r *ImportsRule) Name() string { + return "imports" +} + +type lintImports struct { + file *file.File + fileAst *ast.File + onFailure func(rule.Failure) +} + +func (w lintImports) Visit(n ast.Node) ast.Visitor { + for _, is := range w.fileAst.Imports { + if is.Name != nil && is.Name.Name == "." && !isTest(w.file) { + w.onFailure(rule.Failure{ + Confidence: 1, + Failure: "should not use dot imports", + Node: is, + }) + } + + } + return nil +} diff --git a/defaultrule/imports_test.go b/defaultrule/imports_test.go new file mode 100644 index 0000000..1ee8df8 --- /dev/null +++ b/defaultrule/imports_test.go @@ -0,0 +1,61 @@ +package defaultrule + +import ( + "testing" + + "github.com/mgechev/revive/rule" + "github.com/mgechev/revive/testutil" +) + +func TestImports_Failure(t *testing.T) { + t.Parallel() + + program := ` + package foo + + import ( + "fmt" + [@f1]. "path"[/@f1] + ) + + ` + testutil.AssertFailures(t, program, &ImportsRule{}, rule.Arguments{}) +} + +func TestImports(t *testing.T) { + t.Parallel() + + program := ` + package main + + import ( + "fmt" + + /* MATCH /blank import/ */ _ "os" + + /* MATCH /blank import/ */ _ "net/http" + _ "path" + ) + + ` + testutil.AssertSuccess(t, program, &ImportsRule{}, rule.Arguments{}) +} + +func TestImports_SkipTesting(t *testing.T) { + t.Parallel() + + program := ` + package main + + import ( + "fmt" + + /* MATCH /blank import/ */ _ "os" + + /* MATCH /blank import/ */ _ "net/http" + . "path" + ) + + ` + testutil.AssertSuccessWithName(t, program, "foo_test.go", &ImportsRule{}, rule.Arguments{}) +} diff --git a/testutil/testutil.go b/testutil/testutil.go index d856ab0..b8ebb51 100644 --- a/testutil/testutil.go +++ b/testutil/testutil.go @@ -53,14 +53,14 @@ func stripAnnotations(code string) string { } // AssertSuccess checks if given rule runs correctly with no failures. -func AssertSuccess(t *testing.T, code string, testingRule rule.Rule, args rule.Arguments) { +func AssertSuccessWithName(t *testing.T, code, name string, testingRule rule.Rule, args rule.Arguments) { annotations := extractFailures(code) if annotations != nil { t.Errorf("There should be no failure annotations when verifying successful rule analysis") } var fileSet token.FileSet - file, err := file.New("testing.go", []byte(stripAnnotations(code)), &fileSet) + file, err := file.New(name, []byte(stripAnnotations(code)), &fileSet) if err != nil { t.Errorf("Cannot parse testing file: %s", err.Error()) } @@ -78,6 +78,11 @@ func AssertSuccess(t *testing.T, code string, testingRule rule.Rule, args rule.A } } +// AssertSuccess checks if given rule runs correctly with no failures. +func AssertSuccess(t *testing.T, code string, testingRule rule.Rule, args rule.Arguments) { + AssertSuccessWithName(t, code, "testing.go", testingRule, args) +} + // AssertFailures checks if given rule runs correctly with failures. func AssertFailures(t *testing.T, code string, testingRule rule.Rule, args rule.Arguments) { annotations := extractFailures(code)