Skip to content

Commit

Permalink
Merge pull request #27 from phelmkamp/equal
Browse files Browse the repository at this point in the history
implement `equal` directive
  • Loading branch information
phelmkamp authored Dec 22, 2019
2 parents 444b962 + 8a0a7e5 commit a9b297f
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 3 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ Includes the field in the result of the generated `String` method. Uses value re

Includes the field as an argument to the generated `New$Type` method.

`equal`

Includes the field in the generated `Equal` method.
Specify the `reflect` option to compare the field using `reflect.DeepEqual`.
Uses value receiver by default.

`ptr`

Specifies that a pointer receiver be used for all subsequent directives.
Expand Down
44 changes: 44 additions & 0 deletions directive/directive.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
const (
optOmitField = "omitfield"
optStringer = "stringer"
optReflect = "reflect"
)

// Target represents the target of the directive
Expand Down Expand Up @@ -255,6 +256,49 @@ func New(tgt *Target) {
}
}

// Equal adds each name of the given field to the Equal() implementation
func Equal(tgt *Target, opts []string) {
for _, fldNm := range tgt.FldNames {
log.Print("Adding to method: Equal\n")
found := tgt.MetaFile.FilterMethods(
func(m *meta.Method) bool {
return m.RcvName == tgt.RcvName && m.RcvType == tgt.RcvType && m.Name == "Equal"
},
1,
)
var cmps string
var equal *meta.Method
if len(found) > 0 {
equal = found[0]
cmps = equal.Misc["Cmps"].(string) + "\n\t"
} else {
equal = &meta.Method{
RcvName: tgt.RcvName,
RcvType: tgt.RcvType,
Name: "Equal",
Misc: make(map[string]interface{}),
Tmpl: "equal",
}
tgt.MetaFile.Methods = append(tgt.MetaFile.Methods, equal)
}
var cmp string
if len(opts) > 0 && opts[0] == optReflect {
log.Print("Adding import: \"reflect\"\n")
tgt.MetaFile.Imports["reflect"] = struct{}{}
cmp = fmt.Sprintf(
"if !reflect.DeepEqual(%s.%s, %s2.%s) {\n\t\treturn false\n\t}",
tgt.RcvName, fldNm, tgt.RcvName, fldNm,
)
} else {
cmp = fmt.Sprintf(
"if %s.%s != %s2.%s {\n\t\treturn false\n\t}",
tgt.RcvName, fldNm, tgt.RcvName, fldNm,
)
}
equal.Misc["Cmps"] = cmps + cmp
}
}

func first(s string) (string, int) {
if s == "" {
return "", 0
Expand Down
4 changes: 2 additions & 2 deletions internal/testdata/foo.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ type Foo struct {
}

type Bar struct {
name string `meta:"stringer"`
name string `meta:"stringer;equal"`
foos []Foo `meta:"getter;setter;map:string"`
pairs map[string]float64 `meta:"getter;setter"`
times []time.Time `meta:"getter;setter;filter;map:int64"`
times []time.Time `meta:"getter;setter;filter;map:int64;equal,reflect"`
baz bool `meta:"setter"`
}
19 changes: 18 additions & 1 deletion internal/testdata/foo_meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
package testdata

import (
"fmt"
"time"
"fmt"
"reflect"
)

// NewFoo creates a new Foo with the given initial values.
Expand Down Expand Up @@ -88,6 +89,22 @@ func (b Bar) String() string {
return fmt.Sprintf("%v", b.name)
}

// Equal answers whether v is equivalent to b.
// Always returns false if v is not a Bar.
func (b Bar) Equal(v interface{}) bool {
b2, ok := v.(Bar)
if !ok {
return false
}
if b.name != b2.name {
return false
}
if !reflect.DeepEqual(b.times, b2.times) {
return false
}
return true
}

// Foos returns the value of foos.
func (b Bar) Foos() []Foo {
return b.foos
Expand Down
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ func main() {
directive.Stringer(&fldTgt)
case "new":
directive.New(&fldTgt)
case "equal":
directive.Equal(&fldTgt, opts)
default:
log.Printf("Unknown directive: %s\n", d)
}
Expand Down
10 changes: 10 additions & 0 deletions meta/templates/equal.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Equal answers whether v is equivalent to {{.RcvName}}.
// Always returns false if v is not a {{.RcvType}}.
func ({{.RcvName}} {{.RcvType}}) Equal(v interface{}) bool {
{{.RcvName}}2, ok := v.({{.RcvType}})
if !ok {
return false
}
{{.Misc.Cmps}}
return true
}

0 comments on commit a9b297f

Please sign in to comment.