diff options
Diffstat (limited to 'vendor/github.com/mgechev/revive/rule/range.go')
-rw-r--r-- | vendor/github.com/mgechev/revive/rule/range.go | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/vendor/github.com/mgechev/revive/rule/range.go b/vendor/github.com/mgechev/revive/rule/range.go new file mode 100644 index 0000000000..d18492c71a --- /dev/null +++ b/vendor/github.com/mgechev/revive/rule/range.go @@ -0,0 +1,82 @@ +package rule + +import ( + "fmt" + "go/ast" + "strings" + + "github.com/mgechev/revive/lint" +) + +// RangeRule lints given else constructs. +type RangeRule struct{} + +// Apply applies the rule to given file. +func (r *RangeRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { + var failures []lint.Failure + + onFailure := func(failure lint.Failure) { + failures = append(failures, failure) + } + + w := &lintRanges{file, onFailure} + ast.Walk(w, file.AST) + return failures +} + +// Name returns the rule name. +func (r *RangeRule) Name() string { + return "range" +} + +type lintRanges struct { + file *lint.File + onFailure func(lint.Failure) +} + +func (w *lintRanges) Visit(node ast.Node) ast.Visitor { + rs, ok := node.(*ast.RangeStmt) + if !ok { + return w + } + if rs.Value == nil { + // for x = range m { ... } + return w // single var form + } + if !isIdent(rs.Value, "_") { + // for ?, y = range m { ... } + return w + } + + newRS := *rs // shallow copy + newRS.Value = nil + + w.onFailure(lint.Failure{ + Failure: fmt.Sprintf("should omit 2nd value from range; this loop is equivalent to `for %s %s range ...`", w.file.Render(rs.Key), rs.Tok), + Confidence: 1, + Node: rs.Value, + ReplacementLine: firstLineOf(w.file, &newRS, rs), + }) + + return w +} + +func firstLineOf(f *lint.File, node, match ast.Node) string { + line := f.Render(node) + if i := strings.Index(line, "\n"); i >= 0 { + line = line[:i] + } + return indentOf(f, match) + line +} + +func indentOf(f *lint.File, node ast.Node) string { + line := srcLine(f.Content(), f.ToPosition(node.Pos())) + for i, r := range line { + switch r { + case ' ', '\t': + default: + return line[:i] + } + } + return line // unusual or empty line +} |