You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by jf...@apache.org on 2014/06/27 04:55:01 UTC

git commit: Thrift-THRIFT-2574: Compiler option to generate namespace directories for Ruby Client: rb Patch: Andrew Bloomgarden

Repository: thrift
Updated Branches:
  refs/heads/master c9bdd5027 -> bf2617ed1


Thrift-THRIFT-2574: Compiler option to generate namespace directories for Ruby
Client: rb
Patch: Andrew Bloomgarden

Adds option to generate namespaced ruby classes.

Github: closes #140


Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/bf2617ed
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/bf2617ed
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/bf2617ed

Branch: refs/heads/master
Commit: bf2617ed15f95e22bcf41fd9d08e7ce562464f46
Parents: c9bdd50
Author: jfarrell <jf...@apache.org>
Authored: Thu Jun 26 22:53:01 2014 -0400
Committer: jfarrell <jf...@apache.org>
Committed: Thu Jun 26 22:53:01 2014 -0400

----------------------------------------------------------------------
 compiler/cpp/src/generate/t_rb_generator.cc | 64 ++++++++++++++++++++----
 lib/rb/Rakefile                             |  7 ++-
 lib/rb/spec/Referenced.thrift               | 44 ++++++++++++++++
 lib/rb/spec/ThriftNamespacedSpec.thrift     | 53 ++++++++++++++++++++
 lib/rb/spec/namespaced_spec.rb              | 62 +++++++++++++++++++++++
 5 files changed, 219 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/bf2617ed/compiler/cpp/src/generate/t_rb_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_rb_generator.cc b/compiler/cpp/src/generate/t_rb_generator.cc
index 2a6a472..dec53dd 100644
--- a/compiler/cpp/src/generate/t_rb_generator.cc
+++ b/compiler/cpp/src/generate/t_rb_generator.cc
@@ -82,6 +82,7 @@ class t_rb_generator : public t_oop_generator {
     out_dir_base_ = "gen-rb";
 
     require_rubygems_ = (parsed_options.find("rubygems") != parsed_options.end());
+    namespaced_ = (parsed_options.find("namespaced") != parsed_options.end());
   }
 
   /**
@@ -201,7 +202,7 @@ class t_rb_generator : public t_oop_generator {
   std::string function_signature(t_function* tfunction, std::string prefix="");
   std::string argument_list(t_struct* tstruct);
   std::string type_to_enum(t_type* ttype);
-
+  std::string rb_namespace_to_path_prefix(std::string rb_namespace);
 
 
   std::vector<std::string> ruby_modules(t_program* p) {
@@ -238,8 +239,14 @@ class t_rb_generator : public t_oop_generator {
   t_rb_ofstream f_consts_;
   t_rb_ofstream f_service_;
 
+  std::string namespace_dir_;
+  std::string require_prefix_;
+
   /** If true, add a "require 'rubygems'" line to the top of each gen-rb file. */
   bool require_rubygems_;
+
+  /** If true, generate files in idiomatic namespaced directories. */
+  bool namespaced_;
 };
 
 
