Last active
October 26, 2018 14:21
-
-
Save tenntenn/607e27638a3ec850c9a7c2dec334b5b7 to your computer and use it in GitHub Desktop.
具象のerrorを返してるかチェックする
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"go/ast" | |
"go/importer" | |
"go/parser" | |
"go/token" | |
"go/types" | |
"os" | |
) | |
func run(files []string) error { | |
fset := token.NewFileSet() | |
fs := make([]*ast.File, 0, len(files)) | |
for _, fname := range files { | |
f, err := parser.ParseFile(fset, fname, nil, 0) | |
if err != nil { | |
return err | |
} | |
fs = append(fs, f) | |
} | |
config := types.Config{ | |
Importer: importer.Default(), | |
} | |
info := &types.Info{ | |
Uses: map[*ast.Ident]types.Object{}, | |
} | |
if _, err := config.Check("main", fset, fs, info); err != nil { | |
return err | |
} | |
errTyp := types.Universe.Lookup("error").Type().Underlying().(*types.Interface) | |
for _, f := range fs { | |
ast.Inspect(f, func(n ast.Node) bool { | |
switch n := n.(type) { | |
case *ast.FuncType: | |
if n.Results == nil { | |
return false | |
} | |
for _, r := range n.Results.List { | |
ident, ok := r.Type.(*ast.Ident) | |
if !ok { | |
continue | |
} | |
o := info.Uses[ident] | |
if o == nil { | |
continue | |
} | |
if t := o.Type(); !types.Identical(t.Underlying(), errTyp) && | |
types.Implements(t, errTyp) { | |
fmt.Println(fset.Position(ident.Pos())) | |
} | |
} | |
} | |
return true | |
}) | |
} | |
return nil | |
} | |
func main() { | |
if err := run(os.Args[1:]); err != nil { | |
fmt.Fprintln(os.Stderr, "Error:", err) | |
os.Exit(1) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import "fmt" | |
type Err string | |
func (err Err) Error() string { | |
return string(err) | |
} | |
func f() Err { | |
return Err("error") | |
} | |
func main() { | |
fmt.Println(f()) | |
fmt.Println(func() Err { | |
return Err("error2") | |
}) | |
fmt.Println(func() error { | |
return nil | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ちなみに、このパターンが検出漏れます
https://play.golang.org/p/f4YWYYmVFb