Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issues with latest Go and generics #202

Merged
merged 10 commits into from
Jan 1, 2025
Merged
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
9 changes: 4 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ name: CI

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
schedule:
- cron: '0 */12 * * *'
- cron: '0 3 * * *'

jobs:
build-test:
Expand All @@ -15,14 +14,14 @@ jobs:
strategy:
fail-fast: false
matrix:
go: [ '1.20', '1.19' ]
go: [ 'stable', 'oldstable', '1.21' ]

steps:
- name: "Checkout"
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: "Setup Go ${{ matrix.go }}"
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}

Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ _testmain.go
# Builds
/.build/
go-callvis

# IDE
/.idea/
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ help:
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

build: ## Build go-callvis
go build -tags $(GO_BUILD_TAGS) -ldflags "$(GO_LDFLAGS)" $(GO_BUILD_ARGS)
go build -v -tags $(GO_BUILD_TAGS) -ldflags "$(GO_LDFLAGS)" $(GO_BUILD_ARGS)

test: ## Run unit tests
go test -tags $(GO_BUILD_TAGS) -ldflags "$(GO_LDFLAGS)" $(GO_BUILD_ARGS) -short -race ./...
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ Usage of go-callvis:
a list of build tags to consider satisfied during the build. For more information about build tags, see the description of build constraints in the documentation for the go/build package
-tests
Include test code.
-algo string
Use specific algorithm for package analyzer: static, cha or rta (default "static")
-version
Show version and exit.
```
Expand Down
63 changes: 29 additions & 34 deletions analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,33 @@ import (
"fmt"
"go/build"
"go/types"
"golang.org/x/tools/go/callgraph"
"golang.org/x/tools/go/callgraph/cha"
"golang.org/x/tools/go/callgraph/rta"
"golang.org/x/tools/go/callgraph/static"
"io"
"log"
"net/http"
"os"
"path/filepath"
"strings"
"time"

"golang.org/x/tools/go/callgraph"
"golang.org/x/tools/go/callgraph/cha"
"golang.org/x/tools/go/callgraph/rta"
"golang.org/x/tools/go/callgraph/static"

"golang.org/x/tools/go/packages"
"golang.org/x/tools/go/pointer"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/ssautil"
)

type CallGraphType string

const (
CallGraphTypeStatic CallGraphType = "static"
CallGraphTypeCha = "cha"
CallGraphTypeRta = "rta"
CallGraphTypePointer = "pointer"
CallGraphTypeStatic CallGraphType = "static"
CallGraphTypeCha CallGraphType = "cha"
CallGraphTypeRta CallGraphType = "rta"
)

//==[ type def/func: analysis ]===============================================
// ==[ type def/func: analysis ]===============================================
type renderOpts struct {
cacheDir string
focus string
Expand Down Expand Up @@ -80,7 +80,7 @@ func initFuncs(pkgs []*ssa.Package) ([]*ssa.Function, error) {
return inits, nil
}

//==[ type def/func: analysis ]===============================================
// ==[ type def/func: analysis ]===============================================
type analysis struct {
opts *renderOpts
prog *ssa.Program
Expand All @@ -97,30 +97,35 @@ func (a *analysis) DoAnalysis(
tests bool,
args []string,
) error {
logf("begin analysis")
defer logf("analysis done")

cfg := &packages.Config{
Mode: packages.LoadAllSyntax,
Tests: tests,
Dir: dir,
BuildFlags: getBuildFlags(),
}

logf("loading packages")

initial, err := packages.Load(cfg, args...)
if err != nil {
return err
}

if packages.PrintErrors(initial) > 0 {
return fmt.Errorf("packages contain errors")
}

logf("loaded %d initial packages, building program", len(initial))

// Create and build SSA-form program representation.
mode := ssa.BuilderMode(0)
if algo == CallGraphTypeRta {
mode = ssa.InstantiateGenerics
}
mode := ssa.InstantiateGenerics
prog, pkgs := ssautil.AllPackages(initial, mode)
prog.Build()

logf("build done, computing callgraph (algo: %v)", algo)

var graph *callgraph.Graph
var mainPkg *ssa.Package

Expand All @@ -139,7 +144,7 @@ func (a *analysis) DoAnalysis(
for _, main := range mains {
roots = append(roots, main.Func("main"))
}

inits, err := initFuncs(prog.AllPackages())
if err != nil {
return err
Expand All @@ -149,26 +154,11 @@ func (a *analysis) DoAnalysis(
}

graph = rta.Analyze(roots, true).CallGraph
case CallGraphTypePointer:
mains, err := mainPackages(prog.AllPackages())
if err != nil {
return err
}
mainPkg = mains[0]
config := &pointer.Config{
Mains: mains,
BuildCallGraph: true,
}
ptares, err := pointer.Analyze(config)
if err != nil {
return err
}
graph = ptares.CallGraph
default:
return fmt.Errorf("invalid call graph type: %s", a.opts.algo)
}

//cg.DeleteSyntheticNodes()
logf("callgraph resolved with %d nodes", len(graph.Nodes))

a.prog = prog
a.pkgs = pkgs
Expand Down Expand Up @@ -276,6 +266,9 @@ func (a *analysis) Render() ([]byte, error) {
focusPkg *types.Package
)

start := time.Now()
logf("begin rendering")

if a.opts.focus != "" {
if ssaPkg = a.prog.ImportedPackage(a.opts.focus); ssaPkg == nil {
if strings.Contains(a.opts.focus, "/") {
Expand All @@ -302,7 +295,7 @@ func (a *analysis) Render() ([]byte, error) {
}
}
focusPkg = ssaPkg.Pkg
logf("focusing: %v", focusPkg.Path())
logf("focusing package: %v (path: %v)", focusPkg.Name(), focusPkg.Path())
}

dot, err := printOutput(
Expand All @@ -321,6 +314,8 @@ func (a *analysis) Render() ([]byte, error) {
return nil, fmt.Errorf("processing failed: %v", err)
}

logf("rendering done (took %v sec)", time.Since(start).Round(time.Millisecond).Seconds())

return dot, nil
}

Expand Down
Loading
Loading