diff --git a/framework/lintmain/internal/check/check.go b/framework/lintmain/internal/check/check.go index a38799040..62678e7b6 100644 --- a/framework/lintmain/internal/check/check.go +++ b/framework/lintmain/internal/check/check.go @@ -1,6 +1,7 @@ package check import ( + "bytes" "errors" "flag" "fmt" @@ -13,6 +14,7 @@ import ( "path/filepath" "regexp" "runtime" + "runtime/pprof" "sort" "strings" "sync" @@ -37,10 +39,12 @@ func Main() { {"bind checker params", p.bindCheckerParams}, {"bind default enabled list", p.bindDefaultEnabledList}, {"parse args", p.parseArgs}, + {"start profiling", p.startProfiling}, {"assign checker params", p.assignCheckerParams}, {"load program", p.loadProgram}, {"init checkers", p.initCheckers}, {"run checkers", p.runCheckers}, + {"finish profiling", p.finishProfiling}, {"exit if found issues", p.exit}, } @@ -79,6 +83,11 @@ type program struct { gopath string goroot string + cpuProfile string + memProfile string + + cpuProfileData bytes.Buffer + goVersion string exitCode int checkTests bool @@ -363,6 +372,11 @@ func (p *program) parseArgs() error { flag.StringVar(&p.goVersion, "go", "", `select the Go version to target. Leave as string for the latest`) + flag.StringVar(&p.memProfile, "memprofile", "", + `write memory profile to the specified file`) + flag.StringVar(&p.cpuProfile, "cpuprofile", "", + `write CPU profile to the specified file`) + flag.Parse() p.packages = flag.Args() @@ -389,6 +403,46 @@ func addTrailingSlash(s string) string { return s + string(os.PathSeparator) } +func (p *program) startProfiling() error { + if p.memProfile != "" { + runtime.MemProfileRate = 2048 + } + + if p.cpuProfile == "" { + return nil + } + + if err := pprof.StartCPUProfile(&p.cpuProfileData); err != nil { + return fmt.Errorf("could not start CPU profile: %v", err) + } + + return nil +} + +func (p *program) finishProfiling() error { + if p.cpuProfile != "" { + pprof.StopCPUProfile() + err := os.WriteFile(p.cpuProfile, p.cpuProfileData.Bytes(), 0o666) + if err != nil { + return fmt.Errorf("write CPU profile: %v", err) + } + } + + if p.memProfile != "" { + f, err := os.Create(p.memProfile) + if err != nil { + return fmt.Errorf("create mem profile: %v", err) + } + defer f.Close() + runtime.GC() // get up-to-date statistics + if err := pprof.WriteHeapProfile(f); err != nil { + return fmt.Errorf("write mem profile: %v", err) + } + } + + return nil +} + // assignCheckerParams initializes checker parameter values using // values that are coming from the command-line arguments. func (p *program) assignCheckerParams() error { diff --git a/framework/linttest/linttest.go b/framework/linttest/linttest.go index bb837ed2c..9545ba448 100644 --- a/framework/linttest/linttest.go +++ b/framework/linttest/linttest.go @@ -240,7 +240,7 @@ func loadPackages(cfg *packages.Config, patterns []string) ([]*packages.Package, if u.Test != nil { // Prefer tests to the base package, if present. result = append(result, u.Test) - } else { + } else if u.Base != nil { result = append(result, u.Base) } }) diff --git a/go.mod b/go.mod index 4717032a9..4370a0137 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/go-toolsmith/astequal v1.0.1 github.com/go-toolsmith/astfmt v1.0.0 github.com/go-toolsmith/astp v1.0.0 - github.com/go-toolsmith/pkgload v1.0.0 + github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5 github.com/go-toolsmith/strparse v1.0.0 github.com/go-toolsmith/typep v1.0.2 github.com/google/go-cmp v0.5.6 @@ -16,5 +16,6 @@ require ( github.com/quasilyte/go-ruleguard v0.3.14 github.com/quasilyte/go-ruleguard/dsl v0.3.10 github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 - golang.org/x/tools v0.1.8-0.20211102225717-714668c9f9a3 + golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect + golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da ) diff --git a/go.sum b/go.sum index a2e0b3c70..71ee98ca1 100644 --- a/go.sum +++ b/go.sum @@ -11,6 +11,10 @@ github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KP github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= github.com/go-toolsmith/pkgload v1.0.0 h1:4DFWWMXVfbcN5So1sBNW9+yeiMqLFGl1wFLTL5R0Tgg= github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc= +github.com/go-toolsmith/pkgload v1.0.2-0.20220101211029-f9bca7b6a3d9 h1:izv+hZZg5x9r2fSf1b0mwl8Ysu+O8ZpiwU67cxmsYFk= +github.com/go-toolsmith/pkgload v1.0.2-0.20220101211029-f9bca7b6a3d9/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc= +github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5 h1:eD9POs68PHkwrx7hAB78z1cb6PfGq/jyWn3wJywsH1o= +github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5/go.mod h1:3NAwwmD4uY/yggRxoEjk/S00MIV3A+H7rrE3i87eYxM= github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= github.com/go-toolsmith/typep v1.0.2 h1:8xdsa1+FSIH/RhEkgnD1j2CJOy5mNllW1Q9tRiYwvlk= @@ -58,6 +62,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 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= @@ -70,6 +76,10 @@ golang.org/x/tools v0.0.0-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.8-0.20211102225717-714668c9f9a3 h1:dDxElkpRI634Opa6XdqYX2K1+CHLHHf2TFqPEHyy2XE= golang.org/x/tools v0.1.8-0.20211102225717-714668c9f9a3/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= +golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da h1:Tno72dYE94v/7SyyIj9iBsc7OOjFu2PyNcl7yxxeZD8= +golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=