Added go-mnd linter (#842)
* Initial commit * Fixed goimports * Update pkg/golinters/mnd.go Co-Authored-By: Bot from GolangCI <42910462+golangcibot@users.noreply.github.com> * Run goimports * Update pkg/golinters/mnd.go Co-Authored-By: Bot from GolangCI <42910462+golangcibot@users.noreply.github.com> * Add prefix for goimport local * Run make README.md * Incorporate review comments Add test cases * Update readme * Update the description * Removed subpath in local-prefixes * Update readme
This commit is contained in:
parent
0e5b7a04d5
commit
bd2921655a
@ -219,6 +219,7 @@ godox: Tool for detection of FIXME, TODO and other comment keywords [fast: true,
|
|||||||
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]
|
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]
|
goimports: Goimports does everything that gofmt does. Additionally it checks unused imports [fast: true, auto-fix: true]
|
||||||
golint: Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes [fast: true, auto-fix: false]
|
golint: Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes [fast: true, auto-fix: false]
|
||||||
|
gomnd: checks whether magic number is used [fast: true, auto-fix: false]
|
||||||
gosec (gas): Inspects source code for security problems [fast: true, auto-fix: false]
|
gosec (gas): Inspects source code for security problems [fast: true, auto-fix: false]
|
||||||
interfacer: Linter that suggests narrower interface types [fast: true, auto-fix: false]
|
interfacer: Linter that suggests narrower interface types [fast: true, auto-fix: false]
|
||||||
lll: Reports long lines [fast: true, auto-fix: false]
|
lll: Reports long lines [fast: true, auto-fix: false]
|
||||||
@ -480,6 +481,7 @@ golangci-lint help linters
|
|||||||
- [funlen](https://github.com/ultraware/funlen) - Tool for detection of long functions
|
- [funlen](https://github.com/ultraware/funlen) - Tool for detection of long functions
|
||||||
- [whitespace](https://github.com/ultraware/whitespace) - Tool for detection of leading and trailing whitespace
|
- [whitespace](https://github.com/ultraware/whitespace) - Tool for detection of leading and trailing whitespace
|
||||||
- [wsl](https://github.com/bombsimon/wsl) - Whitespace Linter - Forces you to use empty lines!
|
- [wsl](https://github.com/bombsimon/wsl) - Whitespace Linter - Forces you to use empty lines!
|
||||||
|
- [gomnd](https://github.com/tommy-muehle/go-mnd) - checks whether magic number is used
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
@ -1165,6 +1167,7 @@ Thanks to developers and authors of used linters:
|
|||||||
- [matoous](https://github.com/matoous)
|
- [matoous](https://github.com/matoous)
|
||||||
- [ultraware](https://github.com/ultraware)
|
- [ultraware](https://github.com/ultraware)
|
||||||
- [bombsimon](https://github.com/bombsimon)
|
- [bombsimon](https://github.com/bombsimon)
|
||||||
|
- [tommy-muehle](https://github.com/tommy-muehle)
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
1
go.mod
1
go.mod
@ -37,6 +37,7 @@ require (
|
|||||||
github.com/spf13/viper v1.4.0
|
github.com/spf13/viper v1.4.0
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e
|
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e
|
||||||
|
github.com/tommy-muehle/go-mnd v0.0.0-20190903201840-c93e405da530
|
||||||
github.com/ultraware/funlen v0.0.2
|
github.com/ultraware/funlen v0.0.2
|
||||||
github.com/ultraware/whitespace v0.0.4
|
github.com/ultraware/whitespace v0.0.4
|
||||||
github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517
|
github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517
|
||||||
|
2
go.sum
2
go.sum
@ -232,6 +232,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
|||||||
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e h1:RumXZ56IrCj4CL+g1b9OL/oH0QnsF976bC8xQFYUD5Q=
|
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/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=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
|
github.com/tommy-muehle/go-mnd v0.0.0-20190903201840-c93e405da530 h1:uUctDnVK0uevT4yglJXAXDG74EkQvGdu6L1pSoZx+T4=
|
||||||
|
github.com/tommy-muehle/go-mnd v0.0.0-20190903201840-c93e405da530/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig=
|
||||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||||
github.com/ultraware/funlen v0.0.2 h1:Av96YVBwwNSe4MLR7iI/BIa3VyI7/djnto/pK3Uxbdo=
|
github.com/ultraware/funlen v0.0.2 h1:Av96YVBwwNSe4MLR7iI/BIa3VyI7/djnto/pK3Uxbdo=
|
||||||
|
21
pkg/golinters/gomnd.go
Normal file
21
pkg/golinters/gomnd.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package golinters
|
||||||
|
|
||||||
|
import (
|
||||||
|
magic_numbers "github.com/tommy-muehle/go-mnd"
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
|
||||||
|
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewGomnd() *goanalysis.Linter {
|
||||||
|
analyzers := []*analysis.Analyzer{
|
||||||
|
magic_numbers.Analyzer,
|
||||||
|
}
|
||||||
|
|
||||||
|
return goanalysis.NewLinter(
|
||||||
|
"gomnd",
|
||||||
|
"checks whether magic number is used",
|
||||||
|
analyzers,
|
||||||
|
nil,
|
||||||
|
).WithLoadMode(goanalysis.LoadModeSyntax)
|
||||||
|
}
|
@ -208,6 +208,9 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
|
|||||||
linter.NewConfig(golinters.NewWSL()).
|
linter.NewConfig(golinters.NewWSL()).
|
||||||
WithPresets(linter.PresetStyle).
|
WithPresets(linter.PresetStyle).
|
||||||
WithURL("https://github.com/bombsimon/wsl"),
|
WithURL("https://github.com/bombsimon/wsl"),
|
||||||
|
linter.NewConfig(golinters.NewGomnd()).
|
||||||
|
WithPresets(linter.PresetStyle).
|
||||||
|
WithURL("https://github.com/tommy-muehle/go-mnd"),
|
||||||
}
|
}
|
||||||
|
|
||||||
isLocalRun := os.Getenv("GOLANGCI_COM_RUN") == ""
|
isLocalRun := os.Getenv("GOLANGCI_COM_RUN") == ""
|
||||||
|
36
test/testdata/gomnd.go
vendored
Normal file
36
test/testdata/gomnd.go
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
//args: -Egomnd
|
||||||
|
package testdata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func UseMagicNumber() {
|
||||||
|
c := &http.Client{
|
||||||
|
Timeout: 1 * time.Second, // ERROR : "Magic number: 1, in <assign> detected"
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := c.Get("http://www.google.com")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if res.StatusCode != 200 { // ERROR : "Magic number: 200, in <condition> detected"
|
||||||
|
log.Println("Something went wrong")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func UseNoMagicNumber() {
|
||||||
|
c := &http.Client{
|
||||||
|
Timeout: time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := c.Get("http://www.google.com")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if res.StatusCode != http.StatusOK {
|
||||||
|
log.Println("Something went wrong")
|
||||||
|
}
|
||||||
|
}
|
12
vendor/github.com/tommy-muehle/go-mnd/.editorconfig
generated
vendored
Normal file
12
vendor/github.com/tommy-muehle/go-mnd/.editorconfig
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
2
vendor/github.com/tommy-muehle/go-mnd/.gitignore
generated
vendored
Normal file
2
vendor/github.com/tommy-muehle/go-mnd/.gitignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
build/
|
||||||
|
dist/
|
28
vendor/github.com/tommy-muehle/go-mnd/.goreleaser.yml
generated
vendored
Normal file
28
vendor/github.com/tommy-muehle/go-mnd/.goreleaser.yml
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
builds:
|
||||||
|
-
|
||||||
|
main: ./cmd/mnd/main.go
|
||||||
|
binary: mnd
|
||||||
|
goos:
|
||||||
|
- windows
|
||||||
|
- darwin
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
ldflags: -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.buildTime={{.Date}}`.
|
||||||
|
|
||||||
|
archive:
|
||||||
|
format: tar.gz
|
||||||
|
format_overrides:
|
||||||
|
- goos: windows
|
||||||
|
format: zip
|
||||||
|
|
||||||
|
brew:
|
||||||
|
name: mnd
|
||||||
|
github:
|
||||||
|
owner: tommy-muehle
|
||||||
|
name: homebrew-tap
|
||||||
|
folder: Formula
|
||||||
|
homepage: https://github.com/tommy-muehle/go-mnd
|
||||||
|
description: Magic number detector for Go
|
||||||
|
test: |
|
||||||
|
system "#{bin}/mnd --version"
|
8
vendor/github.com/tommy-muehle/go-mnd/.travis.yml
generated
vendored
Normal file
8
vendor/github.com/tommy-muehle/go-mnd/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.12.x
|
||||||
|
- tip
|
||||||
|
|
||||||
|
script:
|
||||||
|
- go test -v ./...
|
21
vendor/github.com/tommy-muehle/go-mnd/LICENSE
generated
vendored
Normal file
21
vendor/github.com/tommy-muehle/go-mnd/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2019 Tommy Muehle
|
||||||
|
|
||||||
|
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.
|
97
vendor/github.com/tommy-muehle/go-mnd/README.md
generated
vendored
Normal file
97
vendor/github.com/tommy-muehle/go-mnd/README.md
generated
vendored
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
# go-mnd - Magic number detector for Golang
|
||||||
|
|
||||||
|
A vet analyzer to detect magic numbers.
|
||||||
|
|
||||||
|
> **What is a magic number?**
|
||||||
|
> A magic number is a numeric literal that is not defined as a constant, but which may change, and therefore can be hard to update. It's considered a bad programming practice to use numbers directly in any source code without an explanation. It makes programs harder to read, understand, and maintain.
|
||||||
|
|
||||||
|
## Project status
|
||||||
|
|
||||||
|
[](https://travis-ci.org/tommy-muehle/go-mnd)
|
||||||
|
[](https://goreportcard.com/report/github.com/tommy-muehle/go-mnd)
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
This analyzer requires Golang in version >= 1.12 because it's depends on the **go/analysis** API.
|
||||||
|
|
||||||
|
```
|
||||||
|
go get github.com/tommy-muehle/go-mnd/cmd/mnd
|
||||||
|
```
|
||||||
|
|
||||||
|
To install with [Homebrew](https://brew.sh/), run:
|
||||||
|
|
||||||
|
```
|
||||||
|
brew tap tommy-muehle/tap && brew install tommy-muehle/tap/mnd
|
||||||
|
```
|
||||||
|
|
||||||
|
On Windows download the [latest release](https://github.com/tommy-muehle/go-mnd/releases).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
[](https://asciinema.org/a/231021)
|
||||||
|
|
||||||
|
```
|
||||||
|
go vet -vettool $(which mnd) ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
or directly
|
||||||
|
|
||||||
|
```
|
||||||
|
mnd ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
The ```-checks``` option let's you define a comma separated list of checks.
|
||||||
|
|
||||||
|
## Checks
|
||||||
|
|
||||||
|
By default this detector analyses arguments, assigns, cases, conditions, operations and return statements.
|
||||||
|
|
||||||
|
* argument
|
||||||
|
|
||||||
|
```
|
||||||
|
t := http.StatusText(200)
|
||||||
|
```
|
||||||
|
|
||||||
|
* assign
|
||||||
|
|
||||||
|
```
|
||||||
|
c := &http.Client{
|
||||||
|
Timeout: 5 * time.Second,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
* case
|
||||||
|
|
||||||
|
```
|
||||||
|
switch x {
|
||||||
|
case 3:
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
* condition
|
||||||
|
|
||||||
|
```
|
||||||
|
if x > 7 {
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
* operation
|
||||||
|
|
||||||
|
```
|
||||||
|
var x, y int
|
||||||
|
y = 10 * x
|
||||||
|
```
|
||||||
|
|
||||||
|
* return
|
||||||
|
|
||||||
|
```
|
||||||
|
return 3
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notices
|
||||||
|
|
||||||
|
By default the number 0 is excluded!
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
The MIT License (MIT). Please see [LICENSE](LICENSE) for more information.
|
71
vendor/github.com/tommy-muehle/go-mnd/analyzer.go
generated
vendored
Normal file
71
vendor/github.com/tommy-muehle/go-mnd/analyzer.go
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package magic_numbers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"go/ast"
|
||||||
|
|
||||||
|
"github.com/tommy-muehle/go-mnd/checks"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
|
)
|
||||||
|
|
||||||
|
const Doc = `magic number detector`
|
||||||
|
|
||||||
|
var Analyzer = &analysis.Analyzer{
|
||||||
|
Name: "mnd",
|
||||||
|
Doc: Doc,
|
||||||
|
Run: run,
|
||||||
|
Flags: options(),
|
||||||
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
|
RunDespiteErrors: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Checker interface {
|
||||||
|
NodeFilter() []ast.Node
|
||||||
|
Check(n ast.Node)
|
||||||
|
}
|
||||||
|
|
||||||
|
func options() flag.FlagSet {
|
||||||
|
options := flag.NewFlagSet("", flag.ExitOnError)
|
||||||
|
options.String("checks", "", "comma separated list of checks")
|
||||||
|
|
||||||
|
return *options
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(pass *analysis.Pass) (interface{}, error) {
|
||||||
|
config := WithOptions(
|
||||||
|
WithCustomChecks(pass.Analyzer.Flags.Lookup("checks").Value.String()),
|
||||||
|
)
|
||||||
|
|
||||||
|
var checker []Checker
|
||||||
|
if config.IsCheckEnabled(checks.ArgumentCheck) {
|
||||||
|
checker = append(checker, checks.NewArgumentAnalyzer(pass))
|
||||||
|
}
|
||||||
|
if config.IsCheckEnabled(checks.CaseCheck) {
|
||||||
|
checker = append(checker, checks.NewCaseAnalyzer(pass))
|
||||||
|
}
|
||||||
|
if config.IsCheckEnabled(checks.ConditionCheck) {
|
||||||
|
checker = append(checker, checks.NewConditionAnalyzer(pass))
|
||||||
|
}
|
||||||
|
if config.IsCheckEnabled(checks.OperationCheck) {
|
||||||
|
checker = append(checker, checks.NewOperationAnalyzer(pass))
|
||||||
|
}
|
||||||
|
if config.IsCheckEnabled(checks.ReturnCheck) {
|
||||||
|
checker = append(checker, checks.NewReturnAnalyzer(pass))
|
||||||
|
}
|
||||||
|
if config.IsCheckEnabled(checks.AssignCheck) {
|
||||||
|
checker = append(checker, checks.NewAssignAnalyzer(pass))
|
||||||
|
}
|
||||||
|
|
||||||
|
i := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||||
|
|
||||||
|
for _, c := range checker {
|
||||||
|
i.Preorder(c.NodeFilter(), func(node ast.Node) {
|
||||||
|
c.Check(node)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
98
vendor/github.com/tommy-muehle/go-mnd/checks/argument.go
generated
vendored
Normal file
98
vendor/github.com/tommy-muehle/go-mnd/checks/argument.go
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
package checks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ArgumentCheck = "argument"
|
||||||
|
|
||||||
|
// Known excludes for the argument check.
|
||||||
|
var argumentExcludes = map[string]string{
|
||||||
|
// package: function
|
||||||
|
"time": "Date", // https://golang.org/pkg/time/#Date
|
||||||
|
}
|
||||||
|
|
||||||
|
type ArgumentAnalyzer struct {
|
||||||
|
pass *analysis.Pass
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewArgumentAnalyzer(pass *analysis.Pass) *ArgumentAnalyzer {
|
||||||
|
return &ArgumentAnalyzer{
|
||||||
|
pass: pass,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ArgumentAnalyzer) NodeFilter() []ast.Node {
|
||||||
|
return []ast.Node{
|
||||||
|
(*ast.CallExpr)(nil),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ArgumentAnalyzer) Check(n ast.Node) {
|
||||||
|
expr, ok := n.(*ast.CallExpr)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't check if package and function combination is excluded
|
||||||
|
if s, ok := expr.Fun.(*ast.SelectorExpr); ok && a.isExcluded(s) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, arg := range expr.Args {
|
||||||
|
switch x := arg.(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
if !isMagicNumber(x) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// If it's a magic number and has no previous element, report it
|
||||||
|
if i == 0 {
|
||||||
|
a.pass.Reportf(x.Pos(), reportMsg, x.Value, ArgumentCheck)
|
||||||
|
} else {
|
||||||
|
// Otherwise check the previous element type
|
||||||
|
switch expr.Args[i-1].(type) {
|
||||||
|
case *ast.ChanType:
|
||||||
|
// When it's not a simple buffered channel, report it
|
||||||
|
if x.Value != "1" {
|
||||||
|
a.pass.Reportf(x.Pos(), reportMsg, x.Value, ArgumentCheck)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case *ast.BinaryExpr:
|
||||||
|
a.checkBinaryExpr(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ArgumentAnalyzer) isExcluded(expr *ast.SelectorExpr) bool {
|
||||||
|
var p string
|
||||||
|
|
||||||
|
switch x := expr.X.(type) {
|
||||||
|
case *ast.Ident:
|
||||||
|
p = x.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := argumentExcludes[p]; ok && v == expr.Sel.Name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ArgumentAnalyzer) checkBinaryExpr(expr *ast.BinaryExpr) {
|
||||||
|
switch x := expr.X.(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
if isMagicNumber(x) {
|
||||||
|
a.pass.Reportf(x.Pos(), reportMsg, x.Value, ArgumentCheck)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch y := expr.Y.(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
if isMagicNumber(y) {
|
||||||
|
a.pass.Reportf(y.Pos(), reportMsg, y.Value, ArgumentCheck)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
57
vendor/github.com/tommy-muehle/go-mnd/checks/assign.go
generated
vendored
Normal file
57
vendor/github.com/tommy-muehle/go-mnd/checks/assign.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package checks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
)
|
||||||
|
|
||||||
|
const AssignCheck = "assign"
|
||||||
|
|
||||||
|
type AssignAnalyzer struct {
|
||||||
|
pass *analysis.Pass
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAssignAnalyzer(pass *analysis.Pass) *AssignAnalyzer {
|
||||||
|
return &AssignAnalyzer{
|
||||||
|
pass: pass,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AssignAnalyzer) NodeFilter() []ast.Node {
|
||||||
|
return []ast.Node{
|
||||||
|
(*ast.KeyValueExpr)(nil),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AssignAnalyzer) Check(n ast.Node) {
|
||||||
|
expr, ok := n.(*ast.KeyValueExpr)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch x := expr.Value.(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
if isMagicNumber(x) {
|
||||||
|
a.pass.Reportf(x.Pos(), reportMsg, x.Value, AssignCheck)
|
||||||
|
}
|
||||||
|
case *ast.BinaryExpr:
|
||||||
|
a.checkBinaryExpr(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AssignAnalyzer) checkBinaryExpr(expr *ast.BinaryExpr) {
|
||||||
|
switch x := expr.X.(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
if isMagicNumber(x) {
|
||||||
|
a.pass.Reportf(x.Pos(), reportMsg, x.Value, AssignCheck)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch y := expr.Y.(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
if isMagicNumber(y) {
|
||||||
|
a.pass.Reportf(y.Pos(), reportMsg, y.Value, AssignCheck)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
59
vendor/github.com/tommy-muehle/go-mnd/checks/case.go
generated
vendored
Normal file
59
vendor/github.com/tommy-muehle/go-mnd/checks/case.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package checks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
)
|
||||||
|
|
||||||
|
const CaseCheck = "case"
|
||||||
|
|
||||||
|
type CaseAnalyzer struct {
|
||||||
|
pass *analysis.Pass
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCaseAnalyzer(pass *analysis.Pass) *CaseAnalyzer {
|
||||||
|
return &CaseAnalyzer{
|
||||||
|
pass: pass,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *CaseAnalyzer) NodeFilter() []ast.Node {
|
||||||
|
return []ast.Node{
|
||||||
|
(*ast.CaseClause)(nil),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *CaseAnalyzer) Check(n ast.Node) {
|
||||||
|
caseClause, ok := n.(*ast.CaseClause)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range caseClause.List {
|
||||||
|
switch x := c.(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
if isMagicNumber(x) {
|
||||||
|
a.pass.Reportf(x.Pos(), reportMsg, x.Value, CaseCheck)
|
||||||
|
}
|
||||||
|
case *ast.BinaryExpr:
|
||||||
|
a.checkBinaryExpr(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *CaseAnalyzer) checkBinaryExpr(expr *ast.BinaryExpr) {
|
||||||
|
switch x := expr.X.(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
if isMagicNumber(x) {
|
||||||
|
a.pass.Reportf(x.Pos(), reportMsg, x.Value, CaseCheck)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch y := expr.Y.(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
if isMagicNumber(y) {
|
||||||
|
a.pass.Reportf(y.Pos(), reportMsg, y.Value, CaseCheck)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
vendor/github.com/tommy-muehle/go-mnd/checks/checks.go
generated
vendored
Normal file
12
vendor/github.com/tommy-muehle/go-mnd/checks/checks.go
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package checks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"go/token"
|
||||||
|
)
|
||||||
|
|
||||||
|
const reportMsg = "Magic number: %v, in <%s> detected"
|
||||||
|
|
||||||
|
func isMagicNumber(l *ast.BasicLit) bool {
|
||||||
|
return (l.Kind == token.FLOAT || l.Kind == token.INT) && l.Value != "0"
|
||||||
|
}
|
46
vendor/github.com/tommy-muehle/go-mnd/checks/condition.go
generated
vendored
Normal file
46
vendor/github.com/tommy-muehle/go-mnd/checks/condition.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package checks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ConditionCheck = "condition"
|
||||||
|
|
||||||
|
type ConditionAnalyzer struct {
|
||||||
|
pass *analysis.Pass
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConditionAnalyzer(pass *analysis.Pass) *ConditionAnalyzer {
|
||||||
|
return &ConditionAnalyzer{
|
||||||
|
pass: pass,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ConditionAnalyzer) NodeFilter() []ast.Node {
|
||||||
|
return []ast.Node{
|
||||||
|
(*ast.IfStmt)(nil),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ConditionAnalyzer) Check(n ast.Node) {
|
||||||
|
expr, ok := n.(*ast.IfStmt).Cond.(*ast.BinaryExpr)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch x := expr.X.(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
if isMagicNumber(x) {
|
||||||
|
a.pass.Reportf(x.Pos(), reportMsg, x.Value, ConditionCheck)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch y := expr.Y.(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
if isMagicNumber(y) {
|
||||||
|
a.pass.Reportf(y.Pos(), reportMsg, y.Value, ConditionCheck)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
64
vendor/github.com/tommy-muehle/go-mnd/checks/operation.go
generated
vendored
Normal file
64
vendor/github.com/tommy-muehle/go-mnd/checks/operation.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package checks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
)
|
||||||
|
|
||||||
|
const OperationCheck = "operation"
|
||||||
|
|
||||||
|
type OperationAnalyzer struct {
|
||||||
|
pass *analysis.Pass
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOperationAnalyzer(pass *analysis.Pass) *OperationAnalyzer {
|
||||||
|
return &OperationAnalyzer{
|
||||||
|
pass: pass,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *OperationAnalyzer) NodeFilter() []ast.Node {
|
||||||
|
return []ast.Node{
|
||||||
|
(*ast.AssignStmt)(nil),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *OperationAnalyzer) Check(n ast.Node) {
|
||||||
|
stmt, ok := n.(*ast.AssignStmt)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, expr := range stmt.Rhs {
|
||||||
|
switch x := expr.(type) {
|
||||||
|
case *ast.BinaryExpr:
|
||||||
|
switch xExpr := x.X.(type) {
|
||||||
|
case *ast.BinaryExpr:
|
||||||
|
a.checkBinaryExpr(xExpr)
|
||||||
|
}
|
||||||
|
switch yExpr := x.Y.(type) {
|
||||||
|
case *ast.BinaryExpr:
|
||||||
|
a.checkBinaryExpr(yExpr)
|
||||||
|
}
|
||||||
|
|
||||||
|
a.checkBinaryExpr(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *OperationAnalyzer) checkBinaryExpr(expr *ast.BinaryExpr) {
|
||||||
|
switch x := expr.X.(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
if isMagicNumber(x) {
|
||||||
|
a.pass.Reportf(x.Pos(), reportMsg, x.Value, OperationCheck)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch y := expr.Y.(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
if isMagicNumber(y) {
|
||||||
|
a.pass.Reportf(y.Pos(), reportMsg, y.Value, OperationCheck)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
41
vendor/github.com/tommy-muehle/go-mnd/checks/return.go
generated
vendored
Normal file
41
vendor/github.com/tommy-muehle/go-mnd/checks/return.go
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package checks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ReturnCheck = "return"
|
||||||
|
|
||||||
|
type ReturnAnalyzer struct {
|
||||||
|
pass *analysis.Pass
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewReturnAnalyzer(pass *analysis.Pass) *ReturnAnalyzer {
|
||||||
|
return &ReturnAnalyzer{
|
||||||
|
pass: pass,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ReturnAnalyzer) NodeFilter() []ast.Node {
|
||||||
|
return []ast.Node{
|
||||||
|
(*ast.ReturnStmt)(nil),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ReturnAnalyzer) Check(n ast.Node) {
|
||||||
|
stmt, ok := n.(*ast.ReturnStmt)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, expr := range stmt.Results {
|
||||||
|
switch x := expr.(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
if isMagicNumber(x) {
|
||||||
|
a.pass.Reportf(x.Pos(), reportMsg, x.Value, ReturnCheck)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
vendor/github.com/tommy-muehle/go-mnd/config.go
generated
vendored
Normal file
58
vendor/github.com/tommy-muehle/go-mnd/config.go
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package magic_numbers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/tommy-muehle/go-mnd/checks"
|
||||||
|
)
|
||||||
|
|
||||||
|
var knownChecks = map[string]bool{
|
||||||
|
checks.ArgumentCheck: true,
|
||||||
|
checks.CaseCheck: true,
|
||||||
|
checks.ConditionCheck: true,
|
||||||
|
checks.OperationCheck: true,
|
||||||
|
checks.ReturnCheck: true,
|
||||||
|
checks.AssignCheck: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Checks map[string]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Option func(config *Config)
|
||||||
|
|
||||||
|
func DefaultConfig() *Config {
|
||||||
|
return &Config{
|
||||||
|
Checks: knownChecks,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithOptions(options ...Option) *Config {
|
||||||
|
c := DefaultConfig()
|
||||||
|
for _, option := range options {
|
||||||
|
option(c)
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithCustomChecks(checks string) Option {
|
||||||
|
return func(config *Config) {
|
||||||
|
config.Checks = knownChecks
|
||||||
|
|
||||||
|
if checks == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, _ := range knownChecks {
|
||||||
|
config.Checks[name] = false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, name := range strings.Split(checks, ",") {
|
||||||
|
config.Checks[name] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) IsCheckEnabled(name string) bool {
|
||||||
|
return c.Checks[name]
|
||||||
|
}
|
11
vendor/github.com/tommy-muehle/go-mnd/go.mod
generated
vendored
Normal file
11
vendor/github.com/tommy-muehle/go-mnd/go.mod
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
module github.com/tommy-muehle/go-mnd
|
||||||
|
|
||||||
|
go 1.12
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/stretchr/objx v0.1.1 // indirect
|
||||||
|
github.com/stretchr/testify v1.3.0
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect
|
||||||
|
golang.org/x/tools v0.0.0-20190221204921-83362c3779f5
|
||||||
|
)
|
18
vendor/github.com/tommy-muehle/go-mnd/go.sum
generated
vendored
Normal file
18
vendor/github.com/tommy-muehle/go-mnd/go.sum
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190221204921-83362c3779f5 h1:ev5exjGDsOo0NPTB0qdCcE53BfWl1IICJlhgXgfT9fM=
|
||||||
|
golang.org/x/tools v0.0.0-20190221204921-83362c3779f5/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
3
vendor/modules.txt
vendored
3
vendor/modules.txt
vendored
@ -170,6 +170,9 @@ github.com/stretchr/testify/mock
|
|||||||
github.com/stretchr/testify/require
|
github.com/stretchr/testify/require
|
||||||
# github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e
|
# github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e
|
||||||
github.com/timakin/bodyclose/passes/bodyclose
|
github.com/timakin/bodyclose/passes/bodyclose
|
||||||
|
# github.com/tommy-muehle/go-mnd v0.0.0-20190903201840-c93e405da530
|
||||||
|
github.com/tommy-muehle/go-mnd
|
||||||
|
github.com/tommy-muehle/go-mnd/checks
|
||||||
# github.com/ultraware/funlen v0.0.2
|
# github.com/ultraware/funlen v0.0.2
|
||||||
github.com/ultraware/funlen
|
github.com/ultraware/funlen
|
||||||
# github.com/ultraware/whitespace v0.0.4
|
# github.com/ultraware/whitespace v0.0.4
|
||||||
|
Loading…
x
Reference in New Issue
Block a user