Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
2.2 KiB
113 lines
2.2 KiB
package rule |
|
|
|
import ( |
|
"go/ast" |
|
"go/token" |
|
|
|
"github.com/mgechev/revive/lint" |
|
) |
|
|
|
// EmptyLinesRule lints empty lines in blocks. |
|
type EmptyLinesRule struct{} |
|
|
|
// Apply applies the rule to given file. |
|
func (r *EmptyLinesRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { |
|
var failures []lint.Failure |
|
|
|
onFailure := func(failure lint.Failure) { |
|
failures = append(failures, failure) |
|
} |
|
|
|
w := lintEmptyLines{file, file.CommentMap(), onFailure} |
|
ast.Walk(w, file.AST) |
|
return failures |
|
} |
|
|
|
// Name returns the rule name. |
|
func (r *EmptyLinesRule) Name() string { |
|
return "empty-lines" |
|
} |
|
|
|
type lintEmptyLines struct { |
|
file *lint.File |
|
cmap ast.CommentMap |
|
onFailure func(lint.Failure) |
|
} |
|
|
|
func (w lintEmptyLines) Visit(node ast.Node) ast.Visitor { |
|
block, ok := node.(*ast.BlockStmt) |
|
if !ok { |
|
return w |
|
} |
|
|
|
w.checkStart(block) |
|
w.checkEnd(block) |
|
|
|
return w |
|
} |
|
|
|
func (w lintEmptyLines) checkStart(block *ast.BlockStmt) { |
|
if len(block.List) == 0 { |
|
return |
|
} |
|
|
|
start := w.position(block.Lbrace) |
|
firstNode := block.List[0] |
|
|
|
if w.commentBetween(start, firstNode) { |
|
return |
|
} |
|
|
|
first := w.position(firstNode.Pos()) |
|
if first.Line-start.Line > 1 { |
|
w.onFailure(lint.Failure{ |
|
Confidence: 1, |
|
Node: block, |
|
Category: "style", |
|
Failure: "extra empty line at the start of a block", |
|
}) |
|
} |
|
} |
|
|
|
func (w lintEmptyLines) checkEnd(block *ast.BlockStmt) { |
|
if len(block.List) < 1 { |
|
return |
|
} |
|
|
|
end := w.position(block.Rbrace) |
|
lastNode := block.List[len(block.List)-1] |
|
|
|
if w.commentBetween(end, lastNode) { |
|
return |
|
} |
|
|
|
last := w.position(lastNode.End()) |
|
if end.Line-last.Line > 1 { |
|
w.onFailure(lint.Failure{ |
|
Confidence: 1, |
|
Node: lastNode, |
|
Category: "style", |
|
Failure: "extra empty line at the end of a block", |
|
}) |
|
} |
|
} |
|
|
|
func (w lintEmptyLines) commentBetween(position token.Position, node ast.Node) bool { |
|
comments := w.cmap.Filter(node).Comments() |
|
if len(comments) == 0 { |
|
return false |
|
} |
|
|
|
for _, comment := range comments { |
|
start, end := w.position(comment.Pos()), w.position(comment.End()) |
|
if start.Line-position.Line == 1 || position.Line-end.Line == 1 { |
|
return true |
|
} |
|
} |
|
|
|
return false |
|
} |
|
|
|
func (w lintEmptyLines) position(pos token.Pos) token.Position { |
|
return w.file.ToPosition(pos) |
|
}
|
|
|