Uploaded image for project: 'Thrift'
  1. Thrift
  2. THRIFT-4631

Codegen Creates Invalid Ruby for Recursive Structs

    XMLWordPrintableJSON

Details

    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

          Activity

            People

              jking3 James E. King III
              cgardens charles giardina
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: