[
https://issues.apache.org/jira/browse/THRIFT-4631?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16616300#comment-16616300
]
ASF GitHub Bot commented on THRIFT-4631:
----------------------------------------
jeking3 closed pull request #1592: THRIFT-4631 Fix Ruby codegen to gen valid
ruby for recursive structs
URL: https://github.com/apache/thrift/pull/1592
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git a/compiler/cpp/src/thrift/generate/t_rb_generator.cc
b/compiler/cpp/src/thrift/generate/t_rb_generator.cc
index 3f2b78e6ad..13ea2490eb 100644
--- a/compiler/cpp/src/thrift/generate/t_rb_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_rb_generator.cc
@@ -113,6 +113,7 @@ class t_rb_generator : public t_oop_generator {
void generate_enum(t_enum* tenum);
void generate_const(t_const* tconst);
void generate_struct(t_struct* tstruct);
+ void generate_forward_declaration(t_struct* tstruct);
void generate_union(t_struct* tunion);
void generate_xception(t_struct* txception);
void generate_service(t_service* tservice);
@@ -123,6 +124,7 @@ class t_rb_generator : public t_oop_generator {
* Struct generation code
*/
+ void generate_rb_struct_declaration(t_rb_ofstream& out, t_struct* tstruct,
bool is_exception);
void generate_rb_struct(t_rb_ofstream& out, t_struct* tstruct, bool
is_exception);
void generate_rb_struct_required_validator(t_rb_ofstream& out, t_struct*
tstruct);
void generate_rb_union(t_rb_ofstream& out, t_struct* tstruct, bool
is_exception);
@@ -529,6 +531,29 @@ void t_rb_generator::generate_struct(t_struct* tstruct) {
}
}
+
+/**
+ * Generates the "forward declarations" for ruby structs.
+ * These are simply a declaration of each class with proper inheritance.
+ * The rest of the struct is still generated in generate_struct as has
+ * always been the case. These declarations allow thrift to generate valid
+ * ruby in cases where thrift structs rely on recursive definitions.
+ */
+void t_rb_generator::generate_forward_declaration(t_struct* tstruct) {
+ generate_rb_struct_declaration(f_types_, tstruct, tstruct->is_xception());
+}
+
+void t_rb_generator::generate_rb_struct_declaration(t_rb_ofstream& out,
t_struct* tstruct, bool is_exception) {
+ out.indent() << "class " << type_name(tstruct);
+ if (tstruct->is_union()) {
+ out << " < ::Thrift::Union";
+ }
+ if (is_exception) {
+ out << " < ::Thrift::Exception";
+ }
+ out << "; end" << endl << endl;
+}
+
/**
* Generates a struct definition for a thrift exception. Basically the same
* as a struct but extends the Exception class.
diff --git a/test/rb/Makefile.am b/test/rb/Makefile.am
index 4bd4704817..cfdc1496ef 100644
--- a/test/rb/Makefile.am
+++ b/test/rb/Makefile.am
@@ -20,6 +20,7 @@
stubs: $(THRIFT) ../ThriftTest.thrift ../SmallTest.thrift
$(THRIFT) --gen rb ../ThriftTest.thrift
$(THRIFT) --gen rb ../SmallTest.thrift
+ $(THRIFT) --gen rb ../Recursive.thrift
precross: stubs
diff --git a/test/rb/generation/test_recursive.rb
b/test/rb/generation/test_recursive.rb
new file mode 100644
index 0000000000..e912f72f53
--- /dev/null
+++ b/test/rb/generation/test_recursive.rb
@@ -0,0 +1,41 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+require File.join(File.dirname(__FILE__), '../test_helper')
+require 'recursive_types'
+
+class TestRecursiveGeneration < Test::Unit::TestCase
+ CHILD_ITEM = "child item"
+ PARENT_ITEM = "parent item"
+
+ def test_can_create_recursive_tree
+
+ child_tree = RecTree.new
+ child_tree.item = CHILD_ITEM
+
+ parent_tree = RecTree.new
+ parent_tree.item = PARENT_ITEM
+ parent_tree.children = [child_tree]
+
+ assert_equal(PARENT_ITEM, parent_tree.item)
+ assert_equal(1, parent_tree.children.length)
+ assert_equal(CHILD_ITEM, parent_tree.children.first.item)
+ assert_nil(parent_tree.children.first.children)
+ end
+end
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
> Codegen Creates Invalid Ruby for Recursive Structs
> --------------------------------------------------
>
> Key: THRIFT-4631
> URL: https://issues.apache.org/jira/browse/THRIFT-4631
> Project: Thrift
> Issue Type: Bug
> Components: Ruby - Compiler, Ruby - Library
> Affects Versions: 0.11.0
> Reporter: charles giardina
> Assignee: James E. King III
> Priority: Minor
> Fix For: 0.12.0
>
>
> 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:
> {code:java}
> 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
> {code}
>
> 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:
> {code:java}
> #
> # 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
> {code}
>
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)