generated from dogmatiq/template-go
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
Try*()
function generation for one-of groups.
- Loading branch information
1 parent
f86adf6
commit 7e033e9
Showing
8 changed files
with
451 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// Package accessor generates an accessor method for each type in "one-of | ||
// groups". While "protoc-gen-go" plugin already generates accessor methods for | ||
// for each type in "one-of groups", the generated methods lack the ability to | ||
// differentiate between the absence of a value and the presence of a zero | ||
// value. | ||
package accessor |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package accessor | ||
|
||
import ( | ||
"github.com/dave/jennifer/jen" | ||
"github.com/dogmatiq/primo/internal/generator/internal/scope" | ||
) | ||
|
||
// Generate generates accessor methods for each type in one-of group. In | ||
// contrast to already available accessor methods generated by "protoc-gen-go" | ||
// plugin, these accessor methods return a boolean value indicating whether the | ||
// value is present or not. | ||
func Generate(code *jen.File, f *scope.File) error { | ||
for _, m := range f.Messages() { | ||
for _, g := range m.OneOfGroups() { | ||
generateForOneOf(code, g) | ||
} | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package accessor | ||
|
||
import ( | ||
"github.com/dave/jennifer/jen" | ||
"github.com/dogmatiq/primo/internal/generator/internal/scope" | ||
) | ||
|
||
func generateForOneOf(code *jen.File, g *scope.OneOfGroup) { | ||
for _, o := range g.Options { | ||
oneOfAccessorTryFunc(code, o) | ||
} | ||
} | ||
|
||
func oneOfAccessorTryFunc(code *jen.File, o *scope.OneOfOption) { | ||
methodName := "Try" + o.DiscriminatorFieldName | ||
|
||
code. | ||
Commentf( | ||
"%s returns the value of [%s] in one-of field x.%s.", | ||
methodName, | ||
o.DiscriminatorFieldName, | ||
o.Group.GoFieldName, | ||
) | ||
code.Comment("") | ||
code.Comment("ok returns false if the value of this type is not set.") | ||
|
||
code. | ||
Func(). | ||
Params( | ||
jen. | ||
Id("x"). | ||
Op("*"). | ||
Id(o.Group.Message.GoTypeName), | ||
). | ||
Id(methodName). | ||
Params(). | ||
Params( | ||
jen. | ||
Id("v"). | ||
Add(o.Field.GoType()), | ||
jen. | ||
Id("ok"). | ||
Add(jen.Bool()), | ||
). | ||
Block( | ||
jen. | ||
If( | ||
jen.List( | ||
jen.Id("x"), | ||
jen.Id("ok"), | ||
). | ||
Op(":="). | ||
Id("x"). | ||
Dot("Get"+o.Group.GoFieldName). | ||
Call(). | ||
Assert( | ||
jen.Op("*"). | ||
Id(o.DiscriminatorTypeName), | ||
). | ||
Op(";"). | ||
Id("ok"), | ||
).Block( | ||
jen.Return( | ||
jen.Id("x"). | ||
Dot(o.DiscriminatorFieldName), | ||
jen.True(), | ||
), | ||
), | ||
jen.Return( | ||
jen.Id("v"), | ||
jen.False(), | ||
), | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package accessor_test | ||
|
||
import ( | ||
reflect "reflect" | ||
"testing" | ||
|
||
"google.golang.org/protobuf/proto" | ||
) | ||
|
||
// testAccessor calls a mutator method to set the value and verifies that the | ||
// corresponding accessor returns the expected value and boolean ok value. | ||
func testAccessor[M proto.Message, T comparable]( | ||
t *testing.T, | ||
mutator func(M, T), | ||
accessor func(M) (T, bool), | ||
want T, | ||
) { | ||
t.Helper() | ||
|
||
testAccessorFunc( | ||
t, | ||
mutator, | ||
accessor, | ||
want, | ||
func(a, b T) bool { return a == b }, | ||
) | ||
} | ||
|
||
// testAccessorFunc calls a mutator method to set the value and verifies that the | ||
// corresponding accessor returns the expected value and boolean ok value. | ||
func testAccessorFunc[M proto.Message, T any]( | ||
t *testing.T, | ||
mutate func(M, T), | ||
access func(M) (T, bool), | ||
want T, | ||
eq func(T, T) bool, | ||
) { | ||
t.Helper() | ||
|
||
var m M | ||
m = reflect.New( | ||
reflect.TypeOf(m).Elem(), | ||
).Interface().(M) | ||
|
||
mutate(m, want) | ||
|
||
got, gotOK := access(m) | ||
if !gotOK { | ||
t.Fatalf( | ||
"accessor did not return expected ok as true", | ||
) | ||
} | ||
|
||
if !eq(got, want) { | ||
t.Fatalf( | ||
"accessor did not return the expected value: got: %v, want: %v", | ||
got, | ||
want, | ||
) | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
syntax = "proto3"; | ||
package primo.test.mutators; | ||
|
||
option go_package = "github.com/dogmatiq/primo/internal/test/accessor"; | ||
|
||
message OneOf { | ||
oneof group { | ||
int32 field_a = 1; // note: two fields of the same type | ||
int32 field_b = 2; | ||
string field_c = 3; | ||
} | ||
} |
Oops, something went wrong.