forked from skelterjohn/MarGo
/
ac_lint.go
82 lines (72 loc) · 1.61 KB
/
ac_lint.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package main
import (
"go/ast"
"go/parser"
"go/scanner"
"go/token"
)
type AcLintArgs struct {
Fn string `json:"fn"`
Src string `json:"src"`
}
type AcLintReport struct {
Row int `json:"row"`
Col int `json:"col"`
Msg string `json:"msg"`
}
func init() {
act(Action{
Path: "/lint",
Doc: ``,
Func: func(r Request) (data, error) {
a := AcLintArgs{}
res := make([]AcLintReport, 0)
if err := r.Decode(&a); err != nil {
return res, err
}
fset, af, err := parseAstFile(a.Fn, a.Src, parser.DeclarationErrors)
if err == nil {
res = lintCheckFlagParse(fset, af, res)
} else if el, ok := err.(scanner.ErrorList); ok {
for _, e := range el {
res = append(res, AcLintReport{
Row: e.Pos.Line - 1,
Col: e.Pos.Column - 1,
Msg: e.Msg,
})
}
}
return res, nil
},
})
}
func lintCheckFlagParse(fset *token.FileSet, af *ast.File, res []AcLintReport) []AcLintReport {
reps := []AcLintReport{}
foundParse := false
ast.Inspect(af, func(node ast.Node) bool {
switch c := node.(type) {
case *ast.CallExpr:
if sel, ok := c.Fun.(*ast.SelectorExpr); ok {
if id, ok := sel.X.(*ast.Ident); ok && id.Name == "flag" {
if sel.Sel.String() == "Parse" {
foundParse = true
} else if !foundParse && c != nil {
tp := fset.Position(c.Pos())
if tp.IsValid() {
reps = append(reps, AcLintReport{
Row: tp.Line - 1,
Col: tp.Column - 1,
Msg: "Cannot find corresponding call to flag.Parse()",
})
}
}
}
}
}
return !foundParse
})
if !foundParse {
res = append(res, reps...)
}
return res
}