Last active
March 1, 2018 17:50
-
-
Save mantyr/036e8aca6cb0fdfaea49d801d37a13bd to your computer and use it in GitHub Desktop.
Выводим входные и выходные параметры
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/parser" | |
| "go/token" | |
| "go/ast" | |
| "os" | |
| "log" | |
| ) | |
| func main() { | |
| err := PrintFuncs("./testdata") | |
| if err != nil { | |
| log.Fatalf("print func params error: %v", err) | |
| } | |
| } | |
| // PrintFuncParams печатает список функций и параметров | |
| func PrintFuncs(path string) error { | |
| fset := token.NewFileSet() | |
| pkgs, err := parser.ParseDir(fset, path, filter, parser.AllErrors) | |
| if err != nil { | |
| return err | |
| } | |
| for _, pack := range pkgs { | |
| for _, file := range pack.Files { | |
| for _, decl := range file.Decls { | |
| switch t := decl.(type) { | |
| case *ast.FuncDecl: | |
| position := fset.Position(t.Type.Func) | |
| fmt.Printf("%s:%d func %s\r\n", position.Filename, position.Line, t.Name) | |
| fmt.Printf("params: \r\n") | |
| for _, f := range t.Type.Params.List { | |
| switch { | |
| case f.Tag != nil: | |
| fmt.Printf(" %s %s `%s`\r\n", f.Names[0], f.Type, f.Tag) | |
| default: | |
| fmt.Printf(" %T\r\n", f) | |
| fmt.Printf(" %s %s\r\n", f.Names[0], f.Type) | |
| } | |
| } | |
| fmt.Printf("results: \r\n") | |
| for _, f := range t.Type.Results.List { | |
| switch { | |
| case f.Tag != nil: | |
| fmt.Printf(" %s %s `%s`\r\n", f.Names[0], f.Type, f.Tag) | |
| default: | |
| switch t := f.Type.(type) { | |
| case *ast.StarExpr: | |
| switch str := t.X.(type) { | |
| case *ast.Ident: | |
| position := fset.Position(str.NamePos) | |
| fmt.Printf(" %s:%d %s\r\n", position.Filename, position.Line, str.Name) | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| return nil | |
| } | |
| func filter(os.FileInfo) bool { | |
| return true | |
| } |
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/parser" | |
| "go/token" | |
| "go/ast" | |
| "os" | |
| "log" | |
| ) | |
| func main() { | |
| err := PrintFuncs("./testdata") | |
| if err != nil { | |
| log.Fatalf("print func params error: %v", err) | |
| } | |
| } | |
| // PrintFuncParams печатает список функций и параметров | |
| func PrintFuncs(path string) error { | |
| fset := token.NewFileSet() | |
| pkgs, err := parser.ParseDir(fset, path, filter, parser.AllErrors) | |
| if err != nil { | |
| return err | |
| } | |
| for _, pack := range pkgs { | |
| for _, file := range pack.Files { | |
| for _, decl := range file.Decls { | |
| switch t := decl.(type) { | |
| case *ast.FuncDecl: | |
| PrintFunction(fset, t) | |
| } | |
| } | |
| } | |
| } | |
| return nil | |
| } | |
| func filter(os.FileInfo) bool { | |
| return true | |
| } | |
| func PrintFunction( | |
| fset *token.FileSet, | |
| f *ast.FuncDecl, | |
| ) { | |
| pos := fset.Position(f.Type.Func) | |
| fmt.Printf("address: %s:%d\r\n", pos.Filename, pos.Line) | |
| fmt.Printf("func name: %s\r\n", f.Name) | |
| fmt.Println("params:") | |
| for _, param := range f.Type.Params.List { | |
| PrintParam(param) | |
| } | |
| fmt.Println("results:") | |
| for _, param := range f.Type.Results.List { | |
| PrintResult(fset, param) | |
| } | |
| } | |
| func PrintParam(param *ast.Field) { | |
| if param.Tag != nil { | |
| fmt.Printf( | |
| " %s %s `%s`\r\n", | |
| param.Names[0], | |
| param.Type, | |
| param.Tag, | |
| ) | |
| return | |
| } | |
| fmt.Printf( | |
| " %s %s\r\n", | |
| param.Names[0], | |
| param.Type, | |
| ) | |
| } | |
| func PrintResult(fset *token.FileSet, param *ast.Field) { | |
| switch t := param.Type.(type) { | |
| case *ast.StarExpr: | |
| switch str := t.X.(type) { | |
| case *ast.Ident: | |
| pos := fset.Position(str.NamePos) | |
| fmt.Printf( | |
| " %s:%d %s\r\n", | |
| pos.Filename, | |
| pos.Line, | |
| str.Name, | |
| ) | |
| } | |
| } | |
| } |
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 example | |
| // Struct это структура с данными | |
| type Struct struct { | |
| Name string | |
| } | |
| // New возвращает ссылку на новую структуру | |
| // здесь должен сработать линтер на отсутствие err последним элементом | |
| func New(name string) *Struct { | |
| return &Struct{ | |
| Name: name, | |
| } | |
| } |
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/parser" | |
| "go/token" | |
| "go/ast" | |
| "os" | |
| "log" | |
| ) | |
| func main() { | |
| fset := token.NewFileSet() | |
| pkgs, err := parser.ParseDir(fset, "./testdata/", filter, parser.ParseComments) | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| for _, pack := range pkgs { | |
| for _, file := range pack.Files { | |
| for _, decl := range file.Decls { | |
| switch t := decl.(type) { | |
| case *ast.FuncDecl: | |
| if t.Recv == nil { | |
| PrintFunction(fset, t) | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| func filter(os.FileInfo) bool { | |
| return true | |
| } | |
| func PrintFunction( | |
| fset *token.FileSet, | |
| f *ast.FuncDecl, | |
| ) { | |
| if len(f.Type.Results.List) == 0 { | |
| return | |
| } | |
| param := f.Type.Results.List[len(f.Type.Results.List)-1] | |
| pos := fset.Position(f.Type.Func) | |
| fmt.Println(f.Doc.Text()) | |
| ident, err := Ident(param.Type) | |
| if err != nil { | |
| fmt.Printf( | |
| "%s:%d unexpected output parameter error: %v\r\n", | |
| pos.Filename, | |
| pos.Line, | |
| err, | |
| ) | |
| return | |
| } | |
| if ident.Name != "error" { | |
| fmt.Printf( | |
| "%s:%d last output parameter in func %s() is not an error but actual %s\r\n", | |
| pos.Filename, | |
| pos.Line, | |
| f.Name, | |
| ident.Name, | |
| ) | |
| } | |
| } | |
| // Ident возвращает Ident параметра если таковой есть | |
| func Ident(param interface{}) (*ast.Ident, error) { | |
| switch t := param.(type) { | |
| case *ast.Ident: | |
| return t, nil | |
| case *ast.StarExpr: | |
| return Ident(t.X) | |
| } | |
| return nil, fmt.Errorf( | |
| "expected ast.Ident or ast.StarExpt but actual %T", | |
| param, | |
| ) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment