summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kean Mariotti <keanmariotti@google.com> 2024-04-17 07:55:05 +0000
committer Kean Mariotti <keanmariotti@google.com> 2024-04-18 10:54:26 +0000
commit804f0134e8f5e47c59a07a98cf938c84fc85a006 (patch)
tree19583e1538dbb8cd79bdd00e5156f8783c5a1d58
parent2163c8ae365c6cab3988af86d73c28825183dd22 (diff)
Avoid outer/inner class name clashes
In some cases, protoc-gen-javastream could emit outer classes and inner classes with the same name, which is invalid java. This commit extends protoc-gen-javastream to append an "OuterClass" suffix, if the outer class name clashes with any message. This behavior is consistent with the standard protoc. Bug: 276433199 Test: presubmit Change-Id: I4e92d70c10c4d92d103b00f15b159acc08dffff2
-rw-r--r--tools/streaming_proto/java/java_proto_stream_code_generator.cpp47
1 files changed, 34 insertions, 13 deletions
diff --git a/tools/streaming_proto/java/java_proto_stream_code_generator.cpp b/tools/streaming_proto/java/java_proto_stream_code_generator.cpp
index 0e5d35bada47..be5c197b7c5b 100644
--- a/tools/streaming_proto/java/java_proto_stream_code_generator.cpp
+++ b/tools/streaming_proto/java/java_proto_stream_code_generator.cpp
@@ -18,6 +18,7 @@
#include <stdio.h>
+#include <algorithm>
#include <iomanip>
#include <iostream>
#include <map>
@@ -31,21 +32,39 @@ using namespace android::stream_proto;
using namespace google::protobuf::io;
using namespace std;
+static bool outer_class_name_clashes_with_any_message(const string& outer_class_name,
+ const vector<DescriptorProto>& messages) {
+ return any_of(messages.cbegin(), messages.cend(), [&](const DescriptorProto& message) {
+ return message.name() == outer_class_name;
+ });
+}
+
/**
* If the descriptor gives us a class name, use that. Otherwise make one up from
* the filename of the .proto file.
*/
-static string make_outer_class_name(const FileDescriptorProto& file_descriptor) {
+static string make_outer_class_name(const FileDescriptorProto& file_descriptor,
+ const vector<DescriptorProto>& messages) {
string name = file_descriptor.options().java_outer_classname();
- if (name.size() == 0) {
- name = to_camel_case(file_base_name(file_descriptor.name()));
- if (name.size() == 0) {
- ERRORS.Add(UNKNOWN_FILE, UNKNOWN_LINE,
- "Unable to make an outer class name for file: %s",
- file_descriptor.name().c_str());
- name = "Unknown";
- }
+ if (!name.empty()) {
+ return name;
+ }
+
+ // Outer class and messages with the same name would result in invalid java (outer class and
+ // inner class cannot have same names).
+ // If the outer class name clashes with any message, let's append an "OuterClass" suffix.
+ // This behavior is consistent with the standard protoc.
+ name = to_camel_case(file_base_name(file_descriptor.name()));
+ while (outer_class_name_clashes_with_any_message(name, messages)) {
+ name += "OuterClass";
+ }
+
+ if (name.empty()) {
+ ERRORS.Add(UNKNOWN_FILE, UNKNOWN_LINE, "Unable to make an outer class name for file: %s",
+ file_descriptor.name().c_str());
+ name = "Unknown";
}
+
return name;
}
@@ -172,7 +191,7 @@ static void write_file(CodeGeneratorResponse* response, const FileDescriptorProt
stringstream text;
string const package_name = make_java_package(file_descriptor);
- string const outer_class_name = make_outer_class_name(file_descriptor);
+ string const outer_class_name = make_outer_class_name(file_descriptor, messages);
text << "// Generated by protoc-gen-javastream. DO NOT MODIFY." << endl;
text << "// source: " << file_descriptor.name() << endl << endl;
@@ -239,7 +258,8 @@ static void write_multiple_files(CodeGeneratorResponse* response,
if (messages_allowlist.empty() || !enums.empty()) {
write_file(response, file_descriptor,
- make_file_name(file_descriptor, make_outer_class_name(file_descriptor)),
+ make_file_name(file_descriptor,
+ make_outer_class_name(file_descriptor, messages)),
true, enums, messages);
}
}
@@ -297,8 +317,9 @@ static void write_single_file(CodeGeneratorResponse* response,
if (messages_allowlist.empty() || !enums.empty() || !messages.empty()) {
write_file(response, file_descriptor,
- make_file_name(file_descriptor, make_outer_class_name(file_descriptor)), true,
- enums, messages);
+ make_file_name(file_descriptor,
+ make_outer_class_name(file_descriptor, messages)),
+ true, enums, messages);
}
}