github.com/Johnny2210/revive@v1.0.8-0.20210625134200-febf37ccd0f5/lint/linter.go (about) 1 package lint 2 3 import ( 4 "bufio" 5 "bytes" 6 "fmt" 7 "go/token" 8 "os" 9 "sync" 10 ) 11 12 // ReadFile defines an abstraction for reading files. 13 type ReadFile func(path string) (result []byte, err error) 14 15 type disabledIntervalsMap = map[string][]DisabledInterval 16 17 // Linter is used for linting set of files. 18 type Linter struct { 19 reader ReadFile 20 } 21 22 // New creates a new Linter 23 func New(reader ReadFile) Linter { 24 return Linter{reader: reader} 25 } 26 27 var ( 28 genHdr = []byte("// Code generated ") 29 genFtr = []byte(" DO NOT EDIT.") 30 ) 31 32 // Lint lints a set of files with the specified rule. 33 func (l *Linter) Lint(packages [][]string, ruleSet []Rule, config Config) (<-chan Failure, error) { 34 failures := make(chan Failure) 35 36 var wg sync.WaitGroup 37 for _, pkg := range packages { 38 wg.Add(1) 39 go func(pkg []string) { 40 if err := l.lintPackage(pkg, ruleSet, config, failures); err != nil { 41 fmt.Fprintln(os.Stderr, err) 42 os.Exit(1) 43 } 44 defer wg.Done() 45 }(pkg) 46 } 47 48 go func() { 49 wg.Wait() 50 close(failures) 51 }() 52 53 return failures, nil 54 } 55 56 func (l *Linter) lintPackage(filenames []string, ruleSet []Rule, config Config, failures chan Failure) error { 57 pkg := &Package{ 58 fset: token.NewFileSet(), 59 files: map[string]*File{}, 60 mu: sync.Mutex{}, 61 } 62 for _, filename := range filenames { 63 content, err := l.reader(filename) 64 if err != nil { 65 return err 66 } 67 if isGenerated(content) && !config.IgnoreGeneratedHeader { 68 continue 69 } 70 71 file, err := NewFile(filename, content, pkg) 72 if err != nil { 73 return err 74 } 75 pkg.files[filename] = file 76 } 77 78 if len(pkg.files) == 0 { 79 return nil 80 } 81 82 pkg.lint(ruleSet, config, failures) 83 84 return nil 85 } 86 87 // isGenerated reports whether the source file is generated code 88 // according the rules from https://golang.org/s/generatedcode. 89 // This is inherited from the original go lint. 90 func isGenerated(src []byte) bool { 91 sc := bufio.NewScanner(bytes.NewReader(src)) 92 for sc.Scan() { 93 b := sc.Bytes() 94 if bytes.HasPrefix(b, genHdr) && bytes.HasSuffix(b, genFtr) && len(b) >= len(genHdr)+len(genFtr) { 95 return true 96 } 97 } 98 return false 99 }