8000 Limit generated marker detection to file headers by dajiaohuang · Pull Request #1771 · dominikh/go-tools · GitHub
[go: up one dir, main page]

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 31 additions & 39 deletions analysis/facts/generated/generated.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package generated

import (
"bufio"
"bytes"
"io"
"os"
"go/parser"
"go/token"
"reflect"
"strings"

Expand All @@ -27,52 +26,45 @@ var (
oldCgo = []byte("// Created by cgo - DO NOT EDIT")
prefix = []byte("// Code generated ")
suffix = []byte(" DO NOT EDIT.")
nl = []byte("\n")
crnl = []byte("\r\n")
)

func isGenerated(path string) (Generator, bool) {
f, err := os.Open(path)
f, err := parser.ParseFile(token.NewFileSet(), path, nil, parser.ParseComments|parser.PackageClauseOnly|parser.SkipObjectResolution)
if err != nil {
return 0, false
}
defer f.Close()
br := bufio.NewReader(f)
for {
s, err := br.ReadBytes('\n')
if err != nil && err != io.EOF {
return 0, false
}
s = bytes.TrimSuffix(s, crnl)
s = bytes.TrimSuffix(s, nl)
if bytes.HasPrefix(s, prefix) && bytes.HasSuffix(s, suffix) {
if len(s)-len(suffix) < len(prefix) {
return Unknown, true
for _, group := range f.Comments {
for _, comment := range group.List {
if comment.Pos() >= f.Package {
continue
}
s := []byte(comment.Text)
if bytes.HasPrefix(s, prefix) && bytes.HasSuffix(s, suffix) {
if len(s)-len(suffix) < len(prefix) {
return Unknown, true
}

text := string(s[len(prefix) : len(s)-len(suffix)])
switch text {
case "by goyacc.":
return Goyacc, true
case "by cmd/cgo;":
return Cgo, true
case "by protoc-gen-go.":
return ProtocGenGo, true
}
if strings.HasPrefix(text, `by "stringer `) {
return Stringer, true
text := string(s[len(prefix) : len(s)-len(suffix)])
switch text {
case "by goyacc.":
return Goyacc, true
case "by cmd/cgo;":
return Cgo, true
case "by protoc-gen-go.":
return ProtocGenGo, true
}
if strings.HasPrefix(text, `by "stringer `) {
return Stringer, true
}
if strings.HasPrefix(text, `by goyacc `) {
return Goyacc, true
}

return Unknown, true
}
if strings.HasPrefix(text, `by goyacc `) {
return Goyacc, true
if bytes.Equal(s, oldCgo) {
return Cgo, true
}

return Unknown, true
}
if bytes.Equal(s, oldCgo) {
return Cgo, true
}
if err == io.EOF {
break
}
}
return 0, false
Expand Down
65 changes: 65 additions & 0 deletions analysis/facts/generated/generated_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package generated

import (
"os"
"path/filepath"
"strings"
"testing"
)

func TestIsGeneratedOnlyChecksFileHeader(t *testing.T) {
tests := []struct {
name string
text string
want bool
}{
{
name: "long license header",
text: strings.Repeat("// license\n", 20) + "// Code generated by protoc-gen-go. DO NOT EDIT.\npackage p\n",
want: true,
},
{
name: "indented package clause",
text: " package p\n// Code generated by protoc-gen-go. DO NOT EDIT.\n",
want: false,
},
{
name: "marker inside block comment",
text: "/*\n// Code generated by protoc-gen-go. DO NOT EDIT.\n*/\npackage p\n",
want: false,
},
{
name: "old cgo header",
text: "// Created by cgo - DO NOT EDIT\npackage p\n",
want: true,
},
{
name: "header",
text: "// Code generated by protoc-gen-go. DO NOT EDIT.\n\npackage p\n",
want: true,
},
{
name: "body comment",
text: "package p\n\nfunc f() {\n\t// Code generated by protoc-gen-go. DO NOT EDIT.\n}\n",
want: false,
},
{
name: "late comment",
text: "package p\n\n// Code generated by protoc-gen-go. DO NOT EDIT.\n",
want: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
path := filepath.Join(t.TempDir(), "generated.go")
if err := os.WriteFile(path, []byte(tt.text), 0o600); err != nil {
t.Fatal(err)
}
_, got := isGenerated(path)
if got != tt.want {
t.Fatalf("isGenerated() = %v, want %v", got, tt.want)
}
})
}
}
0