aboutsummaryrefslogtreecommitdiffstats
path: root/src/google
diff options
context:
space:
mode:
Diffstat (limited to 'src/google')
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_file.cc94
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_generator.cc22
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_helpers.cc127
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_helpers.h26
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_message.cc18
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum.cc16
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_file.cc96
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_generator.cc22
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_helpers.cc137
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_helpers.h26
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message.cc20
-rw-r--r--src/google/protobuf/unittest_multiple_micro.proto18
-rw-r--r--src/google/protobuf/unittest_multiple_nameclash_micro.proto41
-rw-r--r--src/google/protobuf/unittest_multiple_nameclash_nano.proto (renamed from src/google/protobuf/unittest_enum_multiplejava_nano.proto)20
-rw-r--r--src/google/protobuf/unittest_multiple_nano.proto18
-rw-r--r--src/google/protobuf/unittest_recursive_micro.proto2
-rw-r--r--src/google/protobuf/unittest_recursive_nano.proto2
-rw-r--r--src/google/protobuf/unittest_simple_micro.proto2
-rw-r--r--src/google/protobuf/unittest_simple_nano.proto2
-rw-r--r--src/google/protobuf/unittest_single_micro.proto38
-rw-r--r--src/google/protobuf/unittest_single_nano.proto38
-rw-r--r--src/google/protobuf/unittest_stringutf8_micro.proto2
-rw-r--r--src/google/protobuf/unittest_stringutf8_nano.proto2
23 files changed, 384 insertions, 405 deletions
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_file.cc b/src/google/protobuf/compiler/javamicro/javamicro_file.cc
index 9513aec..43bf012 100644
--- a/src/google/protobuf/compiler/javamicro/javamicro_file.cc
+++ b/src/google/protobuf/compiler/javamicro/javamicro_file.cc
@@ -32,6 +32,8 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <iostream>
+
#include <google/protobuf/compiler/javamicro/javamicro_file.h>
#include <google/protobuf/compiler/javamicro/javamicro_enum.h>
#include <google/protobuf/compiler/javamicro/javamicro_helpers.h>
@@ -101,56 +103,48 @@ bool FileGenerator::Validate(string* error) {
return false;
}
- // If there is no outer class name then there must be only
- // message and no enums defined in the file scope.
- if (!params_.has_java_outer_classname(file_->name())) {
- if (file_->message_type_count() != 1) {
- error->assign(file_->name());
- error->append(
- ": Java MICRO_RUNTIME may only have 1 message if there is no 'option java_outer_classname'\"");
- return false;
- }
+ if (file_->service_count() != 0) {
+ error->assign(file_->name());
+ error->append(
+ ": Java MICRO_RUNTIME does not support services\"");
+ return false;
+ }
- if (file_->enum_type_count() != 0) {
- error->assign(file_->name());
- error->append(
- ": Java MICRO_RUNTIME must have an 'option java_outer_classname' if file scope enums are present\"");
- return false;
- }
+ if (!IsOuterClassNeeded(params_, file_)) {
+ return true;
+ }
+
+ // Check whether legacy javamicro generator would omit the outer class.
+ if (!params_.has_java_outer_classname(file_->name())
+ && file_->message_type_count() == 1
+ && file_->enum_type_count() == 0 && file_->extension_count() == 0) {
+ cout << "INFO: " << file_->name() << ":" << endl;
+ cout << "Javamicro generator has changed to align with java generator. "
+ "An outer class will be created for this file and the single message "
+ "in the file will become a nested class. Use java_multiple_files to "
+ "skip generating the outer class, or set an explicit "
+ "java_outer_classname to suppress this message." << endl;
}
// Check that no class name matches the file's class name. This is a common
// problem that leads to Java compile errors that can be hard to understand.
// It's especially bad when using the java_multiple_files, since we would
// end up overwriting the outer class with one of the inner ones.
- int found_fileName = 0;
- for (int i = 0; i < file_->enum_type_count(); i++) {
- if (file_->enum_type(i)->name() == classname_) {
- found_fileName += 1;
- }
- }
- for (int i = 0; i < file_->message_type_count(); i++) {
+ bool found_conflict = false;
+ for (int i = 0; !found_conflict && i < file_->message_type_count(); i++) {
if (file_->message_type(i)->name() == classname_) {
- found_fileName += 1;
+ found_conflict = true;
}
}
- if (file_->service_count() != 0) {
+ if (found_conflict) {
error->assign(file_->name());
error->append(
- ": Java MICRO_RUNTIME does not support services\"");
- return false;
- }
-
- if (found_fileName > 1) {
- error->assign(file_->name());
- error->append(
- ": Cannot generate Java output because there is more than one class name, \"");
+ ": Cannot generate Java output because the file's outer class name, \"");
error->append(classname_);
error->append(
"\", matches the name of one of the types declared inside it. "
"Please either rename the type or use the java_outer_classname "
- "option to specify a different outer class name for the .proto file."
- " -- FIX THIS MESSAGE");
+ "option to specify a different outer class name for the .proto file.");
return false;
}
return true;
@@ -169,20 +163,19 @@ void FileGenerator::Generate(io::Printer* printer) {
"package", java_package_);
}
- if (params_.has_java_outer_classname(file_->name())) {
- printer->Print(
- "public final class $classname$ {\n"
- " private $classname$() {}\n",
- "classname", classname_);
- printer->Indent();
- }
+ printer->Print(
+ "public final class $classname$ {\n"
+ " private $classname$() {}\n",
+ "classname", classname_);
+ printer->Indent();
// -----------------------------------------------------------------
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ EnumGenerator(file_->enum_type(i), params_).Generate(printer);
+ }
+
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);
- }
for (int i = 0; i < file_->message_type_count(); i++) {
MessageGenerator(file_->message_type(i), params_).Generate(printer);
}
@@ -194,11 +187,9 @@ void FileGenerator::Generate(io::Printer* printer) {
MessageGenerator(file_->message_type(i), params_).GenerateStaticVariables(printer);
}
- if (params_.has_java_outer_classname(file_->name())) {
- printer->Outdent();
- printer->Print(
- "}\n");
- }
+ printer->Outdent();
+ printer->Print(
+ "}\n");
}
template<typename GeneratorClass, typename DescriptorClass>
@@ -232,11 +223,6 @@ void FileGenerator::GenerateSiblings(const string& package_dir,
OutputDirectory* output_directory,
vector<string>* file_list) {
if (params_.java_multiple_files(file_->name())) {
- for (int i = 0; i < file_->enum_type_count(); i++) {
- GenerateSibling<EnumGenerator>(package_dir, java_package_,
- file_->enum_type(i),
- output_directory, file_list, params_);
- }
for (int i = 0; i < file_->message_type_count(); i++) {
GenerateSibling<MessageGenerator>(package_dir, java_package_,
file_->message_type(i),
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_generator.cc b/src/google/protobuf/compiler/javamicro/javamicro_generator.cc
index 4643899..1b74509 100644
--- a/src/google/protobuf/compiler/javamicro/javamicro_generator.cc
+++ b/src/google/protobuf/compiler/javamicro/javamicro_generator.cc
@@ -173,16 +173,18 @@ bool JavaMicroGenerator::Generate(const FileDescriptor* file,
vector<string> all_files;
- string java_filename = package_dir;
- java_filename += file_generator.classname();
- java_filename += ".java";
- all_files.push_back(java_filename);
-
- // Generate main java file.
- scoped_ptr<io::ZeroCopyOutputStream> output(
- output_directory->Open(java_filename));
- io::Printer printer(output.get(), '$');
- file_generator.Generate(&printer);
+ if (IsOuterClassNeeded(params, file)) {
+ string java_filename = package_dir;
+ java_filename += file_generator.classname();
+ java_filename += ".java";
+ all_files.push_back(java_filename);
+
+ // Generate main java file.
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ output_directory->Open(java_filename));
+ io::Printer printer(output.get(), '$');
+ file_generator.Generate(&printer);
+ }
// Generate sibling files.
file_generator.GenerateSiblings(package_dir, output_directory, &all_files);
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_helpers.cc b/src/google/protobuf/compiler/javamicro/javamicro_helpers.cc
index 3647ec3..f6ce653 100644
--- a/src/google/protobuf/compiler/javamicro/javamicro_helpers.cc
+++ b/src/google/protobuf/compiler/javamicro/javamicro_helpers.cc
@@ -120,31 +120,20 @@ string StripProto(const string& filename) {
}
string FileClassName(const Params& params, const FileDescriptor* file) {
- string name;
-
if (params.has_java_outer_classname(file->name())) {
- name = params.java_outer_classname(file->name());
+ return params.java_outer_classname(file->name());
} else {
- if ((file->message_type_count() == 1)
- || (file->enum_type_count() == 0)) {
- // If no outer calls and only one message then
- // use the message name as the file name
- name = file->message_type(0)->name();
+ // Use the filename itself with underscores removed
+ // and a CamelCase style name.
+ string basename;
+ string::size_type last_slash = file->name().find_last_of('/');
+ if (last_slash == string::npos) {
+ basename = file->name();
} else {
- // Use the filename it self with underscores removed
- // and a CamelCase style name.
- string basename;
- string::size_type last_slash = file->name().find_last_of('/');
- if (last_slash == string::npos) {
- basename = file->name();
- } else {
- basename = file->name().substr(last_slash + 1);
- }
- name = UnderscoresToCamelCaseImpl(StripProto(basename), true);
+ basename = file->name().substr(last_slash + 1);
}
+ return UnderscoresToCamelCaseImpl(StripProto(basename), true);
}
-
- return name;
}
string FileJavaPackage(const Params& params, const FileDescriptor* file) {
@@ -160,38 +149,27 @@ 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(file->name())) {
- result = FileJavaPackage(params, file);
- } else {
- result = ClassName(params, file);
+bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file) {
+ // Enums and extensions need the outer class as the scope.
+ if (file->enum_type_count() != 0 || file->extension_count() != 0) {
+ return true;
}
- if (file->package().empty()) {
- result += '.';
- result += full_name;
+ // Messages need the outer class only if java_multiple_files is false.
+ return !params.java_multiple_files(file->name());
+}
+
+string ToJavaName(const Params& params, const string& name, bool is_class,
+ const Descriptor* parent, const FileDescriptor* file) {
+ string result;
+ if (parent != NULL) {
+ result.append(ClassName(params, parent));
+ } else if (is_class && params.java_multiple_files(file->name())) {
+ result.append(FileJavaPackage(params, file));
} else {
- // Strip the proto package from full_name since we've replaced it with
- // the Java package. If there isn't an outer classname then strip it too.
- int sizeToSkipPackageName = file->package().size();
- int sizeToSkipOutClassName;
- if (params.has_java_outer_classname(file->name())) {
- sizeToSkipOutClassName = 0;
- } else {
- sizeToSkipOutClassName =
- full_name.find_first_of('.', sizeToSkipPackageName + 1);
- }
- int sizeToSkip = sizeToSkipOutClassName > 0 ?
- sizeToSkipOutClassName : sizeToSkipPackageName;
- string class_name = full_name.substr(sizeToSkip + 1);
- if (class_name == FileClassName(params, file)) {
- // Done class_name is already present.
- } else {
- result += '.';
- result += class_name;
- }
+ result.append(ClassName(params, file));
}
+ if (!result.empty()) result.append(1, '.');
+ result.append(name); // TODO(maxtroy): add '_' if name is a Java keyword.
return result;
}
@@ -203,51 +181,14 @@ string ClassName(const Params& params, const FileDescriptor* descriptor) {
}
string ClassName(const Params& params, const EnumDescriptor* descriptor) {
- string result;
- const FileDescriptor* file = descriptor->file();
- const string file_name = file->name();
- const string full_name = descriptor->full_name();
-
- // Remove enum class name as we use int's for enums
- string base_name = full_name.substr(0, full_name.find_last_of('.'));
-
- if (!file->package().empty()) {
- if (file->package() == base_name.substr(0, file->package().size())) {
- // Remove package name leaving just the parent class of the enum
- int offset = file->package().size();
- if (base_name.size() > offset) {
- // Remove period between package and class name if there is a classname
- offset += 1;
- }
- base_name = base_name.substr(offset);
- } else {
- GOOGLE_LOG(FATAL) << "Expected package name to start an enum";
- }
- }
-
- // Construct the path name from the package and outer class
-
- // Add the java package name if it exsits
- if (params.has_java_package(file_name)) {
- result += params.java_package(file_name);
- }
-
- // Add the outer classname if it exists
- if (params.has_java_outer_classname(file_name)) {
- if (!result.empty()) {
- result += ".";
- }
- result += params.java_outer_classname(file_name);
- }
-
- // Create the full class name from the base and path
- if (!base_name.empty()) {
- if (!result.empty()) {
- result += ".";
- }
- result += base_name;
+ // An enum's class name is the enclosing message's class name or the outer
+ // class name.
+ const Descriptor* parent = descriptor->containing_type();
+ if (parent != NULL) {
+ return ClassName(params, parent);
+ } else {
+ return ClassName(params, descriptor->file());
}
- return result;
}
string FieldConstantName(const FieldDescriptor *field) {
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_helpers.h b/src/google/protobuf/compiler/javamicro/javamicro_helpers.h
index eeddbf9..6131c15 100644
--- a/src/google/protobuf/compiler/javamicro/javamicro_helpers.h
+++ b/src/google/protobuf/compiler/javamicro/javamicro_helpers.h
@@ -69,25 +69,35 @@ string FileClassName(const Params& params, const FileDescriptor* file);
// Returns the file's Java package name.
string FileJavaPackage(const Params& params, const FileDescriptor* file);
-// Converts the given fully-qualified name in the proto namespace to its
-// fully-qualified name in the Java namespace, given that it is in the given
-// file.
-string ToJavaName(const Params& params, const string& full_name,
- const FileDescriptor* file);
+// Returns whether the Java outer class is needed, i.e. whether the option
+// java_multiple_files is false, or the proto file contains any file-scope
+// enums/extensions.
+bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file);
+
+// Converts the given simple name of a proto entity to its fully-qualified name
+// in the Java namespace, given that it is in the given file enclosed in the
+// given parent message (or NULL for file-scope entities). Whether the file's
+// outer class name should be included in the return value depends on factors
+// inferrable from the given arguments, including is_class which indicates
+// whether the entity translates to a Java class.
+string ToJavaName(const Params& params, const string& name, bool is_class,
+ const Descriptor* parent, const FileDescriptor* file);
// These return the fully-qualified class name corresponding to the given
// descriptor.
inline string ClassName(const Params& params, const Descriptor* descriptor) {
- return ToJavaName(params, descriptor->full_name(), descriptor->file());
+ return ToJavaName(params, descriptor->name(), true,
+ descriptor->containing_type(), descriptor->file());
}
string ClassName(const Params& params, const EnumDescriptor* descriptor);
inline string ClassName(const Params& params,
const ServiceDescriptor* descriptor) {
- return ToJavaName(params, descriptor->full_name(), descriptor->file());
+ return ToJavaName(params, descriptor->name(), true, NULL, descriptor->file());
}
inline string ExtensionIdentifierName(const Params& params,
const FieldDescriptor* descriptor) {
- return ToJavaName(params, descriptor->full_name(), descriptor->file());
+ return ToJavaName(params, descriptor->name(), false,
+ descriptor->extension_scope(), descriptor->file());
}
string ClassName(const Params& params, const FileDescriptor* descriptor);
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_message.cc b/src/google/protobuf/compiler/javamicro/javamicro_message.cc
index 6f67e74..cf48b3c 100644
--- a/src/google/protobuf/compiler/javamicro/javamicro_message.cc
+++ b/src/google/protobuf/compiler/javamicro/javamicro_message.cc
@@ -173,15 +173,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
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(file_name));
-
-#if 0
- GOOGLE_LOG(INFO) << "is_own_file=" << is_own_file;
- GOOGLE_LOG(INFO) << "containing_type()=" << ((descriptor_->containing_type() == NULL) ? "NULL" : "not null");
- GOOGLE_LOG(INFO) << "java_multiple_files()=" << params_.java_multiple_files();
- GOOGLE_LOG(INFO) << "has_java_outer_classname()=" << params_.has_java_outer_classname(file_->name());
-#endif
+ && descriptor_->containing_type() == NULL;
if ((descriptor_->extension_count() != 0)
|| (descriptor_->extension_range_count() != 0)) {
@@ -362,25 +354,21 @@ void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
void MessageGenerator::
GenerateParseFromMethods(io::Printer* printer) {
- bool is_own_file =
- descriptor_->containing_type() == NULL;
-
// Note: These are separate from GenerateMessageSerializationMethods()
// because they need to be generated even for messages that are optimized
// for code size.
printer->Print(
- "public $static$ $classname$ parseFrom(byte[] data)\n"
+ "public static $classname$ parseFrom(byte[] data)\n"
" throws com.google.protobuf.micro.InvalidProtocolBufferMicroException {\n"
" return ($classname$) (new $classname$().mergeFrom(data));\n"
"}\n"
"\n"
- "public $static$ $classname$ parseFrom(\n"
+ "public static $classname$ parseFrom(\n"
" com.google.protobuf.micro.CodedInputStreamMicro input)\n"
" throws java.io.IOException {\n"
" return new $classname$().mergeFrom(input);\n"
"}\n"
"\n",
- "static", (is_own_file ? "static" : ""),
"classname", descriptor_->name());
}
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.cc b/src/google/protobuf/compiler/javanano/javanano_enum.cc
index 973ef68..634943b 100644
--- a/src/google/protobuf/compiler/javanano/javanano_enum.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_enum.cc
@@ -69,18 +69,6 @@ EnumGenerator::~EnumGenerator() {}
void EnumGenerator::Generate(io::Printer* printer) {
printer->Print("// enum $classname$\n", "classname", descriptor_->name());
- 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(file_name));
-
- if (is_own_file) {
- printer->Print("public final class $classname$ {\n", "classname",
- descriptor_->name());
- printer->Indent();
- printer->Print("private $classname$() {}\n", "classname",
- descriptor_->name());
- }
for (int i = 0; i < canonical_values_.size(); i++) {
map<string, string> vars;
vars["name"] = RenameJavaKeywords(canonical_values_[i]->name());
@@ -99,10 +87,6 @@ void EnumGenerator::Generate(io::Printer* printer) {
"public static final int $name$ = $canonical_name$;\n");
}
- if (is_own_file) {
- printer->Outdent();
- printer->Print("}");
- }
printer->Print("\n");
}
diff --git a/src/google/protobuf/compiler/javanano/javanano_file.cc b/src/google/protobuf/compiler/javanano/javanano_file.cc
index 7113699..1a7b2a7 100644
--- a/src/google/protobuf/compiler/javanano/javanano_file.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_file.cc
@@ -32,6 +32,8 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <iostream>
+
#include <google/protobuf/compiler/javanano/javanano_file.h>
#include <google/protobuf/compiler/javanano/javanano_enum.h>
#include <google/protobuf/compiler/javanano/javanano_extension.h>
@@ -103,56 +105,48 @@ bool FileGenerator::Validate(string* error) {
return false;
}
- // If there is no outer class name then there must be only
- // message and no enums defined in the file scope.
- if (!params_.has_java_outer_classname(file_->name())) {
- if (file_->message_type_count() != 1) {
- error->assign(file_->name());
- error->append(
- ": Java NANO_RUNTIME may only have 1 message if there is no 'option java_outer_classname'\"");
- return false;
- }
+ if (file_->service_count() != 0) {
+ error->assign(file_->name());
+ error->append(
+ ": Java NANO_RUNTIME does not support services\"");
+ return false;
+ }
- if (file_->enum_type_count() != 0) {
- error->assign(file_->name());
- error->append(
- ": Java NANO_RUNTIME must have an 'option java_outer_classname' if file scope enums are present\"");
- return false;
- }
+ if (!IsOuterClassNeeded(params_, file_)) {
+ return true;
+ }
+
+ // Check whether legacy javanano generator would omit the outer class.
+ if (!params_.has_java_outer_classname(file_->name())
+ && file_->message_type_count() == 1
+ && file_->enum_type_count() == 0 && file_->extension_count() == 0) {
+ cout << "INFO: " << file_->name() << ":" << endl;
+ cout << "Javanano generator has changed to align with java generator. "
+ "An outer class will be created for this file and the single message "
+ "in the file will become a nested class. Use java_multiple_files to "
+ "skip generating the outer class, or set an explicit "
+ "java_outer_classname to suppress this message." << endl;
}
// Check that no class name matches the file's class name. This is a common
// problem that leads to Java compile errors that can be hard to understand.
// It's especially bad when using the java_multiple_files, since we would
// end up overwriting the outer class with one of the inner ones.
- int found_fileName = 0;
- for (int i = 0; i < file_->enum_type_count(); i++) {
- if (file_->enum_type(i)->name() == classname_) {
- found_fileName += 1;
- }
- }
- for (int i = 0; i < file_->message_type_count(); i++) {
+ bool found_conflict = false;
+ for (int i = 0; !found_conflict && i < file_->message_type_count(); i++) {
if (file_->message_type(i)->name() == classname_) {
- found_fileName += 1;
+ found_conflict = true;
}
}
- if (file_->service_count() != 0) {
+ if (found_conflict) {
error->assign(file_->name());
error->append(
- ": Java NANO_RUNTIME does not support services\"");
- return false;
- }
-
- if (found_fileName > 1) {
- error->assign(file_->name());
- error->append(
- ": Cannot generate Java output because there is more than one class name, \"");
+ ": Cannot generate Java output because the file's outer class name, \"");
error->append(classname_);
error->append(
"\", matches the name of one of the types declared inside it. "
"Please either rename the type or use the java_outer_classname "
- "option to specify a different outer class name for the .proto file."
- " -- FIX THIS MESSAGE");
+ "option to specify a different outer class name for the .proto file.");
return false;
}
return true;
@@ -171,13 +165,11 @@ void FileGenerator::Generate(io::Printer* printer) {
"package", java_package_);
}
- if (params_.has_java_outer_classname(file_->name())) {
- printer->Print(
- "public final class $classname$ {\n"
- " private $classname$() {}\n",
- "classname", classname_);
- printer->Indent();
- }
+ printer->Print(
+ "public final class $classname$ {\n"
+ " private $classname$() {}\n",
+ "classname", classname_);
+ printer->Indent();
// -----------------------------------------------------------------
@@ -186,10 +178,13 @@ void FileGenerator::Generate(io::Printer* printer) {
ExtensionGenerator(file_->extension(i), params_).Generate(printer);
}
+ // Enums.
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ EnumGenerator(file_->enum_type(i), params_).Generate(printer);
+ }
+
+ // Messages.
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);
- }
for (int i = 0; i < file_->message_type_count(); i++) {
MessageGenerator(file_->message_type(i), params_).Generate(printer);
}
@@ -201,11 +196,9 @@ void FileGenerator::Generate(io::Printer* printer) {
MessageGenerator(file_->message_type(i), params_).GenerateStaticVariables(printer);
}
- if (params_.has_java_outer_classname(file_->name())) {
- printer->Outdent();
- printer->Print(
- "}\n");
- }
+ printer->Outdent();
+ printer->Print(
+ "}\n");
}
template<typename GeneratorClass, typename DescriptorClass>
@@ -239,11 +232,6 @@ void FileGenerator::GenerateSiblings(const string& package_dir,
OutputDirectory* output_directory,
vector<string>* file_list) {
if (params_.java_multiple_files(file_->name())) {
- for (int i = 0; i < file_->enum_type_count(); i++) {
- GenerateSibling<EnumGenerator>(package_dir, java_package_,
- file_->enum_type(i),
- output_directory, file_list, params_);
- }
for (int i = 0; i < file_->message_type_count(); i++) {
GenerateSibling<MessageGenerator>(package_dir, java_package_,
file_->message_type(i),
diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc
index 76e7263..5bed1b1 100644
--- a/src/google/protobuf/compiler/javanano/javanano_generator.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc
@@ -138,16 +138,18 @@ bool JavaNanoGenerator::Generate(const FileDescriptor* file,
vector<string> all_files;
- string java_filename = package_dir;
- java_filename += file_generator.classname();
- java_filename += ".java";
- all_files.push_back(java_filename);
-
- // Generate main java file.
- scoped_ptr<io::ZeroCopyOutputStream> output(
- output_directory->Open(java_filename));
- io::Printer printer(output.get(), '$');
- file_generator.Generate(&printer);
+ if (IsOuterClassNeeded(params, file)) {
+ string java_filename = package_dir;
+ java_filename += file_generator.classname();
+ java_filename += ".java";
+ all_files.push_back(java_filename);
+
+ // Generate main java file.
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ output_directory->Open(java_filename));
+ io::Printer printer(output.get(), '$');
+ file_generator.Generate(&printer);
+ }
// Generate sibling files.
file_generator.GenerateSiblings(package_dir, output_directory, &all_files);
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
index 525b9dd..22b4302 100644
--- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
@@ -167,31 +167,20 @@ string StripProto(const string& filename) {
}
string FileClassName(const Params& params, const FileDescriptor* file) {
- string name;
-
if (params.has_java_outer_classname(file->name())) {
- name = params.java_outer_classname(file->name());
+ return params.java_outer_classname(file->name());
} else {
- if ((file->message_type_count() == 1)
- || (file->enum_type_count() == 0)) {
- // If no outer calls and only one message then
- // use the message name as the file name
- name = file->message_type(0)->name();
+ // Use the filename itself with underscores removed
+ // and a CamelCase style name.
+ string basename;
+ string::size_type last_slash = file->name().find_last_of('/');
+ if (last_slash == string::npos) {
+ basename = file->name();
} else {
- // Use the filename it self with underscores removed
- // and a CamelCase style name.
- string basename;
- string::size_type last_slash = file->name().find_last_of('/');
- if (last_slash == string::npos) {
- basename = file->name();
- } else {
- basename = file->name().substr(last_slash + 1);
- }
- name = UnderscoresToCamelCaseImpl(StripProto(basename), true);
+ basename = file->name().substr(last_slash + 1);
}
+ return UnderscoresToCamelCaseImpl(StripProto(basename), true);
}
-
- return name;
}
string FileJavaPackage(const Params& params, const FileDescriptor* file) {
@@ -207,38 +196,27 @@ 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(file->name())) {
- result = FileJavaPackage(params, file);
- } else {
- result = ClassName(params, file);
+bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file) {
+ // Enums and extensions need the outer class as the scope.
+ if (file->enum_type_count() != 0 || file->extension_count() != 0) {
+ return true;
}
- if (file->package().empty()) {
- result += '.';
- result += full_name;
+ // Messages need the outer class only if java_multiple_files is false.
+ return !params.java_multiple_files(file->name());
+}
+
+string ToJavaName(const Params& params, const string& name, bool is_class,
+ const Descriptor* parent, const FileDescriptor* file) {
+ string result;
+ if (parent != NULL) {
+ result.append(ClassName(params, parent));
+ } else if (is_class && params.java_multiple_files(file->name())) {
+ result.append(FileJavaPackage(params, file));
} else {
- // Strip the proto package from full_name since we've replaced it with
- // the Java package. If there isn't an outer classname then strip it too.
- int sizeToSkipPackageName = file->package().size();
- int sizeToSkipOutClassName;
- if (params.has_java_outer_classname(file->name())) {
- sizeToSkipOutClassName = 0;
- } else {
- sizeToSkipOutClassName =
- full_name.find_first_of('.', sizeToSkipPackageName + 1);
- }
- int sizeToSkip = sizeToSkipOutClassName > 0 ?
- sizeToSkipOutClassName : sizeToSkipPackageName;
- string class_name = full_name.substr(sizeToSkip + 1);
- if (class_name == FileClassName(params, file)) {
- // Done class_name is already present.
- } else {
- result += '.';
- result += class_name;
- }
+ result.append(ClassName(params, file));
}
+ if (!result.empty()) result.append(1, '.');
+ result.append(RenameJavaKeywords(name));
return result;
}
@@ -250,61 +228,14 @@ string ClassName(const Params& params, const FileDescriptor* descriptor) {
}
string ClassName(const Params& params, const EnumDescriptor* descriptor) {
- string result;
- const FileDescriptor* file = descriptor->file();
- const string file_name = file->name();
- const string full_name = descriptor->full_name();
-
- // Remove enum class name as we use int's for enums
- int last_dot_in_name = full_name.find_last_of('.');
- string base_name = full_name.substr(0, last_dot_in_name);
-
- if (!file->package().empty()) {
- if (file->package() == base_name.substr(0, file->package().size())) {
- // Remove package name leaving just the parent class of the enum
- int offset = file->package().size();
- if (base_name.size() > offset) {
- // Remove period between package and class name if there is a classname
- offset += 1;
- }
- base_name = base_name.substr(offset);
- } else {
- GOOGLE_LOG(FATAL) << "Expected package name to start an enum";
- }
- }
-
- // Construct the path name from the package and outer class
-
- // Add the java package name if it exists
- if (params.has_java_package(file_name)) {
- result += params.java_package(file_name);
- }
-
- // 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(file_name) && last_dot_in_name != string::npos) {
- string enum_simple_name = full_name.substr(last_dot_in_name + 1);
- if (!result.empty()) {
- result += ".";
- }
- result += enum_simple_name;
- } else if (params.has_java_outer_classname(file_name)) {
- // Add the outer classname if it exists
- if (!result.empty()) {
- result += ".";
- }
- result += params.java_outer_classname(file_name);
- }
-
- // Create the full class name from the base and path
- if (!base_name.empty()) {
- if (!result.empty()) {
- result += ".";
- }
- result += base_name;
+ // An enum's class name is the enclosing message's class name or the outer
+ // class name.
+ const Descriptor* parent = descriptor->containing_type();
+ if (parent != NULL) {
+ return ClassName(params, parent);
+ } else {
+ return ClassName(params, descriptor->file());
}
- return result;
}
string FieldConstantName(const FieldDescriptor *field) {
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.h b/src/google/protobuf/compiler/javanano/javanano_helpers.h
index afadf60..430969b 100644
--- a/src/google/protobuf/compiler/javanano/javanano_helpers.h
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.h
@@ -73,25 +73,35 @@ string FileClassName(const Params& params, const FileDescriptor* file);
// Returns the file's Java package name.
string FileJavaPackage(const Params& params, const FileDescriptor* file);
-// Converts the given fully-qualified name in the proto namespace to its
-// fully-qualified name in the Java namespace, given that it is in the given
-// file.
-string ToJavaName(const Params& params, const string& full_name,
- const FileDescriptor* file);
+// Returns whether the Java outer class is needed, i.e. whether the option
+// java_multiple_files is false, or the proto file contains any file-scope
+// enums/extensions.
+bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file);
+
+// Converts the given simple name of a proto entity to its fully-qualified name
+// in the Java namespace, given that it is in the given file enclosed in the
+// given parent message (or NULL for file-scope entities). Whether the file's
+// outer class name should be included in the return value depends on factors
+// inferrable from the given arguments, including is_class which indicates
+// whether the entity translates to a Java class.
+string ToJavaName(const Params& params, const string& name, bool is_class,
+ const Descriptor* parent, const FileDescriptor* file);
// These return the fully-qualified class name corresponding to the given
// descriptor.
inline string ClassName(const Params& params, const Descriptor* descriptor) {
- return ToJavaName(params, descriptor->full_name(), descriptor->file());
+ return ToJavaName(params, descriptor->name(), true,
+ descriptor->containing_type(), descriptor->file());
}
string ClassName(const Params& params, const EnumDescriptor* descriptor);
inline string ClassName(const Params& params,
const ServiceDescriptor* descriptor) {
- return ToJavaName(params, descriptor->full_name(), descriptor->file());
+ return ToJavaName(params, descriptor->name(), true, NULL, descriptor->file());
}
inline string ExtensionIdentifierName(const Params& params,
const FieldDescriptor* descriptor) {
- return ToJavaName(params, descriptor->full_name(), descriptor->file());
+ return ToJavaName(params, descriptor->name(), false,
+ descriptor->extension_scope(), descriptor->file());
}
string ClassName(const Params& params, const FileDescriptor* descriptor);
diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc
index de56944..851c443 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_message.cc
@@ -114,7 +114,7 @@ void MessageGenerator::GenerateStaticVariableInitializers(
io::Printer* printer) {
// Generate static member initializers for all nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
- // TODO(kenton): Reuse MessageGenerator objects?
+ // TODO(kenton): Reuse MessageGenerator objects?
MessageGenerator(descriptor_->nested_type(i), params_)
.GenerateStaticVariableInitializers(printer);
}
@@ -124,15 +124,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
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(file_name));
-
-#if 0
- GOOGLE_LOG(INFO) << "is_own_file=" << is_own_file;
- GOOGLE_LOG(INFO) << "containing_type()=" << ((descriptor_->containing_type() == NULL) ? "NULL" : "not null");
- GOOGLE_LOG(INFO) << "java_multiple_files()=" << params_.java_multiple_files();
- GOOGLE_LOG(INFO) << "has_java_outer_classname()=" << params_.has_java_outer_classname(file_->name());
-#endif
+ && descriptor_->containing_type() == NULL;
if (!params_.store_unknown_fields() &&
(descriptor_->extension_count() != 0 || descriptor_->extension_range_count() != 0)) {
@@ -355,25 +347,21 @@ void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
void MessageGenerator::
GenerateParseFromMethods(io::Printer* printer) {
- bool is_own_file =
- descriptor_->containing_type() == NULL;
-
// Note: These are separate from GenerateMessageSerializationMethods()
// because they need to be generated even for messages that are optimized
// for code size.
printer->Print(
- "public $static$ $classname$ parseFrom(byte[] data)\n"
+ "public static $classname$ parseFrom(byte[] data)\n"
" throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n"
" return com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n"
"}\n"
"\n"
- "public $static$ $classname$ parseFrom(\n"
+ "public static $classname$ parseFrom(\n"
" com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
" throws java.io.IOException {\n"
" return new $classname$().mergeFrom(input);\n"
"}\n"
"\n",
- "static", (is_own_file ? "static" : ""),
"classname", descriptor_->name());
}
diff --git a/src/google/protobuf/unittest_multiple_micro.proto b/src/google/protobuf/unittest_multiple_micro.proto
index 0b64283..fee8edc 100644
--- a/src/google/protobuf/unittest_multiple_micro.proto
+++ b/src/google/protobuf/unittest_multiple_micro.proto
@@ -35,9 +35,25 @@ package protobuf_unittest_import;
import "google/protobuf/unittest_import_micro.proto";
option java_package = "com.google.protobuf.micro";
-option java_outer_classname = "MicroMultipleImportingNonMultiple";
option java_multiple_files = true;
+enum FileScopeEnum {
+ ONE = 1;
+ TWO = 2;
+}
+
+message FileScopeEnumRefMicro {
+ optional FileScopeEnum enum_field = 1;
+}
+
+message MessageScopeEnumRefMicro {
+ enum MessageScopeEnum {
+ ONE = 1;
+ TWO = 2;
+ }
+ optional MessageScopeEnum enum_field = 1;
+}
+
message MultipleImportingNonMultipleMicro1 {
optional ImportMessageMicro field = 1;
}
diff --git a/src/google/protobuf/unittest_multiple_nameclash_micro.proto b/src/google/protobuf/unittest_multiple_nameclash_micro.proto
new file mode 100644
index 0000000..089fd85
--- /dev/null
+++ b/src/google/protobuf/unittest_multiple_nameclash_micro.proto
@@ -0,0 +1,41 @@
+// 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;
+
+option java_package = "com.google.protobuf.micro";
+option java_outer_classname = "MultipleNameClashMicro";
+option java_multiple_files = true;
+
+message MultipleNameClashMicro {
+ optional int32 field = 1;
+}
diff --git a/src/google/protobuf/unittest_enum_multiplejava_nano.proto b/src/google/protobuf/unittest_multiple_nameclash_nano.proto
index adf017d..f2f62c4 100644
--- a/src/google/protobuf/unittest_enum_multiplejava_nano.proto
+++ b/src/google/protobuf/unittest_multiple_nameclash_nano.proto
@@ -28,26 +28,14 @@
// (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: bduff@google.com (Brian Duff)
-//
+// Author: maxtroy@google.com (Max Cai)
package protobuf_unittest_import;
option java_package = "com.google.protobuf.nano";
-option java_outer_classname = "NanoEnumsWithMultipleFiles";
+option java_outer_classname = "MultipleNameClashNano";
option java_multiple_files = true;
-enum FirstTopLevelEnum {
- FIRST_TOP_LEVEL_FIRST = 1;
- FIRST_TOP_LEVEL_SECOND = 2;
-}
-
-enum SecondTopLevelEnum {
- SECOND_TOP_LEVEL_FIRST = 1;
- SECOND_TOP_LEVEL_SECOND = 2;
-}
-
-message SomeMessage {
- optional FirstTopLevelEnum first = 1;
- optional SecondTopLevelEnum second = 2;
+message MultipleNameClashNano {
+ optional int32 field = 1;
}
diff --git a/src/google/protobuf/unittest_multiple_nano.proto b/src/google/protobuf/unittest_multiple_nano.proto
index bd174c2..5ae790b 100644
--- a/src/google/protobuf/unittest_multiple_nano.proto
+++ b/src/google/protobuf/unittest_multiple_nano.proto
@@ -35,9 +35,25 @@ 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;
+enum FileScopeEnum {
+ ONE = 1;
+ TWO = 2;
+}
+
+message FileScopeEnumRefNano {
+ optional FileScopeEnum enum_field = 1;
+}
+
+message MessageScopeEnumRefNano {
+ enum MessageScopeEnum {
+ ONE = 1;
+ TWO = 2;
+ }
+ optional MessageScopeEnum enum_field = 1;
+}
+
message MultipleImportingNonMultipleNano1 {
optional ImportMessageNano field = 1;
}
diff --git a/src/google/protobuf/unittest_recursive_micro.proto b/src/google/protobuf/unittest_recursive_micro.proto
index a256852..078ca9c 100644
--- a/src/google/protobuf/unittest_recursive_micro.proto
+++ b/src/google/protobuf/unittest_recursive_micro.proto
@@ -34,6 +34,8 @@
package protobuf_unittest_import;
option java_package = "com.google.protobuf.micro";
+// Explicit outer classname to suppress legacy info.
+option java_outer_classname = "UnittestRecursiveMicro";
message RecursiveMessageMicro {
message NestedMessage {
diff --git a/src/google/protobuf/unittest_recursive_nano.proto b/src/google/protobuf/unittest_recursive_nano.proto
index a62613e..3d3a6aa 100644
--- a/src/google/protobuf/unittest_recursive_nano.proto
+++ b/src/google/protobuf/unittest_recursive_nano.proto
@@ -34,6 +34,8 @@
package protobuf_unittest_import;
option java_package = "com.google.protobuf.nano";
+// Explicit outer classname to suppress legacy info.
+option java_outer_classname = "UnittestRecursiveNano";
message RecursiveMessageNano {
message NestedMessage {
diff --git a/src/google/protobuf/unittest_simple_micro.proto b/src/google/protobuf/unittest_simple_micro.proto
index 057bf3d..09d4aab 100644
--- a/src/google/protobuf/unittest_simple_micro.proto
+++ b/src/google/protobuf/unittest_simple_micro.proto
@@ -34,6 +34,8 @@
package protobuf_unittest_import;
option java_package = "com.google.protobuf.micro";
+// Explicit outer classname to suppress legacy info
+option java_outer_classname = "UnittestSimpleMicro";
message SimpleMessageMicro {
message NestedMessage {
diff --git a/src/google/protobuf/unittest_simple_nano.proto b/src/google/protobuf/unittest_simple_nano.proto
index 287e962..0c780c7 100644
--- a/src/google/protobuf/unittest_simple_nano.proto
+++ b/src/google/protobuf/unittest_simple_nano.proto
@@ -34,6 +34,8 @@
package protobuf_unittest_import;
option java_package = "com.google.protobuf.nano";
+// Explicit outer classname to suppress legacy info.
+option java_outer_classname = "UnittestSimpleNano";
message SimpleMessageNano {
message NestedMessage {
diff --git a/src/google/protobuf/unittest_single_micro.proto b/src/google/protobuf/unittest_single_micro.proto
new file mode 100644
index 0000000..17e0645
--- /dev/null
+++ b/src/google/protobuf/unittest_single_micro.proto
@@ -0,0 +1,38 @@
+// 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;
+
+option java_package = "com.google.protobuf.micro";
+
+message SingleMessageMicro {
+}
diff --git a/src/google/protobuf/unittest_single_nano.proto b/src/google/protobuf/unittest_single_nano.proto
new file mode 100644
index 0000000..fcb1539
--- /dev/null
+++ b/src/google/protobuf/unittest_single_nano.proto
@@ -0,0 +1,38 @@
+// 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;
+
+option java_package = "com.google.protobuf.nano";
+
+message SingleMessageNano {
+}
diff --git a/src/google/protobuf/unittest_stringutf8_micro.proto b/src/google/protobuf/unittest_stringutf8_micro.proto
index e4bbe3d..68bd5ef 100644
--- a/src/google/protobuf/unittest_stringutf8_micro.proto
+++ b/src/google/protobuf/unittest_stringutf8_micro.proto
@@ -34,6 +34,8 @@
package protobuf_unittest_import;
option java_package = "com.google.protobuf.micro";
+// Explicit outer classname to suppress legacy info.
+option java_outer_classname = "UnittestStringutf8Micro";
message StringUtf8 {
optional string id = 1;
diff --git a/src/google/protobuf/unittest_stringutf8_nano.proto b/src/google/protobuf/unittest_stringutf8_nano.proto
index da624b0..2bbf2b7 100644
--- a/src/google/protobuf/unittest_stringutf8_nano.proto
+++ b/src/google/protobuf/unittest_stringutf8_nano.proto
@@ -34,6 +34,8 @@
package protobuf_unittest_import;
option java_package = "com.google.protobuf.nano";
+// Explicit outer classname to suppress legacy info.
+option java_outer_classname = "UnittestStringutf8Nano";
message StringUtf8 {
optional string id = 1;