-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathrule.go
More file actions
127 lines (113 loc) · 2.78 KB
/
Copy pathrule.go
File metadata and controls
127 lines (113 loc) · 2.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package nomultipleblanks
import (
"bytes"
"fmt"
"strings"
"github.com/jeduden/mdsmith/internal/lint"
"github.com/jeduden/mdsmith/internal/rule"
"github.com/jeduden/mdsmith/internal/rules/settings"
)
func init() {
rule.Register(&Rule{Max: 1})
}
// Rule checks that there are no more than Max consecutive blank lines.
// Default Max is 1 (no consecutive blank lines allowed).
type Rule struct {
Max int // maximum allowed consecutive blank lines (default: 1)
}
// ID implements rule.Rule.
func (r *Rule) ID() string { return "MDS008" }
// Name implements rule.Rule.
func (r *Rule) Name() string { return "no-multiple-blanks" }
// Category implements rule.Rule.
func (r *Rule) Category() string { return "whitespace" }
// isBlank returns true if the line contains only whitespace.
func isBlank(line []byte) bool {
return len(bytes.TrimSpace(line)) == 0
}
// maxBlanks returns the effective maximum.
func (r *Rule) maxBlanks() int {
if r.Max <= 0 {
return 1
}
return r.Max
}
// Check implements rule.Rule.
func (r *Rule) Check(f *lint.File) []lint.Diagnostic {
codeLines := lint.CollectCodeBlockLines(f)
var diags []lint.Diagnostic
max := r.maxBlanks()
consecutiveBlanks := 0
for i, line := range f.Lines {
lineNum := i + 1
if codeLines[lineNum] {
consecutiveBlanks = 0
continue
}
if isBlank(line) {
consecutiveBlanks++
if consecutiveBlanks > max {
diags = append(diags, lint.Diagnostic{
File: f.Path,
Line: lineNum,
Column: 1,
RuleID: r.ID(),
RuleName: r.Name(),
Severity: lint.Warning,
Message: "multiple consecutive blank lines",
})
}
} else {
consecutiveBlanks = 0
}
}
return diags
}
// Fix implements rule.FixableRule.
func (r *Rule) Fix(f *lint.File) []byte {
codeLines := lint.CollectCodeBlockLines(f)
max := r.maxBlanks()
var result []string
consecutiveBlanks := 0
for i, line := range f.Lines {
lineNum := i + 1
if codeLines[lineNum] {
result = append(result, string(line))
consecutiveBlanks = 0
continue
}
if isBlank(line) {
consecutiveBlanks++
if consecutiveBlanks > max {
continue
}
} else {
consecutiveBlanks = 0
}
result = append(result, string(line))
}
return []byte(strings.Join(result, "\n"))
}
// ApplySettings implements rule.Configurable.
func (r *Rule) ApplySettings(s map[string]any) error {
for k, v := range s {
switch k {
case "max":
n, ok := settings.ToInt(v)
if !ok {
return fmt.Errorf("no-multiple-blanks: max must be an integer, got %T", v)
}
r.Max = n
default:
return fmt.Errorf("no-multiple-blanks: unknown setting %q", k)
}
}
return nil
}
// DefaultSettings implements rule.Configurable.
func (r *Rule) DefaultSettings() map[string]any {
return map[string]any{
"max": 1,
}
}
var _ rule.Configurable = (*Rule)(nil)