Files
gocp/tool_find_symbols.go

101 lines
2.3 KiB
Go
Raw Permalink Normal View History

package main
import (
"go/ast"
"go/token"
"strings"
)
type Symbol struct {
Name string `json:"name"`
Type string `json:"type"`
Package string `json:"package"`
Exported bool `json:"exported"`
Position Position `json:"position"`
}
func findSymbols(dir string, pattern string) ([]Symbol, error) {
var symbols []Symbol
err := walkGoFiles(dir, func(path string, src []byte, file *ast.File, fset *token.FileSet) error {
if strings.HasSuffix(path, "_test.go") && !strings.Contains(pattern, "Test") {
return nil
}
pkgName := file.Name.Name
ast.Inspect(file, func(n ast.Node) bool {
switch decl := n.(type) {
case *ast.FuncDecl:
name := decl.Name.Name
if matchesPattern(name, pattern) {
pos := fset.Position(decl.Pos())
symbols = append(symbols, Symbol{
Name: name,
Type: "function",
Package: pkgName,
Exported: ast.IsExported(name),
Position: newPosition(pos),
})
}
case *ast.GenDecl:
for _, spec := range decl.Specs {
switch s := spec.(type) {
case *ast.TypeSpec:
name := s.Name.Name
if matchesPattern(name, pattern) {
pos := fset.Position(s.Pos())
kind := "type"
switch s.Type.(type) {
case *ast.InterfaceType:
kind = "interface"
case *ast.StructType:
kind = "struct"
}
symbols = append(symbols, Symbol{
Name: name,
Type: kind,
Package: pkgName,
Exported: ast.IsExported(name),
Position: newPosition(pos),
})
}
case *ast.ValueSpec:
for _, name := range s.Names {
if matchesPattern(name.Name, pattern) {
pos := fset.Position(name.Pos())
kind := "variable"
if decl.Tok == token.CONST {
kind = "constant"
}
symbols = append(symbols, Symbol{
Name: name.Name,
Type: kind,
Package: pkgName,
Exported: ast.IsExported(name.Name),
Position: newPosition(pos),
})
}
}
}
}
}
return true
})
return nil
})
return symbols, err
}
func matchesPattern(name, pattern string) bool {
if pattern == "" {
return true
}
pattern = strings.ToLower(pattern)
name = strings.ToLower(name)
return strings.Contains(name, pattern)
}