Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 804f0134 authored by Kean Mariotti's avatar Kean Mariotti
Browse files

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
parent 2163c8ae
Loading
Loading
Loading
Loading
+34 −13
Original line number Diff line number Diff line
@@ -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) {
    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()));
        if (name.size() == 0) {
            ERRORS.Add(UNKNOWN_FILE, UNKNOWN_LINE,
                       "Unable to make an outer class name for file: %s",
    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);
    }
}