diff --git a/formatter/cli_formatter.go b/formatter/cli_formatter.go index 1ad8cf7..432efa8 100644 --- a/formatter/cli_formatter.go +++ b/formatter/cli_formatter.go @@ -33,16 +33,17 @@ func formatFailure(failure linter.Failure) []string { } // Format formats the failures gotten from the linter. -func (f *CLIFormatter) Format(failures []linter.Failure) (string, error) { +func (f *CLIFormatter) Format(failures <-chan linter.Failure) (string, error) { var result [][]string var totalErrors = 0 - for _, f := range failures { + var total = 0 + for f := range failures { result = append(result, formatFailure(f)) + total++ if f.Type == linter.FailureTypeError { totalErrors++ } } - total := len(failures) ps := "problems" if total == 1 { ps = "problem" diff --git a/formatter/json_formatter.go b/formatter/json_formatter.go index a1a3a03..1d7e70d 100644 --- a/formatter/json_formatter.go +++ b/formatter/json_formatter.go @@ -13,7 +13,7 @@ type JSONFormatter struct { } // Format formats the failures gotten from the linter. -func (f *JSONFormatter) Format(failures []linter.Failure) (string, error) { +func (f *JSONFormatter) Format(failures <-chan linter.Failure) (string, error) { result, error := json.Marshal(failures) if error != nil { return "", error diff --git a/linter/file.go b/linter/file.go index c011361..1031860 100644 --- a/linter/file.go +++ b/linter/file.go @@ -84,8 +84,7 @@ func (f *File) isMain() bool { return false } -func (f *File) lint(rules []Rule, rulesConfig RulesConfig) []Failure { - var failures []Failure +func (f *File) lint(rules []Rule, rulesConfig RulesConfig, failures chan Failure) { disabledIntervals := f.disabledIntervals(rules) for _, currentRule := range rules { config := rulesConfig[currentRule.Name()] @@ -100,9 +99,10 @@ func (f *File) lint(rules []Rule, rulesConfig RulesConfig) []Failure { currentFailures[idx] = failure } currentFailures = f.filterFailures(currentFailures, disabledIntervals) - failures = append(failures, currentFailures...) + for _, failure := range currentFailures { + failures <- failure + } } - return failures } type enableDisableConfig struct { diff --git a/linter/formatter.go b/linter/formatter.go index 209febe..d30522f 100644 --- a/linter/formatter.go +++ b/linter/formatter.go @@ -9,5 +9,5 @@ type FormatterMetadata struct { // Formatter defines an interface for failure formatters type Formatter interface { - Format([]Failure) string + Format(<-chan Failure) string } diff --git a/linter/linter.go b/linter/linter.go index f8c669e..c114662 100644 --- a/linter/linter.go +++ b/linter/linter.go @@ -42,7 +42,8 @@ func isGenerated(src []byte) bool { } // Lint lints a set of files with the specified rule. -func (l *Linter) Lint(filenames []string, ruleSet []Rule, rulesConfig RulesConfig) ([]Failure, error) { +func (l *Linter) Lint(filenames []string, ruleSet []Rule, rulesConfig RulesConfig) (<-chan Failure, error) { + failures := make(chan Failure) pkg := &Package{ fset: token.NewFileSet(), files: map[string]*File{}, @@ -71,5 +72,9 @@ func (l *Linter) Lint(filenames []string, ruleSet []Rule, rulesConfig RulesConfi pkg.files[filename] = file } - return pkg.lint(ruleSet, rulesConfig), nil + go (func() { + pkg.lint(ruleSet, rulesConfig, failures) + })() + + return failures, nil } diff --git a/linter/package.go b/linter/package.go index 6e0a9c2..d6a8378 100644 --- a/linter/package.go +++ b/linter/package.go @@ -4,6 +4,7 @@ import ( "go/ast" "go/token" "go/types" + "sync" "golang.org/x/tools/go/gcexportdata" ) @@ -84,11 +85,16 @@ func (p *Package) TypeOf(expr ast.Expr) types.Type { return p.TypesInfo.TypeOf(expr) } -func (p *Package) lint(rules []Rule, config RulesConfig) []Failure { - var failures []Failure +func (p *Package) lint(rules []Rule, config RulesConfig, failures chan Failure) { p.TypeCheck() + var wg sync.WaitGroup for _, file := range p.files { - failures = append(failures, file.lint(rules, config)...) + wg.Add(1) + go (func(file *File) { + file.lint(rules, config, failures) + defer wg.Done() + })(file) } - return failures + wg.Wait() + close(failures) }