diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 18b7b73..d024a08 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - go: [ '1.20', '1.19' ] + go: [ '1.22' ] steps: - name: "Checkout" diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000..7e0d6ce --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,11 @@ +{ + "line-length": false, + "MD033": { + "allowed_elements": [ + "a", + "p", + "img", + "h1" + ] + } +} diff --git a/README.md b/README.md index d8c7068..8ac0187 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +# README +

gopher

go-callvis

@@ -9,14 +11,14 @@ Slack channel

-

go-callvis is a development tool to help visualize call graph of a Go program using interactive view.

+

**go-callvis** is a development tool to help visualize call graph of a Go program using interactive view.

--- ## Introduction -The purpose of this tool is to provide developers with a visual overview of a Go program using data from call graph -and its relations with packages and types. This is especially useful in larger projects where the complexity of +The purpose of this tool is to provide developers with a visual overview of a Go program using data from call graph +and its relations with packages and types. This is especially useful in larger projects where the complexity of the code much higher or when you are just simply trying to understand code of somebody else. ### Features @@ -37,7 +39,7 @@ the code much higher or when you are just simply trying to understand code of so ### How it works -It runs [pointer analysis](https://godoc.org/golang.org/x/tools/go/pointer) to construct the call graph of the program and +It runs [pointer analysis](https://godoc.org/golang.org/x/tools/go/pointer) to construct the call graph of the program and uses the data to generate output in [dot format](http://www.graphviz.org/content/dot-language), which can be rendered with Graphviz tools. ## Quick start @@ -76,7 +78,7 @@ make install To use the interactive view provided by a web server that serves SVG images of focused packages, you can simply run: -`go-callvis ` +`go-callvis ` HTTP server is listening on [http://localhost:7878/](http://localhost:7878/) by default, use option `-http="ADDR:PORT"` to change HTTP server address. @@ -88,48 +90,50 @@ The output format defaults to `svg`, use option `-format=` to p #### Options -``` +```sh Usage of go-callvis: -debug - Enable verbose log. + Enable verbose log. -file string - output filename - omit to use server mode + output filename - omit to use server mode -cacheDir string - Enable caching to avoid unnecessary re-rendering. + Enable caching to avoid unnecessary re-rendering. -focus string - Focus specific package using name or import path. (default "main") + Focus specific package using name or import path. (default "main") -format string - output file format [svg | png | jpg | ...] (default "svg") + output file format [svg | png | jpg | ...] (default "svg") -graphviz - Use Graphviz's dot program to render images. + Use Graphviz's dot program to render images. -group string - Grouping functions by packages and/or types [pkg, type] (separated by comma) (default "pkg") + Grouping functions by packages and/or types [pkg, type] (separated by comma) (default "pkg") -http string - HTTP service address. (default ":7878") + HTTP service address. (default ":7878") -ignore string - Ignore package paths containing given prefixes (separated by comma) + Ignore package paths containing given prefixes (separated by comma) -include string - Include package paths with given prefixes (separated by comma) + Include package paths with given prefixes (separated by comma) -limit string - Limit package paths to given prefixes (separated by comma) + Limit package paths to given prefixes (separated by comma) -minlen uint - Minimum edge length (for wider output). (default 2) + Minimum edge length (for wider output). (default 2) -nodesep float - Minimum space between two adjacent nodes in the same rank (for taller output). (default 0.35) + Minimum space between two adjacent nodes in the same rank (for taller output). (default 0.35) -nointer - Omit calls to unexported functions. + Omit calls to unexported functions. -nostd - Omit calls to/from packages in standard library. + Omit calls to/from packages in standard library. -rankdir - Direction of graph layout [LR | RL | TB | BT] (default "LR") + Direction of graph layout [LR | RL | TB | BT] (default "LR") -skipbrowser - Skip opening browser. + Skip opening browser. -tags build tags - 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 + 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. + Include test code. + -algo string + Use specific algorithm for package analyzer: static, cha or rta (default "static") -version - Show version and exit. + Show version and exit. ``` Run `go-callvis -h` to list all supported options. @@ -181,15 +185,17 @@ Join [#go-callvis](https://gophers.slack.com/archives/go-callvis) channel at [go ### How to help Did you find any bugs or have some suggestions? + - Feel free to open [new issue](https://github.com/ofabry/go-callvis/issues/new) or start discussion in the slack channel. Do you want to contribute to the project? + - Fork the repository and open a pull request. [Here](https://github.com/ofabry/go-callvis/projects/1) you can find TODO features. --- #### Roadmap -##### The *interactive tool* described below has been published as a *separate project* called [goexplorer](https://github.com/ofabry/goexplorer)! +##### The *interactive tool* described below has been published as a *separate project* called [goexplorer](https://github.com/ofabry/goexplorer) > Ideal goal of this project is to make web app that would locally store the call graph data and then provide quick access of the call graphs for any package of your dependency tree. At first it would show an interactive map of overall dependencies between packages and then by selecting particular package it would show the call graph and provide various options to alter the output dynamically. diff --git a/analysis.go b/analysis.go index 1ca13d0..318485a 100644 --- a/analysis.go +++ b/analysis.go @@ -5,10 +5,6 @@ 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" @@ -16,8 +12,13 @@ import ( "path/filepath" "strings" + "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" ) @@ -25,13 +26,12 @@ import ( 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 @@ -60,7 +60,7 @@ func mainPackages(pkgs []*ssa.Package) ([]*ssa.Package, error) { return mains, nil } -//==[ type def/func: analysis ]=============================================== +// ==[ type def/func: analysis ]=============================================== type analysis struct { opts *renderOpts prog *ssa.Program @@ -116,21 +116,6 @@ func (a *analysis) DoAnalysis( roots = append(roots, main.Func("main")) } 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) } @@ -231,7 +216,7 @@ func (a *analysis) OverrideByHTTP(r *http.Request) { if inc := r.FormValue("include"); inc != "" { a.opts.include[0] = inc } - return + //return } // basically do printOutput() with previously checking diff --git a/examples/README.md b/examples/README.md index cdfdff6..ab10c6a 100644 --- a/examples/README.md +++ b/examples/README.md @@ -2,11 +2,11 @@ This document contains examples of various projects from Github. -#### Projects - - [Syncthing](https://github.com/syncthing/syncthing) - - [Docker](https://github.com/docker/docker) - - [Travis CI Worker](https://github.com/travis-ci/worker) +## Projects +- [Syncthing](https://github.com/syncthing/syncthing) +- [Docker](https://github.com/docker/docker) +- [Travis CI Worker](https://github.com/travis-ci/worker) ## Syncthing @@ -20,7 +20,8 @@ cd $GOPATH/src/github.com/syncthing/syncthing ./build.sh ``` -# Generate graph and launch webserver +## Generate graph and launch webserver + ```sh go-callvis -focus upgrade -group pkg,type -limit github.com/syncthing/syncthing -ignore github.com/syncthing/syncthing/lib/logger github.com/syncthing/syncthing/cmd/syncthing ``` @@ -34,26 +35,31 @@ go-callvis -focus upgrade -group pkg,type -limit github.com/syncthing/syncthing ```sh go-callvis -format=png -file=syncthing_focus -focus upgrade -limit github.com/syncthing/syncthing github.com/syncthing/syncthing/cmd/syncthing ``` + --- ### Grouping by _packages_ [![syncthing example output pkg](../images/syncthing_group.png)](https://raw.githubusercontent.com/ofabry/go-callvis/master/images/syncthing_group.png) -# Generate graph focused on module 'upgrade', output to PNG file +## Generate graph focused on module 'upgrade', output to PNG file + ```sh go-callvis -format=png -file=syncthing_group -focus upgrade -group pkg -limit github.com/syncthing/syncthing github.com/syncthing/syncthing/cmd/syncthing ``` + --- ### Ignoring package _logger_ [![syncthing example output ignore](../images/syncthing_ignore.png)](https://raw.githubusercontent.com/ofabry/go-callvis/master/images/syncthing_ignore.png) -# Generate graph focused on module 'upgrade' and ignoring 'logger', output to webserver +## Generate graph focused on module 'upgrade' and ignoring 'logger', output to webserver + ```sh go-callvis -focus upgrade -group pkg -ignore github.com/syncthing/syncthing/lib/logger -limit github.com/syncthing/syncthing github.com/syncthing/syncthing/cmd/syncthing ``` + --- ## Docker @@ -63,6 +69,7 @@ go-callvis -focus upgrade -group pkg -ignore github.com/syncthing/syncthing/lib/ ```sh go-callvis -format=png -file=docker -limit github.com/docker/docker -ignore github.com/docker/docker/vendor github.com/docker/docker/cmd/docker | dot -Tpng -o docker.png ``` + --- ## Travis CI Worker diff --git a/go.mod b/go.mod index cafc0b3..5bf405c 100644 --- a/go.mod +++ b/go.mod @@ -1,18 +1,19 @@ module github.com/ofabry/go-callvis -go 1.19 +go 1.22 require ( - github.com/goccy/go-graphviz v0.1.1 - github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 - golang.org/x/tools v0.8.0 + github.com/goccy/go-graphviz v0.1.3 + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c + golang.org/x/tools v0.22.0 ) require ( github.com/fogleman/gg v1.3.0 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/pkg/errors v0.9.1 // indirect - golang.org/x/image v0.6.0 // indirect - golang.org/x/mod v0.10.0 // indirect - golang.org/x/sys v0.7.0 // indirect + golang.org/x/image v0.18.0 // indirect + golang.org/x/mod v0.18.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.21.0 // indirect ) diff --git a/go.sum b/go.sum index 89dcb03..52d66ed 100644 --- a/go.sum +++ b/go.sum @@ -1,53 +1,25 @@ github.com/corona10/goimagehash v1.0.2 h1:pUfB0LnsJASMPGEZLj7tGY251vF+qLGqOgEP4rUs6kA= +github.com/corona10/goimagehash v1.0.2/go.mod h1:/l9umBhvcHQXVtQO1V6Gp1yD20STawkhRnnX0D1bvVI= github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/goccy/go-graphviz v0.1.1 h1:MGrsnzBxTyt7KG8FhHsFPDTGvF7UaQMmSa6A610DqPg= -github.com/goccy/go-graphviz v0.1.1/go.mod h1:lpnwvVDjskayq84ZxG8tGCPeZX/WxP88W+OJajh+gFk= +github.com/goccy/go-graphviz v0.1.3 h1:Pkt8y4FBnBNI9tfSobpoN5qy1qMNqRXPQYvLhaSUasY= +github.com/goccy/go-graphviz v0.1.3/go.mod h1:pMYpbAqJT10V8dzV1JN/g/wUlG/0imKPzn3ZsrchGCI= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 h1:BvoENQQU+fZ9uukda/RzCAL/191HHwJA5b13R6diVlY= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/image v0.6.0 h1:bR8b5okrPI3g/gyZakLZHeWxAR8Dn5CyxXv1hLH5g/4= -golang.org/x/image v0.6.0/go.mod h1:MXLdDR43H7cDJq5GEGXEVeeNhPgi+YYEQ2pC1byI1x0= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y= -golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= +golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= diff --git a/main.go b/main.go index 1e8e7db..9f0b051 100644 --- a/main.go +++ b/main.go @@ -1,12 +1,10 @@ // go-callvis: a tool to help visualize the call graph of a Go program. -// package main import ( "flag" "fmt" "go/build" - "io/ioutil" "log" "net" "net/http" @@ -40,13 +38,13 @@ var ( nointerFlag = flag.Bool("nointer", false, "Omit calls to unexported functions.") testFlag = flag.Bool("tests", false, "Include test code.") graphvizFlag = flag.Bool("graphviz", false, "Use Graphviz's dot program to render images.") - httpFlag = flag.String("http", ":7878", "HTTP service address.") + httpFlag = flag.String("http", "localhost:7878", "HTTP service address.") skipBrowser = flag.Bool("skipbrowser", false, "Skip opening browser.") outputFile = flag.String("file", "", "output filename - omit to use server mode") outputFormat = flag.String("format", "svg", "output file format [svg | png | jpg | ...]") cacheDir = flag.String("cacheDir", "", "Enable caching to avoid unnecessary re-rendering, you can force rendering by adding 'refresh=true' to the URL query or emptying the cache directory") - callgraphAlgo = flag.String("algo", CallGraphTypePointer, fmt.Sprintf("The algorithm used to construct the call graph. Possible values inlcude: %q, %q, %q, %q", - CallGraphTypeStatic, CallGraphTypeCha, CallGraphTypeRta, CallGraphTypePointer)) + callgraphAlgo = flag.String("algo", string(CallGraphTypeStatic), fmt.Sprintf("The algorithm used to construct the call graph. Possible values inlcude: %q, %q, %q", + CallGraphTypeStatic, CallGraphTypeCha, CallGraphTypeRta)) debugFlag = flag.Bool("debug", false, "Enable verbose log.") versionFlag = flag.Bool("version", false, "Show version and exit.") @@ -69,12 +67,15 @@ func logf(f string, a ...interface{}) { } func parseHTTPAddr(addr string) string { - host, port, _ := net.SplitHostPort(addr) + host, port, err := net.SplitHostPort(addr) + if err != nil { + log.Fatalf("%v\n", err) + } if host == "" { host = "localhost" } if port == "" { - port = "80" + port = "7878" } u := url.URL{ Scheme: "http", @@ -84,7 +85,7 @@ func parseHTTPAddr(addr string) string { } func openBrowser(url string) { - time.Sleep(time.Millisecond * 100) + time.Sleep(100 * time.Millisecond) // 100 ms if err := browser.OpenURL(url); err != nil { log.Printf("OpenURL error: %v", err) } @@ -105,7 +106,7 @@ func outputDot(fname string, outputFormat string) { log.Println("writing dot output..") - writeErr := ioutil.WriteFile(fmt.Sprintf("%s.gv", fname), output, 0755) + writeErr := os.WriteFile(fmt.Sprintf("%s.gv", fname), output, 0755) if writeErr != nil { log.Fatalf("%v\n", writeErr) } @@ -118,7 +119,7 @@ func outputDot(fname string, outputFormat string) { } } -//noinspection GoUnhandledErrorResult +// noinspection GoUnhandledErrorResult func main() { flag.Parse()