ast_inspect.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. package main
  2. import (
  3. "fmt"
  4. "go/ast"
  5. "go/build"
  6. "go/parser"
  7. "go/token"
  8. "path/filepath"
  9. "github.com/pkg/errors"
  10. )
  11. var (
  12. _defaultFileFilter = FilterOnlyCodeFile
  13. _errors = make([]string, 0)
  14. _warns = make([]string, 0)
  15. )
  16. // AstInspect .
  17. func AstInspect(dir string) (err error) {
  18. var (
  19. files []*ast.File
  20. fset *token.FileSet
  21. )
  22. if dir, err = filepath.Abs(dir); err != nil {
  23. err = errors.WithStack(err)
  24. return
  25. }
  26. if files, fset, err = parsePackageFiles(dir); err != nil {
  27. return
  28. }
  29. for _, f := range files {
  30. handler := defaultNodeHandler(f, dir, fset)
  31. ast.Inspect(f, handler)
  32. }
  33. return
  34. }
  35. func defaultNodeHandler(f *ast.File, dir string, fileset *token.FileSet) func(ast.Node) bool {
  36. return func(node ast.Node) bool {
  37. if node == nil {
  38. return false
  39. }
  40. for _, l := range _lints {
  41. if !l.fn(dir, f, node) {
  42. switch l.s.l {
  43. case "e":
  44. _errors = append(_errors, fmt.Sprintf("%s --> %s", fileset.PositionFor(node.Pos(), true), l.s.d))
  45. case "w":
  46. _warns = append(_warns, fmt.Sprintf("%s --> %s", fileset.PositionFor(node.Pos(), true), l.s.d))
  47. }
  48. }
  49. }
  50. return true
  51. }
  52. }
  53. func parsePackageFilesByPath(dir string, importPath string) (files []*ast.File, fset *token.FileSet, err error) {
  54. var pkg *build.Package
  55. if pkg, err = build.Import(importPath, dir, build.FindOnly); err != nil {
  56. return
  57. }
  58. return parsePackageFiles(pkg.Dir)
  59. }
  60. func parsePackageFiles(absDir string) (files []*ast.File, fset *token.FileSet, err error) {
  61. var ok bool
  62. if files, fset, ok = packageCache(absDir); ok {
  63. return
  64. }
  65. defer func() {
  66. setPackageCache(absDir, fset, files)
  67. }()
  68. fset = token.NewFileSet()
  69. var (
  70. pkgMap map[string]*ast.Package
  71. )
  72. if pkgMap, err = parser.ParseDir(fset, absDir, _defaultFileFilter, parser.ParseComments); err != nil {
  73. err = errors.WithStack(err)
  74. return
  75. }
  76. for _, v := range pkgMap {
  77. for _, f := range v.Files {
  78. files = append(files, f)
  79. }
  80. }
  81. return
  82. }