Skip to content

Commit c6298da

Browse files
committed
Allow exclude to skip invalid interfaces, close #23
1 parent 096dc57 commit c6298da

File tree

3 files changed

+83
-5
lines changed

3 files changed

+83
-5
lines changed

examples/query.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ var _ = genconfig.Config{
1818
"date": field.Time{},
1919
"json": JSON{},
2020
},
21-
IncludeStructs: []any{},
21+
IncludeStructs: []any{},
22+
ExcludeInterfaces: []any{Entity(nil)},
2223
}
2324

2425
type Query[T any] interface {
@@ -72,6 +73,11 @@ type Query[T any] interface {
7273
FilterWithTime(start, end time.Time) ([]T, error)
7374
}
7475

76+
type Entity interface {
77+
TableName() string
78+
Key() any
79+
}
80+
7581
type Params struct {
7682
Name string
7783
Age int

internal/gen/generator.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ type (
5050
IfaceName string
5151
Doc string
5252
Methods []*Method
53+
err error
5354
}
5455
Method struct {
5556
Name string
@@ -186,6 +187,12 @@ func (g *Generator) Gen() error {
186187
}
187188
}
188189

190+
for _, iface := range file.Interfaces {
191+
if iface.err != nil {
192+
return fmt.Errorf("invalid interface %s: %w", iface.Name, iface.err)
193+
}
194+
}
195+
189196
if len(file.Interfaces) == 0 && len(file.Structs) == 0 {
190197
continue
191198
}
@@ -621,15 +628,27 @@ func (p *File) processInterfaceType(n *ast.TypeSpec, data *ast.InterfaceType) In
621628

622629
if len(method.Result) == 0 {
623630
if method.SQL.Where == "" && method.SQL.Select == "" || method.SQL.Raw != "" {
624-
panic(fmt.Sprintf("Method %s.%s: finish method must return at least one value (last return value must be error)", n.Name.Name, method.Name))
631+
if r.err == nil {
632+
r.err = fmt.Errorf("Method %s.%s: finish method must return at least one value (last return value must be error)", n.Name.Name, method.Name)
633+
}
634+
return r
625635
}
626636
} else if len(method.Result) > 2 {
627-
panic(fmt.Sprintf("Method %s.%s: maximum number of return values allowed is 2 (first as data, second as error)", n.Name.Name, method.Name))
637+
if r.err == nil {
638+
r.err = fmt.Errorf("Method %s.%s: maximum number of return values allowed is 2 (first as data, second as error)", n.Name.Name, method.Name)
639+
}
640+
return r
628641
} else if strings.ToLower(method.Result[len(method.Result)-1].Type) != "error" {
629642
if len(method.Result) == 1 {
630-
panic(fmt.Sprintf("Method %s.%s: when only one return value is defined, its type must be error", n.Name.Name, method.Name))
643+
if r.err == nil {
644+
r.err = fmt.Errorf("Method %s.%s: when only one return value is defined, its type must be error", n.Name.Name, method.Name)
645+
}
646+
return r
647+
}
648+
if r.err == nil {
649+
r.err = fmt.Errorf("Method %s.%s: when two return values are defined, the second must be error", n.Name.Name, method.Name)
631650
}
632-
panic(fmt.Sprintf("Method %s.%s: when two return values are defined, the second must be error", n.Name.Name, method.Name))
651+
return r
633652
}
634653
}
635654
}

internal/gen/generator_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package gen
22

33
import (
4+
"fmt"
45
"go/ast"
56
"go/parser"
67
"go/token"
@@ -78,6 +79,58 @@ func TestGeneratorWithQueryInterface(t *testing.T) {
7879
}
7980
}
8081

82+
func TestExcludeInterfacesSkipsInvalidInterfaces(t *testing.T) {
83+
writeSample := func(dir string, withExclude bool) string {
84+
if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module temp.test\n\ngo 1.21\n"), 0o644); err != nil {
85+
t.Fatalf("write go.mod: %v", err)
86+
}
87+
88+
cfg := "ExcludeInterfaces: []any{Entity(nil)},"
89+
if !withExclude {
90+
cfg = ""
91+
}
92+
93+
src := fmt.Sprintf(`package sample
94+
95+
import "gorm.io/cli/gorm/genconfig"
96+
97+
var _ = genconfig.Config{
98+
%s
99+
}
100+
101+
type Entity interface {
102+
TableName() string
103+
}
104+
`, cfg)
105+
106+
path := filepath.Join(dir, "sample.go")
107+
if err := os.WriteFile(path, []byte(src), 0o644); err != nil {
108+
t.Fatalf("write sample.go: %v", err)
109+
}
110+
return path
111+
}
112+
113+
runGen := func(file string) error {
114+
g := &Generator{Files: map[string]*File{}, outPath: filepath.Join(filepath.Dir(file), "out")}
115+
if err := g.Process(file); err != nil {
116+
return err
117+
}
118+
return g.Gen()
119+
}
120+
121+
withExcludeDir := t.TempDir()
122+
withExcludeFile := writeSample(withExcludeDir, true)
123+
if err := runGen(withExcludeFile); err != nil {
124+
t.Fatalf("generator should succeed when interface is excluded: %v", err)
125+
}
126+
127+
withoutExcludeDir := t.TempDir()
128+
withoutExcludeFile := writeSample(withoutExcludeDir, false)
129+
if err := runGen(withoutExcludeFile); err == nil {
130+
t.Fatalf("expected generator failure when interface is not excluded")
131+
}
132+
}
133+
81134
func TestProcessStructType(t *testing.T) {
82135
fileset := token.NewFileSet()
83136
file, err := parser.ParseFile(fileset, "../../examples/models/user.go", nil, parser.AllErrors)

0 commit comments

Comments
 (0)