Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ type analysis struct {
pkgs []*ssa.Package
mainPkg *ssa.Package
callgraph *callgraph.Graph
initial []*packages.Package
}

var Analysis *analysis
Expand All @@ -101,7 +102,7 @@ func (a *analysis) DoAnalysis(
defer logf("analysis done")

cfg := &packages.Config{
Mode: packages.LoadAllSyntax,
Mode: packages.LoadAllSyntax | packages.NeedModule,
Tests: tests,
Dir: dir,
BuildFlags: getBuildFlags(),
Expand Down Expand Up @@ -164,6 +165,7 @@ func (a *analysis) DoAnalysis(
a.pkgs = pkgs
a.mainPkg = mainPkg
a.callgraph = graph
a.initial = initial
return nil
}

Expand Down Expand Up @@ -235,6 +237,8 @@ func (a *analysis) OverrideByHTTP(r *http.Request) {
}
if std := r.FormValue("std"); std != "" {
a.opts.nostd = false
} else if nostd := r.FormValue("nostd"); nostd != "" {
a.opts.nostd = true
}
if inter := r.FormValue("nointer"); inter != "" {
a.opts.nointer = true
Expand Down Expand Up @@ -299,6 +303,7 @@ func (a *analysis) Render() ([]byte, error) {
}

dot, err := printOutput(
a.initial,
a.prog,
a.mainPkg,
a.callgraph,
Expand Down
10 changes: 5 additions & 5 deletions dot.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,18 +167,18 @@ func runDotToImageCallSystemGraphviz(outfname string, format string, dot []byte)
dotSystemBinary = dot
}

var img string
var path string
if outfname == "" {
img = filepath.Join(os.TempDir(), fmt.Sprintf("go-callvis_export.%s", format))
path = filepath.Join(os.TempDir(), fmt.Sprintf("go-callvis_export.%s", format))
} else {
img = fmt.Sprintf("%s.%s", outfname, format)
path = fmt.Sprintf("%s.%s", outfname, format)
}
cmd := exec.Command(dotSystemBinary, fmt.Sprintf("-T%s", format), "-o", img)
cmd := exec.Command(dotSystemBinary, fmt.Sprintf("-T%s", format), "-o", path)
cmd.Stdin = bytes.NewReader(dot)
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return "", fmt.Errorf("command '%v': %v\n%v", cmd, err, stderr.String())
}
return img, nil
return path, nil
}
11 changes: 5 additions & 6 deletions dot_cgo.go → graphviz_cgo.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

package main

Expand All @@ -26,14 +25,14 @@ func runDotToImage(outfname string, format string, dot []byte) (string, error) {
log.Printf("error closing graphviz: %v", err)
}
}()
var img string
var path string
if outfname == "" {
img = filepath.Join(os.TempDir(), fmt.Sprintf("go-callvis_export.%s", format))
path = filepath.Join(os.TempDir(), fmt.Sprintf("go-callvis_export.%s", format))
} else {
img = fmt.Sprintf("%s.%s", outfname, format)
path = fmt.Sprintf("%s.%s", outfname, format)
}
if err := g.RenderFilename(graph, graphviz.Format(format), img); err != nil {
if err := g.RenderFilename(graph, graphviz.Format(format), path); err != nil {
return "", err
}
return img, nil
return path, nil
}
1 change: 0 additions & 1 deletion dot_nocgo.go → graphviz_nocgo.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build !cgo
// +build !cgo

package main

Expand Down
16 changes: 14 additions & 2 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"log"
"net/http"
"strings"
"time"
)

