.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.1-0.20210319172145-bda8f5cee399 / copyright / copyright.go
1 // Copyright 2020 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Package copyright checks that files have the correct copyright notices.
6 package copyright
7
8 import (
9         "go/ast"
10         "go/parser"
11         "go/token"
12         "io/ioutil"
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.Walk(dir, func(path string, info os.FileInfo, err error) error {
22                 if err != nil {
23                         return err
24                 }
25                 if info.IsDir() {
26                         // Skip directories like ".git".
27                         if strings.HasPrefix(info.Name(), ".") {
28                                 return filepath.SkipDir
29                         }
30                         return nil
31                 }
32                 needsCopyright, err := checkFile(dir, path)
33                 if err != nil {
34                         return err
35                 }
36                 if needsCopyright {
37                         files = append(files, path)
38                 }
39                 return nil
40         })
41         return files, err
42 }
43
44 var copyrightRe = regexp.MustCompile(`Copyright \d{4} The Go Authors. All rights reserved.
45 Use of this source code is governed by a BSD-style
46 license that can be found in the LICENSE file.`)
47
48 func checkFile(toolsDir, filename string) (bool, error) {
49         // Only check Go files.
50         if !strings.HasSuffix(filename, "go") {
51                 return false, nil
52         }
53         // Don't check testdata files.
54         normalized := strings.TrimPrefix(filepath.ToSlash(filename), filepath.ToSlash(toolsDir))
55         if strings.Contains(normalized, "/testdata/") {
56                 return false, nil
57         }
58         // goyacc is the only file with a different copyright header.
59         if strings.HasSuffix(normalized, "cmd/goyacc/yacc.go") {
60                 return false, nil
61         }
62         content, err := ioutil.ReadFile(filename)
63         if err != nil {
64                 return false, err
65         }
66         fset := token.NewFileSet()
67         parsed, err := parser.ParseFile(fset, filename, content, parser.ParseComments)
68         if err != nil {
69                 return false, err
70         }
71         // Don't require headers on generated files.
72         if isGenerated(fset, parsed) {
73                 return false, nil
74         }
75         shouldAddCopyright := true
76         for _, c := range parsed.Comments {
77                 // The copyright should appear before the package declaration.
78                 if c.Pos() > parsed.Package {
79                         break
80                 }
81                 if copyrightRe.MatchString(c.Text()) {
82                         shouldAddCopyright = false
83                         break
84                 }
85         }
86         return shouldAddCopyright, nil
87 }
88
89 // Copied from golang.org/x/tools/internal/lsp/source/util.go.
90 // Matches cgo generated comment as well as the proposed standard:
91 //      https://golang.org/s/generatedcode
92 var generatedRx = regexp.MustCompile(`// .*DO NOT EDIT\.?`)
93
94 func isGenerated(fset *token.FileSet, file *ast.File) bool {
95         for _, commentGroup := range file.Comments {
96                 for _, comment := range commentGroup.List {
97                         if matched := generatedRx.MatchString(comment.Text); !matched {
98                                 continue
99                         }
100                         // Check if comment is at the beginning of the line in source.
101                         if pos := fset.Position(comment.Slash); pos.Column == 1 {
102                                 return true
103                         }
104                 }
105         }
106         return false
107 }