st1017.go raw
1 package st1017
2
3 import (
4 "go/ast"
5
6 "honnef.co/go/tools/analysis/code"
7 "honnef.co/go/tools/analysis/edit"
8 "honnef.co/go/tools/analysis/facts/generated"
9 "honnef.co/go/tools/analysis/lint"
10 "honnef.co/go/tools/analysis/report"
11 "honnef.co/go/tools/pattern"
12
13 "golang.org/x/tools/go/analysis"
14 "golang.org/x/tools/go/analysis/passes/inspect"
15 )
16
17 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
18 Analyzer: &analysis.Analyzer{
19 Name: "ST1017",
20 Run: run,
21 Requires: []*analysis.Analyzer{inspect.Analyzer, generated.Analyzer},
22 },
23 Doc: &lint.RawDocumentation{
24 Title: `Don't use Yoda conditions`,
25 Text: `Yoda conditions are conditions of the kind \"if 42 == x\", where the
26 literal is on the left side of the comparison. These are a common
27 idiom in languages in which assignment is an expression, to avoid bugs
28 of the kind \"if (x = 42)\". In Go, which doesn't allow for this kind of
29 bug, we prefer the more idiomatic \"if x == 42\".`,
30 Since: "2019.2",
31 MergeIf: lint.MergeIfAny,
32 },
33 })
34
35 var Analyzer = SCAnalyzer.Analyzer
36
37 var (
38 checkYodaConditionsQ = pattern.MustParse(`(BinaryExpr left@(TrulyConstantExpression _) tok@(Or "==" "!=") right@(Not (TrulyConstantExpression _)))`)
39 checkYodaConditionsR = pattern.MustParse(`(BinaryExpr right tok left)`)
40 )
41
42 func run(pass *analysis.Pass) (interface{}, error) {
43 fn := func(node ast.Node) {
44 if _, edits, ok := code.MatchAndEdit(pass, checkYodaConditionsQ, checkYodaConditionsR, node); ok {
45 report.Report(pass, node, "don't use Yoda conditions",
46 report.FilterGenerated(),
47 report.Fixes(edit.Fix("un-Yoda-fy", edits...)))
48 }
49 }
50 code.Preorder(pass, fn, (*ast.BinaryExpr)(nil))
51 return nil, nil
52 }
53