func handler(w http.ResponseWriter, r *http.Request) {
Expand All @@ -13,10 +14,18 @@ func handler(w http.ResponseWriter, r *http.Request) {
return
}


logf("----------------------")
logf(" => handling request: %v", r.URL)
logf(" => handling request: %v %v", r.Method, r.URL)
logf("----------------------")

t0 := time.Now()
defer func() {
logf("----------------------")
logf(" -> request done (took %.3fs): %v", time.Since(t0).Round(time.Millisecond).Seconds(), r.URL)
logf("----------------------")
}()

// set up cmdline default for analysis
Analysis.OptsSetup()

Expand Down Expand Up @@ -49,13 +58,16 @@ func handler(w http.ResponseWriter, r *http.Request) {
}

log.Printf("converting dot to %s\n", *outputFormat)

t := time.Now()

img, err = dotToImage("", *outputFormat, output)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

log.Printf("conversion done (took %.3fs)", time.Since(t).Round(time.Millisecond).Seconds())

err = Analysis.CacheImg(img)
if err != nil {
http.Error(w, "cache img error: "+err.Error(), http.StatusBadRequest)
Expand Down
48 changes: 32 additions & 16 deletions output.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strings"

"golang.org/x/tools/go/callgraph"
"golang.org/x/tools/go/packages"
"golang.org/x/tools/go/ssa"
)

Expand All @@ -31,18 +32,27 @@ func isStdPkgPath(path string) bool {
return true
}

func printOutput(
prog *ssa.Program,
mainPkg *ssa.Package,
cg *callgraph.Graph,
focusPkg *types.Package,
limitPaths,
ignorePaths,
includePaths []string,
groupBy []string,
nostd,
nointer bool,
) ([]byte, error) {
func printOutput(initial []*packages.Package, prog *ssa.Program, mainPkg *ssa.Package, cg *callgraph.Graph, focusPkg *types.Package, limitPaths, ignorePaths, includePaths, groupBy []string, nostd, nointer bool, ) ([]byte, error) {
var initialPkg *packages.Package
for _, p := range initial {
if p.PkgPath == mainPkg.Pkg.Path() {
initialPkg = p
break
}
}
if initialPkg != nil {
logf("initial package: %+v, module: %+v", initialPkg, initialPkg.Module)
} else {
logf("initial package: NOT FOUND")
}

var modulePath string
if initialPkg != nil && initialPkg.Module != nil {
modulePath = initialPkg.Module.Path
} else {
split := strings.SplitN(mainPkg.Pkg.Path(), "/", 3)
modulePath = strings.Join(split[:2], "/")
}

logf("printing output for: %v", focusPkg)
logf("src dirs: %+v, default build context: %+v", build.Default.SrcDirs(), build.Default)
Expand Down Expand Up @@ -264,9 +274,11 @@ func printOutput(
if isFocused {
attrs["fillcolor"] = "lightblue"
} else if isStdPkg {
attrs["fillcolor"] = "#adedad"
attrs["fillcolor"] = "#bfffbf"
} else if strings.HasPrefix(pkgPath, modulePath) {
attrs["fillcolor"] = "#FFF9CA"
} else {
attrs["fillcolor"] = "moccasin"
attrs["fillcolor"] = "#fccfcf"
}

// include pkg name
Expand Down Expand Up @@ -303,7 +315,7 @@ func printOutput(
"fontsize": "16",
"label": label,
"style": "filled",
"fillcolor": "lightyellow",
"fillcolor": "mistyrose",
"URL": fmt.Sprintf("/?f=%s", key),
"fontname": "Tahoma bold",
"tooltip": fmt.Sprintf("package: %s", key),
Expand All @@ -312,6 +324,8 @@ func printOutput(
}
if isStdPkg {
c.Clusters[key].Attrs["fillcolor"] = "#E0FFE1"
} else if strings.HasPrefix(node.Func.Pkg.Pkg.Path(), modulePath) {
c.Clusters[key].Attrs["fillcolor"] = "lightyellow"
}
}
c = c.Clusters[key]
Expand All @@ -332,14 +346,16 @@ func printOutput(
"label": label,
"labelloc": "b",
"style": "rounded,filled",
"fillcolor": "wheat2",
"fillcolor": "#DCAFAF",
"tooltip": fmt.Sprintf("type: %s", key),
},
}
if isFocused {
c.Clusters[key].Attrs["fillcolor"] = "lightsteelblue"
} else if isStdPkg {
c.Clusters[key].Attrs["fillcolor"] = "#c2e3c2"
} else if strings.HasPrefix(node.Func.Pkg.Pkg.Path(), modulePath) {
c.Clusters[key].Attrs["fillcolor"] = "wheat2"
}
}
c = c.Clusters[key]
Expand Down
Loading