diff options
author | nechda <[email protected]> | 2024-08-29 23:50:27 +0300 |
---|---|---|
committer | nechda <[email protected]> | 2024-08-30 00:05:25 +0300 |
commit | e10d6638f07a82edae3ea8197b9f5c0affcc07ea (patch) | |
tree | 571c38cec05813766a1ad290c9d51ce7ace52919 /contrib/libs/protoc/src/google/protobuf/compiler/parser.cc | |
parent | e79b38f2bbbf78d295d1901d2a79f898022d5224 (diff) |
Update cpp-protobuf to 22.5
Привет!\
Этот PR переключат cpp & python библиотеки protobuf на версию 22.5
Если у вас возникли проблемы после влития этого PR:
1. Если начали падать канон тесты, то проведите их переканонизацию
2. Прочитайте <https://wiki.yandex-team.ru/users/nechda/obnovlenie-cpp-protobuf-22.5/> страничку с основными изменениями
3. Если страничка в вики не помогла, то пишите в [DEVTOOLSSUPPORT](https://st.yandex-team.ru/DEVTOOLSSUPPORT)
7fecade616c20a841b9e9af7b7998bdfc8d2807d
Diffstat (limited to 'contrib/libs/protoc/src/google/protobuf/compiler/parser.cc')
-rw-r--r-- | contrib/libs/protoc/src/google/protobuf/compiler/parser.cc | 398 |
1 files changed, 219 insertions, 179 deletions
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/parser.cc b/contrib/libs/protoc/src/google/protobuf/compiler/parser.cc index 2900d324d21..e244db96cc8 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/parser.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/parser.cc @@ -34,35 +34,43 @@ // // Recursive descent FTW. -#include <google/protobuf/compiler/parser.h> +#include "google/protobuf/compiler/parser.h" #include <float.h> #include <cstdint> #include <limits> -#include <unordered_map> -#include <unordered_set> - -#include <google/protobuf/stubs/casts.h> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/tokenizer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/map_util.h> -#include <google/protobuf/stubs/hash.h> +#include <string> +#include <tuple> +#include <utility> +#include <vector> + +#include "y_absl/base/casts.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_format.h" +#include "y_absl/strings/string_view.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/strtod.h" +#include "google/protobuf/io/tokenizer.h" +#include "google/protobuf/port.h" +#include "google/protobuf/wire_format.h" namespace google { namespace protobuf { namespace compiler { - -using internal::WireFormat; - namespace { -typedef std::unordered_map<TProtoStringType, FieldDescriptorProto::Type> TypeNameMap; +using ::google::protobuf::internal::DownCast; + +using TypeNameMap = + y_absl::flat_hash_map<y_absl::string_view, FieldDescriptorProto::Type>; const TypeNameMap& GetTypeNameTable() { static auto* table = new auto([]() { @@ -93,7 +101,7 @@ const TypeNameMap& GetTypeNameTable() { // Camel-case the field name and append "Entry" for generated map entry name. // e.g. map<KeyType, ValueType> foo_map => FooMapEntry -TProtoStringType MapEntryName(const TProtoStringType& field_name) { +TProtoStringType MapEntryName(y_absl::string_view field_name) { TProtoStringType result; static const char kSuffix[] = "Entry"; result.reserve(field_name.size() + sizeof(kSuffix)); @@ -123,7 +131,7 @@ bool IsLowercase(char c) { return c >= 'a' && c <= 'z'; } bool IsNumber(char c) { return c >= '0' && c <= '9'; } -bool IsUpperCamelCase(const TProtoStringType& name) { +bool IsUpperCamelCase(y_absl::string_view name) { if (name.empty()) { return true; } @@ -140,7 +148,7 @@ bool IsUpperCamelCase(const TProtoStringType& name) { return true; } -bool IsUpperUnderscore(const TProtoStringType& name) { +bool IsUpperUnderscore(y_absl::string_view name) { for (const char c : name) { if (!IsUppercase(c) && c != '_' && !IsNumber(c)) { return false; @@ -149,7 +157,7 @@ bool IsUpperUnderscore(const TProtoStringType& name) { return true; } -bool IsLowerUnderscore(const TProtoStringType& name) { +bool IsLowerUnderscore(y_absl::string_view name) { for (const char c : name) { if (!IsLowercase(c) && c != '_' && !IsNumber(c)) { return false; @@ -158,7 +166,7 @@ bool IsLowerUnderscore(const TProtoStringType& name) { return true; } -bool IsNumberFollowUnderscore(const TProtoStringType& name) { +bool IsNumberFollowUnderscore(y_absl::string_view name) { for (int i = 1; i < name.length(); i++) { const char c = name[i]; if (IsNumber(c) && name[i - 1] == '_') { @@ -193,7 +201,7 @@ Parser::~Parser() {} // =================================================================== -inline bool Parser::LookingAt(const char* text) { +inline bool Parser::LookingAt(y_absl::string_view text) { return input_->current().text == text; } @@ -203,7 +211,7 @@ inline bool Parser::LookingAtType(io::Tokenizer::TokenType token_type) { inline bool Parser::AtEnd() { return LookingAtType(io::Tokenizer::TYPE_END); } -bool Parser::TryConsume(const char* text) { +bool Parser::TryConsume(y_absl::string_view text) { if (LookingAt(text)) { input_->Next(); return true; @@ -212,50 +220,49 @@ bool Parser::TryConsume(const char* text) { } } -bool Parser::Consume(const char* text, const char* error) { +bool Parser::Consume(y_absl::string_view text, y_absl::string_view error) { if (TryConsume(text)) { return true; } else { - AddError(error); + RecordError(error); return false; } } -bool Parser::Consume(const char* text) { - TProtoStringType error = "Expected \"" + TProtoStringType(text) + "\"."; - return Consume(text, error.c_str()); +bool Parser::Consume(y_absl::string_view text) { + return Consume(text, y_absl::StrCat("Expected \"", text, "\".")); } -bool Parser::ConsumeIdentifier(TProtoStringType* output, const char* error) { +bool Parser::ConsumeIdentifier(TProtoStringType* output, y_absl::string_view error) { if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { *output = input_->current().text; input_->Next(); return true; } else { - AddError(error); + RecordError(error); return false; } } -bool Parser::ConsumeInteger(int* output, const char* error) { +bool Parser::ConsumeInteger(int* output, y_absl::string_view error) { if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { arc_ui64 value = 0; if (!io::Tokenizer::ParseInteger(input_->current().text, std::numeric_limits<arc_i32>::max(), &value)) { - AddError("Integer out of range."); + RecordError("Integer out of range."); // We still return true because we did, in fact, parse an integer. } *output = value; input_->Next(); return true; } else { - AddError(error); + RecordError(error); return false; } } -bool Parser::ConsumeSignedInteger(int* output, const char* error) { +bool Parser::ConsumeSignedInteger(int* output, y_absl::string_view error) { bool is_negative = false; arc_ui64 max_value = std::numeric_limits<arc_i32>::max(); if (TryConsume("-")) { @@ -270,23 +277,32 @@ bool Parser::ConsumeSignedInteger(int* output, const char* error) { } bool Parser::ConsumeInteger64(arc_ui64 max_value, arc_ui64* output, - const char* error) { + y_absl::string_view error) { if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { if (!io::Tokenizer::ParseInteger(input_->current().text, max_value, output)) { - AddError("Integer out of range."); + RecordError("Integer out of range."); // We still return true because we did, in fact, parse an integer. *output = 0; } input_->Next(); return true; } else { - AddError(error); + RecordError(error); return false; } } -bool Parser::ConsumeNumber(double* output, const char* error) { +bool Parser::TryConsumeInteger64(arc_ui64 max_value, arc_ui64* output) { + if (LookingAtType(io::Tokenizer::TYPE_INTEGER) && + io::Tokenizer::ParseInteger(input_->current().text, max_value, output)) { + input_->Next(); + return true; + } + return false; +} + +bool Parser::ConsumeNumber(double* output, y_absl::string_view error) { if (LookingAtType(io::Tokenizer::TYPE_FLOAT)) { *output = io::Tokenizer::ParseFloat(input_->current().text); input_->Next(); @@ -294,13 +310,19 @@ bool Parser::ConsumeNumber(double* output, const char* error) { } else if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { // Also accept integers. arc_ui64 value = 0; - if (!io::Tokenizer::ParseInteger(input_->current().text, - std::numeric_limits<arc_ui64>::max(), - &value)) { - AddError("Integer out of range."); + if (io::Tokenizer::ParseInteger(input_->current().text, + std::numeric_limits<arc_ui64>::max(), + &value)) { + *output = value; + } else if (input_->current().text[0] == '0') { + // octal or hexadecimal; don't bother parsing as float + RecordError("Integer out of range."); + // We still return true because we did, in fact, parse a number. + } else if (!io::Tokenizer::TryParseFloat(input_->current().text, output)) { + // out of int range, and not valid float? 🤷 + RecordError("Integer out of range."); // We still return true because we did, in fact, parse a number. } - *output = value; input_->Next(); return true; } else if (LookingAt("inf")) { @@ -312,12 +334,12 @@ bool Parser::ConsumeNumber(double* output, const char* error) { input_->Next(); return true; } else { - AddError(error); + RecordError(error); return false; } } -bool Parser::ConsumeString(TProtoStringType* output, const char* error) { +bool Parser::ConsumeString(TProtoStringType* output, y_absl::string_view error) { if (LookingAtType(io::Tokenizer::TYPE_STRING)) { io::Tokenizer::ParseString(input_->current().text, output); input_->Next(); @@ -328,12 +350,12 @@ bool Parser::ConsumeString(TProtoStringType* output, const char* error) { } return true; } else { - AddError(error); + RecordError(error); return false; } } -bool Parser::TryConsumeEndOfDeclaration(const char* text, +bool Parser::TryConsumeEndOfDeclaration(y_absl::string_view text, const LocationRecorder* location) { if (LookingAt(text)) { TProtoStringType leading, trailing; @@ -347,7 +369,7 @@ bool Parser::TryConsumeEndOfDeclaration(const char* text, if (location != nullptr) { upcoming_detached_comments_.swap(detached); location->AttachComments(&leading, &trailing, &detached); - } else if (strcmp(text, "}") == 0) { + } else if (text == "}") { // If the current location is null and we are finishing the current scope, // drop pending upcoming detached comments. upcoming_detached_comments_.swap(detached); @@ -364,36 +386,39 @@ bool Parser::TryConsumeEndOfDeclaration(const char* text, } } -bool Parser::ConsumeEndOfDeclaration(const char* text, +bool Parser::ConsumeEndOfDeclaration(y_absl::string_view text, const LocationRecorder* location) { if (TryConsumeEndOfDeclaration(text, location)) { return true; } else { - AddError("Expected \"" + TProtoStringType(text) + "\"."); + RecordError(y_absl::StrCat("Expected \"", text, "\".")); return false; } } // ------------------------------------------------------------------- -void Parser::AddError(int line, int column, const TProtoStringType& error) { +void Parser::RecordError(int line, int column, y_absl::string_view error) { if (error_collector_ != nullptr) { - error_collector_->AddError(line, column, error); + error_collector_->RecordError(line, column, error); } had_errors_ = true; } -void Parser::AddError(const TProtoStringType& error) { - AddError(input_->current().line, input_->current().column, error); +void Parser::RecordError(y_absl::string_view error) { + RecordError(input_->current().line, input_->current().column, error); } -void Parser::AddWarning(const TProtoStringType& warning) { +void Parser::RecordWarning(int line, int column, y_absl::string_view warning) { if (error_collector_ != nullptr) { - error_collector_->AddWarning(input_->current().line, - input_->current().column, warning); + error_collector_->RecordWarning(line, column, warning); } } +void Parser::RecordWarning(y_absl::string_view warning) { + RecordWarning(input_->current().line, input_->current().column, warning); +} + // ------------------------------------------------------------------- Parser::LocationRecorder::LocationRecorder(Parser* parser) @@ -491,8 +516,8 @@ int Parser::LocationRecorder::CurrentPathSize() const { void Parser::LocationRecorder::AttachComments( TProtoStringType* leading, TProtoStringType* trailing, std::vector<TProtoStringType>* detached_comments) const { - GOOGLE_CHECK(!location_->has_leading_comments()); - GOOGLE_CHECK(!location_->has_trailing_comments()); + Y_ABSL_CHECK(!location_->has_leading_comments()); + Y_ABSL_CHECK(!location_->has_trailing_comments()); if (!leading->empty()) { location_->mutable_leading_comments()->swap(*leading); @@ -563,16 +588,16 @@ bool Parser::ValidateEnum(const EnumDescriptorProto* proto) { } if (has_allow_alias && !allow_alias) { - TProtoStringType error = - "\"" + proto->name() + + TProtoStringType error = y_absl::StrCat( + "\"", proto->name(), "\" declares 'option allow_alias = false;' which has no effect. " - "Please remove the declaration."; + "Please remove the declaration."); // This needlessly clutters declarations with nops. - AddError(error); + RecordError(error); return false; } - std::set<int> used_values; + y_absl::flat_hash_set<int> used_values; bool has_duplicates = false; for (int i = 0; i < proto->value_size(); ++i) { const EnumValueDescriptorProto& enum_value = proto->value(i); @@ -584,14 +609,14 @@ bool Parser::ValidateEnum(const EnumDescriptorProto* proto) { } } if (allow_alias && !has_duplicates) { - TProtoStringType error = - "\"" + proto->name() + + TProtoStringType error = y_absl::StrCat( + "\"", proto->name(), "\" declares support for enum aliases but no enum values share field " "numbers. Please remove the unnecessary 'option allow_alias = true;' " - "declaration."; + "declaration."); // Generate an error if an enum declares support for duplicate enum values // and does not use it protect future authors. - AddError(error); + RecordError(error); return false; } @@ -600,10 +625,9 @@ bool Parser::ValidateEnum(const EnumDescriptorProto* proto) { if (!allow_alias) { for (const auto& enum_value : proto->value()) { if (!IsUpperUnderscore(enum_value.name())) { - AddWarning( - "Enum constant should be in UPPER_CASE. Found: " + - enum_value.name() + - ". See https://developers.google.com/protocol-buffers/docs/style"); + RecordWarning(y_absl::StrCat( + "Enum constant should be in UPPER_CASE. Found: ", enum_value.name(), + ". See https://developers.google.com/protocol-buffers/docs/style")); } } } @@ -634,14 +658,17 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { root_location.RecordLegacyLocation(file, DescriptorPool::ErrorCollector::OTHER); - if (require_syntax_identifier_ || LookingAt("syntax")) { + if (require_syntax_identifier_ || LookingAt("syntax") + ) { if (!ParseSyntaxIdentifier(root_location)) { // Don't attempt to parse the file if we didn't recognize the syntax // identifier. return false; } // Store the syntax into the file. - if (file != nullptr) file->set_syntax(syntax_identifier_); + if (file != nullptr) { + file->set_syntax(syntax_identifier_); + } } else if (!stop_after_syntax_identifier_) { syntax_identifier_ = "proto2"; } @@ -656,7 +683,7 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { SkipStatement(); if (LookingAt("}")) { - AddError("Unmatched \"}\"."); + RecordError("Unmatched \"}\"."); input_->NextWithComments(nullptr, &upcoming_detached_comments_, &upcoming_doc_comments_); } @@ -674,9 +701,10 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) { LocationRecorder syntax_location(parent, FileDescriptorProto::kSyntaxFieldNumber); - DO(Consume( - "syntax", - "File must begin with a syntax statement, e.g. 'syntax = \"proto2\";'.")); + DO(Consume("syntax", + "File must begin with a syntax statement, e.g. 'syntax = " + "\"proto2\";'.")); + DO(Consume("=")); io::Tokenizer::Token syntax_token = input_->current(); TProtoStringType syntax; @@ -684,13 +712,12 @@ bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) { DO(ConsumeEndOfDeclaration(";", &syntax_location)); syntax_identifier_ = syntax; - if (syntax != "proto2" && syntax != "proto3" && !stop_after_syntax_identifier_) { - AddError(syntax_token.line, syntax_token.column, - "Unrecognized syntax identifier \"" + syntax + - "\". This parser " - "only recognizes \"proto2\" and \"proto3\"."); + RecordError(syntax_token.line, syntax_token.column, + y_absl::StrCat("Unrecognized syntax identifier \"", syntax, + "\". This parser " + "only recognizes \"proto2\" and \"proto3\".")); return false; } @@ -735,7 +762,7 @@ bool Parser::ParseTopLevelStatement(FileDescriptorProto* file, return ParseOption(file->mutable_options(), location, file, OPTION_STATEMENT); } else { - AddError("Expected top-level statement (e.g. \"message\")."); + RecordError("Expected top-level statement (e.g. \"message\")."); return false; } } @@ -754,10 +781,9 @@ bool Parser::ParseMessageDefinition( DescriptorPool::ErrorCollector::NAME); DO(ConsumeIdentifier(message->mutable_name(), "Expected message name.")); if (!IsUpperCamelCase(message->name())) { - AddWarning( - "Message name should be in UpperCamelCase. Found: " + - message->name() + - ". See https://developers.google.com/protocol-buffers/docs/style"); + RecordWarning(y_absl::StrCat( + "Message name should be in UpperCamelCase. Found: ", message->name(), + ". See https://developers.google.com/protocol-buffers/docs/style")); } } DO(ParseMessageBlock(message, message_location, containing_file)); @@ -768,7 +794,7 @@ bool Parser::ParseMessageDefinition( // // We have to make sure the oneof names don't conflict with any other // field or oneof. - std::unordered_set<TProtoStringType> names; + y_absl::flat_hash_set<TProtoStringType> names; for (const auto& field : message->field()) { names.insert(field.name()); } @@ -793,7 +819,7 @@ bool Parser::ParseMessageDefinition( names.insert(oneof_name); field.set_oneof_index(message->oneof_decl_size()); OneofDescriptorProto* oneof = message->add_oneof_decl(); - oneof->set_name(oneof_name); + oneof->set_name(std::move(oneof_name)); } } } @@ -857,7 +883,7 @@ bool Parser::ParseMessageBlock(DescriptorProto* message, while (!TryConsumeEndOfDeclaration("}", nullptr)) { if (AtEnd()) { - AddError("Reached end of input in message definition (missing '}')."); + RecordError("Reached end of input in message definition (missing '}')."); return false; } @@ -986,7 +1012,7 @@ bool Parser::ParseMessageFieldNoLabel( field->set_label(FieldDescriptorProto::LABEL_OPTIONAL); } if (!field->has_label()) { - AddError("Expected \"required\", \"optional\", or \"repeated\"."); + RecordError("Expected \"required\", \"optional\", or \"repeated\"."); // We can actually reasonably recover here by just assuming the user // forgot the label altogether. field->set_label(FieldDescriptorProto::LABEL_OPTIONAL); @@ -1016,15 +1042,15 @@ bool Parser::ParseMessageFieldNoLabel( DO(ConsumeIdentifier(field->mutable_name(), "Expected field name.")); if (!IsLowerUnderscore(field->name())) { - AddWarning( - "Field name should be lowercase. Found: " + field->name() + - ". See: https://developers.google.com/protocol-buffers/docs/style"); + RecordWarning(y_absl::StrCat( + "Field name should be lowercase. Found: ", field->name(), + ". See: https://developers.google.com/protocol-buffers/docs/style")); } if (IsNumberFollowUnderscore(field->name())) { - AddWarning( - "Number should not come right after an underscore. Found: " + - field->name() + - ". See: https://developers.google.com/protocol-buffers/docs/style"); + RecordWarning(y_absl::StrCat( + "Number should not come right after an underscore. Found: ", + field->name(), + ". See: https://developers.google.com/protocol-buffers/docs/style")); } } DO(Consume("=", "Missing field number.")); @@ -1077,16 +1103,16 @@ bool Parser::ParseMessageFieldNoLabel( // with a capital letter and lower-case the field name. New code should // not use groups; it should use nested messages. if (group->name()[0] < 'A' || 'Z' < group->name()[0]) { - AddError(name_token.line, name_token.column, - "Group names must start with a capital letter."); + RecordError(name_token.line, name_token.column, + "Group names must start with a capital letter."); } - LowerString(field->mutable_name()); + y_absl::AsciiStrToLower(field->mutable_name()); field->set_type_name(group->name()); if (LookingAt("{")) { DO(ParseMessageBlock(group, group_location, containing_file)); } else { - AddError("Missing group body."); + RecordError("Missing group body."); return false; } } else { @@ -1104,17 +1130,17 @@ bool Parser::ParseMessageFieldNoLabel( bool Parser::ParseMapType(MapField* map_field, FieldDescriptorProto* field, LocationRecorder& type_name_location) { if (field->has_oneof_index()) { - AddError("Map fields are not allowed in oneofs."); + RecordError("Map fields are not allowed in oneofs."); return false; } if (field->has_label()) { - AddError( + RecordError( "Field labels (required/optional/repeated) are not allowed on " "map fields."); return false; } if (field->has_extendee()) { - AddError("Map fields are not allowed to be extensions."); + RecordError("Map fields are not allowed to be extensions."); return false; } field->set_label(FieldDescriptorProto::LABEL_REPEATED); @@ -1226,7 +1252,7 @@ bool Parser::ParseDefaultAssignment( FieldDescriptorProto* field, const LocationRecorder& field_location, const FileDescriptorProto* containing_file) { if (field->has_default_value()) { - AddError("Already set option \"default\"."); + RecordError("Already set option \"default\"."); field->clear_default_value(); } @@ -1279,7 +1305,7 @@ bool Parser::ParseDefaultAssignment( DO(ConsumeInteger64(max_value, &value, "Expected integer for field default value.")); // And stringify it again. - default_value->append(StrCat(value)); + default_value->append(y_absl::StrCat(value)); break; } @@ -1295,38 +1321,38 @@ bool Parser::ParseDefaultAssignment( // Numeric, not negative. if (TryConsume("-")) { - AddError("Unsigned field can't have negative default value."); + RecordError("Unsigned field can't have negative default value."); } // Parse the integer to verify that it is not out-of-range. arc_ui64 value; DO(ConsumeInteger64(max_value, &value, "Expected integer for field default value.")); // And stringify it again. - default_value->append(StrCat(value)); + default_value->append(y_absl::StrCat(value)); break; } case FieldDescriptorProto::TYPE_FLOAT: - case FieldDescriptorProto::TYPE_DOUBLE: + case FieldDescriptorProto::TYPE_DOUBLE: { // These types can be negative. if (TryConsume("-")) { default_value->append("-"); } // Parse the integer because we have to convert hex integers to decimal // floats. - double value; + double value = 0.0; DO(ConsumeNumber(&value, "Expected number.")); // And stringify it again. - default_value->append(SimpleDtoa(value)); + default_value->append(io::SimpleDtoa(value)); break; - + } case FieldDescriptorProto::TYPE_BOOL: if (TryConsume("true")) { default_value->assign("true"); } else if (TryConsume("false")) { default_value->assign("false"); } else { - AddError("Expected \"true\" or \"false\"."); + RecordError("Expected \"true\" or \"false\"."); return false; } break; @@ -1342,7 +1368,7 @@ bool Parser::ParseDefaultAssignment( case FieldDescriptorProto::TYPE_BYTES: DO(ConsumeString(default_value, "Expected string.")); - *default_value = CEscape(*default_value); + *default_value = y_absl::CEscape(*default_value); break; case FieldDescriptorProto::TYPE_ENUM: @@ -1353,7 +1379,7 @@ bool Parser::ParseDefaultAssignment( case FieldDescriptorProto::TYPE_MESSAGE: case FieldDescriptorProto::TYPE_GROUP: - AddError("Messages can't have default values."); + RecordError("Messages can't have default values."); return false; } @@ -1364,7 +1390,7 @@ bool Parser::ParseJsonName(FieldDescriptorProto* field, const LocationRecorder& field_location, const FileDescriptorProto* containing_file) { if (field->has_json_name()) { - AddError("Already set option \"json_name\"."); + RecordError("Already set option \"json_name\"."); field->clear_json_name(); } @@ -1443,7 +1469,7 @@ bool Parser::ParseUninterpretedBlock(TProtoStringType* value) { value->append(input_->current().text); input_->Next(); } - AddError("Unexpected end of stream while parsing aggregate value."); + RecordError("Unexpected end of stream while parsing aggregate value."); return false; } @@ -1456,7 +1482,7 @@ bool Parser::ParseOption(Message* options, // Create an entry in the uninterpreted_option field. const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()->FindFieldByName("uninterpreted_option"); - GOOGLE_CHECK(uninterpreted_option_field != nullptr) + Y_ABSL_CHECK(uninterpreted_option_field != nullptr) << "No field named \"uninterpreted_option\" in the Options proto."; const Reflection* reflection = options->GetReflection(); @@ -1470,7 +1496,7 @@ bool Parser::ParseOption(Message* options, } UninterpretedOption* uninterpreted_option = - down_cast<UninterpretedOption*>(options->GetReflection()->AddMessage( + DownCast<UninterpretedOption*>(options->GetReflection()->AddMessage( options, uninterpreted_option_field)); // Parse dot-separated name. @@ -1509,25 +1535,26 @@ bool Parser::ParseOption(Message* options, switch (input_->current().type) { case io::Tokenizer::TYPE_START: - GOOGLE_LOG(FATAL) << "Trying to read value before any tokens have been read."; + Y_ABSL_LOG(FATAL) + << "Trying to read value before any tokens have been read."; return false; case io::Tokenizer::TYPE_END: - AddError("Unexpected end of stream while parsing option value."); + RecordError("Unexpected end of stream while parsing option value."); return false; case io::Tokenizer::TYPE_WHITESPACE: case io::Tokenizer::TYPE_NEWLINE: - GOOGLE_CHECK(!input_->report_whitespace() && !input_->report_newlines()) + Y_ABSL_CHECK(!input_->report_whitespace() && !input_->report_newlines()) << "Whitespace tokens were not requested."; - GOOGLE_LOG(FATAL) << "Tokenizer reported whitespace."; + Y_ABSL_LOG(FATAL) << "Tokenizer reported whitespace."; return false; case io::Tokenizer::TYPE_IDENTIFIER: { value_location.AddPath( UninterpretedOption::kIdentifierValueFieldNumber); if (is_negative) { - AddError("Invalid '-' symbol before identifier."); + RecordError("Invalid '-' symbol before identifier."); return false; } TProtoStringType value; @@ -1542,23 +1569,27 @@ bool Parser::ParseOption(Message* options, is_negative ? static_cast<arc_ui64>(std::numeric_limits<arc_i64>::max()) + 1 : std::numeric_limits<arc_ui64>::max(); - DO(ConsumeInteger64(max_value, &value, "Expected integer.")); - if (is_negative) { - value_location.AddPath( - UninterpretedOption::kNegativeIntValueFieldNumber); - uninterpreted_option->set_negative_int_value( - static_cast<arc_i64>(0 - value)); - } else { - value_location.AddPath( - UninterpretedOption::kPositiveIntValueFieldNumber); - uninterpreted_option->set_positive_int_value(value); + if (TryConsumeInteger64(max_value, &value)) { + if (is_negative) { + value_location.AddPath( + UninterpretedOption::kNegativeIntValueFieldNumber); + uninterpreted_option->set_negative_int_value( + static_cast<arc_i64>(0 - value)); + } else { + value_location.AddPath( + UninterpretedOption::kPositiveIntValueFieldNumber); + uninterpreted_option->set_positive_int_value(value); + } + break; } - break; + // value too large for an integer; fall through below to treat as + // floating point + Y_ABSL_FALLTHROUGH_INTENDED; } case io::Tokenizer::TYPE_FLOAT: { value_location.AddPath(UninterpretedOption::kDoubleValueFieldNumber); - double value; + double value = 0.0; DO(ConsumeNumber(&value, "Expected number.")); uninterpreted_option->set_double_value(is_negative ? -value : value); break; @@ -1567,7 +1598,7 @@ bool Parser::ParseOption(Message* options, case io::Tokenizer::TYPE_STRING: { value_location.AddPath(UninterpretedOption::kStringValueFieldNumber); if (is_negative) { - AddError("Invalid '-' symbol before string."); + RecordError("Invalid '-' symbol before string."); return false; } TProtoStringType value; @@ -1583,7 +1614,7 @@ bool Parser::ParseOption(Message* options, DO(ParseUninterpretedBlock( uninterpreted_option->mutable_aggregate_value())); } else { - AddError("Expected option value."); + RecordError("Expected option value."); return false; } break; @@ -1719,11 +1750,27 @@ bool Parser::ParseReserved(DescriptorProto* message, } } +bool Parser::ParseReservedName(TProtoStringType* name, + y_absl::string_view error_message) { + // Capture the position of the token, in case we have to report an + // error after it is consumed. + int line = input_->current().line; + int col = input_->current().column; + DO(ConsumeString(name, error_message)); + if (!io::Tokenizer::IsIdentifier(*name)) { + RecordWarning( + line, col, + y_absl::StrFormat("Reserved name \"%s\" is not a valid identifier.", + *name)); + } + return true; +} + bool Parser::ParseReservedNames(DescriptorProto* message, const LocationRecorder& parent_location) { do { LocationRecorder location(parent_location, message->reserved_name_size()); - DO(ConsumeString(message->add_reserved_name(), "Expected field name.")); + DO(ParseReservedName(message->add_reserved_name(), "Expected field name.")); } while (TryConsume(",")); DO(ConsumeEndOfDeclaration(";", &parent_location)); return true; @@ -1778,42 +1825,41 @@ bool Parser::ParseReservedNumbers(DescriptorProto* message, return true; } -bool Parser::ParseReserved(EnumDescriptorProto* message, - const LocationRecorder& message_location) { +bool Parser::ParseReserved(EnumDescriptorProto* proto, + const LocationRecorder& enum_location) { io::Tokenizer::Token start_token = input_->current(); // Parse the declaration. DO(Consume("reserved")); if (LookingAtType(io::Tokenizer::TYPE_STRING)) { - LocationRecorder location(message_location, + LocationRecorder location(enum_location, EnumDescriptorProto::kReservedNameFieldNumber); location.StartAt(start_token); - return ParseReservedNames(message, location); + return ParseReservedNames(proto, location); } else { - LocationRecorder location(message_location, + LocationRecorder location(enum_location, EnumDescriptorProto::kReservedRangeFieldNumber); location.StartAt(start_token); - return ParseReservedNumbers(message, location); + return ParseReservedNumbers(proto, location); } } -bool Parser::ParseReservedNames(EnumDescriptorProto* message, +bool Parser::ParseReservedNames(EnumDescriptorProto* proto, const LocationRecorder& parent_location) { do { - LocationRecorder location(parent_location, message->reserved_name_size()); - DO(ConsumeString(message->add_reserved_name(), "Expected enum value.")); + LocationRecorder location(parent_location, proto->reserved_name_size()); + DO(ParseReservedName(proto->add_reserved_name(), "Expected enum value.")); } while (TryConsume(",")); DO(ConsumeEndOfDeclaration(";", &parent_location)); return true; } -bool Parser::ParseReservedNumbers(EnumDescriptorProto* message, +bool Parser::ParseReservedNumbers(EnumDescriptorProto* proto, const LocationRecorder& parent_location) { bool first = true; do { - LocationRecorder location(parent_location, message->reserved_range_size()); + LocationRecorder location(parent_location, proto->reserved_range_size()); - EnumDescriptorProto::EnumReservedRange* range = - message->add_reserved_range(); + EnumDescriptorProto::EnumReservedRange* range = proto->add_reserved_range(); int start, end; io::Tokenizer::Token start_token; { @@ -1873,7 +1919,7 @@ bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions, do { if (AtEnd()) { - AddError("Reached end of input in extend definition (missing '}')."); + RecordError("Reached end of input in extend definition (missing '}')."); return false; } @@ -1926,7 +1972,7 @@ bool Parser::ParseOneof(OneofDescriptorProto* oneof_decl, do { if (AtEnd()) { - AddError("Reached end of input in oneof definition (missing '}')."); + RecordError("Reached end of input in oneof definition (missing '}')."); return false; } @@ -1944,7 +1990,7 @@ bool Parser::ParseOneof(OneofDescriptorProto* oneof_decl, // on an individual member of a oneof. if (LookingAt("required") || LookingAt("optional") || LookingAt("repeated")) { - AddError( + RecordError( "Fields in oneofs must not have labels (required / optional " "/ repeated)."); // We can continue parsing here because we understand what the user @@ -2003,7 +2049,7 @@ bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type, while (!TryConsumeEndOfDeclaration("}", nullptr)) { if (AtEnd()) { - AddError("Reached end of input in enum definition (missing '}')."); + RecordError("Reached end of input in enum definition (missing '}')."); return false; } @@ -2120,7 +2166,7 @@ bool Parser::ParseServiceBlock(ServiceDescriptorProto* service, while (!TryConsumeEndOfDeclaration("}", nullptr)) { if (AtEnd()) { - AddError("Reached end of input in service definition (missing '}')."); + RecordError("Reached end of input in service definition (missing '}')."); return false; } @@ -2224,7 +2270,7 @@ bool Parser::ParseMethodOptions(const LocationRecorder& parent_location, ConsumeEndOfDeclaration("{", &parent_location); while (!TryConsumeEndOfDeclaration("}", nullptr)) { if (AtEnd()) { - AddError("Reached end of input in method options (missing '}')."); + RecordError("Reached end of input in method options (missing '}')."); return false; } @@ -2288,7 +2334,7 @@ bool Parser::ParseUserDefinedType(TProtoStringType* type_name) { // if we are parsing a field type then we would not get here because // primitives are allowed there as well. So this error message doesn't // need to account for enums. - AddError("Expected message type."); + RecordError("Expected message type."); // Pretend to accept this type so that we can go on parsing. *type_name = input_->current().text; @@ -2320,7 +2366,7 @@ bool Parser::ParsePackage(FileDescriptorProto* file, const LocationRecorder& root_location, const FileDescriptorProto* containing_file) { if (file->has_package()) { - AddError("Multiple package definitions."); + RecordError("Multiple package definitions."); // Don't append the new package to the old one. Just replace it. Not // that it really matters since this is an error anyway. file->clear_package(); @@ -2391,33 +2437,27 @@ bool SourceLocationTable::Find( const Message* descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, int* line, int* column) const { - const std::pair<int, int>* result = - FindOrNull(location_map_, std::make_pair(descriptor, location)); - if (result == nullptr) { + auto it = location_map_.find({descriptor, location}); + if (it == location_map_.end()) { *line = -1; *column = 0; return false; - } else { - *line = result->first; - *column = result->second; - return true; } + std::tie(*line, *column) = it->second; + return true; } bool SourceLocationTable::FindImport(const Message* descriptor, - const TProtoStringType& name, int* line, + y_absl::string_view name, int* line, int* column) const { - const std::pair<int, int>* result = - FindOrNull(import_location_map_, std::make_pair(descriptor, name)); - if (result == nullptr) { + auto it = import_location_map_.find({descriptor, TProtoStringType(name)}); + if (it == import_location_map_.end()) { *line = -1; *column = 0; return false; - } else { - *line = result->first; - *column = result->second; - return true; } + std::tie(*line, *column) = it->second; + return true; } void SourceLocationTable::Add( |