Skip to content

Commit

Permalink
Add flag --skip-generated to skip generated code (#150)
Browse files Browse the repository at this point in the history
This diff adds the flag `--skip-generated` to be able to skip running
gopatch on files containing generated code. When the flag is set to
true, if the comments contains `@generated` or the special go generated
code comment `^// Code generated .* DO NOT EDIT\.$`, we do not run
gopatch on that particular file.
We are adding a check for the former case(@generated) as at times, the
generated code does not follow the the special go generated code format
perfectly.

Example:
For test file
`testdata/test_file/skip_generated_file/special_notation_generated.go`,
if we apply the patch `testdata/patch/time.go`

Without running `--skip-generated`, the file gets modified to
```
--- testdata/test_files/skip_generated_files/test1.go
+++ testdata/test_files/skip_generated_files/test1.go
@@ -9,6 +9,6 @@

 func main() {
        startOfYear := time.Date(2021, 0o1, 0o1, 0, 0, 0, 0, time.UTC)
-       result := time.Now().Sub(startOfYear)
+       result := time.Since(startOfYear)
        fmt.Println(result)
 }
```
Running with flag `--skip-generated`, file isn't modified at all.
Internal ref: GO-2502

Note: We also upgraded the go version to 1.22 to use the
[ast.IsGenerated ](https://pkg.go.dev/go/ast#IsGenerated) function which
was introduced in 1.21.
  • Loading branch information
lverma14 authored Feb 29, 2024
1 parent 85b232b commit a8f6206
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.20.x
go-version: 1.22.x

- name: Load cached dependencies
uses: actions/cache@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: 1.20.x
go-version: 1.22.x

- name: Checkout
uses: actions/checkout@v4
Expand Down
37 changes: 37 additions & 0 deletions e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,43 @@ func runIntegrationTest(t *testing.T, testFile string) {
}
}

func TestGeneratedE2e(t *testing.T) {
patch := "testdata/patch/time.patch"
t.Parallel()
tests := []struct {
name string
path string
want string
}{
{
name: "go special comment for generated code",
path: "testdata/test_files/skip_generated_files/special_notation_generated.go",
},
{
name: "@generated",
path: "testdata/test_files/skip_generated_files/simple_generated.go",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
want, err := os.ReadFile(tt.path)
require.NoError(t, err)
var stdoutbuf bytes.Buffer
cmd := mainCmd{
Stdout: &stdoutbuf,
Getwd: os.Getwd,
}
err = cmd.Run([]string{"--skip-generated", "-p", patch, tt.path})
require.NoError(t, err, "could not run patch")
assert.Empty(t, stdoutbuf)
// verify the target file's content didn't modify.
got, err := os.ReadFile(tt.path)
require.NoError(t, err)
assert.Equal(t, want, got)
})
}
}

// includeSkipImportTest returns whether we should include a testfile for
// the skipImportProcessing flag testing
func includeSkipImportTest(testFile, testName string) bool {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/uber-go/gopatch

go 1.18
go 1.22

require (
github.com/google/go-intervals v0.0.2
Expand Down
22 changes: 22 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ type options struct {
DisplayVersion bool `long:"version"`
Print bool `long:"print-only"`
SkipImportProcessing bool `long:"skip-import-processing"`
SkipGenerated bool `long:"skip-generated"`
Args arguments `positional-args:"yes"`
Verbose bool `short:"v" long:"verbose"`
}
Expand Down Expand Up @@ -94,6 +95,10 @@ func newArgParser() (*flags.Parser, *options) {

parser.FindOptionByLongName("skip-import-processing").
Description = "Skips processing of imports."

parser.FindOptionByLongName("skip-generated").
Description = "Skips running on files with generated code."

parser.Args()[0].
Description = "One or more files or directores containing Go code. " +
"When directories are provided, all Go files in them and their " +
Expand Down Expand Up @@ -284,6 +289,11 @@ func (cmd *mainCmd) Run(args []string) error {
continue
}

if opts.SkipGenerated && checkGeneratedCode(f) {
log.Printf("generated file %s: skipped", filename)
continue
}

f, comments, ok := patchRunner.Apply(filename, f)
// If at least one patch didn't match, there's nothing to do.
// If --print-only was passed, print the contents out as-is.
Expand Down Expand Up @@ -341,6 +351,18 @@ func (cmd *mainCmd) Run(args []string) error {
return multierr.Combine(errors...)
}

func checkGeneratedCode(f *ast.File) bool {
if ast.IsGenerated(f) {
return true
}
for _, comm := range f.Doc.List {
if strings.Contains(comm.Text, "@generated") {
return true
}
}
return false
}

func (cmd *mainCmd) preview(
filename string,
originalContent, modifiedContent []byte,
Expand Down
49 changes: 49 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ package main

import (
"bytes"
"go/ast"
"go/token"
"os"
"path/filepath"
Expand Down Expand Up @@ -60,6 +61,15 @@ func TestNewArgParser(t *testing.T) {
SkipImportProcessing: false,
},
},
{
desc: "skip-generated",
give: []string{"--skip-generated", "-p", "testdata/patch/replace_to_with_ptr.patch", "testdata/test_files/skip_generated_files/test1.go"},
want: options{
Patches: []string{"testdata/patch/replace_to_with_ptr.patch"},
Args: arguments{Patterns: []string{"testdata/test_files/skip_generated_files/test1.go"}},
SkipGenerated: true,
},
},
{
desc: "skip-import-processing",
give: []string{"--skip-import-processing", "-p", "testdata/patch/replace_to_with_ptr.patch", "testdata/test_files/skip_import_processing_example/test1.go"},
Expand All @@ -78,6 +88,7 @@ func TestNewArgParser(t *testing.T) {
assert.Equal(t, tt.want.Patches, opts.Patches)
assert.Equal(t, tt.want.Args, opts.Args)
assert.Equal(t, tt.want.Diff, opts.Diff)
assert.Equal(t, tt.want.SkipGenerated, opts.SkipGenerated)
assert.Equal(t, tt.want.SkipImportProcessing, opts.SkipImportProcessing)
})
}
Expand Down Expand Up @@ -211,3 +222,41 @@ func TestPreview(t *testing.T) {
stdout.String())
})
}

func TestCheckGeneratedCode(t *testing.T) {
t.Parallel()
tests := []struct {
name string
file *ast.File
want bool
}{
{
name: "@generated",
file: &ast.File{
Doc: &ast.CommentGroup{
List: []*ast.Comment{
{Text: "@generated"},
},
},
},
want: true,
},
{
name: "non-generated code",
file: &ast.File{
Doc: &ast.CommentGroup{
List: []*ast.Comment{
{Text: "sad times"},
{Text: "not generated code"},
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := checkGeneratedCode(tt.file)
assert.Equal(t, tt.want, got)
})
}
}
13 changes: 13 additions & 0 deletions testdata/test_files/skip_generated_files/simple_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tools/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/uber-go/gopatch/tools

go 1.18
go 1.22

require (
github.com/stretchr/testify v1.8.4
Expand Down
1 change: 1 addition & 0 deletions tools/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
Expand Down

0 comments on commit a8f6206

Please sign in to comment.