aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/tommy-muehle
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-07-04 11:12:55 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-07-04 15:05:30 +0200
commitc7d7f10bdff703e4a3c0414e8a33d4e45c91eb35 (patch)
tree0dff0ee1f98dbfa3ad8776112053a450d176592b /vendor/github.com/tommy-muehle
parent9573094ce235bd9afe88f5da27a47dd6bcc1e13b (diff)
go.mod: vendor golangci-lint
Diffstat (limited to 'vendor/github.com/tommy-muehle')
-rw-r--r--vendor/github.com/tommy-muehle/go-mnd/.editorconfig12
-rw-r--r--vendor/github.com/tommy-muehle/go-mnd/.gitignore2
-rw-r--r--vendor/github.com/tommy-muehle/go-mnd/.goreleaser.yml30
-rw-r--r--vendor/github.com/tommy-muehle/go-mnd/.travis.yml12
-rw-r--r--vendor/github.com/tommy-muehle/go-mnd/LICENSE21
-rw-r--r--vendor/github.com/tommy-muehle/go-mnd/README.md111
-rw-r--r--vendor/github.com/tommy-muehle/go-mnd/analyzer.go91
-rw-r--r--vendor/github.com/tommy-muehle/go-mnd/checks/argument.go107
-rw-r--r--vendor/github.com/tommy-muehle/go-mnd/checks/assign.go66
-rw-r--r--vendor/github.com/tommy-muehle/go-mnd/checks/case.go68
-rw-r--r--vendor/github.com/tommy-muehle/go-mnd/checks/checks.go3
-rw-r--r--vendor/github.com/tommy-muehle/go-mnd/checks/condition.go55
-rw-r--r--vendor/github.com/tommy-muehle/go-mnd/checks/operation.go73
-rw-r--r--vendor/github.com/tommy-muehle/go-mnd/checks/return.go50
-rw-r--r--vendor/github.com/tommy-muehle/go-mnd/config/config.go84
-rw-r--r--vendor/github.com/tommy-muehle/go-mnd/go.mod11
-rw-r--r--vendor/github.com/tommy-muehle/go-mnd/go.sum18
17 files changed, 814 insertions, 0 deletions
diff --git a/vendor/github.com/tommy-muehle/go-mnd/.editorconfig b/vendor/github.com/tommy-muehle/go-mnd/.editorconfig
new file mode 100644
index 000000000..316b8cae0
--- /dev/null
+++ b/vendor/github.com/tommy-muehle/go-mnd/.editorconfig
@@ -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 \ No newline at end of file
diff --git a/vendor/github.com/tommy-muehle/go-mnd/.gitignore b/vendor/github.com/tommy-muehle/go-mnd/.gitignore
new file mode 100644
index 000000000..edd9d60a7
--- /dev/null
+++ b/vendor/github.com/tommy-muehle/go-mnd/.gitignore
@@ -0,0 +1,2 @@
+build/
+dist/
diff --git a/vendor/github.com/tommy-muehle/go-mnd/.goreleaser.yml b/vendor/github.com/tommy-muehle/go-mnd/.goreleaser.yml
new file mode 100644
index 000000000..0986ff2f0
--- /dev/null
+++ b/vendor/github.com/tommy-muehle/go-mnd/.goreleaser.yml
@@ -0,0 +1,30 @@
+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}}`.
+
+archives:
+ -
+ format: tar.gz
+ format_overrides:
+ - goos: windows
+ format: zip
+
+brews:
+ -
+ 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"
diff --git a/vendor/github.com/tommy-muehle/go-mnd/.travis.yml b/vendor/github.com/tommy-muehle/go-mnd/.travis.yml
new file mode 100644
index 000000000..fd76a2fc6
--- /dev/null
+++ b/vendor/github.com/tommy-muehle/go-mnd/.travis.yml
@@ -0,0 +1,12 @@
+language: go
+
+go:
+ - 1.13.x
+ - 1.12.x
+ - tip
+
+script:
+ - go test -v ./...
+
+notifications:
+ email: false
diff --git a/vendor/github.com/tommy-muehle/go-mnd/LICENSE b/vendor/github.com/tommy-muehle/go-mnd/LICENSE
new file mode 100644
index 000000000..8825fad20
--- /dev/null
+++ b/vendor/github.com/tommy-muehle/go-mnd/LICENSE
@@ -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.
diff --git a/vendor/github.com/tommy-muehle/go-mnd/README.md b/vendor/github.com/tommy-muehle/go-mnd/README.md
new file mode 100644
index 000000000..a85ed780c
--- /dev/null
+++ b/vendor/github.com/tommy-muehle/go-mnd/README.md
@@ -0,0 +1,111 @@
+# 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
+
+[![Build Status](https://travis-ci.org/tommy-muehle/go-mnd.svg?branch=master)](https://travis-ci.org/tommy-muehle/go-mnd)
+[![Go Report Card](https://goreportcard.com/badge/github.com/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
+
+[![asciicast](https://asciinema.org/a/231021.svg)](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.
+
+The ```-ignored-numbers``` option let's you define a comma separated list of numbers to ignore.
+
+The ```-excludes``` option let's you define a comma separated list of regexp patterns to exclude.
+
+## 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
+```
+
+## Excludes
+
+By default the numbers 0 and 1 as well as test files are excluded!
+
+### Further known excludes
+
+The function "Date" in the "Time" package.
+
+```
+t := time.Date(2017, time.September, 26, 12, 13, 14, 0, time.UTC)
+```
+
+Additional custom excludes can be defined via option flag.
+
+## License
+
+The MIT License (MIT). Please see [LICENSE](LICENSE) for more information.
diff --git a/vendor/github.com/tommy-muehle/go-mnd/analyzer.go b/vendor/github.com/tommy-muehle/go-mnd/analyzer.go
new file mode 100644
index 000000000..9930170f2
--- /dev/null
+++ b/vendor/github.com/tommy-muehle/go-mnd/analyzer.go
@@ -0,0 +1,91 @@
+package magic_numbers
+
+import (
+ "flag"
+ "go/ast"
+
+ "github.com/tommy-muehle/go-mnd/checks"
+ "github.com/tommy-muehle/go-mnd/config"
+
+ "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("excludes", "", "comma separated list of patterns to exclude from analysis")
+ options.String("ignored-numbers", "", "comma separated list of numbers excluded from analysis")
+ options.String(
+ "checks",
+ checks.ArgumentCheck+","+
+ checks.CaseCheck+","+
+ checks.ConditionCheck+","+
+ checks.OperationCheck+","+
+ checks.ReturnCheck+","+
+ checks.AssignCheck,
+ "comma separated list of checks",
+ )
+
+ return *options
+}
+
+func run(pass *analysis.Pass) (interface{}, error) {
+ conf := config.WithOptions(
+ config.WithCustomChecks(pass.Analyzer.Flags.Lookup("checks").Value.String()),
+ config.WithExcludes(pass.Analyzer.Flags.Lookup("excludes").Value.String()),
+ config.WithIgnoredNumbers(pass.Analyzer.Flags.Lookup("ignored-numbers").Value.String()),
+ )
+
+ var checker []Checker
+ if conf.IsCheckEnabled(checks.ArgumentCheck) {
+ checker = append(checker, checks.NewArgumentAnalyzer(pass, conf))
+ }
+ if conf.IsCheckEnabled(checks.CaseCheck) {
+ checker = append(checker, checks.NewCaseAnalyzer(pass, conf))
+ }
+ if conf.IsCheckEnabled(checks.ConditionCheck) {
+ checker = append(checker, checks.NewConditionAnalyzer(pass, conf))
+ }
+ if conf.IsCheckEnabled(checks.OperationCheck) {
+ checker = append(checker, checks.NewOperationAnalyzer(pass, conf))
+ }
+ if conf.IsCheckEnabled(checks.ReturnCheck) {
+ checker = append(checker, checks.NewReturnAnalyzer(pass, conf))
+ }
+ if conf.IsCheckEnabled(checks.AssignCheck) {
+ checker = append(checker, checks.NewAssignAnalyzer(pass, conf))
+ }
+
+ i := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
+
+ for _, c := range checker {
+ i.Preorder(c.NodeFilter(), func(node ast.Node) {
+ for _, exclude := range conf.Excludes {
+ if exclude.MatchString(pass.Fset.Position(node.Pos()).Filename) {
+ return
+ }
+ }
+
+ c.Check(node)
+ })
+ }
+
+ return nil, nil
+}
diff --git a/vendor/github.com/tommy-muehle/go-mnd/checks/argument.go b/vendor/github.com/tommy-muehle/go-mnd/checks/argument.go
new file mode 100644
index 000000000..34cc1d09f
--- /dev/null
+++ b/vendor/github.com/tommy-muehle/go-mnd/checks/argument.go
@@ -0,0 +1,107 @@
+package checks
+
+import (
+ "go/ast"
+ "go/token"
+
+ "golang.org/x/tools/go/analysis"
+
+ config "github.com/tommy-muehle/go-mnd/config"
+)
+
+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 {
+ config *config.Config
+ pass *analysis.Pass
+}
+
+func NewArgumentAnalyzer(pass *analysis.Pass, config *config.Config) *ArgumentAnalyzer {
+ return &ArgumentAnalyzer{
+ pass: pass,
+ config: config,
+ }
+}
+
+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 !a.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 a.isMagicNumber(x) {
+ 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 a.isMagicNumber(x) {
+ a.pass.Reportf(x.Pos(), reportMsg, x.Value, ArgumentCheck)
+ }
+ }
+
+ switch y := expr.Y.(type) {
+ case *ast.BasicLit:
+ if a.isMagicNumber(y) {
+ a.pass.Reportf(y.Pos(), reportMsg, y.Value, ArgumentCheck)
+ }
+ }
+}
+
+func (a *ArgumentAnalyzer) isMagicNumber(l *ast.BasicLit) bool {
+ return (l.Kind == token.FLOAT || l.Kind == token.INT) && !a.config.IsIgnoredNumber(l.Value)
+}
diff --git a/vendor/github.com/tommy-muehle/go-mnd/checks/assign.go b/vendor/github.com/tommy-muehle/go-mnd/checks/assign.go
new file mode 100644
index 000000000..8699ce17f
--- /dev/null
+++ b/vendor/github.com/tommy-muehle/go-mnd/checks/assign.go
@@ -0,0 +1,66 @@
+package checks
+
+import (
+ "go/ast"
+ "go/token"
+
+ "golang.org/x/tools/go/analysis"
+
+ config "github.com/tommy-muehle/go-mnd/config"
+)
+
+const AssignCheck = "assign"
+
+type AssignAnalyzer struct {
+ pass *analysis.Pass
+ config *config.Config
+}
+
+func NewAssignAnalyzer(pass *analysis.Pass, config *config.Config) *AssignAnalyzer {
+ return &AssignAnalyzer{
+ pass: pass,
+ config: config,
+ }
+}
+
+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 a.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 a.isMagicNumber(x) {
+ a.pass.Reportf(x.Pos(), reportMsg, x.Value, AssignCheck)
+ }
+ }
+
+ switch y := expr.Y.(type) {
+ case *ast.BasicLit:
+ if a.isMagicNumber(y) {
+ a.pass.Reportf(y.Pos(), reportMsg, y.Value, AssignCheck)
+ }
+ }
+}
+
+func (a *AssignAnalyzer) isMagicNumber(l *ast.BasicLit) bool {
+ return (l.Kind == token.FLOAT || l.Kind == token.INT) && !a.config.IsIgnoredNumber(l.Value)
+}
diff --git a/vendor/github.com/tommy-muehle/go-mnd/checks/case.go b/vendor/github.com/tommy-muehle/go-mnd/checks/case.go
new file mode 100644
index 000000000..d7993ede0
--- /dev/null
+++ b/vendor/github.com/tommy-muehle/go-mnd/checks/case.go
@@ -0,0 +1,68 @@
+package checks
+
+import (
+ "go/ast"
+ "go/token"
+
+ "golang.org/x/tools/go/analysis"
+
+ config "github.com/tommy-muehle/go-mnd/config"
+)
+
+const CaseCheck = "case"
+
+type CaseAnalyzer struct {
+ pass *analysis.Pass
+ config *config.Config
+}
+
+func NewCaseAnalyzer(pass *analysis.Pass, config *config.Config) *CaseAnalyzer {
+ return &CaseAnalyzer{
+ pass: pass,
+ config: config,
+ }
+}
+
+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 a.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 a.isMagicNumber(x) {
+ a.pass.Reportf(x.Pos(), reportMsg, x.Value, CaseCheck)
+ }
+ }
+
+ switch y := expr.Y.(type) {
+ case *ast.BasicLit:
+ if a.isMagicNumber(y) {
+ a.pass.Reportf(y.Pos(), reportMsg, y.Value, CaseCheck)
+ }
+ }
+}
+
+func (a *CaseAnalyzer) isMagicNumber(l *ast.BasicLit) bool {
+ return (l.Kind == token.FLOAT || l.Kind == token.INT) && !a.config.IsIgnoredNumber(l.Value)
+}
diff --git a/vendor/github.com/tommy-muehle/go-mnd/checks/checks.go b/vendor/github.com/tommy-muehle/go-mnd/checks/checks.go
new file mode 100644
index 000000000..deff0c7bf
--- /dev/null
+++ b/vendor/github.com/tommy-muehle/go-mnd/checks/checks.go
@@ -0,0 +1,3 @@
+package checks
+
+const reportMsg = "Magic number: %v, in <%s> detected"
diff --git a/vendor/github.com/tommy-muehle/go-mnd/checks/condition.go b/vendor/github.com/tommy-muehle/go-mnd/checks/condition.go
new file mode 100644
index 000000000..b61bc0de9
--- /dev/null
+++ b/vendor/github.com/tommy-muehle/go-mnd/checks/condition.go
@@ -0,0 +1,55 @@
+package checks
+
+import (
+ "go/ast"
+ "go/token"
+
+ "golang.org/x/tools/go/analysis"
+
+ config "github.com/tommy-muehle/go-mnd/config"
+)
+
+const ConditionCheck = "condition"
+
+type ConditionAnalyzer struct {
+ pass *analysis.Pass
+ config *config.Config
+}
+
+func NewConditionAnalyzer(pass *analysis.Pass, config *config.Config) *ConditionAnalyzer {
+ return &ConditionAnalyzer{
+ pass: pass,
+ config: config,
+ }
+}
+
+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 a.isMagicNumber(x) {
+ a.pass.Reportf(x.Pos(), reportMsg, x.Value, ConditionCheck)
+ }
+ }
+
+ switch y := expr.Y.(type) {
+ case *ast.BasicLit:
+ if a.isMagicNumber(y) {
+ a.pass.Reportf(y.Pos(), reportMsg, y.Value, ConditionCheck)
+ }
+ }
+}
+
+func (a *ConditionAnalyzer) isMagicNumber(l *ast.BasicLit) bool {
+ return (l.Kind == token.FLOAT || l.Kind == token.INT) && !a.config.IsIgnoredNumber(l.Value)
+}
diff --git a/vendor/github.com/tommy-muehle/go-mnd/checks/operation.go b/vendor/github.com/tommy-muehle/go-mnd/checks/operation.go
new file mode 100644
index 000000000..f1f8cf445
--- /dev/null
+++ b/vendor/github.com/tommy-muehle/go-mnd/checks/operation.go
@@ -0,0 +1,73 @@
+package checks
+
+import (
+ "go/ast"
+ "go/token"
+
+ "golang.org/x/tools/go/analysis"
+
+ config "github.com/tommy-muehle/go-mnd/config"
+)
+
+const OperationCheck = "operation"
+
+type OperationAnalyzer struct {
+ pass *analysis.Pass
+ config *config.Config
+}
+
+func NewOperationAnalyzer(pass *analysis.Pass, config *config.Config) *OperationAnalyzer {
+ return &OperationAnalyzer{
+ pass: pass,
+ config: config,
+ }
+}
+
+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 a.isMagicNumber(x) {
+ a.pass.Reportf(x.Pos(), reportMsg, x.Value, OperationCheck)
+ }
+ }
+
+ switch y := expr.Y.(type) {
+ case *ast.BasicLit:
+ if a.isMagicNumber(y) {
+ a.pass.Reportf(y.Pos(), reportMsg, y.Value, OperationCheck)
+ }
+ }
+}
+
+func (a *OperationAnalyzer) isMagicNumber(l *ast.BasicLit) bool {
+ return (l.Kind == token.FLOAT || l.Kind == token.INT) && !a.config.IsIgnoredNumber(l.Value)
+}
diff --git a/vendor/github.com/tommy-muehle/go-mnd/checks/return.go b/vendor/github.com/tommy-muehle/go-mnd/checks/return.go
new file mode 100644
index 000000000..be7f54697
--- /dev/null
+++ b/vendor/github.com/tommy-muehle/go-mnd/checks/return.go
@@ -0,0 +1,50 @@
+package checks
+
+import (
+ "go/ast"
+ "go/token"
+
+ "golang.org/x/tools/go/analysis"
+
+ config "github.com/tommy-muehle/go-mnd/config"
+)
+
+const ReturnCheck = "return"
+
+type ReturnAnalyzer struct {
+ pass *analysis.Pass
+ config *config.Config
+}
+
+func NewReturnAnalyzer(pass *analysis.Pass, config *config.Config) *ReturnAnalyzer {
+ return &ReturnAnalyzer{
+ pass: pass,
+ config: config,
+ }
+}
+
+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 a.isMagicNumber(x) {
+ a.pass.Reportf(x.Pos(), reportMsg, x.Value, ReturnCheck)
+ }
+ }
+ }
+}
+
+func (a *ReturnAnalyzer) isMagicNumber(l *ast.BasicLit) bool {
+ return (l.Kind == token.FLOAT || l.Kind == token.INT) && !a.config.IsIgnoredNumber(l.Value)
+}
diff --git a/vendor/github.com/tommy-muehle/go-mnd/config/config.go b/vendor/github.com/tommy-muehle/go-mnd/config/config.go
new file mode 100644
index 000000000..35c82eaf2
--- /dev/null
+++ b/vendor/github.com/tommy-muehle/go-mnd/config/config.go
@@ -0,0 +1,84 @@
+package config
+
+import (
+ "regexp"
+ "strings"
+)
+
+type Config struct {
+ Checks map[string]bool
+ IgnoredNumbers map[string]struct{}
+ Excludes []*regexp.Regexp
+}
+
+type Option func(config *Config)
+
+func DefaultConfig() *Config {
+ return &Config{
+ Checks: map[string]bool{},
+ IgnoredNumbers: map[string]struct{}{
+ "0": {},
+ "1": {},
+ },
+ Excludes: []*regexp.Regexp{
+ regexp.MustCompile(`_test.go`),
+ },
+ }
+}
+
+func WithOptions(options ...Option) *Config {
+ c := DefaultConfig()
+ for _, option := range options {
+ option(c)
+ }
+ return c
+}
+
+func WithExcludes(excludes string) Option {
+ return func(config *Config) {
+ if excludes == "" {
+ return
+ }
+
+ for _, exclude := range strings.Split(excludes, ",") {
+ config.Excludes = append(config.Excludes, regexp.MustCompile(exclude))
+ }
+ }
+}
+
+func WithIgnoredNumbers(numbers string) Option {
+ return func(config *Config) {
+ if numbers == "" {
+ return
+ }
+
+ for _, number := range strings.Split(numbers, ",") {
+ config.IgnoredNumbers[number] = struct{}{}
+ }
+ }
+}
+
+func WithCustomChecks(checks string) Option {
+ return func(config *Config) {
+ if checks == "" {
+ return
+ }
+
+ for name, _ := range config.Checks {
+ 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]
+}
+
+func (c *Config) IsIgnoredNumber(number string) bool {
+ _, ok := c.IgnoredNumbers[number]
+ return ok
+}
diff --git a/vendor/github.com/tommy-muehle/go-mnd/go.mod b/vendor/github.com/tommy-muehle/go-mnd/go.mod
new file mode 100644
index 000000000..5119a7cc1
--- /dev/null
+++ b/vendor/github.com/tommy-muehle/go-mnd/go.mod
@@ -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
+)
diff --git a/vendor/github.com/tommy-muehle/go-mnd/go.sum b/vendor/github.com/tommy-muehle/go-mnd/go.sum
new file mode 100644
index 000000000..bdc021ab2
--- /dev/null
+++ b/vendor/github.com/tommy-muehle/go-mnd/go.sum
@@ -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=