-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
THRIFT-3037 Go Codegen - Support Struct TypeDefs #2888
base: master
Are you sure you want to change the base?
THRIFT-3037 Go Codegen - Support Struct TypeDefs #2888
Conversation
0ed4cd1
to
cc2d009
Compare
Please create a jira ticket to describe what problem you are trying to resolve, what's the before and after generated go code from what thrift code. |
Hello @fishy ! :) The ticket THRIFT-3037 best describes this issue so I figured it best not to create a duplicate. Here is an example of how the generated code changes. I've listed them as bullet points for the major changes. Change descriptionThis PR makes it possible for typedefs that don't refer to a primative type to compile. This is accomplished by using a struct instead of declaring a type pointer (fixes the issue with READ methods etc. not existing). Code changesHere is the example schema which we will be using to describe the issue. Without the change, the code does not compile. struct ExampleRequest {
1: required string example_field
}
struct ExampleResponse {
1: required string example_field
}
typedef ExampleRequest TypedefExampleRequest
typedef ExampleResponse TypedefExampleResponse
service EnvironmentService {
ExampleResponse exampleMethod(1: ExampleRequest request)
TypedefExampleResponse typedefExampleMethod(1: TypedefExampleRequest request)
} Each change will have a title and will be formatted in three sections. Code Change (this PR), previous generated code and new generated code. Use Structs instead of aliasesThis was needed as you can't refer to methods on aliased types. You instead need to implement the existing struct to inherit it's methods. Code changethrift/compiler/cpp/src/thrift/generate/t_go_generator.cc Lines 769 to 773 in cc2d009
Old Codetype TypedefExampleRequest *ExampleRequest
func TypedefExampleRequestPtr(v TypedefExampleRequest) *TypedefExampleRequest { return &v }
type TypedefExampleResponse *ExampleResponse
func TypedefExampleResponsePtr(v TypedefExampleResponse) *TypedefExampleResponse { return &v } New Codetype TypedefExampleRequest struct { *ExampleRequest }
func TypedefExampleRequestPtr(v TypedefExampleRequest) *TypedefExampleRequest { return &v }
type TypedefExampleResponse struct { *ExampleResponse }
func TypedefExampleResponsePtr(v TypedefExampleResponse) *TypedefExampleResponse { return &v } For Forward TypeDefs use the original typedef nameThis was needed as it wouldn't use the correct type. For example it would use Code changethrift/compiler/cpp/src/thrift/generate/t_go_generator.cc Lines 2093 to 2094 in cc2d009
Old Codefunc (p *EnvironmentServiceTypedefExampleMethodArgs) ReadField1(ctx context.Context, iprot thrift.TProtocol) error {
p.Request = &ExampleRequest{}
if err := p.Request.Read(ctx, iprot); err != nil {
return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Request), err)
}
return nil
} New Codefunc (p *EnvironmentServiceTypedefExampleMethodArgs) ReadField1(ctx context.Context, iprot thrift.TProtocol) error {
p.Request = &TypedefExampleRequest{}
if err := p.Request.Read(ctx, iprot); err != nil {
return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Request), err)
}
return nil
} Pleasse let me know if there's anything else I can clarify :) |
Thanks. Please
|
Thanks for the PR! I've unassigned myself from the ticket and I agree with @fishy that an alias would be better. |
b6ebd28
to
2905dfa
Compare
@dcelasun and @fishy thank you for the quick response :) I have a Jira account As for the struct implementation, I've added it to simplify the code ex: For testing I added a service to the Go test which will cause a compile failure. I'm struggling to get the suite working locally. Do you have any other guidance aside from the existing Readme file I can reference? |
test/TypedefTest.thrift
Outdated
typedef TypedefTestStruct MyStruct | ||
typedef string MyStringTypedef |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you have the order wrong here, you want this instead:
typedef string MyStringTypedef | |
typedef MyStringTypedef string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oddly my IDE says that string needs to be put first in this case.
Is it not typedef actual_type alias_name
as the format?
also, thrift files under |
2905dfa
to
344119c
Compare
@fishy I've added a test in the Currently it will test:
|
5084784
to
4c7799b
Compare
4c7799b
to
4762b4e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it looks like this change also changes primitive type typedefs into aliases, from the compiler generated go code:
type PrimativeTypedefExampleRequest = string
while previously that's
type PrimativeTypedefExampleRequest string
while this does not seem to break any tests, I'd prefer the old behavior. The reason is that with the old behavior, it forces you to do a typecasting when writing the go code, so the name of the type can be used as both documentation and reminder of the unit of the value. Take this example:
typedef i64 UnixMilliseconds
struct Foo {
1: optional UnixMilliseconds timestamp;
}
with alias you could write this go code:
foo.Timestamp = thrift.Pointer(int64(now.Seconds()))
without compiler complaining anything, and that's wrong. with the old behavior you have to write this to make compiler happy:
foo.Timestamp = thrift.Pointer(UnixMilliseconds(now.Seconds()))
which makes it obvious that the code has a bug.
@@ -172,4 +175,5 @@ EXTRA_DIST = \ | |||
TypedefFieldTest.thrift \ | |||
UnionBinaryTest.thrift \ | |||
UnionDefaultValueTest.thrift \ | |||
ValidateTest.thrift | |||
ValidateTest.thrift \ | |||
TypedefServiceTest.thrift |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrong indentation (should be a tab instead of 4 spaces)
@@ -124,7 +126,8 @@ check: gopath | |||
./gopath/src/processormiddlewaretest \ | |||
./gopath/src/clientmiddlewareexceptiontest \ | |||
./gopath/src/validatetest \ | |||
./gopath/src/forwardtypetest | |||
./gopath/src/forwardtypetest \ | |||
./gopath/src/typedefservicetest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrong indentation (should be 4 spaces tabs)
@@ -62,7 +62,8 @@ gopath: $(THRIFT) $(THRIFTTEST) \ | |||
ProcessorMiddlewareTest.thrift \ | |||
ClientMiddlewareExceptionTest.thrift \ | |||
ValidateTest.thrift \ | |||
ForwardType.thrift | |||
ForwardType.thrift \ | |||
TypedefServiceTest.thrift |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
@@ -176,7 +177,8 @@ class t_go_generator : public t_generator { | |||
t_struct* tstruct, | |||
bool is_pointer_field, | |||
bool declare, | |||
std::string prefix = ""); | |||
std::string prefix = "", | |||
string alias_name = ""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you use std::string
over string
here?
it doesn't look like we are very consistent here, but being consistent partially is still better, while the line right above is using std::string
it's better to keep that.
@@ -124,7 +124,8 @@ class t_go_generator : public t_generator { | |||
bool is_args = false); | |||
void generate_go_struct_initializer(std::ostream& out, | |||
t_struct* tstruct, | |||
bool is_args_or_result = false); | |||
bool is_args_or_result = false, | |||
string alias_name = ""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similar here, let's use std::string
instead
also, now #2886 is merged, please rebase your change on top of latest master so the CI will actually run your tests. |
@ethan-gallant any progress on this? Happy to help with any issues. |
@ethan-gallant Is there any update on this? I am also facing the similar issue. |
No description provided.