Do a single build for all packages.

This is much faster because the loader can reuse packages.
This commit is contained in:
Andrew S. Brown 2018-01-07 15:02:33 -08:00
parent 085e0f65af
commit 22dc89384d
3 changed files with 45 additions and 17 deletions

View file

@ -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

View file

@ -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

View file

@ -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