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