From c7d7f10bdff703e4a3c0414e8a33d4e45c91eb35 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Sat, 4 Jul 2020 11:12:55 +0200 Subject: go.mod: vendor golangci-lint --- vendor/github.com/ultraware/whitespace/main.go | 158 +++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 vendor/github.com/ultraware/whitespace/main.go (limited to 'vendor/github.com/ultraware/whitespace/main.go') diff --git a/vendor/github.com/ultraware/whitespace/main.go b/vendor/github.com/ultraware/whitespace/main.go new file mode 100644 index 000000000..c36086c0e --- /dev/null +++ b/vendor/github.com/ultraware/whitespace/main.go @@ -0,0 +1,158 @@ +package whitespace + +import ( + "go/ast" + "go/token" +) + +// Message contains a message +type Message struct { + Pos token.Position + Type MessageType + Message string +} + +// MessageType describes what should happen to fix the warning +type MessageType uint8 + +// List of MessageTypes +const ( + MessageTypeLeading MessageType = iota + 1 + MessageTypeTrailing + MessageTypeAddAfter +) + +// Settings contains settings for edge-cases +type Settings struct { + MultiIf bool + MultiFunc bool +} + +// Run runs this linter on the provided code +func Run(file *ast.File, fset *token.FileSet, settings Settings) []Message { + var messages []Message + + for _, f := range file.Decls { + decl, ok := f.(*ast.FuncDecl) + if !ok || decl.Body == nil { // decl.Body can be nil for e.g. cgo + continue + } + + vis := visitor{file.Comments, fset, nil, make(map[*ast.BlockStmt]bool), settings} + ast.Walk(&vis, decl) + + messages = append(messages, vis.messages...) + } + + return messages +} + +type visitor struct { + comments []*ast.CommentGroup + fset *token.FileSet + messages []Message + wantNewline map[*ast.BlockStmt]bool + settings Settings +} + +func (v *visitor) Visit(node ast.Node) ast.Visitor { + if node == nil { + return v + } + + if stmt, ok := node.(*ast.IfStmt); ok && v.settings.MultiIf { + checkMultiLine(v, stmt.Body, stmt.Cond) + } + + if stmt, ok := node.(*ast.FuncDecl); ok && v.settings.MultiFunc { + checkMultiLine(v, stmt.Body, stmt.Type) + } + + if stmt, ok := node.(*ast.BlockStmt); ok { + wantNewline := v.wantNewline[stmt] + + comments := v.comments + if wantNewline { + comments = nil // Comments also count as a newline if we want a newline + } + first, last := firstAndLast(comments, v.fset, stmt.Pos(), stmt.End(), stmt.List) + + startMsg := checkStart(v.fset, stmt.Lbrace, first) + + if wantNewline && startMsg == nil { + v.messages = append(v.messages, Message{v.fset.Position(stmt.Pos()), MessageTypeAddAfter, `multi-line statement should be followed by a newline`}) + } else if !wantNewline && startMsg != nil { + v.messages = append(v.messages, *startMsg) + } + + if msg := checkEnd(v.fset, stmt.Rbrace, last); msg != nil { + v.messages = append(v.messages, *msg) + } + } + + return v +} + +func checkMultiLine(v *visitor, body *ast.BlockStmt, stmtStart ast.Node) { + start, end := posLine(v.fset, stmtStart.Pos()), posLine(v.fset, stmtStart.End()) + + if end > start { // Check only multi line conditions + v.wantNewline[body] = true + } +} + +func posLine(fset *token.FileSet, pos token.Pos) int { + return fset.Position(pos).Line +} + +func firstAndLast(comments []*ast.CommentGroup, fset *token.FileSet, start, end token.Pos, stmts []ast.Stmt) (ast.Node, ast.Node) { + if len(stmts) == 0 { + return nil, nil + } + + first, last := ast.Node(stmts[0]), ast.Node(stmts[len(stmts)-1]) + + for _, c := range comments { + if posLine(fset, c.Pos()) == posLine(fset, start) || posLine(fset, c.End()) == posLine(fset, end) { + continue + } + + if c.Pos() < start || c.End() > end { + continue + } + if c.Pos() < first.Pos() { + first = c + } + if c.End() > last.End() { + last = c + } + } + + return first, last +} + +func checkStart(fset *token.FileSet, start token.Pos, first ast.Node) *Message { + if first == nil { + return nil + } + + if posLine(fset, start)+1 < posLine(fset, first.Pos()) { + pos := fset.Position(start) + return &Message{pos, MessageTypeLeading, `unnecessary leading newline`} + } + + return nil +} + +func checkEnd(fset *token.FileSet, end token.Pos, last ast.Node) *Message { + if last == nil { + return nil + } + + if posLine(fset, end)-1 > posLine(fset, last.End()) { + pos := fset.Position(end) + return &Message{pos, MessageTypeTrailing, `unnecessary trailing newline`} + } + + return nil +} -- cgit mrf-deployment