summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjfarrell <jfarrell@apache.org>2014-06-26 22:53:01 -0400
committerjfarrell <jfarrell@apache.org>2014-06-26 22:53:01 -0400
commitbf2617ed15f95e22bcf41fd9d08e7ce562464f46 (patch)
tree83c17a7b0234d6bf1174afeb1b23f31d7e4a2b59
parentc9bdd50270d2eb60488ef38c56f990b781bbb3d2 (diff)
downloadthrift-bf2617ed15f95e22bcf41fd9d08e7ce562464f46.tar.gz
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
-rw-r--r--compiler/cpp/src/generate/t_rb_generator.cc64
-rw-r--r--lib/rb/Rakefile7
-rw-r--r--lib/rb/spec/Referenced.thrift44
-rw-r--r--lib/rb/spec/ThriftNamespacedSpec.thrift53
-rw-r--r--lib/rb/spec/namespaced_spec.rb62
5 files changed, 219 insertions, 11 deletions
diff --git a/compiler/cpp/src/generate/t_rb_generator.cc b/compiler/cpp/src/generate/t_rb_generator.cc
index 2a6a4721d..dec53ddd2 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")
diff --git a/lib/rb/Rakefile b/lib/rb/Rakefile
index f533d0680..ef00a9f53 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"
diff --git a/lib/rb/spec/Referenced.thrift b/lib/rb/spec/Referenced.thrift
new file mode 100644
index 000000000..98f183fe0
--- /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
+}
diff --git a/lib/rb/spec/ThriftNamespacedSpec.thrift b/lib/rb/spec/ThriftNamespacedSpec.thrift
new file mode 100644
index 000000000..02f28895a
--- /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)
+}
diff --git a/lib/rb/spec/namespaced_spec.rb b/lib/rb/spec/namespaced_spec.rb
new file mode 100644
index 000000000..8d4f88be1
--- /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