diff --git a/checkers/testdata/todoCommentWithoutDetail/negative_tests.go b/checkers/testdata/todoCommentWithoutDetail/negative_tests.go new file mode 100644 index 000000000..fdfeea521 --- /dev/null +++ b/checkers/testdata/todoCommentWithoutDetail/negative_tests.go @@ -0,0 +1,10 @@ +package checker_test + +func ExampleFoo() { + // TODO: something important + // TODO(jim) + // FIX fix this + // FIXME(bob) + // TODO this + // BUG: oh no this is broken +} diff --git a/checkers/testdata/todoCommentWithoutDetail/positive_tests.go b/checkers/testdata/todoCommentWithoutDetail/positive_tests.go new file mode 100644 index 000000000..927ac2050 --- /dev/null +++ b/checkers/testdata/todoCommentWithoutDetail/positive_tests.go @@ -0,0 +1,16 @@ +package checker_test + +func singleLineCode() { + + /*! may want to add detail/assignee to this TODO/FIXME/BUG comment */ + // TODO + + /*! may want to add detail/assignee to this TODO/FIXME/BUG comment */ + // FIX + + /*! may want to add detail/assignee to this TODO/FIXME/BUG comment */ + // FIXME + + /*! may want to add detail/assignee to this TODO/FIXME/BUG comment */ + // BUG +} diff --git a/checkers/todoCommentWithoutDetail_checker.go b/checkers/todoCommentWithoutDetail_checker.go new file mode 100644 index 000000000..5ec2881b4 --- /dev/null +++ b/checkers/todoCommentWithoutDetail_checker.go @@ -0,0 +1,50 @@ +package checkers + +import ( + "go/ast" + "regexp" + + "github.com/go-critic/go-critic/checkers/internal/astwalk" + "github.com/go-critic/go-critic/framework/linter" +) + +func init() { + var info linter.CheckerInfo + info.Name = "todoCommentWithoutDetail" + info.Tags = []string{"style", "opinionated", "experimental"} + info.Summary = "Detects TODO comments without detail/assignee" + info.Before = ` +// TODO +fiiWithCtx(nil, a, b) +` + info.After = ` +// TODO(admin): pass context.TODO() instead of nil +fiiWithCtx(nil, a, b) +` + collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { + visitor := &todoCommentWithoutCodeChecker{ + ctx: ctx, + regex: regexp.MustCompile(`^(//|/\*)?\s*(TODO|FIX|FIXME|BUG)\s*(\*/)?$`), + } + return astwalk.WalkerForComment(visitor), nil + }) +} + +type todoCommentWithoutCodeChecker struct { + astwalk.WalkHandler + ctx *linter.CheckerContext + regex *regexp.Regexp +} + +func (c *todoCommentWithoutCodeChecker) VisitComment(cg *ast.CommentGroup) { + for _, comment := range cg.List { + if c.regex.MatchString(comment.Text) { + c.warn(cg) + break + } + } +} + +func (c *todoCommentWithoutCodeChecker) warn(cause ast.Node) { + c.ctx.Warn(cause, "may want to add detail/assignee to this TODO/FIXME/BUG comment") +}