diff --git a/java/src/test/java/com/google/protobuf/NanoTest.java b/java/src/test/java/com/google/protobuf/NanoTest.java index 92ddda62b6..0ea80d400f 100644 --- a/java/src/test/java/com/google/protobuf/NanoTest.java +++ b/java/src/test/java/com/google/protobuf/NanoTest.java @@ -35,6 +35,8 @@ import com.google.protobuf.nano.Extensions; import com.google.protobuf.nano.Extensions.AnotherMessage; import com.google.protobuf.nano.InternalNano; import com.google.protobuf.nano.MessageNano; +import com.google.protobuf.nano.MultipleImportingNonMultipleNano1; +import com.google.protobuf.nano.MultipleImportingNonMultipleNano2; import com.google.protobuf.nano.NanoOuterClass; import com.google.protobuf.nano.NanoOuterClass.TestAllTypesNano; import com.google.protobuf.nano.RecursiveMessageNano; @@ -2039,6 +2041,20 @@ public class NanoTest extends TestCase { assertEquals(nestedMsg2.bb, newMsg.repeatedNestedMessage[2].bb); } + /** + * Tests that code generation with mixed values of the java_multiple_files + * options between the main source file and the imported source files would + * generate correct references. Any error would cause this method to fail + * compilation. + */ + public void testNanoMultipleImportingNonMultiple() throws Exception { + UnittestImportNano.ImportMessageNano importMsg = new UnittestImportNano.ImportMessageNano(); + MultipleImportingNonMultipleNano1 nano1 = new MultipleImportingNonMultipleNano1(); + nano1.field = importMsg; + MultipleImportingNonMultipleNano2 nano2 = new MultipleImportingNonMultipleNano2(); + nano2.nano1 = nano1; + } + public void testNanoDefaults() throws Exception { TestAllTypesNano msg = new TestAllTypesNano(); for (int i = 0; i < 2; i++) { diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.cc b/src/google/protobuf/compiler/javanano/javanano_enum.cc index 66b671b159..973ef6810d 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum.cc +++ b/src/google/protobuf/compiler/javanano/javanano_enum.cc @@ -69,9 +69,10 @@ EnumGenerator::~EnumGenerator() {} void EnumGenerator::Generate(io::Printer* printer) { printer->Print("// enum $classname$\n", "classname", descriptor_->name()); - bool is_own_file = params_.java_multiple_files() || + const string& file_name = descriptor_->file()->name(); + bool is_own_file = params_.java_multiple_files(file_name) || ((descriptor_->containing_type() == NULL) && - !params_.has_java_outer_classname(descriptor_->file()->name())); + !params_.has_java_outer_classname(file_name)); if (is_own_file) { printer->Print("public final class $classname$ {\n", "classname", diff --git a/src/google/protobuf/compiler/javanano/javanano_file.cc b/src/google/protobuf/compiler/javanano/javanano_file.cc index 6efa2bf327..711369931f 100644 --- a/src/google/protobuf/compiler/javanano/javanano_file.cc +++ b/src/google/protobuf/compiler/javanano/javanano_file.cc @@ -186,7 +186,7 @@ void FileGenerator::Generate(io::Printer* printer) { ExtensionGenerator(file_->extension(i), params_).Generate(printer); } - if (!params_.java_multiple_files()) { + if (!params_.java_multiple_files(file_->name())) { for (int i = 0; i < file_->enum_type_count(); i++) { EnumGenerator(file_->enum_type(i), params_).Generate(printer); } @@ -238,7 +238,7 @@ static void GenerateSibling(const string& package_dir, void FileGenerator::GenerateSiblings(const string& package_dir, OutputDirectory* output_directory, vector* file_list) { - if (params_.java_multiple_files()) { + if (params_.java_multiple_files(file_->name())) { for (int i = 0; i < file_->enum_type_count(); i++) { GenerateSibling(package_dir, java_package_, file_->enum_type(i), diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc index 19a3dccdb2..4b6b6a591e 100644 --- a/src/google/protobuf/compiler/javanano/javanano_generator.cc +++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc @@ -57,6 +57,10 @@ void UpdateParamsRecursively(Params& params, params.set_java_package( file->name(), file->options().java_package()); } + if (file->options().has_java_multiple_files()) { + params.set_java_multiple_files( + file->name(), file->options().java_multiple_files()); + } // Loop through all dependent files recursively // adding dep @@ -84,11 +88,6 @@ bool JavaNanoGenerator::Generate(const FileDescriptor* file, string output_list_file; Params params(file->name()); - // Get options from the proto file - if (file->options().has_java_multiple_files()) { - params.set_java_multiple_files(file->options().java_multiple_files()); - } - // Update per file params UpdateParamsRecursively(params, file); @@ -118,7 +117,7 @@ bool JavaNanoGenerator::Generate(const FileDescriptor* file, } else if (options[i].first == "store_unknown_fields") { params.set_store_unknown_fields(options[i].second == "true"); } else if (options[i].first == "java_multiple_files") { - params.set_java_multiple_files(options[i].second == "true"); + params.set_override_java_multiple_files(options[i].second == "true"); } else { *error = "Ignore unknown javanano generator option: " + options[i].first; } diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc index 2564a58701..525b9dd9cb 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc +++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc @@ -210,7 +210,7 @@ string FileJavaPackage(const Params& params, const FileDescriptor* file) { string ToJavaName(const Params& params, const string& full_name, const FileDescriptor* file) { string result; - if (params.java_multiple_files()) { + if (params.java_multiple_files(file->name())) { result = FileJavaPackage(params, file); } else { result = ClassName(params, file); @@ -283,7 +283,7 @@ string ClassName(const Params& params, const EnumDescriptor* descriptor) { // If the java_multiple_files option is present, we will generate enums into separate // classes, each named after the original enum type. This takes precedence over // any outer_classname. - if (params.java_multiple_files() && last_dot_in_name != string::npos) { + if (params.java_multiple_files(file_name) && last_dot_in_name != string::npos) { string enum_simple_name = full_name.substr(last_dot_in_name + 1); if (!result.empty()) { result += "."; diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index 90ae0417f6..b5983a2a90 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -121,9 +121,11 @@ void MessageGenerator::GenerateStaticVariableInitializers( } void MessageGenerator::Generate(io::Printer* printer) { + const string& file_name = descriptor_->file()->name(); bool is_own_file = - params_.java_multiple_files() || ((descriptor_->containing_type() == NULL) - && !params_.has_java_outer_classname(descriptor_->file()->name())); + params_.java_multiple_files(file_name) + || ((descriptor_->containing_type() == NULL) + && !params_.has_java_outer_classname(file_name)); #if 0 GOOGLE_LOG(INFO) << "is_own_file=" << is_own_file; diff --git a/src/google/protobuf/compiler/javanano/javanano_params.h b/src/google/protobuf/compiler/javanano/javanano_params.h index 30eedff0e9..5c0e6f0400 100644 --- a/src/google/protobuf/compiler/javanano/javanano_params.h +++ b/src/google/protobuf/compiler/javanano/javanano_params.h @@ -34,6 +34,7 @@ #define PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_ #include +#include #include namespace google { @@ -41,24 +42,28 @@ namespace protobuf { namespace compiler { namespace javanano { +enum eMultipleFiles { JAVANANO_MUL_UNSET, JAVANANO_MUL_FALSE, JAVANANO_MUL_TRUE }; + // Parameters for used by the generators class Params { public: typedef map NameMap; + typedef set NameSet; private: string empty_; string base_name_; - bool java_multiple_files_; + eMultipleFiles override_java_multiple_files_; bool store_unknown_fields_; NameMap java_packages_; NameMap java_outer_classnames_; + NameSet java_multiple_files_; public: Params(const string & base_name) : empty_(""), base_name_(base_name), - store_unknown_fields_(false), - java_multiple_files_(false) { + override_java_multiple_files_(JAVANANO_MUL_UNSET), + store_unknown_fields_(false) { } const string& base_name() const { @@ -109,6 +114,36 @@ class Params { return java_outer_classnames_; } + void set_override_java_multiple_files(bool java_multiple_files) { + if (java_multiple_files) { + override_java_multiple_files_ = JAVANANO_MUL_TRUE; + } else { + override_java_multiple_files_ = JAVANANO_MUL_FALSE; + } + } + void clear_override_java_multiple_files() { + override_java_multiple_files_ = JAVANANO_MUL_UNSET; + } + + void set_java_multiple_files(const string& file_name, bool value) { + if (value) { + java_multiple_files_.insert(file_name); + } else { + java_multiple_files_.erase(file_name); + } + } + bool java_multiple_files(const string& file_name) const { + switch (override_java_multiple_files_) { + case JAVANANO_MUL_FALSE: + return false; + case JAVANANO_MUL_TRUE: + return true; + default: + return java_multiple_files_.find(file_name) + != java_multiple_files_.end(); + } + } + void set_store_unknown_fields(bool value) { store_unknown_fields_ = value; } @@ -116,13 +151,6 @@ class Params { return store_unknown_fields_; } - void set_java_multiple_files(bool value) { - java_multiple_files_ = value; - } - bool java_multiple_files() const { - return java_multiple_files_; - } - }; } // namespace javanano diff --git a/src/google/protobuf/unittest_multiple_nano.proto b/src/google/protobuf/unittest_multiple_nano.proto new file mode 100644 index 0000000000..bd174c270b --- /dev/null +++ b/src/google/protobuf/unittest_multiple_nano.proto @@ -0,0 +1,47 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: maxtroy@google.com (Max Cai) + +package protobuf_unittest_import; + +import "google/protobuf/unittest_import_nano.proto"; + +option java_package = "com.google.protobuf.nano"; +option java_outer_classname = "NanoMultipleImportingNonMultiple"; +option java_multiple_files = true; + +message MultipleImportingNonMultipleNano1 { + optional ImportMessageNano field = 1; +} + +message MultipleImportingNonMultipleNano2 { + optional MultipleImportingNonMultipleNano1 nano1 = 1; +}