aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/tetafro
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-09-15 18:05:35 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-09-15 19:34:30 +0200
commit712de1c63d9db97c81af68cd0dc4372c53d2e57a (patch)
treeae1761fec52c3ae4ddd003a4130ddbda8d0a2d69 /vendor/github.com/tetafro
parent298a69c38dd5c8a9bbd7a022e88f4ddbcf885e16 (diff)
vendor/github.com/golangci/golangci-lint: update to v1.31
Diffstat (limited to 'vendor/github.com/tetafro')
-rw-r--r--vendor/github.com/tetafro/godot/.golangci.yml67
-rw-r--r--vendor/github.com/tetafro/godot/.goreleaser.yml3
-rw-r--r--vendor/github.com/tetafro/godot/Makefile10
-rw-r--r--vendor/github.com/tetafro/godot/README.md17
-rw-r--r--vendor/github.com/tetafro/godot/godot.go246
5 files changed, 299 insertions, 44 deletions
diff --git a/vendor/github.com/tetafro/godot/.golangci.yml b/vendor/github.com/tetafro/godot/.golangci.yml
new file mode 100644
index 000000000..2b799b265
--- /dev/null
+++ b/vendor/github.com/tetafro/godot/.golangci.yml
@@ -0,0 +1,67 @@
+run:
+ concurrency: 2
+ deadline: 5m
+
+skip-dirs:
+ - path: ./testdata/
+
+linters:
+ disable-all: true
+ enable:
+ - deadcode
+ - errcheck
+ - gosimple
+ - govet
+ - ineffassign
+ - staticcheck
+ - structcheck
+ - typecheck
+ - unused
+ - varcheck
+ - bodyclose
+ - depguard
+ - dogsled
+ - dupl
+ - funlen
+ - gochecknoinits
+ - goconst
+ - gocritic
+ - gocyclo
+ - godot
+ - gofmt
+ - gofumpt
+ - goimports
+ - golint
+ - gomnd
+ - gomodguard
+ - goprintffuncname
+ - gosec
+ - lll
+ - maligned
+ - misspell
+ - nakedret
+ - nestif
+ - prealloc
+ - rowserrcheck
+ - scopelint
+ - stylecheck
+ - unconvert
+ - unparam
+ - whitespace
+
+linters-settings:
+ godot:
+ check-all: true
+
+issues:
+ exclude-use-default: false
+ exclude-rules:
+ - path: _test\.go
+ linters:
+ - dupl
+ - errcheck
+ - funlen
+ - gosec
+ - path: cmd/godot/main\.go
+ linters:
+ - gomnd
diff --git a/vendor/github.com/tetafro/godot/.goreleaser.yml b/vendor/github.com/tetafro/godot/.goreleaser.yml
index 87a05a2a7..c0fc2b6b1 100644
--- a/vendor/github.com/tetafro/godot/.goreleaser.yml
+++ b/vendor/github.com/tetafro/godot/.goreleaser.yml
@@ -8,5 +8,4 @@ changelog:
sort: asc
filters:
exclude:
- - '^docs:'
- - '^test:'
+ - '^Merge pull request'
diff --git a/vendor/github.com/tetafro/godot/Makefile b/vendor/github.com/tetafro/godot/Makefile
index fee7693ae..98a691d78 100644
--- a/vendor/github.com/tetafro/godot/Makefile
+++ b/vendor/github.com/tetafro/godot/Makefile
@@ -2,6 +2,16 @@
test:
go test ./...
+.PHONY: cover
+cover:
+ go test -coverprofile cover.out ./...
+ go tool cover -html=cover.out
+ rm -f cover.out
+
+.PHONY: lint
+lint:
+ golangci-lint run
+
.PHONY: build
build:
go build -o godot ./cmd/godot
diff --git a/vendor/github.com/tetafro/godot/README.md b/vendor/github.com/tetafro/godot/README.md
index e2d2f6b0d..864767e3c 100644
--- a/vendor/github.com/tetafro/godot/README.md
+++ b/vendor/github.com/tetafro/godot/README.md
@@ -13,23 +13,32 @@ end of the last sentence if needed.
> Comments should begin with the name of the thing being described
> and end in a period
-## Install and run
+## Install
*NOTE: Godot is available as a part of [GolangCI Lint](https://github.com/golangci/golangci-lint)
(disabled by default).*
Build from source
+
```sh
go get -u github.com/tetafro/godot/cmd/godot
```
or download binary from [releases page](https://github.com/tetafro/godot/releases).
-Run
+## Run
+
```sh
godot ./myproject
```
+Autofix flags are also available
+
+```sh
+godot -f ./myproject # fix issues and print the result
+godot -w ./myproject # fix issues and replace the original file
+```
+
## Examples
Code
@@ -50,5 +59,5 @@ Top level comment should end in a period: math/math.go:3:1
```
See more examples in test files:
-- [for default mode](testdata/example_default.go)
-- [for using --all flag](testdata/example_checkall.go)
+- [for default mode](testdata/default/in/main.go)
+- [for using --all flag](testdata/checkall/in/main.go)
diff --git a/vendor/github.com/tetafro/godot/godot.go b/vendor/github.com/tetafro/godot/godot.go
index 5eec83579..81211d725 100644
--- a/vendor/github.com/tetafro/godot/godot.go
+++ b/vendor/github.com/tetafro/godot/godot.go
@@ -3,19 +3,25 @@
package godot
import (
+ "fmt"
"go/ast"
"go/token"
+ "io/ioutil"
+ "os"
"regexp"
+ "sort"
"strings"
)
-const noPeriodMessage = "Top level comment should end in a period"
-
-// Message contains a message of linting error.
-type Message struct {
- Pos token.Position
- Message string
-}
+const (
+ // noPeriodMessage is an error message to return.
+ noPeriodMessage = "Top level comment should end in a period"
+ // topLevelColumn is just the most left column of the file.
+ topLevelColumn = 1
+ // topLevelGroupColumn is the most left column inside a group declaration
+ // on the top level.
+ topLevelGroupColumn = 2
+)
// Settings contains linter settings.
type Settings struct {
@@ -23,12 +29,25 @@ type Settings struct {
CheckAll bool
}
+// Issue contains a description of linting error and a possible replacement.
+type Issue struct {
+ Pos token.Position
+ Message string
+ Replacement string
+}
+
+// position is an position inside a comment (might be multiline comment).
+type position struct {
+ line int
+ column int
+}
+
var (
// List of valid last characters.
lastChars = []string{".", "?", "!"}
- // Special tags in comments like "nolint" or "build".
- tags = regexp.MustCompile("^[a-z]+:")
+ // Special tags in comments like "// nolint:", or "// +k8s:".
+ tags = regexp.MustCompile(`^\+?[a-z0-9]+:`)
// Special hashtags in comments like "#nosec".
hashtags = regexp.MustCompile("^#[a-z]+ ")
@@ -38,43 +57,150 @@ var (
)
// Run runs this linter on the provided code.
-func Run(file *ast.File, fset *token.FileSet, settings Settings) []Message {
- msgs := []Message{}
+func Run(file *ast.File, fset *token.FileSet, settings Settings) []Issue {
+ issues := checkBlocks(file, fset)
// Check all top-level comments
if settings.CheckAll {
- for _, group := range file.Comments {
- if ok, msg := check(fset, group); !ok {
- msgs = append(msgs, msg)
- }
- }
- return msgs
+ issues = append(issues, checkTopLevel(file, fset)...)
+ sortIssues(issues)
+ return issues
}
// Check only declaration comments
+ issues = append(issues, checkDeclarations(file, fset)...)
+ sortIssues(issues)
+ return issues
+}
+
+// Fix fixes all issues and return new version of file content.
+func Fix(path string, file *ast.File, fset *token.FileSet, settings Settings) ([]byte, error) {
+ // Read file
+ content, err := ioutil.ReadFile(path) // nolint: gosec
+ if err != nil {
+ return nil, fmt.Errorf("read file: %v", err)
+ }
+ if len(content) == 0 {
+ return nil, nil
+ }
+
+ issues := Run(file, fset, settings)
+
+ // slice -> map
+ m := map[int]Issue{}
+ for _, iss := range issues {
+ m[iss.Pos.Line] = iss
+ }
+
+ // Replace lines from issues
+ fixed := make([]byte, 0, len(content))
+ for i, line := range strings.Split(string(content), "\n") {
+ newline := line
+ if iss, ok := m[i+1]; ok {
+ newline = iss.Replacement
+ }
+ fixed = append(fixed, []byte(newline+"\n")...)
+ }
+ fixed = fixed[:len(fixed)-1] // trim last "\n"
+
+ return fixed, nil
+}
+
+// Replace rewrites original file with it's fixed version.
+func Replace(path string, file *ast.File, fset *token.FileSet, settings Settings) error {
+ info, err := os.Stat(path)
+ if err != nil {
+ return fmt.Errorf("check file: %v", err)
+ }
+ mode := info.Mode()
+
+ fixed, err := Fix(path, file, fset, settings)
+ if err != nil {
+ return fmt.Errorf("fix issues: %v", err)
+ }
+
+ if err := ioutil.WriteFile(path, fixed, mode); err != nil {
+ return fmt.Errorf("write file: %v", err)
+ }
+ return nil
+}
+
+// sortIssues sorts by filename, line and column.
+func sortIssues(iss []Issue) {
+ sort.Slice(iss, func(i, j int) bool {
+ if iss[i].Pos.Filename != iss[j].Pos.Filename {
+ return iss[i].Pos.Filename < iss[j].Pos.Filename
+ }
+ if iss[i].Pos.Line != iss[j].Pos.Line {
+ return iss[i].Pos.Line < iss[j].Pos.Line
+ }
+ return iss[i].Pos.Column < iss[j].Pos.Column
+ })
+}
+
+// checkTopLevel checks all top-level comments.
+func checkTopLevel(file *ast.File, fset *token.FileSet) (issues []Issue) {
+ for _, group := range file.Comments {
+ if iss, ok := check(fset, group, topLevelColumn); !ok {
+ issues = append(issues, iss)
+ }
+ }
+ return issues
+}
+
+// checkDeclarations checks top level declaration comments.
+func checkDeclarations(file *ast.File, fset *token.FileSet) (issues []Issue) {
for _, decl := range file.Decls {
switch d := decl.(type) {
case *ast.GenDecl:
- if ok, msg := check(fset, d.Doc); !ok {
- msgs = append(msgs, msg)
+ if iss, ok := check(fset, d.Doc, topLevelColumn); !ok {
+ issues = append(issues, iss)
}
case *ast.FuncDecl:
- if ok, msg := check(fset, d.Doc); !ok {
- msgs = append(msgs, msg)
+ if iss, ok := check(fset, d.Doc, topLevelColumn); !ok {
+ issues = append(issues, iss)
+ }
+ }
+ }
+ return issues
+}
+
+// checkBlocks checks comments inside top level blocks (var (...), const (...), etc).
+func checkBlocks(file *ast.File, fset *token.FileSet) (issues []Issue) {
+ for _, decl := range file.Decls {
+ d, ok := decl.(*ast.GenDecl)
+ if !ok {
+ continue
+ }
+ // No parenthesis == no block
+ if d.Lparen == 0 {
+ continue
+ }
+ for _, group := range file.Comments {
+ // Skip comments outside this block
+ if d.Lparen > group.Pos() || group.Pos() > d.Rparen {
+ continue
+ }
+ // Skip comments that are not top-level for this block
+ if fset.Position(group.Pos()).Column != topLevelGroupColumn {
+ continue
+ }
+ if iss, ok := check(fset, group, topLevelGroupColumn); !ok {
+ issues = append(issues, iss)
}
}
}
- return msgs
+ return issues
}
-func check(fset *token.FileSet, group *ast.CommentGroup) (ok bool, msg Message) {
+func check(fset *token.FileSet, group *ast.CommentGroup, level int) (iss Issue, ok bool) {
if group == nil || len(group.List) == 0 {
- return true, Message{}
+ return Issue{}, true
}
// Check only top-level comments
- if fset.Position(group.Pos()).Column > 1 {
- return true, Message{}
+ if fset.Position(group.Pos()).Column > level {
+ return Issue{}, true
}
// Get last element from comment group - it can be either
@@ -82,29 +208,40 @@ func check(fset *token.FileSet, group *ast.CommentGroup) (ok bool, msg Message)
// for "/*"-comment
last := group.List[len(group.List)-1]
- line, ok := checkComment(last.Text)
+ p, ok := checkComment(last.Text)
if ok {
- return true, Message{}
+ return Issue{}, true
}
+
pos := fset.Position(last.Slash)
- pos.Line += line
- return false, Message{
- Pos: pos,
- Message: noPeriodMessage,
+ pos.Line += p.line
+ pos.Column = p.column + level - 1
+
+ indent := strings.Repeat("\t", level-1)
+
+ iss = Issue{
+ Pos: pos,
+ Message: noPeriodMessage,
+ Replacement: indent + makeReplacement(last.Text, p),
}
+ return iss, false
}
-func checkComment(comment string) (line int, ok bool) {
+func checkComment(comment string) (pos position, ok bool) {
// Check last line of "//"-comment
if strings.HasPrefix(comment, "//") {
+ pos.column = len([]rune(comment)) // runes for non-latin chars
comment = strings.TrimPrefix(comment, "//")
- return 0, checkLastChar(comment)
+ if checkLastChar(comment) {
+ return position{}, true
+ }
+ return pos, false
}
// Skip cgo code blocks
- // TODO: Find a better way to detect cgo code.
+ // TODO: Find a better way to detect cgo code
if strings.Contains(comment, "#include") || strings.Contains(comment, "#define") {
- return 0, true
+ return position{}, true
}
// Check last non-empty line in multiline "/*"-comment block
@@ -116,9 +253,19 @@ func checkComment(comment string) (line int, ok bool) {
}
break
}
- comment = strings.TrimPrefix(lines[i], "/*")
+ pos.line = i
+ comment = lines[i]
comment = strings.TrimSuffix(comment, "*/")
- return i, checkLastChar(comment)
+ comment = strings.TrimRight(comment, " ")
+ // Get position of the last non-space char in comment line, use runes
+ // in case of non-latin chars
+ pos.column = len([]rune(comment))
+ comment = strings.TrimPrefix(comment, "/*")
+
+ if checkLastChar(comment) {
+ return position{}, true
+ }
+ return pos, false
}
func checkLastChar(s string) bool {
@@ -142,6 +289,8 @@ func checkLastChar(s string) bool {
if s == "" {
return true
}
+ // Trim parenthesis for cases when the whole sentence is inside parenthesis
+ s = strings.TrimRight(s, ")")
for _, ch := range lastChars {
if string(s[len(s)-1]) == ch {
return true
@@ -149,3 +298,24 @@ func checkLastChar(s string) bool {
}
return false
}
+
+// makeReplacement basically just inserts a period into comment on
+// the given position.
+func makeReplacement(s string, pos position) string {
+ lines := strings.Split(s, "\n")
+ if len(lines) < pos.line {
+ // This should never happen
+ return s
+ }
+ line := []rune(lines[pos.line])
+ if len(line) < pos.column {
+ // This should never happen
+ return s
+ }
+ // Insert a period
+ newline := append(
+ line[:pos.column],
+ append([]rune{'.'}, line[pos.column:]...)...,
+ )
+ return string(newline)
+}