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
pull/11378/head
Mike Kruskal 2 years ago committed by Copybara-Service
parent f60f478f45
commit 6cadb1875a
  1. 132
      src/google/protobuf/compiler/php/php_generator.cc
  2. 76
      src/google/protobuf/compiler/python/generator.cc
  3. 20
      src/google/protobuf/compiler/python/generator.h
  4. 35
      src/google/protobuf/compiler/python/helpers.cc
  5. 15
      src/google/protobuf/compiler/python/helpers.h
  6. 24
      src/google/protobuf/compiler/python/plugin_unittest.cc
  7. 33
      src/google/protobuf/compiler/python/pyi_generator.cc
  8. 32
      src/google/protobuf/compiler/ruby/ruby_generator.cc
  9. 30
      src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc

@ -30,8 +30,10 @@
#include "google/protobuf/compiler/php/php_generator.h"
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#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 <typename DescriptorType>
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 <typename DescriptorType>
@ -344,7 +348,7 @@ std::string LegacyGeneratedClassFileName(const DescriptorType* desc,
result[i] = '/';
}
}
return result + ".php";
return absl::StrCat(result, ".php");
}
template <typename DescriptorType>
@ -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<std::string> lines = absl::StrSplit(comments, "\n", absl::SkipEmpty());
std::vector<absl::string_view> 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) {

@ -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()) +
return absl::StrCat("b\"", absl::CEscape(field.default_value_string()),
(field.type() != FieldDescriptor::TYPE_STRING
? "\""
: "\".decode('utf-8')");
: "\".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<std::string>* 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<std::string>* 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<absl::string_view, std::string> 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,7 +1113,7 @@ 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,
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();
@ -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 <typename DescriptorT, typename DescriptorProtoT>
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());

@ -36,7 +36,9 @@
#define GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__
#include <string>
#include <vector>
#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,7 +104,7 @@ 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,
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;
@ -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<std::string>* to_register,
bool is_nested) const;
void PrintNestedMessages(const Descriptor& containing_descriptor,
const std::string& prefix,
absl::string_view prefix,
std::vector<std::string>* 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 <typename DescriptorT>
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 <typename DescriptorT>
@ -167,7 +169,7 @@ class PROTOC_EXPORT Generator : public CodeGenerator {
template <typename DescriptorT, typename DescriptorProtoT>
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.

@ -31,12 +31,15 @@
#include "google/protobuf/compiler/python/helpers.h"
#include <algorithm>
#include <string>
#include <vector>
#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<std::string> tokens = absl::StrSplit(module_name, ".");
bool ContainsPythonKeyword(absl::string_view module_name) {
std::vector<absl::string_view> tokens = absl::StrSplit(module_name, '.');
for (int i = 0; i < static_cast<int>(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 <typename DescriptorT>
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<Descriptor>(
const Descriptor& descriptor, const std::string& separator);
const Descriptor& descriptor, absl::string_view separator);
template std::string NamePrefixedWithNestedTypes<EnumDescriptor>(
const EnumDescriptor& descriptor, const std::string& separator);
const EnumDescriptor& descriptor, absl::string_view separator);
} // namespace python
} // namespace compiler

@ -34,6 +34,7 @@
#include <string>
#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 <typename DescriptorT>
std::string NamePrefixedWithNestedTypes(const DescriptorT& descriptor,
const std::string& separator);
absl::string_view separator);
} // namespace python
} // namespace compiler

@ -32,6 +32,7 @@
#include <memory>
#include <string>
#include <vector>
#include "google/protobuf/testing/file.h"
#include "google/protobuf/testing/file.h"
@ -79,7 +80,8 @@ 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",
GOOGLE_ABSL_CHECK_OK(
File::SetContents(absl::StrCat(TestTempDir(), "/test1.proto"),
"syntax = \"proto3\";\n"
"package foo;\n"
"import \"test2.proto\";"
@ -87,7 +89,8 @@ TEST(PythonPluginTest, ImportTest) {
" Message2 message_2 = 1;\n"
"}\n",
true));
GOOGLE_ABSL_CHECK_OK(File::SetContents(TestTempDir() + "/test2.proto",
GOOGLE_ABSL_CHECK_OK(
File::SetContents(absl::StrCat(TestTempDir(), "/test2.proto"),
"syntax = \"proto3\";\n"
"package foo;\n"
"message Message2 {}\n",
@ -97,8 +100,8 @@ TEST(PythonPluginTest, ImportTest) {
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<std::string> lines = absl::StrSplit(output, "\n");
GOOGLE_ABSL_CHECK_OK(
File::GetContents(absl::StrCat(TestTempDir(), "/test1_pb2.py"),
&output, true));
std::vector<absl::string_view> 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);
}

@ -32,6 +32,7 @@
#include <string>
#include <utility>
#include <vector>
#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<std::string> tokens = absl::StrSplit(module_name, ".");
module_alias = "_" + tokens.back();
std::vector<absl::string_view> 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 <typename DescriptorT>
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 = "";
}
@ -450,7 +453,7 @@ void PyiGenerator::PrintMessage(
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");
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
field_type =
absl::StrCat(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);
: "_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;
}
}

@ -31,6 +31,7 @@
#include "google/protobuf/compiler/ruby/ruby_generator.h"
#include <iomanip>
#include <memory>
#include <sstream>
#include "google/protobuf/compiler/code_generator.h"
@ -49,15 +50,15 @@ namespace ruby {
// Forward decls.
template <class numeric_type>
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$ = ",

@ -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",
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);
}

Loading…
Cancel
Save