diff --git a/README.md b/README.md index 07ac3f8..f8b6fef 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,8 @@ Represents | Style Grouping functions by [pkg, type]. (separate multiple by comma) -ignore string Ignore package paths with prefix. (separate multiple by comma) +-nostd + Omit calls from/to std packages. -minlen uint Minimum edge length (for wider output). (default: 2) -nodesep float @@ -125,12 +127,14 @@ Join [#go-callvis](https://gophers.slack.com/archives/go-callvis) channel at [go > *Not a member yet?* [Get invitation](https://gophersinvite.herokuapp.com). -### How to contribute +### How to help ###### Did you find any bugs or have some suggestions? - Feel free to open [new issue](https://github.com/TrueFurby/go-callvis/issues/new) or start discussion in the slack channel. +###### Do you want to contribute to the development? +Fork the project and do a pull request. [Here](https://github.com/TrueFurby/go-callvis/projects/1) you can find the state of features. + ### Known Issues ###### Each execution takes a lot of time, because currently: diff --git a/main.go b/main.go index e53a01e..4e674c9 100644 --- a/main.go +++ b/main.go @@ -24,6 +24,7 @@ var ( limitFlag = flag.String("limit", "", "Limit package paths to prefix. (separate multiple by comma)") groupFlag = flag.String("group", "", "Grouping functions by [pkg, type] (separate multiple by comma).") ignoreFlag = flag.String("ignore", "", "Ignore package paths with prefix (separate multiple by comma).") + nostdFlag = flag.Bool("nostd", false, "Omit calls to/from std packages.") testFlag = flag.Bool("tests", false, "Include test code.") debugFlag = flag.Bool("debug", false, "Enable verbose log.") versionFlag = flag.Bool("version", false, "Show version and exit.") @@ -73,13 +74,13 @@ func main() { } } - if err := run(&build.Default, *focusFlag, groupBy, limitPaths, ignorePaths, *testFlag, flag.Args()); err != nil { + if err := run(&build.Default, *focusFlag, groupBy, limitPaths, ignorePaths, *nostdFlag, *testFlag, flag.Args()); err != nil { fmt.Fprintf(os.Stderr, "go-callvis: %s\n", err) os.Exit(1) } } -func run(ctxt *build.Context, focus string, groupBy map[string]bool, limitPaths, ignorePaths []string, tests bool, args []string) error { +func run(ctxt *build.Context, focus string, groupBy map[string]bool, limitPaths, ignorePaths []string, nostd, tests bool, args []string) error { if len(args) == 0 { return fmt.Errorf("missing arguments") } @@ -162,7 +163,7 @@ func run(ctxt *build.Context, focus string, groupBy map[string]bool, limitPaths, logf("analysis took: %v", time.Since(t0)) return printOutput(mains[0].Pkg, result.CallGraph, - focusPkg, limitPaths, ignorePaths, groupBy) + focusPkg, limitPaths, ignorePaths, groupBy, nostd) } func logf(f string, a ...interface{}) { diff --git a/output.go b/output.go index 98e508d..e757b7c 100644 --- a/output.go +++ b/output.go @@ -14,7 +14,7 @@ import ( var output io.Writer = os.Stdout -func printOutput(mainPkg *types.Package, cg *callgraph.Graph, focusPkg *build.Package, limitPaths, ignorePaths []string, groupBy map[string]bool) error { +func printOutput(mainPkg *types.Package, cg *callgraph.Graph, focusPkg *build.Package, limitPaths, ignorePaths []string, groupBy map[string]bool, nostd bool) error { groupType := groupBy["type"] groupPkg := groupBy["pkg"] @@ -41,31 +41,37 @@ func printOutput(mainPkg *types.Package, cg *callgraph.Graph, focusPkg *build.Pa logf("%d limit prefixes: %v", len(limitPaths), limitPaths) logf("%d ignore prefixes: %v", len(ignorePaths), ignorePaths) + logf("no std packages: %v", nostd) - var inLimit = func(from, to *callgraph.Node) bool { - if len(limitPaths) == 0 { - return true - } - var fromOk, toOk bool - fromPath := from.Func.Pkg.Pkg.Path() - toPath := to.Func.Pkg.Pkg.Path() + var inLimit = func(node *callgraph.Node) bool { + pkgPath := node.Func.Pkg.Pkg.Path() for _, p := range limitPaths { - if strings.HasPrefix(fromPath, p) { - fromOk = true - } - if strings.HasPrefix(toPath, p) { - toOk = true + if strings.HasPrefix(pkgPath, p) { + return true } - if fromOk && toOk { - logf("in limit: %s -> %s", from, to) + } + return false + } + + var isIgnored = func(node *callgraph.Node) bool { + pkgPath := node.Func.Pkg.Pkg.Path() + for _, p := range ignorePaths { + if strings.HasPrefix(pkgPath, p) { return true } } - logf("NOT in limit: %s -> %s", from, to) return false } + var isStd = func(node *callgraph.Node) bool { + pkg, _ := build.Import(node.Func.Pkg.Pkg.Path(), "", 0) + return pkg.Goroot + } + + count := 0 err := callgraph.GraphVisitEdges(cg, func(edge *callgraph.Edge) error { + count++ + caller := edge.Caller callee := edge.Callee @@ -79,21 +85,26 @@ func printOutput(mainPkg *types.Package, cg *callgraph.Graph, focusPkg *build.Pa // focus specific pkg if focusPkg != nil && - !(callerPkg.Path() == focusPkg.ImportPath || calleePkg.Path() == focusPkg.ImportPath) { + (callerPkg.Path() != focusPkg.ImportPath && calleePkg.Path() != focusPkg.ImportPath) { return nil } // limit path prefixes - if !inLimit(caller, callee) { + if len(limitPaths) > 0 && + (!inLimit(caller) || !inLimit(callee)) { + logf("NOT in limit: %s -> %s", caller, callee) return nil } // ignore path prefixes - for _, p := range ignorePaths { - if strings.HasPrefix(callerPkg.Path(), p) || - strings.HasPrefix(calleePkg.Path(), p) { - return nil - } + if len(ignorePaths) > 0 && + (isIgnored(caller) || isIgnored(callee)) { + return nil + } + + // omit std + if nostd && (isStd(caller) || isStd(callee)) { + return nil } var sprintNode = func(node *callgraph.Node) *dotNode { @@ -261,7 +272,7 @@ func printOutput(mainPkg *types.Package, cg *callgraph.Graph, focusPkg *build.Pa return err } - logf("%d edges", len(edges)) + logf("%d/%d edges", len(edges), count) dot := &dotGraph{ Title: mainPkg.Path(),