From 22dc89384de4daabfe83f0e49918ac35385ab1d6 Mon Sep 17 00:00:00 2001 From: "Andrew S. Brown" Date: Sun, 7 Jan 2018 15:02:33 -0800 Subject: [PATCH] Do a single build for all packages. This is much faster because the loader can reuse packages. --- analyzer.go | 29 ++++++++++++++++++----------- analyzer_test.go | 22 ++++++++++++++++++++++ cmd/gas/main.go | 11 +++++------ 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/analyzer.go b/analyzer.go index 12aff3c..f050ab7 100644 --- a/analyzer.go +++ b/analyzer.go @@ -27,6 +27,8 @@ import ( "reflect" "strings" + "path/filepath" + "golang.org/x/tools/go/loader" ) @@ -93,20 +95,25 @@ func (gas *Analyzer) LoadRules(ruleDefinitions ...RuleBuilder) { } // Process kicks off the analysis process for a given package -func (gas *Analyzer) Process(packagePath string) error { - - basePackage, err := build.Default.ImportDir(packagePath, build.ImportComment) - if err != nil { - return err - } - +func (gas *Analyzer) Process(packagePaths ...string) error { packageConfig := loader.Config{Build: &build.Default, ParserMode: parser.ParseComments} - var packageFiles []string - for _, filename := range basePackage.GoFiles { - packageFiles = append(packageFiles, path.Join(packagePath, filename)) + for _, packagePath := range packagePaths { + abspath, _ := filepath.Abs(packagePath) + gas.logger.Println("Searching directory:", abspath) + + basePackage, err := build.Default.ImportDir(packagePath, build.ImportComment) + if err != nil { + return err + } + + var packageFiles []string + for _, filename := range basePackage.GoFiles { + packageFiles = append(packageFiles, path.Join(packagePath, filename)) + } + + packageConfig.CreateFromFilenames(basePackage.Name, packageFiles...) } - packageConfig.CreateFromFilenames(basePackage.Name, packageFiles...) builtPackage, err := packageConfig.Load() if err != nil { return err diff --git a/analyzer_test.go b/analyzer_test.go index e69a822..cff3415 100644 --- a/analyzer_test.go +++ b/analyzer_test.go @@ -73,6 +73,28 @@ var _ = Describe("Analyzer", func() { Expect(metrics.NumFiles).To(Equal(2)) }) + It("should be able to analyze mulitple Go packages", func() { + analyzer.LoadRules(rules.Generate().Builders()...) + pkg1 := testutils.NewTestPackage() + pkg2 := testutils.NewTestPackage() + defer pkg1.Close() + defer pkg2.Close() + pkg1.AddFile("foo.go", ` + package main + func main(){ + }`) + pkg2.AddFile("bar.go", ` + package main + func bar(){ + }`) + pkg1.Build() + pkg2.Build() + err := analyzer.Process(pkg1.Path, pkg2.Path) + Expect(err).ShouldNot(HaveOccurred()) + _, metrics := analyzer.Report() + Expect(metrics.NumFiles).To(Equal(2)) + }) + It("should find errors when nosec is not in use", func() { // Rule for MD5 weak crypto usage diff --git a/cmd/gas/main.go b/cmd/gas/main.go index ef20462..5a04c02 100644 --- a/cmd/gas/main.go +++ b/cmd/gas/main.go @@ -19,7 +19,6 @@ import ( "fmt" "log" "os" - "path/filepath" "regexp" "sort" "strings" @@ -202,6 +201,7 @@ func main() { vendor := regexp.MustCompile(`[\\/]vendor([\\/]|$)`) + var packages []string // Iterate over packages on the import paths for _, pkg := range gotool.ImportPaths(flag.Args()) { @@ -209,12 +209,11 @@ func main() { if vendor.MatchString(pkg) { continue } + packages = append(packages, pkg) + } - abspath, _ := filepath.Abs(pkg) - logger.Println("Searching directory:", abspath) - if err := analyzer.Process(pkg); err != nil { - logger.Fatal(err) - } + if err := analyzer.Process(packages...); err != nil { + logger.Fatal(err) } // Collect the results