diff --git a/checkstyle.go b/checkstyle.go index 2adf788..f03fabb 100644 --- a/checkstyle.go +++ b/checkstyle.go @@ -7,6 +7,7 @@ import ( "go/format" "go/parser" "go/token" + "reflect" "strconv" "strings" ) @@ -14,13 +15,14 @@ import ( type ProblemType string const ( - FileLine ProblemType = "file_line" - FunctionLine ProblemType = "func_line" - ParamsNum ProblemType = "params_num" - ResultsNum ProblemType = "results_num" - Formated ProblemType = "formated" - PackageName ProblemType = "pkg_name" - CamelName ProblemType = "camel_name" + FileLine ProblemType = "file_line" + FunctionLine ProblemType = "func_line" + ParamsNum ProblemType = "params_num" + ResultsNum ProblemType = "results_num" + Formated ProblemType = "formated" + PackageName ProblemType = "pkg_name" + CamelName ProblemType = "camel_name" + ForbiddenExpr ProblemType = "forbidden_expr" ) type Problem struct { @@ -36,16 +38,17 @@ type Checker interface { } type checker struct { - FunctionComment bool `json:"func_comment"` - FileLine int `json:"file_line"` - FunctionLine int `json:"func_line"` - MaxIndent int `json:"max_indent"` - Formated bool `json:"formated"` - Fatal []string `json:"fatal"` - ParamsNum int `json:"params_num"` - ResultsNum int `json:"results_num"` - PackageName bool `json:"pkg_name"` - CamelName bool `json:"camel_name"` + FunctionComment bool `json:"func_comment"` + FileLine int `json:"file_line"` + FunctionLine int `json:"func_line"` + MaxIndent int `json:"max_indent"` + Formated bool `json:"formated"` + Fatal []string `json:"fatal"` + ParamsNum int `json:"params_num"` + ResultsNum int `json:"results_num"` + PackageName bool `json:"pkg_name"` + CamelName bool `json:"camel_name"` + ForbiddenExpr []reflect.Type `json:"forbidden_expr"` } func New(config []byte) (Checker, error) { @@ -159,6 +162,11 @@ func genFuncBodyProblem(name string, start token.Position) Problem { return Problem{Description: desc, Position: &start, Type: ResultsNum} } +func genForbExprProblem(name string, start token.Position) Problem { + desc := "expr " + name + " is forbidden" + return Problem{Description: desc, Position: &start, Type: ForbiddenExpr} +} + func (f *file) checkPkgName(pkg *ast.Ident) { //ref "http://golang.org/doc/effective_go.html#package-names" pkgName := pkg.Name @@ -353,6 +361,19 @@ func (f *file) checkAssign(assign *ast.AssignStmt) { } } +func (f *file) checkForbiddenExpr(n *ast.Node, t reflect.Type) { + if t != nil { + for _, fbExpr := range f.config.ForbiddenExpr { + t = t.Elem() + if t == fbExpr { + pos := f.fset.Position((*n).Pos()) + problem := genForbExprProblem(t.String(), pos) + f.problems = append(f.problems, problem) + } + } + } +} + func (f *file) checkFileContent() { if f.isTest() { return @@ -380,6 +401,7 @@ func (f *file) checkFileContent() { case *ast.StructType: f.checkStruct(decl2) } + f.checkForbiddenExpr(&node, reflect.TypeOf(node)) return true }) case *ast.GenDecl: diff --git a/checkstyle_test.go b/checkstyle_test.go index 33e3a84..e085b59 100644 --- a/checkstyle_test.go +++ b/checkstyle_test.go @@ -1,6 +1,7 @@ package checkstyle import ( + "go/ast" "go/parser" "go/token" "io/ioutil" @@ -232,3 +233,34 @@ func TestCamelName(t *testing.T) { t.Fatal("expect no error") } } + +func TestDefer(t *testing.T) { + fileName := "defer.go" + file := readFile(fileName) + _checker := checker{ForbiddenExpr: []reflect.Type{}} + ps, err := _checker.Check(fileName, file) + if err != nil { + t.Fatal(err) + } + if len(ps) != 0 { + t.Fatal("expect no error") + } + fbExpr := []reflect.Type{reflect.TypeOf(ast.DeferStmt{})} + _checkerFail := checker{ForbiddenExpr: fbExpr} + ps, err = _checkerFail.Check(fileName, file) + if err != nil { + t.Fatal(err) + } + if len(ps) != 1 { + t.Fatal("expect 1 error but ", len(ps)) + } + fileName = "no_defer.go" + file = readFile(fileName) + ps, err = _checkerFail.Check(fileName, file) + if err != nil { + t.Fatal(err) + } + if len(ps) != 0 { + t.Fatal("expect no error") + } +} diff --git a/testdata/defer.go b/testdata/defer.go new file mode 100644 index 0000000..cf5703d --- /dev/null +++ b/testdata/defer.go @@ -0,0 +1,9 @@ +package testdata + +import "fmt" + +func HelloWorld() { + defer fmt.Println("world") + + fmt.Println("hello") +} diff --git a/testdata/no_defer.go b/testdata/no_defer.go new file mode 100644 index 0000000..6d554b8 --- /dev/null +++ b/testdata/no_defer.go @@ -0,0 +1,8 @@ +package testdata + +import "fmt" + +func HelloWorld() { + fmt.Println("hello") + fmt.Println("world") +}