From 6cadb1875a60cdd955e84493d810adc073b07ac5 Mon Sep 17 00:00:00 2001 From: Mike Kruskal Date: Wed, 18 Jan 2023 14:11:07 -0800 Subject: [PATCH] Migrate std::operator+ to Abseil helpers in Ruby/PHP/Python compiler directories. This also opportunistically migrates many C-style and STL strings to string_view in touched code. PiperOrigin-RevId: 502975473 --- .../protobuf/compiler/php/php_generator.cc | 132 +++++++++--------- .../protobuf/compiler/python/generator.cc | 82 +++++------ .../protobuf/compiler/python/generator.h | 22 +-- .../protobuf/compiler/python/helpers.cc | 35 ++--- src/google/protobuf/compiler/python/helpers.h | 15 +- .../compiler/python/plugin_unittest.cc | 46 +++--- .../protobuf/compiler/python/pyi_generator.cc | 37 ++--- .../protobuf/compiler/ruby/ruby_generator.cc | 32 +++-- .../compiler/ruby/ruby_generator_unittest.cc | 32 +++-- 9 files changed, 229 insertions(+), 204 deletions(-) diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc index 956fe0b800..0401435ea0 100644 --- a/src/google/protobuf/compiler/php/php_generator.cc +++ b/src/google/protobuf/compiler/php/php_generator.cc @@ -30,8 +30,10 @@ #include "google/protobuf/compiler/php/php_generator.h" +#include #include #include +#include #include "google/protobuf/compiler/code_generator.h" #include "absl/container/flat_hash_map.h" @@ -39,6 +41,7 @@ #include "google/protobuf/stubs/logging.h" #include "absl/strings/ascii.h" #include "absl/strings/escaping.h" +#include "absl/strings/str_cat.h" #include "absl/strings/str_replace.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" @@ -79,12 +82,12 @@ struct Options { namespace { // Forward decls. -std::string PhpName(const std::string& full_name, const Options& options); +std::string PhpName(absl::string_view full_name, const Options& options); std::string IntToString(int32_t value); -std::string FilenameToClassname(const std::string& filename); +std::string FilenameToClassname(absl::string_view filename); std::string GeneratedMetadataFileName(const FileDescriptor* file, const Options& options); -std::string UnderscoresToCamelCase(const std::string& name, +std::string UnderscoresToCamelCase(absl::string_view name, bool cap_first_letter); void Indent(io::Printer* printer); void Outdent(io::Printer* printer); @@ -136,10 +139,10 @@ std::string LegacyGeneratedClassName(const DescriptorType* desc) { return ClassNamePrefix(classname, desc) + classname; } -std::string ConstantNamePrefix(const std::string& classname) { +std::string ConstantNamePrefix(absl::string_view classname) { bool is_reserved = false; - std::string lower = classname; + std::string lower(classname); std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); is_reserved = IsReservedName(lower); @@ -162,9 +165,9 @@ template std::string RootPhpNamespace(const DescriptorType* desc, const Options& options) { if (desc->file()->options().has_php_namespace()) { - const std::string& php_namespace = desc->file()->options().php_namespace(); + absl::string_view php_namespace = desc->file()->options().php_namespace(); if (!php_namespace.empty()) { - return php_namespace; + return std::string(php_namespace); } return ""; } @@ -180,7 +183,7 @@ std::string FullClassName(const DescriptorType* desc, const Options& options) { std::string classname = GeneratedClassName(desc); std::string php_namespace = RootPhpNamespace(desc, options); if (!php_namespace.empty()) { - return php_namespace + "\\" + classname; + return absl::StrCat(php_namespace, "\\", classname); } return classname; } @@ -198,17 +201,17 @@ std::string LegacyFullClassName(const DescriptorType* desc, std::string classname = LegacyGeneratedClassName(desc); std::string php_namespace = RootPhpNamespace(desc, options); if (!php_namespace.empty()) { - return php_namespace + "\\" + classname; + return absl::StrCat(php_namespace, "\\", classname); } return classname; } -std::string PhpNamePrefix(const std::string& classname) { +std::string PhpNamePrefix(absl::string_view classname) { if (IsReservedName(classname)) return "PB"; return ""; } -std::string PhpName(const std::string& full_name, const Options& options) { +std::string PhpName(absl::string_view full_name, const Options& options) { if (options.is_descriptor) { return std::string(kDescriptorPackageName); } @@ -259,7 +262,7 @@ std::string DefaultForField(const FieldDescriptor* field) { std::string GeneratedMetadataFileName(const FileDescriptor* file, const Options& options) { - const std::string& proto_file = file->name(); + absl::string_view proto_file = file->name(); int start_index = 0; int first_index = proto_file.find_first_of('/', start_index); std::string result = ""; @@ -273,7 +276,7 @@ std::string GeneratedMetadataFileName(const FileDescriptor* file, } // Append directory name. - std::string file_no_suffix; + absl::string_view file_no_suffix; int lastindex = proto_file.find_last_of('.'); if (proto_file == kEmptyFile) { return std::string(kEmptyMetadataFile); @@ -282,21 +285,21 @@ std::string GeneratedMetadataFileName(const FileDescriptor* file, } if (file->options().has_php_metadata_namespace()) { - const std::string& php_metadata_namespace = + absl::string_view php_metadata_namespace = file->options().php_metadata_namespace(); if (!php_metadata_namespace.empty() && php_metadata_namespace != "\\") { - result += php_metadata_namespace; + absl::StrAppend(&result, php_metadata_namespace); std::replace(result.begin(), result.end(), '\\', '/'); if (result.at(result.size() - 1) != '/') { - result += "/"; + absl::StrAppend(&result, "/"); } } } else { - result += "GPBMetadata/"; + absl::StrAppend(&result, "GPBMetadata/"); while (first_index != std::string::npos) { segment = UnderscoresToCamelCase( file_no_suffix.substr(start_index, first_index - start_index), true); - result += ReservedNamePrefix(segment, file) + segment + "/"; + absl::StrAppend(&result, ReservedNamePrefix(segment, file), segment, "/"); start_index = first_index + 1; first_index = file_no_suffix.find_first_of('/', start_index); } @@ -312,7 +315,8 @@ std::string GeneratedMetadataFileName(const FileDescriptor* file, segment = UnderscoresToCamelCase( file_no_suffix.substr(file_name_start, first_index - file_name_start), true); - return result + ReservedNamePrefix(segment, file) + segment + ".php"; + return absl::StrCat(result, ReservedNamePrefix(segment, file), segment, + ".php"); } std::string GeneratedMetadataFileName(const FileDescriptor* file, @@ -331,7 +335,7 @@ std::string GeneratedClassFileName(const DescriptorType* desc, result[i] = '/'; } } - return result + ".php"; + return absl::StrCat(result, ".php"); } template @@ -344,7 +348,7 @@ std::string LegacyGeneratedClassFileName(const DescriptorType* desc, result[i] = '/'; } } - return result + ".php"; + return absl::StrCat(result, ".php"); } template @@ -356,21 +360,21 @@ std::string LegacyReadOnlyGeneratedClassFileName(std::string php_namespace, php_namespace[i] = '/'; } } - return php_namespace + "/" + desc->name() + ".php"; + return absl::StrCat(php_namespace, "/", desc->name(), ".php"); } - return desc->name() + ".php"; + return absl::StrCat(desc->name(), ".php"); } std::string GeneratedServiceFileName(const ServiceDescriptor* service, const Options& options) { - std::string result = FullClassName(service, options) + "Interface"; + std::string result = FullClassName(service, options); for (int i = 0; i < result.size(); i++) { if (result[i] == '\\') { result[i] = '/'; } } - return result + ".php"; + return absl::StrCat(result, "Interface", ".php"); } std::string IntToString(int32_t value) { @@ -422,7 +426,7 @@ std::string PhpSetterTypeName(const FieldDescriptor* field, type = "string"; break; case FieldDescriptor::TYPE_MESSAGE: - type = "\\" + FullClassName(field->message_type(), options); + type = absl::StrCat("\\", FullClassName(field->message_type(), options)); break; case FieldDescriptor::TYPE_GROUP: return "null"; @@ -434,7 +438,8 @@ std::string PhpSetterTypeName(const FieldDescriptor* field, if (start_pos != std::string::npos) { type.replace(start_pos, 1, ">|array<"); } - type = "array<" + type + ">|\\Google\\Protobuf\\Internal\\RepeatedField"; + type = absl::StrCat("array<", type, + ">|\\Google\\Protobuf\\Internal\\RepeatedField"); } return type; } @@ -472,7 +477,7 @@ std::string PhpGetterTypeName(const FieldDescriptor* field, case FieldDescriptor::TYPE_STRING: case FieldDescriptor::TYPE_BYTES: return "string"; case FieldDescriptor::TYPE_MESSAGE: - return "\\" + FullClassName(field->message_type(), options); + return absl::StrCat("\\", FullClassName(field->message_type(), options)); case FieldDescriptor::TYPE_GROUP: return "null"; default: assert(false); return ""; } @@ -488,13 +493,14 @@ std::string PhpGetterTypeName(const FieldDescriptor* field, std::string EnumOrMessageSuffix(const FieldDescriptor* field, const Options& options) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - return ", '" + - DescriptorFullName(field->message_type(), options.is_descriptor) + - "'"; + return absl::StrCat( + ", '", DescriptorFullName(field->message_type(), options.is_descriptor), + "'"); } if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { - return ", '" + - DescriptorFullName(field->enum_type(), options.is_descriptor) + "'"; + return absl::StrCat( + ", '", DescriptorFullName(field->enum_type(), options.is_descriptor), + "'"); } return ""; } @@ -508,7 +514,7 @@ std::string EnumOrMessageSuffix(const FieldDescriptor* field, // Converts a name to camel-case. If cap_first_letter is true, capitalize the // first letter. -std::string UnderscoresToCamelCase(const std::string& name, +std::string UnderscoresToCamelCase(absl::string_view name, bool cap_first_letter) { std::string result; for (int i = 0; i < name.size(); i++) { @@ -589,8 +595,11 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, GenerateFieldDocComment(printer, field, options, kFieldGetter); // deprecation - std::string deprecation_trigger = (field->options().deprecated()) ? "@trigger_error('" + - field->name() + " is deprecated.', E_USER_DEPRECATED);\n " : ""; + std::string deprecation_trigger = + (field->options().deprecated()) + ? absl::StrCat("@trigger_error('", field->name(), + " is deprecated.', E_USER_DEPRECATED);\n ") + : ""; // Emit getter. if (oneof != NULL) { @@ -693,15 +702,13 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, "key_type", absl::AsciiStrToUpper(key->type_name()), "value_type", absl::AsciiStrToUpper(value->type_name())); if (value->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - printer->Print( - ", \\^class_name^);\n", - "class_name", - FullClassName(value->message_type(), options) + "::class"); + printer->Print(", \\^class_name^);\n", "class_name", + absl::StrCat(FullClassName(value->message_type(), options), + "::class")); } else if (value->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { printer->Print( - ", \\^class_name^);\n", - "class_name", - FullClassName(value->enum_type(), options) + "::class"); + ", \\^class_name^);\n", "class_name", + absl::StrCat(FullClassName(value->enum_type(), options), "::class")); } else { printer->Print(");\n"); } @@ -711,15 +718,13 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, "\\Google\\Protobuf\\Internal\\GPBType::^type^", "type", absl::AsciiStrToUpper(field->type_name())); if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - printer->Print( - ", \\^class_name^);\n", - "class_name", - FullClassName(field->message_type(), options) + "::class"); + printer->Print(", \\^class_name^);\n", "class_name", + absl::StrCat(FullClassName(field->message_type(), options), + "::class")); } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { printer->Print( - ", \\^class_name^);\n", - "class_name", - FullClassName(field->enum_type(), options) + "::class"); + ", \\^class_name^);\n", "class_name", + absl::StrCat(FullClassName(field->enum_type(), options), "::class")); } else { printer->Print(");\n"); } @@ -809,16 +814,16 @@ void GenerateServiceMethod(const MethodDescriptor* method, ); } -void GenerateMessageToPool(const std::string& name_prefix, +void GenerateMessageToPool(absl::string_view name_prefix, const Descriptor* message, io::Printer* printer) { // Don't generate MapEntry messages -- we use the PHP extension's native // support for map fields instead. if (message->options().map_entry()) { return; } - std::string class_name = - (name_prefix.empty() ? "" : name_prefix + "\\") + - ReservedNamePrefix(message->name(), message->file()) + message->name(); + std::string class_name = absl::StrCat( + name_prefix.empty() ? "" : absl::StrCat(name_prefix, "\\"), + ReservedNamePrefix(message->name(), message->file()), message->name()); printer->Print( "$pool->addMessage('^message^', " @@ -920,7 +925,7 @@ void GenerateAddFileToPool(const FileDescriptor* file, const Options& options, "$pool->finish();\n"); } else { for (int i = 0; i < file->dependency_count(); i++) { - const std::string& name = file->dependency(i)->name(); + absl::string_view name = file->dependency(i)->name(); // Currently, descriptor.proto is not ready for external usage. Skip to // import it for now, so that its dependencies can still work as long as // they don't use protos defined in descriptor.proto. @@ -1164,10 +1169,10 @@ void GenerateHead(const FileDescriptor* file, io::Printer* printer) { "filename", file->name()); } -std::string FilenameToClassname(const std::string& filename) { - int lastindex = filename.find_last_of('.'); - std::string result = filename.substr(0, lastindex); - for (int i = 0; i < result.size(); i++) { +std::string FilenameToClassname(absl::string_view filename) { + size_t lastindex = filename.find_last_of('.'); + std::string result(filename.substr(0, lastindex)); + for (size_t i = 0; i < result.size(); i++) { if (result[i] == '/') { result[i] = '\\'; } @@ -1622,7 +1627,7 @@ void GenerateFile(const FileDescriptor* file, const Options& options, } } -static std::string EscapePhpdoc(const std::string& input) { +static std::string EscapePhpdoc(absl::string_view input) { std::string result; result.reserve(input.size() * 2); @@ -1679,7 +1684,8 @@ static void GenerateDocCommentBodyForLocation( // HTML-escape them so that they don't accidentally close the doc comment. comments = EscapePhpdoc(comments); - std::vector lines = absl::StrSplit(comments, "\n", absl::SkipEmpty()); + std::vector lines = + absl::StrSplit(comments, '\n', absl::SkipEmpty()); while (!lines.empty() && lines.back().empty()) { lines.pop_back(); } @@ -1710,8 +1716,8 @@ static void GenerateDocCommentBody( } } -static std::string FirstLineOf(const std::string& value) { - std::string result = value; +static std::string FirstLineOf(absl::string_view value) { + std::string result(value); std::string::size_type pos = result.find_first_of('\n'); if (pos != std::string::npos) { diff --git a/src/google/protobuf/compiler/python/generator.cc b/src/google/protobuf/compiler/python/generator.cc index 91f17626eb..60158190c8 100644 --- a/src/google/protobuf/compiler/python/generator.cc +++ b/src/google/protobuf/compiler/python/generator.cc @@ -80,7 +80,7 @@ namespace { // when importing. See testPackageInitializationImport in // third_party/py/google/protobuf/internal/reflection_test.py // to see why we need the alias. -std::string ModuleAlias(const std::string& filename) { +std::string ModuleAlias(absl::string_view filename) { std::string module_name = ModuleName(filename); // We can't have dots in the module name, so we replace each with _dot_. // But that could lead to a collision between a.b and a_dot_b, so we also @@ -135,7 +135,7 @@ std::string StringifyDefaultValue(const FieldDescriptor& field) { // infinity * 0 = nan return "(1e10000 * 0)"; } else { - return "float(" + io::SimpleDtoa(value) + ")"; + return absl::StrCat("float(", io::SimpleDtoa(value), ")"); } } case FieldDescriptor::CPPTYPE_FLOAT: { @@ -151,7 +151,7 @@ std::string StringifyDefaultValue(const FieldDescriptor& field) { // infinity - infinity = nan return "(1e10000 * 0)"; } else { - return "float(" + io::SimpleFtoa(value) + ")"; + return absl::StrCat("float(", io::SimpleFtoa(value), ")"); } } case FieldDescriptor::CPPTYPE_BOOL: @@ -159,10 +159,10 @@ std::string StringifyDefaultValue(const FieldDescriptor& field) { case FieldDescriptor::CPPTYPE_ENUM: return absl::StrCat(field.default_value_enum()->number()); case FieldDescriptor::CPPTYPE_STRING: - return "b\"" + absl::CEscape(field.default_value_string()) + - (field.type() != FieldDescriptor::TYPE_STRING - ? "\"" - : "\".decode('utf-8')"); + return absl::StrCat("b\"", absl::CEscape(field.default_value_string()), + (field.type() != FieldDescriptor::TYPE_STRING + ? "\"" + : "\".decode('utf-8')")); case FieldDescriptor::CPPTYPE_MESSAGE: return "None"; } @@ -197,7 +197,7 @@ uint64_t Generator::GetSupportedFeatures() const { return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL; } -GeneratorOptions Generator::ParseParameter(const std::string& parameter, +GeneratorOptions Generator::ParseParameter(absl::string_view parameter, std::string* error) const { GeneratorOptions options; @@ -215,7 +215,7 @@ GeneratorOptions Generator::ParseParameter(const std::string& parameter, } else if (option.first == "annotate_code") { options.annotate_pyi = true; } else { - *error = "Unknown generator option: " + option.first; + *error = absl::StrCat("Unknown generator option: ", option.first); } } return options; @@ -387,7 +387,7 @@ void Generator::PrintTopBoilerplate() const { // Prints Python imports for all modules imported by |file|. void Generator::PrintImports() const { for (int i = 0; i < file_->dependency_count(); ++i) { - const std::string& filename = file_->dependency(i)->name(); + absl::string_view filename = file_->dependency(i)->name(); std::string module_name = ModuleName(filename); std::string module_alias = ModuleAlias(filename); @@ -404,15 +404,16 @@ void Generator::PrintImports() const { printer_->Print("$alias$ = importlib.import_module('$name$')\n", "alias", module_alias, "name", module_name); } else { - int last_dot_pos = module_name.rfind('.'); + size_t last_dot_pos = module_name.rfind('.'); std::string import_statement; if (last_dot_pos == std::string::npos) { // NOTE(petya): this is not tested as it would require a protocol buffer // outside of any package, and I don't think that is easily achievable. - import_statement = "import " + module_name; + import_statement = absl::StrCat("import ", module_name); } else { - import_statement = "from " + module_name.substr(0, last_dot_pos) + - " import " + module_name.substr(last_dot_pos + 1); + import_statement = + absl::StrCat("from ", module_name.substr(0, last_dot_pos), + " import ", module_name.substr(last_dot_pos + 1)); } printer_->Print("$statement$ as $alias$\n", "statement", import_statement, "alias", module_alias); @@ -711,7 +712,8 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { if (options_string == "None") { m["serialized_options"] = ""; } else { - m["serialized_options"] = ", serialized_options=" + options_string; + m["serialized_options"] = + absl::StrCat(", serialized_options=", options_string); } printer_->Print(m, "_descriptor.OneofDescriptor(\n" @@ -760,16 +762,16 @@ void Generator::PrintMessages() const { // Mutually recursive with PrintNestedMessages(). // Collect nested message names to_register for the symbol_database. void Generator::PrintMessage(const Descriptor& message_descriptor, - const std::string& prefix, + absl::string_view prefix, std::vector* to_register, bool is_nested) const { std::string qualified_name; if (is_nested) { if (IsPythonKeyword(message_descriptor.name())) { - qualified_name = - "getattr(" + prefix + ", '" + message_descriptor.name() + "')"; + qualified_name = absl::StrCat("getattr(", prefix, ", '", + message_descriptor.name(), "')"); } else { - qualified_name = prefix + "." + message_descriptor.name(); + qualified_name = absl::StrCat(prefix, ".", message_descriptor.name()); } printer_->Print( "'$name$' : _reflection.GeneratedProtocolMessageType('$name$', " @@ -807,7 +809,7 @@ void Generator::PrintMessage(const Descriptor& message_descriptor, // Prints all nested messages within |containing_descriptor|. // Mutually recursive with PrintMessage(). void Generator::PrintNestedMessages( - const Descriptor& containing_descriptor, const std::string& prefix, + const Descriptor& containing_descriptor, absl::string_view prefix, std::vector* to_register) const { for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) { printer_->Print("\n"); @@ -918,7 +920,7 @@ void Generator::AddExtensionToFileDescriptor( // is NULL. void Generator::FixForeignFieldsInField( const Descriptor* containing_type, const FieldDescriptor& field, - const std::string& python_dict_name) const { + absl::string_view python_dict_name) const { const std::string field_referencing_expression = FieldReferencingExpression(containing_type, field, python_dict_name); absl::flat_hash_map m; @@ -946,7 +948,7 @@ void Generator::FixForeignFieldsInField( // is NULL. std::string Generator::FieldReferencingExpression( const Descriptor* containing_type, const FieldDescriptor& field, - const std::string& python_dict_name) const { + absl::string_view python_dict_name) const { // We should only ever be looking up fields in the current file. // The only things we refer to from other files are message descriptors. GOOGLE_ABSL_CHECK_EQ(field.file(), file_) @@ -1064,11 +1066,11 @@ void Generator::PrintEnumValueDescriptor( // Returns a CEscaped string of serialized_options. std::string Generator::OptionsValue( - const std::string& serialized_options) const { + absl::string_view serialized_options) const { if (serialized_options.length() == 0 || GeneratingDescriptorProto()) { return "None"; } else { - return "b'" + absl::CEscape(serialized_options) + "'"; + return absl::StrCat("b'", absl::CEscape(serialized_options), "'"); } } @@ -1089,8 +1091,9 @@ void Generator::PrintFieldDescriptor(const FieldDescriptor& field, m["default_value"] = StringifyDefaultValue(field); m["is_extension"] = is_extension ? "True" : "False"; m["serialized_options"] = OptionsValue(options_string); - m["json_name"] = - field.has_json_name() ? ", json_name='" + field.json_name() + "'" : ""; + m["json_name"] = field.has_json_name() + ? absl::StrCat(", json_name='", field.json_name(), "'") + : ""; // We always set message_type and enum_type to None at this point, and then // these fields in correctly after all referenced descriptors have been // defined and/or imported (see FixForeignFieldsInDescriptors()). @@ -1110,8 +1113,8 @@ void Generator::PrintFieldDescriptor(const FieldDescriptor& field, // Helper for Print{Fields,Extensions}InDescriptor(). void Generator::PrintFieldDescriptorsInDescriptor( const Descriptor& message_descriptor, bool is_extension, - const std::string& list_variable_name, int (Descriptor::*CountFn)() const, - const FieldDescriptor* (Descriptor::*GetterFn)(int)const) const { + absl::string_view list_variable_name, int (Descriptor::*CountFn)() const, + const FieldDescriptor* (Descriptor::*GetterFn)(int) const) const { printer_->Print("$list$=[\n", "list", list_variable_name); printer_->Indent(); for (int i = 0; i < (message_descriptor.*CountFn)(); ++i) { @@ -1169,11 +1172,11 @@ std::string Generator::ModuleLevelDescriptorName( absl::AsciiStrToUpper(&name); // Module-private for now. Easy to make public later; almost impossible // to make private later. - name = "_" + name; + name = absl::StrCat("_", name); // We now have the name relative to its own module. Also qualify with // the module name iff this descriptor is from a different .proto file. if (descriptor.file() != file_) { - name = ModuleAlias(descriptor.file()->name()) + "." + name; + name = absl::StrCat(ModuleAlias(descriptor.file()->name()), ".", name); } return name; } @@ -1186,7 +1189,7 @@ std::string Generator::ModuleLevelMessageName( const Descriptor& descriptor) const { std::string name = NamePrefixedWithNestedTypes(descriptor, "."); if (descriptor.file() != file_) { - name = ModuleAlias(descriptor.file()->name()) + "." + name; + name = absl::StrCat(ModuleAlias(descriptor.file()->name()), ".", name); } return name; } @@ -1195,11 +1198,10 @@ std::string Generator::ModuleLevelMessageName( // descriptor. std::string Generator::ModuleLevelServiceDescriptorName( const ServiceDescriptor& descriptor) const { - std::string name = descriptor.name(); + std::string name = absl::StrCat("_", descriptor.name()); absl::AsciiStrToUpper(&name); - name = "_" + name; if (descriptor.file() != file_) { - name = ModuleAlias(descriptor.file()->name()) + "." + name; + name = absl::StrCat(ModuleAlias(descriptor.file()->name()), ".", name); } return name; } @@ -1225,7 +1227,7 @@ std::string Generator::InternalPackage() const { template void Generator::PrintSerializedPbInterval(const DescriptorT& descriptor, DescriptorProtoT& proto, - const std::string& name) const { + absl::string_view name) const { descriptor.CopyTo(&proto); std::string sp; proto.SerializeToString(&sp); @@ -1240,8 +1242,8 @@ void Generator::PrintSerializedPbInterval(const DescriptorT& descriptor, } namespace { -void PrintDescriptorOptionsFixingCode(const std::string& descriptor, - const std::string& options, +void PrintDescriptorOptionsFixingCode(absl::string_view descriptor, + absl::string_view options, io::Printer* printer) { // Reset the _options to None thus DescriptorBase.GetOptions() can // parse _options again after extensions are registered. @@ -1373,8 +1375,8 @@ void Generator::FixOptionsForService( std::string method_options = OptionsValue(method->options().SerializeAsString()); if (method_options != "None") { - std::string method_name = - descriptor_name + ".methods_by_name['" + method->name() + "']"; + std::string method_name = absl::StrCat( + descriptor_name, ".methods_by_name['", method->name(), "']"); PrintDescriptorOptionsFixingCode(method_name, method_options, printer_); } } @@ -1440,7 +1442,7 @@ void Generator::FixOptionsForMessage(const Descriptor& descriptor) const { // If a dependency forwards other files through public dependencies, let's // copy over the corresponding module aliases. void Generator::CopyPublicDependenciesAliases( - const std::string& copy_from, const FileDescriptor* file) const { + absl::string_view copy_from, const FileDescriptor* file) const { for (int i = 0; i < file->public_dependency_count(); ++i) { std::string module_name = ModuleName(file->public_dependency(i)->name()); std::string module_alias = ModuleAlias(file->public_dependency(i)->name()); diff --git a/src/google/protobuf/compiler/python/generator.h b/src/google/protobuf/compiler/python/generator.h index 3fa946d959..c5182c42c0 100644 --- a/src/google/protobuf/compiler/python/generator.h +++ b/src/google/protobuf/compiler/python/generator.h @@ -36,7 +36,9 @@ #define GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__ #include +#include +#include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "google/protobuf/compiler/code_generator.h" @@ -90,7 +92,7 @@ class PROTOC_EXPORT Generator : public CodeGenerator { } private: - GeneratorOptions ParseParameter(const std::string& parameter, + GeneratorOptions ParseParameter(absl::string_view parameter, std::string* error) const; void PrintImports() const; void PrintFileDescriptor() const; @@ -102,8 +104,8 @@ class PROTOC_EXPORT Generator : public CodeGenerator { bool is_extension) const; void PrintFieldDescriptorsInDescriptor( const Descriptor& message_descriptor, bool is_extension, - const std::string& list_variable_name, int (Descriptor::*CountFn)() const, - const FieldDescriptor* (Descriptor::*GetterFn)(int)const) const; + absl::string_view list_variable_name, int (Descriptor::*CountFn)() const, + const FieldDescriptor* (Descriptor::*GetterFn)(int) const) const; void PrintFieldsInDescriptor(const Descriptor& message_descriptor) const; void PrintExtensionsInDescriptor(const Descriptor& message_descriptor) const; void PrintMessageDescriptors() const; @@ -112,11 +114,11 @@ class PROTOC_EXPORT Generator : public CodeGenerator { void PrintMessages() const; void PrintMessage(const Descriptor& message_descriptor, - const std::string& prefix, + absl::string_view prefix, std::vector* to_register, bool is_nested) const; void PrintNestedMessages(const Descriptor& containing_descriptor, - const std::string& prefix, + absl::string_view prefix, std::vector* to_register) const; void FixForeignFieldsInDescriptors() const; @@ -125,14 +127,14 @@ class PROTOC_EXPORT Generator : public CodeGenerator { const Descriptor* containing_descriptor) const; void FixForeignFieldsInField(const Descriptor* containing_type, const FieldDescriptor& field, - const std::string& python_dict_name) const; + absl::string_view python_dict_name) const; void AddMessageToFileDescriptor(const Descriptor& descriptor) const; void AddEnumToFileDescriptor(const EnumDescriptor& descriptor) const; void AddExtensionToFileDescriptor(const FieldDescriptor& descriptor) const; void AddServiceToFileDescriptor(const ServiceDescriptor& descriptor) const; std::string FieldReferencingExpression( const Descriptor* containing_type, const FieldDescriptor& field, - const std::string& python_dict_name) const; + absl::string_view python_dict_name) const; template void FixContainingTypeInDescriptor( const DescriptorT& descriptor, @@ -153,7 +155,7 @@ class PROTOC_EXPORT Generator : public CodeGenerator { const ServiceDescriptor& descriptor) const; void PrintEnumValueDescriptor(const EnumValueDescriptor& descriptor) const; - std::string OptionsValue(const std::string& serialized_options) const; + std::string OptionsValue(absl::string_view serialized_options) const; bool GeneratingDescriptorProto() const; template @@ -167,7 +169,7 @@ class PROTOC_EXPORT Generator : public CodeGenerator { template void PrintSerializedPbInterval(const DescriptorT& descriptor, DescriptorProtoT& proto, - const std::string& name) const; + absl::string_view name) const; void FixAllDescriptorOptions() const; void FixOptionsForField(const FieldDescriptor& field) const; @@ -179,7 +181,7 @@ class PROTOC_EXPORT Generator : public CodeGenerator { void SetSerializedPbInterval() const; void SetMessagePbInterval(const Descriptor& descriptor) const; - void CopyPublicDependenciesAliases(const std::string& copy_from, + void CopyPublicDependenciesAliases(absl::string_view copy_from, const FileDescriptor* file) const; // Very coarse-grained lock to ensure that Generate() is reentrant. diff --git a/src/google/protobuf/compiler/python/helpers.cc b/src/google/protobuf/compiler/python/helpers.cc index 2a129f1a7f..fe35a74f4f 100644 --- a/src/google/protobuf/compiler/python/helpers.cc +++ b/src/google/protobuf/compiler/python/helpers.cc @@ -31,12 +31,15 @@ #include "google/protobuf/compiler/python/helpers.h" #include +#include +#include #include "google/protobuf/stubs/logging.h" #include "absl/strings/escaping.h" #include "absl/strings/match.h" #include "absl/strings/str_replace.h" #include "absl/strings/str_split.h" +#include "absl/strings/string_view.h" #include "absl/strings/strip.h" #include "google/protobuf/compiler/code_generator.h" #include "google/protobuf/descriptor.h" @@ -48,13 +51,13 @@ namespace compiler { namespace python { // Returns the Python module name expected for a given .proto filename. -std::string ModuleName(const std::string& filename) { +std::string ModuleName(absl::string_view filename) { std::string basename = StripProto(filename); absl::StrReplaceAll({{"-", "_"}, {"/", "."}}, &basename); - return basename + "_pb2"; + return absl::StrCat(basename, "_pb2"); } -std::string StrippedModuleName(const std::string& filename) { +std::string StrippedModuleName(absl::string_view filename) { std::string module_name = ModuleName(filename); return module_name; } @@ -71,8 +74,8 @@ const char* const kKeywords[] = { const char* const* kKeywordsEnd = kKeywords + (sizeof(kKeywords) / sizeof(kKeywords[0])); -bool ContainsPythonKeyword(const std::string& module_name) { - std::vector tokens = absl::StrSplit(module_name, "."); +bool ContainsPythonKeyword(absl::string_view module_name) { + std::vector tokens = absl::StrSplit(module_name, '.'); for (int i = 0; i < static_cast(tokens.size()); ++i) { if (std::find(kKeywords, kKeywordsEnd, tokens[i]) != kKeywordsEnd) { return true; @@ -81,23 +84,23 @@ bool ContainsPythonKeyword(const std::string& module_name) { return false; } -bool IsPythonKeyword(const std::string& name) { +bool IsPythonKeyword(absl::string_view name) { return (std::find(kKeywords, kKeywordsEnd, name) != kKeywordsEnd); } -std::string ResolveKeyword(const std::string& name) { +std::string ResolveKeyword(absl::string_view name) { if (IsPythonKeyword(name)) { - return "globals()['" + name + "']"; + return absl::StrCat("globals()['", name, "']"); } - return name; + return std::string(name); } std::string GetFileName(const FileDescriptor* file_des, - const std::string& suffix) { + absl::string_view suffix) { std::string module_name = ModuleName(file_des->name()); std::string filename = module_name; absl::StrReplaceAll({{".", "/"}}, &filename); - filename += suffix; + absl::StrAppend(&filename, suffix); return filename; } @@ -113,15 +116,15 @@ std::string GeneratedCodeToBase64(const GeneratedCodeInfo& annotations) { template std::string NamePrefixedWithNestedTypes(const DescriptorT& descriptor, - const std::string& separator) { + absl::string_view separator) { std::string name = descriptor.name(); const Descriptor* parent = descriptor.containing_type(); if (parent != nullptr) { std::string prefix = NamePrefixedWithNestedTypes(*parent, separator); if (separator == "." && IsPythonKeyword(name)) { - return "getattr(" + prefix + ", '" + name + "')"; + return absl::StrCat("getattr(", prefix, ", '", name, "')"); } else { - return prefix + separator + name; + return absl::StrCat(prefix, separator, name); } } if (separator == ".") { @@ -131,9 +134,9 @@ std::string NamePrefixedWithNestedTypes(const DescriptorT& descriptor, } template std::string NamePrefixedWithNestedTypes( - const Descriptor& descriptor, const std::string& separator); + const Descriptor& descriptor, absl::string_view separator); template std::string NamePrefixedWithNestedTypes( - const EnumDescriptor& descriptor, const std::string& separator); + const EnumDescriptor& descriptor, absl::string_view separator); } // namespace python } // namespace compiler diff --git a/src/google/protobuf/compiler/python/helpers.h b/src/google/protobuf/compiler/python/helpers.h index 3741fbb2f3..f648b6054f 100644 --- a/src/google/protobuf/compiler/python/helpers.h +++ b/src/google/protobuf/compiler/python/helpers.h @@ -34,6 +34,7 @@ #include #include "absl/strings/str_replace.h" +#include "absl/strings/string_view.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" @@ -42,19 +43,19 @@ namespace protobuf { namespace compiler { namespace python { -std::string ModuleName(const std::string& filename); -std::string StrippedModuleName(const std::string& filename); -bool ContainsPythonKeyword(const std::string& module_name); -bool IsPythonKeyword(const std::string& name); -std::string ResolveKeyword(const std::string& name); +std::string ModuleName(absl::string_view filename); +std::string StrippedModuleName(absl::string_view filename); +bool ContainsPythonKeyword(absl::string_view module_name); +bool IsPythonKeyword(absl::string_view name); +std::string ResolveKeyword(absl::string_view name); std::string GetFileName(const FileDescriptor* file_des, - const std::string& suffix); + absl::string_view suffix); bool HasGenericServices(const FileDescriptor* file); std::string GeneratedCodeToBase64(const GeneratedCodeInfo& annotations); template std::string NamePrefixedWithNestedTypes(const DescriptorT& descriptor, - const std::string& separator); + absl::string_view separator); } // namespace python } // namespace compiler diff --git a/src/google/protobuf/compiler/python/plugin_unittest.cc b/src/google/protobuf/compiler/python/plugin_unittest.cc index 54cad05f8c..f1e86b3ffd 100644 --- a/src/google/protobuf/compiler/python/plugin_unittest.cc +++ b/src/google/protobuf/compiler/python/plugin_unittest.cc @@ -32,6 +32,7 @@ #include #include +#include #include "google/protobuf/testing/file.h" #include "google/protobuf/testing/file.h" @@ -79,26 +80,28 @@ class TestGenerator : public CodeGenerator { TEST(PythonPluginTest, ImportTest) { // Create files test1.proto and test2.proto with the former importing the // latter. - GOOGLE_ABSL_CHECK_OK(File::SetContents(TestTempDir() + "/test1.proto", - "syntax = \"proto3\";\n" - "package foo;\n" - "import \"test2.proto\";" - "message Message1 {\n" - " Message2 message_2 = 1;\n" - "}\n", - true)); - GOOGLE_ABSL_CHECK_OK(File::SetContents(TestTempDir() + "/test2.proto", - "syntax = \"proto3\";\n" - "package foo;\n" - "message Message2 {}\n", - true)); + GOOGLE_ABSL_CHECK_OK( + File::SetContents(absl::StrCat(TestTempDir(), "/test1.proto"), + "syntax = \"proto3\";\n" + "package foo;\n" + "import \"test2.proto\";" + "message Message1 {\n" + " Message2 message_2 = 1;\n" + "}\n", + true)); + GOOGLE_ABSL_CHECK_OK( + File::SetContents(absl::StrCat(TestTempDir(), "/test2.proto"), + "syntax = \"proto3\";\n" + "package foo;\n" + "message Message2 {}\n", + true)); compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); python::Generator python_generator; cli.RegisterGenerator("--python_out", &python_generator, ""); - std::string proto_path = "-I" + TestTempDir(); - std::string python_out = "--python_out=" + TestTempDir(); + std::string proto_path = absl::StrCat("-I", TestTempDir()); + std::string python_out = absl::StrCat("--python_out=", TestTempDir()); const char* argv[] = {"protoc", proto_path.c_str(), "-I.", python_out.c_str(), "test1.proto"}; ASSERT_EQ(0, cli.Run(5, argv)); @@ -106,16 +109,17 @@ TEST(PythonPluginTest, ImportTest) { // Loop over the lines of the generated code and verify that we find an // ordinary Python import but do not find the string "importlib". std::string output; - GOOGLE_ABSL_CHECK_OK(File::GetContents(TestTempDir() + "/test1_pb2.py", &output, - true)); - std::vector lines = absl::StrSplit(output, "\n"); + GOOGLE_ABSL_CHECK_OK( + File::GetContents(absl::StrCat(TestTempDir(), "/test1_pb2.py"), + &output, true)); + std::vector lines = absl::StrSplit(output, '\n'); std::string expected_import = "import test2_pb2"; bool found_expected_import = false; - for (int i = 0; i < lines.size(); ++i) { - if (lines[i].find(expected_import) != std::string::npos) { + for (absl::string_view line : lines) { + if (absl::StrContains(line, expected_import)) { found_expected_import = true; } - EXPECT_EQ(std::string::npos, lines[i].find("importlib")); + EXPECT_FALSE(absl::StrContains(line, "importlib")); } EXPECT_TRUE(found_expected_import); } diff --git a/src/google/protobuf/compiler/python/pyi_generator.cc b/src/google/protobuf/compiler/python/pyi_generator.cc index a239a7840f..8427169539 100644 --- a/src/google/protobuf/compiler/python/pyi_generator.cc +++ b/src/google/protobuf/compiler/python/pyi_generator.cc @@ -32,6 +32,7 @@ #include #include +#include #include "absl/container/flat_hash_set.h" #include "google/protobuf/stubs/logging.h" @@ -62,12 +63,12 @@ std::string PyiGenerator::ModuleLevelName(const DescriptorT& descriptor) const { std::string filename = descriptor.file()->name(); if (import_map_.find(filename) == import_map_.end()) { std::string module_name = ModuleName(descriptor.file()->name()); - std::vector tokens = absl::StrSplit(module_name, "."); - module_alias = "_" + tokens.back(); + std::vector tokens = absl::StrSplit(module_name, '.'); + module_alias = absl::StrCat("_", tokens.back()); } else { module_alias = import_map_.at(filename); } - name = module_alias + "." + name; + name = absl::StrCat(module_alias, ".", name); } return name; } @@ -172,7 +173,7 @@ void PyiGenerator::PrintImportForDescriptor( std::string alias = absl::StrCat("_", module_name); // Generate a unique alias by adding _1 suffixes until we get an unused alias. while (seen_aliases->find(alias) != seen_aliases->end()) { - alias = alias + "_1"; + absl::StrAppend(&alias, "_1"); } printer_->Print("$statement$ as $alias$\n", "statement", import_statement, "alias", alias); @@ -341,7 +342,8 @@ template void PyiGenerator::PrintExtensions(const DescriptorT& descriptor) const { for (int i = 0; i < descriptor.extension_count(); ++i) { const FieldDescriptor* extension_field = descriptor.extension(i); - std::string constant_name = extension_field->name() + "_FIELD_NUMBER"; + std::string constant_name = + absl::StrCat(extension_field->name(), "_FIELD_NUMBER"); absl::AsciiStrToUpper(&constant_name); printer_->Print("$constant_name$: _ClassVar[int]\n", "constant_name", constant_name); @@ -381,7 +383,7 @@ std::string PyiGenerator::GetFieldType( if ((containing_des.containing_type() != nullptr && name == containing_des.name())) { std::string module = ModuleName(field_des.file()->name()); - name = module + "." + name; + name = absl::StrCat(module, ".", name); } return name; } @@ -401,7 +403,8 @@ void PyiGenerator::PrintMessage( // A well-known type needs to inherit from its corresponding base class in // net/proto2/python/internal/well_known_types. if (IsWellKnownType(message_descriptor.full_name())) { - extra_base = ", _well_known_types." + message_descriptor.name(); + extra_base = + absl::StrCat(", _well_known_types.", message_descriptor.name()); } else { extra_base = ""; } @@ -449,8 +452,8 @@ void PyiGenerator::PrintMessage( for (int i = 0; i < message_descriptor.field_count(); ++i) { const FieldDescriptor& field_des = *message_descriptor.field(i); printer_->Print( - "$field_number_name$: _ClassVar[int]\n", "field_number_name", - absl::AsciiStrToUpper(field_des.name()) + "_FIELD_NUMBER"); + "$field_number_name$: _ClassVar[int]\n", "field_number_name", + absl::StrCat(absl::AsciiStrToUpper(field_des.name()), "_FIELD_NUMBER")); } // Prints field name and type for (int i = 0; i < message_descriptor.field_count(); ++i) { @@ -462,12 +465,12 @@ void PyiGenerator::PrintMessage( if (field_des.is_map()) { const FieldDescriptor* key_des = field_des.message_type()->field(0); const FieldDescriptor* value_des = field_des.message_type()->field(1); - field_type = (value_des->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE - ? "_containers.MessageMap[" - : "_containers.ScalarMap["); - field_type += GetFieldType(*key_des, message_descriptor); - field_type += ", "; - field_type += GetFieldType(*value_des, message_descriptor); + field_type = + absl::StrCat(value_des->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE + ? "_containers.MessageMap[" + : "_containers.ScalarMap[", + GetFieldType(*key_des, message_descriptor), ", ", + GetFieldType(*value_des, message_descriptor)); } else { if (field_des.is_repeated()) { field_type = (field_des.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE @@ -478,7 +481,7 @@ void PyiGenerator::PrintMessage( } if (field_des.is_repeated()) { - field_type += "]"; + absl::StrAppend(&field_type, "]"); } printer_->Print("$name$: $type$\n", "name", field_des.name(), "type", field_type); @@ -591,7 +594,7 @@ bool PyiGenerator::Generate(const FileDescriptor* file, } else if (absl::EndsWith(option.first, ".pyi")) { filename = option.first; } else { - *error = "Unknown generator option: " + option.first; + *error = absl::StrCat("Unknown generator option: ", option.first); return false; } } diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index 47a621eefd..bf196a9ecb 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -31,6 +31,7 @@ #include "google/protobuf/compiler/ruby/ruby_generator.h" #include +#include #include #include "google/protobuf/compiler/code_generator.h" @@ -49,15 +50,15 @@ namespace ruby { // Forward decls. template std::string NumberToString(numeric_type value); -std::string GetRequireName(const std::string& proto_file); +std::string GetRequireName(absl::string_view proto_file); std::string LabelForField(FieldDescriptor* field); std::string TypeName(FieldDescriptor* field); bool GenerateMessage(const Descriptor* message, io::Printer* printer, std::string* error); void GenerateEnum(const EnumDescriptor* en, io::Printer* printer); -void GenerateMessageAssignment(const std::string& prefix, +void GenerateMessageAssignment(absl::string_view prefix, const Descriptor* message, io::Printer* printer); -void GenerateEnumAssignment(const std::string& prefix, const EnumDescriptor* en, +void GenerateEnumAssignment(absl::string_view prefix, const EnumDescriptor* en, io::Printer* printer); std::string DefaultValueForField(const FieldDescriptor* field); @@ -68,13 +69,13 @@ std::string NumberToString(numeric_type value) { return os.str(); } -std::string GetRequireName(const std::string& proto_file) { - int lastindex = proto_file.find_last_of('.'); - return proto_file.substr(0, lastindex) + "_pb"; +std::string GetRequireName(absl::string_view proto_file) { + size_t lastindex = proto_file.find_last_of('.'); + return absl::StrCat(proto_file.substr(0, lastindex), "_pb"); } -std::string GetOutputFilename(const std::string& proto_file) { - return GetRequireName(proto_file) + ".rb"; +std::string GetOutputFilename(absl::string_view proto_file) { + return absl::StrCat(GetRequireName(proto_file), ".rb"); } std::string LabelForField(const FieldDescriptor* field) { @@ -323,7 +324,7 @@ char UpperChar(char ch) { return IsLower(ch) ? (ch - 'a' + 'A') : ch; } // names must be PascalCased. // // foo_bar_baz -> FooBarBaz -std::string PackageToModule(const std::string& name) { +std::string PackageToModule(absl::string_view name) { bool next_upper = true; std::string result; result.reserve(name.size()); @@ -348,8 +349,8 @@ std::string PackageToModule(const std::string& name) { // since there is nothing enforcing this we need to ensure that they are valid // Ruby constants. That mainly means making sure that the first character is // an upper-case letter. -std::string RubifyConstant(const std::string& name) { - std::string ret = name; +std::string RubifyConstant(absl::string_view name) { + std::string ret(name); if (!ret.empty()) { if (IsLower(ret[0])) { // If it starts with a lowercase letter, capitalize it. @@ -360,14 +361,14 @@ std::string RubifyConstant(const std::string& name) { // here, e.g. try to strip leading underscores, but this may cause other // problems if the user really intended the name. So let's just prepend a // well-known suffix. - ret = "PB_" + ret; + return absl::StrCat("PB_", ret); } } return ret; } -void GenerateMessageAssignment(const std::string& prefix, +void GenerateMessageAssignment(absl::string_view prefix, const Descriptor* message, io::Printer* printer) { // Don't generate MapEntry messages -- we use the Ruby extension's native @@ -385,7 +386,8 @@ void GenerateMessageAssignment(const std::string& prefix, "lookup(\"$full_name$\").msgclass\n", "full_name", message->full_name()); - std::string nested_prefix = prefix + RubifyConstant(message->name()) + "::"; + std::string nested_prefix = + absl::StrCat(prefix, RubifyConstant(message->name()), "::"); for (int i = 0; i < message->nested_type_count(); i++) { GenerateMessageAssignment(nested_prefix, message->nested_type(i), printer); } @@ -394,7 +396,7 @@ void GenerateMessageAssignment(const std::string& prefix, } } -void GenerateEnumAssignment(const std::string& prefix, const EnumDescriptor* en, +void GenerateEnumAssignment(absl::string_view prefix, const EnumDescriptor* en, io::Printer* printer) { printer->Print( "$prefix$$name$ = ", diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc index 729f370cb1..4b2a2a625c 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc @@ -47,7 +47,7 @@ namespace ruby { namespace { std::string FindRubyTestDir() { - return TestSourceDir() + "/google/protobuf/compiler/ruby"; + return absl::StrCat(TestSourceDir(), "/google/protobuf/compiler/ruby"); } // This test is a simple golden-file test over the output of the Ruby code @@ -68,25 +68,27 @@ void RubyTest(std::string proto_file, std::string import_proto_file = "") { // Copy generated_code.proto to the temporary test directory. std::string test_input; - GOOGLE_ABSL_CHECK_OK( - File::GetContents(ruby_tests + proto_file + ".proto", &test_input, true)); - GOOGLE_ABSL_CHECK_OK(File::SetContents(TestTempDir() + proto_file + ".proto", - test_input, true)); + GOOGLE_ABSL_CHECK_OK(File::GetContents( + absl::StrCat(ruby_tests, proto_file, ".proto"), &test_input, true)); + GOOGLE_ABSL_CHECK_OK(File::SetContents( + absl::StrCat(TestTempDir(), proto_file, ".proto"), test_input, true)); // Copy generated_code_import.proto to the temporary test directory. std::string test_import; if (!import_proto_file.empty()) { - GOOGLE_ABSL_CHECK_OK(File::GetContents(ruby_tests + import_proto_file + ".proto", - &test_import, true)); + GOOGLE_ABSL_CHECK_OK( + File::GetContents(absl::StrCat(ruby_tests, import_proto_file, ".proto"), + &test_import, true)); GOOGLE_ABSL_CHECK_OK(File::SetContents( - TestTempDir() + import_proto_file + ".proto", test_import, true)); + absl::StrCat(TestTempDir(), import_proto_file, ".proto"), test_import, + true)); } // Invoke the proto compiler (we will be inside TestTempDir() at this point). - std::string ruby_out = "--ruby_out=" + TestTempDir(); - std::string proto_path = "--proto_path=" + TestTempDir(); + std::string ruby_out = absl::StrCat("--ruby_out=", TestTempDir()); + std::string proto_path = absl::StrCat("--proto_path=", TestTempDir()); - std::string proto_target = TestTempDir() + proto_file + ".proto"; + std::string proto_target = absl::StrCat(TestTempDir(), proto_file, ".proto"); const char* argv[] = { "protoc", ruby_out.c_str(), @@ -98,11 +100,11 @@ void RubyTest(std::string proto_file, std::string import_proto_file = "") { // Load the generated output and compare to the expected result. std::string output; - GOOGLE_ABSL_CHECK_OK(File::GetContentsAsText(TestTempDir() + proto_file + "_pb.rb", - &output, true)); + GOOGLE_ABSL_CHECK_OK(File::GetContentsAsText( + absl::StrCat(TestTempDir(), proto_file, "_pb.rb"), &output, true)); std::string expected_output; - GOOGLE_ABSL_CHECK_OK(File::GetContentsAsText(ruby_tests + proto_file + "_pb.rb", - &expected_output, true)); + GOOGLE_ABSL_CHECK_OK(File::GetContentsAsText( + absl::StrCat(ruby_tests, proto_file, "_pb.rb"), &expected_output, true)); EXPECT_EQ(expected_output, output); }