Details
-
Bug
-
Status: Closed
-
Minor
-
Resolution: Fixed
-
0.11.0
-
None
Description
Though thrift supports defining recursive structs, it appears that the Ruby codegen does not generate valid Ruby for for recursive structs.
e.g. Here's an example of what I'm seeing and how to recreate it using Recursive.thrift in the Thrift test suite.
- add $(THRIFT) --gen rb ../Recursive.thrift to test/rb/Makefile.am
- and add require "recursive_types" to test/rb/generation/test_struct.rb
- run make -k check from test/rb
- this ends up raising the following exception:
thrift/test/rb/gen-rb/recursive_types.rb:50:in `<class:CoRec>': uninitialized constant CoRec2 (NameError) Did you mean? CoRec from thrift/test/rb/gen-rb/recursive_types.rb:45:in `<top (required)>' from thrift/test/rb/generation/test_struct.rb:22:in `require' from thrift/test/rb/generation/test_struct.rb:22:in `<top (required)>' from test_suite.rb:20:in `require' from test_suite.rb:20:in `block in <main>' from test_suite.rb:20:in `each' from test_suite.rb:20:in `<main>' make: *** [check] Error 1
I've copied the generated code below. But essentially the issue appears to be that recursive structs are referencing constants or classes that have not yet been declared. I have some ideas on how to address this and can post a proposed solution.
generated code:
# # Autogenerated by Thrift Compiler (0.11.0) # # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING # require 'thrift' module RecursiveExample class Node < ::Thrift::Union include ::Thrift::Struct_Union class << self def inner_node(val) Node.new(:inner_node, val) end def leaf_node(val) Node.new(:leaf_node, val) end end INNER_NODE = 1 LEAF_NODE = 2 FIELDS = { INNER_NODE => {:type => ::Thrift::Types::STRUCT, :name => 'inner_node', :class => ::RecursiveExample::InnerNode, :optional => true}, LEAF_NODE => {:type => ::Thrift::Types::STRUCT, :name => 'leaf_node', :class => ::RecursiveExample::LeafNode, :optional => true} } def struct_fields; FIELDS; end def validate raise(StandardError, 'Union fields are not set.') if get_set_field.nil? || get_value.nil? end ::Thrift::Union.generate_accessors self end class InnerNode include ::Thrift::Struct, ::Thrift::Struct_Union NODE = 1 FIELDS = { NODE => {:type => ::Thrift::Types::STRUCT, :name => 'node', :class => ::RecursiveExample::Node} } def struct_fields; FIELDS; end def validate raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, 'Required field node is unset!') unless @node end ::Thrift::Struct.generate_accessors self end class LeafNode include ::Thrift::Struct, ::Thrift::Struct_Union FIELDS = { } def struct_fields; FIELDS; end def validate end ::Thrift::Struct.generate_accessors self end end
Attachments
Issue Links
- links to