/
main.go
96 lines (87 loc) · 2.31 KB
/
main.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package main
import (
"exp/types"
"fmt"
"go/ast"
"go/parser"
"go/token"
"os"
)
// Conversion between ast.Visitor and the simpler type func(ast.Node) (bool).
type SimpleVisitor struct {
pack *ast.Package
fset *token.FileSet
}
// Returns itself if 'visitFunc' returns true - otherwise returns nil.
func (v SimpleVisitor) Visit(node ast.Node) ast.Visitor {
switch a := node.(type) {
case *ast.ExprStmt:
//fmt.Printf("%#v\n",a.X.(*ast.CallExpr).Fun.(*ast.SelectorExpr).X)
switch b := a.X.(*ast.CallExpr).Fun.(type){
case *ast.Ident:
ident:=v.pack.Scope.Lookup(b.Name)
//fmt.Printf("%#v", ident)
if ident != nil && ident.Decl.(*ast.FuncDecl).Type.Results != nil{
fmt.Println(ident.Name," has unassigned return values",v.fset.Position(ident.Pos()))
}
case *ast.SelectorExpr:
X := a.X.(*ast.CallExpr).Fun.(*ast.SelectorExpr).X.(*ast.Ident).Name
I := a.X.(*ast.CallExpr).Fun.(*ast.SelectorExpr).Sel.Name
//fmt.Println(X+"."+I)
f := v.pack.Imports[X].Data.(*ast.Scope).Lookup(I)
//fmt.Printf("%#v\n",v.pack.Scope.Objects)
//fmt.Printf("%#v\n",f)
if f != nil && f.Type.(*types.Func).Results != nil{
fmt.Println(X+"."+I," has unassigned return values",v.fset.Position(a.Pos()))
}
}
}
return v
}
func main() {
fset := token.NewFileSet()
files := map[string]*ast.File{}
for _,f := range os.Args[1:] {
file, err := parser.ParseFile(fset, f, nil, 0)
if err != nil {
panic("parse file:" + err.Error())
}
files[f] = file
}
pack, err := ast.NewPackage(fset, files, types.GcImporter, types.Universe)
if err != nil {
panic("new package" + err.Error())
}
/*for name, object := range pack.Scope.Objects {
if f, ok := object.Decl.(*ast.FuncDecl); ok {
if f.Type.Results == nil {
continue
}
for _, returnValue := range f.Type.Results.List {
if returnValue.Type.(*ast.Ident).Name == "error" {
fmt.Println(name, ": function returns error")
}
}
}
}*/
//check that the file is valid
/*valid := true
ast.Walk(visitor(func(node ast.Node) bool {
switch node.(type) {
case *ast.BadDecl,
*ast.BadExpr,
*ast.BadStmt:
valid = false
return false
}
return true
}), pack)
if !valid {
panic("invalid file")
}*/
ast.Walk(SimpleVisitor{pack,fset},pack)
}
/*
find all function calls
check return values against assignment
*/