@@ -250,14 +257,31 @@ class t_rb_generator : public t_oop_generator {
  * @param tprogram The program to generate
  */
 void t_rb_generator::init_generator() {
+  string subdir = get_out_dir();
+
   // Make output directory
-  MKDIR(get_out_dir().c_str());
+  MKDIR(subdir.c_str());
+
+  if (namespaced_) {
+    require_prefix_ = rb_namespace_to_path_prefix(program_->get_namespace("rb"));
+
+    string dir = require_prefix_;
+    string::size_type loc;
+
+    while ((loc = dir.find("/")) != string::npos) {
+      subdir = subdir + dir.substr(0, loc) + "/";
+      MKDIR(subdir.c_str());
+      dir = dir.substr(loc+1);
+    }
+  }
+
+  namespace_dir_ = subdir;
 
   // Make output file
-  string f_types_name = get_out_dir()+underscore(program_name_)+"_types.rb";
+  string f_types_name = namespace_dir_+underscore(program_name_)+"_types.rb";
   f_types_.open(f_types_name.c_str());
 
-  string f_consts_name = get_out_dir()+underscore(program_name_)+"_constants.rb";
+  string f_consts_name = namespace_dir_+underscore(program_name_)+"_constants.rb";
   f_consts_.open(f_consts_name.c_str());
 
   // Print header
@@ -268,7 +292,7 @@ void t_rb_generator::init_generator() {
 
   f_consts_ <<
     rb_autogen_comment() << endl << render_require_thrift() <<
-    "require '" << underscore(program_name_) << "_types'" << endl <<
+    "require '" << require_prefix_ << underscore(program_name_) << "_types'" << endl <<
     endl;
     begin_namespace(f_consts_, ruby_modules(program_));
 
@@ -292,7 +316,10 @@ string t_rb_generator::render_includes() {
   const vector<t_program*>& includes = program_->get_includes();
   string result = "";
   for (size_t i = 0; i < includes.size(); ++i) {
-    result += "require '" + underscore(includes[i]->get_name()) + "_types'\n";
+    t_program* included = includes[i];
+    std::string included_require_prefix = rb_namespace_to_path_prefix(included->get_namespace("rb"));
+    std::string included_name = included->get_name();
+    result += "require '" + included_require_prefix + underscore(included_name) + "_types'\n";
   }
   if (includes.size() > 0) {
     result += "\n";
@@ -728,7 +755,7 @@ void t_rb_generator::end_namespace(t_rb_ofstream& out, vector<std::string> modul
  * @param tservice The service definition
  */
 void t_rb_generator::generate_service(t_service* tservice) {
-  string f_service_name = get_out_dir()+underscore(service_name_)+".rb";
+  string f_service_name = namespace_dir_+underscore(service_name_)+".rb";
   f_service_.open(f_service_name.c_str());
 
   f_service_ <<
@@ -736,11 +763,11 @@ void t_rb_generator::generate_service(t_service* tservice) {
 
   if (tservice->get_extends() != NULL) {
     f_service_ <<
-      "require '" << underscore(tservice->get_extends()->get_name()) << "'" << endl;
+      "require '" << require_prefix_ << underscore(tservice->get_extends()->get_name()) << "'" << endl;
   }
 
   f_service_ <<
-    "require '" << underscore(program_name_) << "_types'" << endl <<
+    "require '" << require_prefix_ << underscore(program_name_) << "_types'" << endl <<
     endl;
 
   begin_namespace(f_service_, ruby_modules(tservice->get_program()));
@@ -1138,6 +1165,22 @@ string t_rb_generator::type_to_enum(t_type* type) {
   throw "INVALID TYPE IN type_to_enum: " + type->get_name();
 }
 
+string t_rb_generator::rb_namespace_to_path_prefix(string rb_namespace) {
+  string namespaces_left = rb_namespace;
+  string::size_type loc;
+
+  string path_prefix = "";
+
+  while ((loc = namespaces_left.find(".")) != string::npos) {
+    path_prefix = path_prefix + underscore(namespaces_left.substr(0, loc)) + "/";
+    namespaces_left = namespaces_left.substr(loc+1);
+  }
+  if (namespaces_left.size() > 0) {
+    path_prefix = path_prefix + underscore(namespaces_left) + "/";
+  }
+  return path_prefix;
+}
+
 
 void t_rb_generator::generate_rdoc(t_rb_ofstream& out, t_doc* tdoc) {
   if (tdoc->has_doc()) {
@@ -1221,4 +1264,5 @@ void t_rb_generator::generate_rb_union_validator(t_rb_ofstream& out,
 }
 
 THRIFT_REGISTER_GENERATOR(rb, "Ruby",
-"    rubygems:        Add a \"require 'rubygems'\" line to the top of each generated file.\n")
+"    rubygems:        Add a \"require 'rubygems'\" line to the top of each generated file.\n"
+"    namespaced:      Generate files in idiomatic namespaced directories.\n")

http://git-wip-us.apache.org/repos/asf/thrift/blob/bf2617ed/lib/rb/Rakefile
----------------------------------------------------------------------
diff --git a/lib/rb/Rakefile b/lib/rb/Rakefile
index f533d06..ef00a9f 100644
--- a/lib/rb/Rakefile
+++ b/lib/rb/Rakefile
@@ -38,13 +38,18 @@ RSpec::Core::RakeTask.new(:'spec:rcov') do |t|
 end
 
 desc 'Compile the .thrift files for the specs'
-task :'gen-rb' => [:'gen-rb:spec', :'gen-rb:benchmark', :'gen-rb:debug_proto']
+task :'gen-rb' => [:'gen-rb:spec', :'gen-rb:namespaced_spec', :'gen-rb:benchmark', :'gen-rb:debug_proto']
 namespace :'gen-rb' do
   task :'spec' do
     dir = File.dirname(__FILE__) + '/spec'
     sh THRIFT, '--gen', 'rb', '-o', dir, "#{dir}/ThriftSpec.thrift"
   end
 
+  task :'namespaced_spec' do
+    dir = File.dirname(__FILE__) + '/spec'
+    sh THRIFT, '--gen', 'rb:namespaced', '-recurse', '-o', dir, "#{dir}/ThriftNamespacedSpec.thrift"
+  end
+
   task :'benchmark' do
     dir = File.dirname(__FILE__) + '/benchmark'
     sh THRIFT, '--gen', 'rb', '-o', dir, "#{dir}/Benchmark.thrift"

http://git-wip-us.apache.org/repos/asf/thrift/blob/bf2617ed/lib/rb/spec/Referenced.thrift
----------------------------------------------------------------------
diff --git a/lib/rb/spec/Referenced.thrift b/lib/rb/spec/Referenced.thrift
new file mode 100644
index 0000000..98f183f
--- /dev/null
+++ b/lib/rb/spec/Referenced.thrift
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#
+# 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.
+#
+
+namespace rb OtherNamespace
+
+enum SomeEnum {
+  ONE
+  TWO
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/bf2617ed/lib/rb/spec/ThriftNamespacedSpec.thrift
----------------------------------------------------------------------
diff --git a/lib/rb/spec/ThriftNamespacedSpec.thrift b/lib/rb/spec/ThriftNamespacedSpec.thrift
new file mode 100644
index 0000000..02f2889
--- /dev/null
+++ b/lib/rb/spec/ThriftNamespacedSpec.thrift
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+#
+# 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.
+#
+
+namespace rb NamespacedSpecNamespace
+
+include "Referenced.thrift"
+
+struct Hello {
+  1: string greeting = "hello world"
+}
+
+service NamespacedNonblockingService {
+  Hello greeting(1:bool english)
+  bool block()
+  oneway void unblock(1:i32 n)
+  oneway void shutdown()
+  void sleep(1:double seconds)
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/bf2617ed/lib/rb/spec/namespaced_spec.rb
----------------------------------------------------------------------
diff --git a/lib/rb/spec/namespaced_spec.rb b/lib/rb/spec/namespaced_spec.rb
new file mode 100644
index 0000000..8d4f88b
--- /dev/null
+++ b/lib/rb/spec/namespaced_spec.rb
@@ -0,0 +1,62 @@
+#
+# 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 'spec_helper'
+
+describe 'namespaced generation' do
+  before do
+    require 'namespaced_spec_namespace/namespaced_nonblocking_service'
+  end
+
+  it "generated the right files" do
+    prefix = File.expand_path("../gen-rb", __FILE__)
+    ["namespaced_spec_namespace/namespaced_nonblocking_service.rb",
+     "namespaced_spec_namespace/thrift_namespaced_spec_constants.rb",
+     "namespaced_spec_namespace/thrift_namespaced_spec_types.rb",
+     "other_namespace/referenced_constants.rb",
+     "other_namespace/referenced_types.rb"
+    ].each do |name|
+      File.exist?(File.join(prefix, name)).should be_true
+    end
+  end
+
+  it "did not generate the wrong files" do
+    prefix = File.expand_path("../gen-rb", __FILE__)
+    ["namespaced_nonblocking_service.rb",
+     "thrift_namespaced_spec_constants.rb",
+     "thrift_namespaced_spec_types.rb",
+     "referenced_constants.rb",
+     "referenced_types.rb"
+    ].each do |name|
+      File.exist?(File.join(prefix, name)).should_not be_true
+    end
+  end
+
+  it "has a service class in the right place" do
+    defined?(NamespacedSpecNamespace::NamespacedNonblockingService).should be_true
+  end
+
+  it "has a struct in the right place" do
+    defined?(NamespacedSpecNamespace::Hello).should be_true
+  end
+
+  it "required an included file" do
+    defined?(OtherNamespace::SomeEnum).should be_true
+  end
+end