Add new linter: godot
This commit is contained in:
parent
4958e50dfe
commit
58572c7789
@ -126,6 +126,9 @@ linters-settings:
|
||||
gocyclo:
|
||||
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
||||
min-complexity: 10
|
||||
godot:
|
||||
# check all top-level comments, not only declarations
|
||||
check-all: false
|
||||
godox:
|
||||
# report any comments starting with keywords, this is useful for TODO or FIXME comments that
|
||||
# might be left in the code accidentally and should be resolved before merging
|
||||
|
@ -217,6 +217,7 @@ gocognit: Computes and checks the cognitive complexity of functions [fast: true,
|
||||
goconst: Finds repeated strings that could be replaced by a constant [fast: true, auto-fix: false]
|
||||
gocritic: The most opinionated Go source code linter [fast: true, auto-fix: false]
|
||||
gocyclo: Computes and checks the cyclomatic complexity of functions [fast: true, auto-fix: false]
|
||||
godot: Check if comments end in a period [fast: true, auto-fix: false]
|
||||
godox: Tool for detection of FIXME, TODO and other comment keywords [fast: true, auto-fix: false]
|
||||
gofmt: Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification [fast: true, auto-fix: true]
|
||||
goimports: Goimports does everything that gofmt does. Additionally it checks unused imports [fast: true, auto-fix: true]
|
||||
@ -488,6 +489,7 @@ golangci-lint help linters
|
||||
- [wsl](https://github.com/bombsimon/wsl) - Whitespace Linter - Forces you to use empty lines!
|
||||
- [goprintffuncname](https://github.com/jirfag/go-printf-func-name) - Checks that printf-like functions are named with `f` at the end
|
||||
- [gomnd](https://github.com/tommy-muehle/go-mnd) - An analyzer to detect magic numbers.
|
||||
- [godot](https://github.com/tetafro/godot) - Check if comments end in a period
|
||||
|
||||
## Configuration
|
||||
|
||||
@ -736,6 +738,9 @@ linters-settings:
|
||||
gocyclo:
|
||||
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
||||
min-complexity: 10
|
||||
godot:
|
||||
# check all top-level comments, not only declarations
|
||||
check-all: false
|
||||
godox:
|
||||
# report any comments starting with keywords, this is useful for TODO or FIXME comments that
|
||||
# might be left in the code accidentally and should be resolved before merging
|
||||
@ -1261,6 +1266,7 @@ Thanks to developers and authors of used linters:
|
||||
- [bombsimon](https://github.com/bombsimon)
|
||||
- [jirfag](https://github.com/jirfag)
|
||||
- [tommy-muehle](https://github.com/tommy-muehle)
|
||||
- [tetafro](https://github.com/tetafro)
|
||||
|
||||
## Changelog
|
||||
|
||||
|
1
go.mod
1
go.mod
@ -38,6 +38,7 @@ require (
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.6.1
|
||||
github.com/stretchr/testify v1.5.1
|
||||
github.com/tetafro/godot v0.2.5
|
||||
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e
|
||||
github.com/tommy-muehle/go-mnd v1.3.1-0.20200224220436-e6f9a994e8fa
|
||||
github.com/ultraware/funlen v0.0.2
|
||||
|
2
go.sum
2
go.sum
@ -262,6 +262,8 @@ github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tetafro/godot v0.2.5 h1:7+EYJM/Z4gYZhBFdRrVm6JTj5ZLw/QI1j4RfEOXJviE=
|
||||
github.com/tetafro/godot v0.2.5/go.mod h1:pT6/T8+h6//L/LwQcFc4C0xpfy1euZwzS1sHdrFCms0=
|
||||
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e h1:RumXZ56IrCj4CL+g1b9OL/oH0QnsF976bC8xQFYUD5Q=
|
||||
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
|
@ -196,6 +196,7 @@ type LintersSettings struct {
|
||||
Godox GodoxSettings
|
||||
Dogsled DogsledSettings
|
||||
Gocognit GocognitSettings
|
||||
Godot GodotSettings
|
||||
|
||||
Custom map[string]CustomLinterSettings
|
||||
}
|
||||
@ -273,6 +274,10 @@ type WSLSettings struct {
|
||||
ForceCaseTrailingWhitespaceLimit int `mapstructure:"force-case-trailing-whitespace"`
|
||||
}
|
||||
|
||||
type GodotSettings struct {
|
||||
CheckAll bool `mapstructure:"check-all"`
|
||||
}
|
||||
|
||||
//nolint:gomnd
|
||||
var defaultLintersSettings = LintersSettings{
|
||||
Lll: LllSettings{
|
||||
|
64
pkg/golinters/godot.go
Normal file
64
pkg/golinters/godot.go
Normal file
@ -0,0 +1,64 @@
|
||||
package golinters
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/tetafro/godot"
|
||||
"golang.org/x/tools/go/analysis"
|
||||
|
||||
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
|
||||
"github.com/golangci/golangci-lint/pkg/lint/linter"
|
||||
"github.com/golangci/golangci-lint/pkg/result"
|
||||
)
|
||||
|
||||
const godotName = "godot"
|
||||
|
||||
func NewGodot() *goanalysis.Linter {
|
||||
var mu sync.Mutex
|
||||
var resIssues []goanalysis.Issue
|
||||
|
||||
analyzer := &analysis.Analyzer{
|
||||
Name: godotName,
|
||||
Doc: goanalysis.TheOnlyanalyzerDoc,
|
||||
}
|
||||
return goanalysis.NewLinter(
|
||||
godotName,
|
||||
"Check if comments end in a period",
|
||||
[]*analysis.Analyzer{analyzer},
|
||||
nil,
|
||||
).WithContextSetter(func(lintCtx *linter.Context) {
|
||||
cfg := lintCtx.Cfg.LintersSettings.Godot
|
||||
settings := godot.Settings{CheckAll: cfg.CheckAll}
|
||||
|
||||
analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
|
||||
var issues []godot.Message
|
||||
for _, file := range pass.Files {
|
||||
issues = append(issues, godot.Run(file, pass.Fset, settings)...)
|
||||
}
|
||||
|
||||
if len(issues) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
res := make([]goanalysis.Issue, len(issues))
|
||||
for k, i := range issues {
|
||||
issue := result.Issue{
|
||||
Pos: i.Pos,
|
||||
Text: i.Message,
|
||||
FromLinter: godotName,
|
||||
Replacement: &result.Replacement{},
|
||||
}
|
||||
|
||||
res[k] = goanalysis.NewIssue(&issue, pass)
|
||||
}
|
||||
|
||||
mu.Lock()
|
||||
resIssues = append(resIssues, res...)
|
||||
mu.Unlock()
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
}).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
|
||||
return resIssues
|
||||
}).WithLoadMode(goanalysis.LoadModeSyntax)
|
||||
}
|
@ -247,6 +247,9 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
|
||||
linter.NewConfig(golinters.NewGoMND(m.cfg)).
|
||||
WithPresets(linter.PresetStyle).
|
||||
WithURL("https://github.com/tommy-muehle/go-mnd"),
|
||||
linter.NewConfig(golinters.NewGodot()).
|
||||
WithPresets(linter.PresetStyle).
|
||||
WithURL("https://github.com/tetafro/godot"),
|
||||
}
|
||||
|
||||
isLocalRun := os.Getenv("GOLANGCI_COM_RUN") == ""
|
||||
|
7
test/testdata/godot.go
vendored
Normal file
7
test/testdata/godot.go
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
//args: -Egodot
|
||||
package testdata
|
||||
|
||||
// Godot checks top-level comments // ERROR "Top level comment should end in a period"
|
||||
func Godot() {
|
||||
// nothing to do here
|
||||
}
|
1
vendor/github.com/tetafro/godot/.gitignore
generated
vendored
Normal file
1
vendor/github.com/tetafro/godot/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
/godot
|
21
vendor/github.com/tetafro/godot/LICENSE
generated
vendored
Normal file
21
vendor/github.com/tetafro/godot/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Denis Krivak
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
40
vendor/github.com/tetafro/godot/README.md
generated
vendored
Normal file
40
vendor/github.com/tetafro/godot/README.md
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
# godot
|
||||
|
||||
[](https://raw.githubusercontent.com/tetafro/godot/master/LICENSE)
|
||||
[](https://github.com/tetafro/godot/actions?query=workflow%3ATest)
|
||||
[](https://goreportcard.com/report/github.com/tetafro/godot)
|
||||
[](https://codecov.io/gh/tetafro/godot)
|
||||
|
||||
Linter that checks if all top-level comments contain a period at the
|
||||
end of the last sentence if needed.
|
||||
|
||||
[CodeReviewComments](https://github.com/golang/go/wiki/CodeReviewComments#comment-sentences) quote:
|
||||
|
||||
> Comments should begin with the name of the thing being described
|
||||
> and end in a period
|
||||
|
||||
## Install and run
|
||||
|
||||
```sh
|
||||
go get -u github.com/tetafro/godot/cmd/godot
|
||||
godot ./myproject
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
Code
|
||||
|
||||
```go
|
||||
package math
|
||||
|
||||
// Sum sums two integers
|
||||
func Sum(a, b int) int {
|
||||
return a + b // result
|
||||
}
|
||||
```
|
||||
|
||||
Output
|
||||
|
||||
```sh
|
||||
Top level comment should end in a period: math/math.go:3:1
|
||||
```
|
3
vendor/github.com/tetafro/godot/go.mod
generated
vendored
Normal file
3
vendor/github.com/tetafro/godot/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module github.com/tetafro/godot
|
||||
|
||||
go 1.13
|
130
vendor/github.com/tetafro/godot/godot.go
generated
vendored
Normal file
130
vendor/github.com/tetafro/godot/godot.go
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
// Package godot checks if all top-level comments contain a period at the
|
||||
// end of the last sentence if needed.
|
||||
package godot
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Message contains a message of linting error.
|
||||
type Message struct {
|
||||
Pos token.Position
|
||||
Message string
|
||||
}
|
||||
|
||||
// Settings contains linter settings.
|
||||
type Settings struct {
|
||||
// Check all top-level comments, not only declarations
|
||||
CheckAll bool
|
||||
}
|
||||
|
||||
var (
|
||||
// List of valid last characters.
|
||||
lastChars = []string{".", "?", "!"}
|
||||
|
||||
// Special tags in comments like "nolint" or "build".
|
||||
tags = regexp.MustCompile("^[a-z]+:")
|
||||
|
||||
// URL at the end of the line.
|
||||
endURL = regexp.MustCompile(`[a-z]+://[^\s]+$`)
|
||||
)
|
||||
|
||||
// Run runs this linter on the provided code.
|
||||
func Run(file *ast.File, fset *token.FileSet, settings Settings) []Message {
|
||||
msgs := []Message{}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// Check only declaration comments
|
||||
for _, decl := range file.Decls {
|
||||
switch d := decl.(type) {
|
||||
case *ast.GenDecl:
|
||||
case *ast.FuncDecl:
|
||||
if ok, msg := check(fset, d.Doc); !ok {
|
||||
msgs = append(msgs, msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
return msgs
|
||||
}
|
||||
|
||||
func check(fset *token.FileSet, group *ast.CommentGroup) (ok bool, msg Message) {
|
||||
if group == nil || len(group.List) == 0 {
|
||||
return true, Message{}
|
||||
}
|
||||
|
||||
// Check only top-level comments
|
||||
if fset.Position(group.Pos()).Column > 1 {
|
||||
return true, Message{}
|
||||
}
|
||||
|
||||
// Get last element from comment group - it can be either
|
||||
// last (or single) line for "//"-comment, or multiline string
|
||||
// for "/*"-comment
|
||||
last := group.List[len(group.List)-1]
|
||||
|
||||
line, ok := checkComment(last.Text)
|
||||
if ok {
|
||||
return true, Message{}
|
||||
}
|
||||
pos := fset.Position(last.Slash)
|
||||
pos.Line += line
|
||||
return false, Message{
|
||||
Pos: pos,
|
||||
Message: "Top level comment should end in a period",
|
||||
}
|
||||
}
|
||||
|
||||
func checkComment(comment string) (line int, ok bool) {
|
||||
// Check last line of "//"-comment
|
||||
if strings.HasPrefix(comment, "//") {
|
||||
comment = strings.TrimPrefix(comment, "//")
|
||||
return 0, checkLastChar(comment)
|
||||
}
|
||||
|
||||
// Check multiline "/*"-comment block
|
||||
lines := strings.Split(comment, "\n")
|
||||
var i int
|
||||
for i = len(lines) - 1; i >= 0; i-- {
|
||||
if s := strings.TrimSpace(lines[i]); s == "*/" || s == "" {
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
comment = strings.TrimPrefix(lines[i], "/*")
|
||||
comment = strings.TrimSuffix(comment, "*/")
|
||||
return i, checkLastChar(comment)
|
||||
}
|
||||
|
||||
func checkLastChar(s string) bool {
|
||||
// Don't check comments starting with space indentation - they may
|
||||
// contain code examples, which shouldn't end with period
|
||||
if strings.HasPrefix(s, " ") || strings.HasPrefix(s, "\t") {
|
||||
return true
|
||||
}
|
||||
s = strings.TrimSpace(s)
|
||||
if tags.MatchString(s) || endURL.MatchString(s) || strings.HasPrefix(s, "+build") {
|
||||
return true
|
||||
}
|
||||
// Don't check empty lines
|
||||
if s == "" {
|
||||
return true
|
||||
}
|
||||
for _, ch := range lastChars {
|
||||
if string(s[len(s)-1]) == ch {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -174,6 +174,8 @@ github.com/stretchr/testify/mock
|
||||
github.com/stretchr/testify/require
|
||||
# github.com/subosito/gotenv v1.2.0
|
||||
github.com/subosito/gotenv
|
||||
# github.com/tetafro/godot v0.2.5
|
||||
github.com/tetafro/godot
|
||||
# github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e
|
||||
github.com/timakin/bodyclose/passes/bodyclose
|
||||
# github.com/tommy-muehle/go-mnd v1.3.1-0.20200224220436-e6f9a994e8fa
|
||||
|
Loading…
x
Reference in New Issue
Block a user