Skip to content

Commit 5f26378

Browse files
qascadechavacava
andauthored
Comment spacing rule (#761)
* added comment-spacing rule for revive * added test for comment-spacings rule * adds comment-spacings rule to the configuration * renames the source file to match rule name * adds some tests * refactor Comment-Spacings Rule to remove whiteList and avoid Panic at empty comment * refactoring and adds rule configuration * adds rule documentation Co-authored-by: chavacava <[email protected]>
1 parent 5fd3b2c commit 5f26378

8 files changed

+145
-2
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,8 @@ List of all available rules. The rules ported from `golint` are left unchanged a
499499
| [`optimize-operands-order`](./RULES_DESCRIPTIONS.md#optimize-operands-order) | n/a | Checks inefficient conditional expressions | no | no |
500500
| [`use-any`](./RULES_DESCRIPTIONS.md#use-any) | n/a | Proposes to replace `interface{}` with its alias `any` | no | no |
501501
| [`datarace`](./RULES_DESCRIPTIONS.md#datarace) | n/a | Spots potential dataraces | no | no |
502+
| [`comment-spacings`](./RULES_DESCRIPTIONS.md#comment-spacings) | []string | Warns on malformed comments | no | no |
503+
502504

503505
## Configurable rules
504506

RULES_DESCRIPTIONS.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ List of all available rules.
1313
- [bool-literal-in-expr](#bool-literal-in-expr)
1414
- [call-to-gc](#call-to-gc)
1515
- [confusing-naming](#confusing-naming)
16+
- [comment-spacings](#comment-spacings)
1617
- [confusing-results](#confusing-results)
1718
- [cognitive-complexity](#cognitive-complexity)
1819
- [constant-logical-expr](#constant-logical-expr)
@@ -168,6 +169,24 @@ Example:
168169
arguments =[7]
169170
```
170171

172+
## comment-spacings
173+
_Description_: Spots comments of the form:
174+
```go
175+
//This is a malformed comment: no space between // and the start of the sentence
176+
```
177+
178+
_Configuration_: ([]string) list of exceptions. For example, to accept comments of the form
179+
```go
180+
//mypragma: activate something
181+
```
182+
You need to add `"mypragma"` in the configuration
183+
184+
Example:
185+
186+
```toml
187+
[rule.comment-spacings]
188+
arguments =["mypragma","otherpragma"]
189+
```
171190
## confusing-naming
172191

173192
_Description_: Methods or fields of `struct` that have names different only by capitalization could be confusing.

config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ var allRules = append([]lint.Rule{
8686
&rule.OptimizeOperandsOrderRule{},
8787
&rule.UseAnyRule{},
8888
&rule.DataRaceRule{},
89+
&rule.CommentSpacingsRule{},
8990
}, defaultRules...)
9091

9192
var allFormatters = []lint.Formatter{

rule/comment-spacings.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package rule
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
"sync"
7+
8+
"github.com/mgechev/revive/lint"
9+
)
10+
11+
// CommentSpacings Rule check the whether there is a space between
12+
// the comment symbol( // ) and the start of the comment text
13+
type CommentSpacingsRule struct {
14+
allowList []string
15+
sync.Mutex
16+
}
17+
18+
func (r *CommentSpacingsRule) configure(arguments lint.Arguments) {
19+
r.Lock()
20+
defer r.Unlock()
21+
22+
if r.allowList == nil {
23+
r.allowList = []string{
24+
"//go:",
25+
"//revive:",
26+
}
27+
28+
for _, arg := range arguments {
29+
allow, ok := arg.(string) // Alt. non panicking version
30+
if !ok {
31+
panic(fmt.Sprintf("invalid argument %v for %s; expected string but got %T", arg, r.Name(), arg))
32+
}
33+
r.allowList = append(r.allowList, `//`+allow+`:`)
34+
}
35+
}
36+
}
37+
38+
func (r *CommentSpacingsRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure {
39+
r.configure(args)
40+
41+
var failures []lint.Failure
42+
43+
for _, cg := range file.AST.Comments {
44+
for _, comment := range cg.List {
45+
commentLine := comment.Text
46+
if len(commentLine) < 3 {
47+
continue // nothing to do
48+
}
49+
50+
isOK := commentLine[2] == ' '
51+
if isOK {
52+
continue
53+
}
54+
55+
if r.isAllowed(commentLine) {
56+
continue
57+
}
58+
59+
failures = append(failures, lint.Failure{
60+
Node: comment,
61+
Confidence: 1,
62+
Category: "style",
63+
Failure: "no space between comment delimiter and comment text",
64+
})
65+
}
66+
}
67+
return failures
68+
}
69+
70+
func (*CommentSpacingsRule) Name() string {
71+
return "comment-spacings"
72+
}
73+
74+
func (r *CommentSpacingsRule) isAllowed(line string) bool {
75+
for _, allow := range r.allowList {
76+
if strings.HasPrefix(line, allow) {
77+
return true
78+
}
79+
}
80+
81+
return false
82+
}

test/comment-spacings_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/mgechev/revive/lint"
7+
"github.com/mgechev/revive/rule"
8+
)
9+
10+
func TestCommentSpacings(t *testing.T) {
11+
12+
testRule(t, "comment-spacings", &rule.CommentSpacingsRule{}, &lint.RuleConfig{
13+
Arguments: []interface{}{"myOwnDirective"}},
14+
)
15+
}

test/disable-annotations_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ func TestModifiedAnnotations(t *testing.T) {
1717

1818
func TestDisableNextLineAnnotations(t *testing.T) {
1919
testRule(t, "disable-annotations3", &rule.VarNamingRule{}, &lint.RuleConfig{})
20-
}
20+
}

test/utils.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func assertFailures(t *testing.T, baseDir string, fi os.FileInfo, src []byte, ru
107107
copy(failures[i:], failures[i+1:])
108108
failures = failures[:len(failures)-1]
109109

110-
// t.Logf("/%v/ matched at %s:%d", in.Match, fi.Name(), in.Line)
110+
//t.Logf("/%v/ matched at %s:%d", in.Match, fi.Name(), in.Line)
111111
ok = true
112112
break
113113
}

testdata/comment-spacings.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package commentspacings
2+
3+
//revive:disable:cyclomatic
4+
type some struct{}
5+
6+
//revive:disable:cyclomatic High complexity score but easy to understand
7+
type some1 struct{}
8+
9+
// Some nice comment
10+
//
11+
// With an empty line in the middle will make the rule panic!
12+
func itsATrap() {}
13+
14+
// This is a well formed comment
15+
type hello struct {
16+
random `json:random`
17+
}
18+
19+
// MATCH:21 /no space between comment delimiter and comment text/
20+
21+
//This comment does not respect the spacing rule!
22+
var a string
23+
24+
//myOwnDirective: do something

0 commit comments

Comments
 (0)