Client: Ruby

re: https://issues.apache.org/jira/browse/THRIFT-4631

The goal of this PR is to alter the thrift ruby code generator so that in cases 
where we define structs that rely on recursion, it generates valid ruby.

The codegen include a `generate_forward_declaration` method which gets called 
before `generate_struct`. It allows us to eagerly declare ruby classes so that 
all classes are declared before any of the recursion within the classes 
executes. Without implementing something like this you get an `uninitialized 
constant` exception.

I've added tests to catch the original issue as well.

The delta caused by the this change is adding class declarations at the top of 
the generated files. Here's the delta alone. Full copies of the before / after 
below.
```
class RecTree; end

class RecList; end

class CoRec; end

class CoRec2; end

class VectorTest; end
```


What gets generated now for Recursive.thrift
```
#
# Autogenerated by Thrift Compiler (1.0.0-dev)
#
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
#

require 'thrift'

class RecTree
  include ::Thrift::Struct, ::Thrift::Struct_Union
  CHILDREN = 1
  ITEM = 2

  FIELDS = {
    CHILDREN => {:type => ::Thrift::Types::LIST, :name => 'children', :element 
=> {:type => ::Thrift::Types::STRUCT, :class => ::RecTree}},
    ITEM => {:type => ::Thrift::Types::I16, :name => 'item'}
  }

  def struct_fields; FIELDS; end

  def validate
  end

  ::Thrift::Struct.generate_accessors self
end

class RecList
  include ::Thrift::Struct, ::Thrift::Struct_Union
  NEXTITEM = 1
  ITEM = 3

  FIELDS = {
    NEXTITEM => {:type => ::Thrift::Types::STRUCT, :name => 'nextitem', :class 
=> ::RecList},
    ITEM => {:type => ::Thrift::Types::I16, :name => 'item'}
  }

  def struct_fields; FIELDS; end

  def validate
  end

  ::Thrift::Struct.generate_accessors self
end

class CoRec
  include ::Thrift::Struct, ::Thrift::Struct_Union
  OTHER = 1

  FIELDS = {
    OTHER => {:type => ::Thrift::Types::STRUCT, :name => 'other', :class => 
::CoRec2}
  }

  def struct_fields; FIELDS; end

  def validate
  end

  ::Thrift::Struct.generate_accessors self
end

class CoRec2
  include ::Thrift::Struct, ::Thrift::Struct_Union
  OTHER = 1

  FIELDS = {
    OTHER => {:type => ::Thrift::Types::STRUCT, :name => 'other', :class => 
::CoRec}
  }

  def struct_fields; FIELDS; end

  def validate
  end

  ::Thrift::Struct.generate_accessors self
end

class VectorTest
  include ::Thrift::Struct, ::Thrift::Struct_Union
  LISTER = 1

  FIELDS = {
    LISTER => {:type => ::Thrift::Types::LIST, :name => 'lister', :element => 
{:type => ::Thrift::Types::STRUCT, :class => ::RecList}}
  }

  def struct_fields; FIELDS; end

  def validate
  end

  ::Thrift::Struct.generate_accessors self
end
```

What is generated using this PR:
```
#
# Autogenerated by Thrift Compiler (1.0.0-dev)
#
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
#

require 'thrift'

class RecTree; end

class RecList; end

class CoRec; end

class CoRec2; end

class VectorTest; end

class RecTree
  include ::Thrift::Struct, ::Thrift::Struct_Union
  CHILDREN = 1
  ITEM = 2

  FIELDS = {
    CHILDREN => {:type => ::Thrift::Types::LIST, :name => 'children', :element 
=> {:type => ::Thrift::Types::STRUCT, :class => ::RecTree}},
    ITEM => {:type => ::Thrift::Types::I16, :name => 'item'}
  }

  def struct_fields; FIELDS; end

  def validate
  end

  ::Thrift::Struct.generate_accessors self
end

class RecList
  include ::Thrift::Struct, ::Thrift::Struct_Union
  NEXTITEM = 1
  ITEM = 3

  FIELDS = {
    NEXTITEM => {:type => ::Thrift::Types::STRUCT, :name => 'nextitem', :class 
=> ::RecList},
    ITEM => {:type => ::Thrift::Types::I16, :name => 'item'}
  }

  def struct_fields; FIELDS; end

  def validate
  end

  ::Thrift::Struct.generate_accessors self
end

class CoRec
  include ::Thrift::Struct, ::Thrift::Struct_Union
  OTHER = 1

  FIELDS = {
    OTHER => {:type => ::Thrift::Types::STRUCT, :name => 'other', :class => 
::CoRec2}
  }

  def struct_fields; FIELDS; end

  def validate
  end

  ::Thrift::Struct.generate_accessors self
end

class CoRec2
  include ::Thrift::Struct, ::Thrift::Struct_Union
  OTHER = 1

  FIELDS = {
    OTHER => {:type => ::Thrift::Types::STRUCT, :name => 'other', :class => 
::CoRec}
  }

  def struct_fields; FIELDS; end

  def validate
  end

  ::Thrift::Struct.generate_accessors self
end

class VectorTest
  include ::Thrift::Struct, ::Thrift::Struct_Union
  LISTER = 1

  FIELDS = {
    LISTER => {:type => ::Thrift::Types::LIST, :name => 'lister', :element => 
{:type => ::Thrift::Types::STRUCT, :class => ::RecList}}
  }

  def struct_fields; FIELDS; end

  def validate
  end

  ::Thrift::Struct.generate_accessors self
end
```




[ Full content available at: https://github.com/apache/thrift/pull/1592 ]
This message was relayed via gitbox.apache.org for [email protected]

Reply via email to