...
1
2
3
4
5
6
7
8
9 package copyright
10
11 import (
12 "go/ast"
13 "go/parser"
14 "go/token"
15 "io/fs"
16 "io/ioutil"
17 "path/filepath"
18 "regexp"
19 "strings"
20 )
21
22 func checkCopyright(dir string) ([]string, error) {
23 var files []string
24 err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
25 if err != nil {
26 return err
27 }
28 if d.IsDir() {
29
30 if strings.HasPrefix(d.Name(), ".") {
31 return filepath.SkipDir
32 }
33
34
35 if strings.HasPrefix(d.Name(), "_") {
36 return filepath.SkipDir
37 }
38 return nil
39 }
40 needsCopyright, err := checkFile(dir, path)
41 if err != nil {
42 return err
43 }
44 if needsCopyright {
45 files = append(files, path)
46 }
47 return nil
48 })
49 return files, err
50 }
51
52 var copyrightRe = regexp.MustCompile(`Copyright \d{4} The Go Authors. All rights reserved.
53 Use of this source code is governed by a BSD-style
54 license that can be found in the LICENSE file.`)
55
56 func checkFile(toolsDir, filename string) (bool, error) {
57
58 if !strings.HasSuffix(filename, "go") {
59 return false, nil
60 }
61
62 normalized := strings.TrimPrefix(filepath.ToSlash(filename), filepath.ToSlash(toolsDir))
63 if strings.Contains(normalized, "/testdata/") {
64 return false, nil
65 }
66
67 if strings.HasSuffix(normalized, "cmd/goyacc/yacc.go") {
68 return false, nil
69 }
70 content, err := ioutil.ReadFile(filename)
71 if err != nil {
72 return false, err
73 }
74 fset := token.NewFileSet()
75 parsed, err := parser.ParseFile(fset, filename, content, parser.ParseComments)
76 if err != nil {
77 return false, err
78 }
79
80 if isGenerated(fset, parsed) {
81 return false, nil
82 }
83 shouldAddCopyright := true
84 for _, c := range parsed.Comments {
85
86 if c.Pos() > parsed.Package {
87 break
88 }
89 if copyrightRe.MatchString(c.Text()) {
90 shouldAddCopyright = false
91 break
92 }
93 }
94 return shouldAddCopyright, nil
95 }
96
97
98
99
100
101 var generatedRx = regexp.MustCompile(`// .*DO NOT EDIT\.?`)
102
103 func isGenerated(fset *token.FileSet, file *ast.File) bool {
104 for _, commentGroup := range file.Comments {
105 for _, comment := range commentGroup.List {
106 if matched := generatedRx.MatchString(comment.Text); !matched {
107 continue
108 }
109
110 if pos := fset.Position(comment.Slash); pos.Column == 1 {
111 return true
112 }
113 }
114 }
115 return false
116 }
117
View as plain text