From 84946ed55affa36d502430cd6219f6e440961f88 Mon Sep 17 00:00:00 2001 From: Tristan Willy Date: Mon, 25 Mar 2019 15:32:07 -0700 Subject: [PATCH] `func (v ) Ptr() *` for primitive typedefs Using typedefs on a base type is a common thrift pattern used to describe the kind of value that is within. While structs are trivial to form a pointer to (`&Foo{"foo"}`), this is not the case with primitive types (`type Jack string`, `&Jack("RJ45")`). This adds `.Ptr()` methods for primitive type aliases (`Jack("RJ45").Ptr()`). --- gen/internal/tests/collision/types.go | 10 +++++++ gen/internal/tests/services/types.go | 5 ++++ gen/internal/tests/typedefs/types.go | 15 +++++++++++ gen/internal/tests/uuid_conflict/types.go | 5 ++++ gen/quick_test.go | 33 +++++++++++++++++++++++ gen/typedef.go | 8 ++++++ gen/typedef_test.go | 4 +++ plugin/api/types.go | 10 +++++++ 8 files changed, 90 insertions(+) diff --git a/gen/internal/tests/collision/types.go b/gen/internal/tests/collision/types.go index 641c3d1e..6adbc7d2 100644 --- a/gen/internal/tests/collision/types.go +++ b/gen/internal/tests/collision/types.go @@ -446,6 +446,11 @@ func (v *AccessorNoConflict) IsSetGetName() bool { type LittlePotatoe int64 +// LittlePotatoePtr returns a pointer to a LittlePotatoe +func (v LittlePotatoe) Ptr() *LittlePotatoe { + return &v +} + // ToWire translates LittlePotatoe into a Thrift-level intermediate // representation. This intermediate representation may be serialized // into bytes using a ThriftRW protocol implementation. @@ -1659,6 +1664,11 @@ func (v *WithDefault) IsSetPouet() bool { type LittlePotatoe2 float64 +// LittlePotatoe2Ptr returns a pointer to a LittlePotatoe2 +func (v LittlePotatoe2) Ptr() *LittlePotatoe2 { + return &v +} + // ToWire translates LittlePotatoe2 into a Thrift-level intermediate // representation. This intermediate representation may be serialized // into bytes using a ThriftRW protocol implementation. diff --git a/gen/internal/tests/services/types.go b/gen/internal/tests/services/types.go index ae71605e..110df994 100644 --- a/gen/internal/tests/services/types.go +++ b/gen/internal/tests/services/types.go @@ -340,6 +340,11 @@ func (v *InternalError) Error() string { type Key string +// KeyPtr returns a pointer to a Key +func (v Key) Ptr() *Key { + return &v +} + // ToWire translates Key into a Thrift-level intermediate // representation. This intermediate representation may be serialized // into bytes using a ThriftRW protocol implementation. diff --git a/gen/internal/tests/typedefs/types.go b/gen/internal/tests/typedefs/types.go index b329c916..928a862c 100644 --- a/gen/internal/tests/typedefs/types.go +++ b/gen/internal/tests/typedefs/types.go @@ -947,6 +947,11 @@ func _EnumWithValues_Read(w wire.Value) (enums.EnumWithValues, error) { type MyEnum enums.EnumWithValues +// MyEnumPtr returns a pointer to a MyEnum +func (v MyEnum) Ptr() *MyEnum { + return &v +} + // ToWire translates MyEnum into a Thrift-level intermediate // representation. This intermediate representation may be serialized // into bytes using a ThriftRW protocol implementation. @@ -1217,6 +1222,11 @@ func (v PointMap) MarshalLogArray(enc zapcore.ArrayEncoder) error { type State string +// StatePtr returns a pointer to a State +func (v State) Ptr() *State { + return &v +} + // ToWire translates State into a Thrift-level intermediate // representation. This intermediate representation may be serialized // into bytes using a ThriftRW protocol implementation. @@ -1377,6 +1387,11 @@ func (v StateMap) MarshalLogObject(enc zapcore.ObjectEncoder) error { // Deprecated: Use ISOTime instead. type Timestamp int64 +// TimestampPtr returns a pointer to a Timestamp +func (v Timestamp) Ptr() *Timestamp { + return &v +} + // ToWire translates Timestamp into a Thrift-level intermediate // representation. This intermediate representation may be serialized // into bytes using a ThriftRW protocol implementation. diff --git a/gen/internal/tests/uuid_conflict/types.go b/gen/internal/tests/uuid_conflict/types.go index 5d71a11d..d0066296 100644 --- a/gen/internal/tests/uuid_conflict/types.go +++ b/gen/internal/tests/uuid_conflict/types.go @@ -15,6 +15,11 @@ import ( type UUID string +// UUIDPtr returns a pointer to a UUID +func (v UUID) Ptr() *UUID { + return &v +} + // ToWire translates UUID into a Thrift-level intermediate // representation. This intermediate representation may be serialized // into bytes using a ThriftRW protocol implementation. diff --git a/gen/quick_test.go b/gen/quick_test.go index 808893f1..50b48ae2 100644 --- a/gen/quick_test.go +++ b/gen/quick_test.go @@ -212,6 +212,19 @@ func isThriftNillable(typ reflect.Type) bool { return false } +// isThriftPrimitive returns true for Go types that are considered primitive +// (see gen.isPrimitiveType). +func isThriftPrimitive(typ reflect.Type) bool { + switch typ.Kind() { + case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, + reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, + reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, + reflect.Float64, reflect.String: + return true + } + return false +} + type thriftKind int const ( @@ -531,6 +544,15 @@ func TestQuickSuite(t *testing.T) { t.Run("Accessors/IsSetOnNil", func(t *testing.T) { suite.testIsSetAccessorsOnNil(t) }) + + case thriftTypedef: + if isThriftPrimitive(typ) { + t.Run("Ptr", func(t *testing.T) { + for _, give := range values { + suite.testTypedefPrimitivePtr(t, give) + } + }) + } } if !tt.NoLog { @@ -783,6 +805,17 @@ func (q *quickSuite) testEnumPtr(t *testing.T, give thriftType) { "pointer must point back to original value") } +// Tests that Ptr methods on typedefs exist and return the same value back. +func (q *quickSuite) testTypedefPrimitivePtr(t *testing.T, give thriftType) { + v := reflect.ValueOf(give) + method := v.MethodByName("Ptr") + require.True(t, method.IsValid(), "expected Ptr method to be present") + ptr := method.Call(nil)[0] + require.Equal(t, reflect.Ptr, ptr.Kind(), "must be a pointer") + assert.Equal(t, give, ptr.Interface(), + "pointer must point back to original value") +} + // Tests that each field of a struct has an accessor that returns the same // value as the field. func (q *quickSuite) testGetAccessors(t *testing.T, giveVal thriftType) { diff --git a/gen/typedef.go b/gen/typedef.go index 54f1d300..3a97b0e7 100644 --- a/gen/typedef.go +++ b/gen/typedef.go @@ -64,6 +64,14 @@ func typedef(g Generator, spec *compile.TypedefSpec) error { <$v := newVar "v"> <$x := newVar "x"> + + <- if isPrimitiveType .> + // Ptr returns a pointer to a <$typedefType> + func (<$v> ) Ptr() *<$typedefType>{ + return &<$v> + } + <- end> + // ToWire translates into a Thrift-level intermediate // representation. This intermediate representation may be serialized // into bytes using a ThriftRW protocol implementation. diff --git a/gen/typedef_test.go b/gen/typedef_test.go index 5b38810c..f54deede 100644 --- a/gen/typedef_test.go +++ b/gen/typedef_test.go @@ -538,3 +538,7 @@ func TestTypedefAccessors(t *testing.T) { }) }) } + +func TestTypedefPtr(t *testing.T) { + assert.Equal(t, td.State("foo"), *td.State("foo").Ptr()) +} diff --git a/plugin/api/types.go b/plugin/api/types.go index d4fdc3cd..1c027433 100644 --- a/plugin/api/types.go +++ b/plugin/api/types.go @@ -2499,6 +2499,11 @@ func (v *Module) GetThriftFilePath() (o string) { // modules in this request. type ModuleID int32 +// ModuleIDPtr returns a pointer to a ModuleID +func (v ModuleID) Ptr() *ModuleID { + return &v +} + // ToWire translates ModuleID into a Thrift-level intermediate // representation. This intermediate representation may be serialized // into bytes using a ThriftRW protocol implementation. @@ -2971,6 +2976,11 @@ func (v *Service) IsSetAnnotations() bool { // services in this request. type ServiceID int32 +// ServiceIDPtr returns a pointer to a ServiceID +func (v ServiceID) Ptr() *ServiceID { + return &v +} + // ToWire translates ServiceID into a Thrift-level intermediate // representation. This intermediate representation may be serialized // into bytes using a ThriftRW protocol implementation.