Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
2.0 KiB
99 lines
2.0 KiB
package lint |
|
|
|
import ( |
|
"bufio" |
|
"bytes" |
|
"fmt" |
|
"go/token" |
|
"os" |
|
"sync" |
|
) |
|
|
|
// ReadFile defines an abstraction for reading files. |
|
type ReadFile func(path string) (result []byte, err error) |
|
|
|
type disabledIntervalsMap = map[string][]DisabledInterval |
|
|
|
// Linter is used for linting set of files. |
|
type Linter struct { |
|
reader ReadFile |
|
} |
|
|
|
// New creates a new Linter |
|
func New(reader ReadFile) Linter { |
|
return Linter{reader: reader} |
|
} |
|
|
|
var ( |
|
genHdr = []byte("// Code generated ") |
|
genFtr = []byte(" DO NOT EDIT.") |
|
) |
|
|
|
// Lint lints a set of files with the specified rule. |
|
func (l *Linter) Lint(packages [][]string, ruleSet []Rule, config Config) (<-chan Failure, error) { |
|
failures := make(chan Failure) |
|
|
|
var wg sync.WaitGroup |
|
for _, pkg := range packages { |
|
wg.Add(1) |
|
go func(pkg []string) { |
|
if err := l.lintPackage(pkg, ruleSet, config, failures); err != nil { |
|
fmt.Fprintln(os.Stderr, err) |
|
os.Exit(1) |
|
} |
|
defer wg.Done() |
|
}(pkg) |
|
} |
|
|
|
go func() { |
|
wg.Wait() |
|
close(failures) |
|
}() |
|
|
|
return failures, nil |
|
} |
|
|
|
func (l *Linter) lintPackage(filenames []string, ruleSet []Rule, config Config, failures chan Failure) error { |
|
pkg := &Package{ |
|
fset: token.NewFileSet(), |
|
files: map[string]*File{}, |
|
mu: sync.Mutex{}, |
|
} |
|
for _, filename := range filenames { |
|
content, err := l.reader(filename) |
|
if err != nil { |
|
return err |
|
} |
|
if isGenerated(content) && !config.IgnoreGeneratedHeader { |
|
continue |
|
} |
|
|
|
file, err := NewFile(filename, content, pkg) |
|
if err != nil { |
|
return err |
|
} |
|
pkg.files[filename] = file |
|
} |
|
|
|
if len(pkg.files) == 0 { |
|
return nil |
|
} |
|
|
|
pkg.lint(ruleSet, config, failures) |
|
|
|
return nil |
|
} |
|
|
|
// isGenerated reports whether the source file is generated code |
|
// according the rules from https://golang.org/s/generatedcode. |
|
// This is inherited from the original go lint. |
|
func isGenerated(src []byte) bool { |
|
sc := bufio.NewScanner(bytes.NewReader(src)) |
|
for sc.Scan() { |
|
b := sc.Bytes() |
|
if bytes.HasPrefix(b, genHdr) && bytes.HasSuffix(b, genFtr) && len(b) >= len(genHdr)+len(genFtr) { |
|
return true |
|
} |
|
} |
|
return false |
|
}
|
|
|