Merge branch 'main' into sync-stage

pull/10729/head
Mike Kruskal 2 years ago committed by GitHub
commit c009b7b0b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 21
      conformance/conformance_objc.m
  2. 6
      objectivec/.clang-format
  3. 96
      src/google/protobuf/compiler/objectivec/enum.cc
  4. 3
      src/google/protobuf/compiler/objectivec/enum.h
  5. 20
      src/google/protobuf/compiler/objectivec/enum_field.cc
  6. 1
      src/google/protobuf/compiler/objectivec/enum_field.h
  7. 45
      src/google/protobuf/compiler/objectivec/extension.cc
  8. 54
      src/google/protobuf/compiler/objectivec/field.cc
  9. 25
      src/google/protobuf/compiler/objectivec/field.h
  10. 125
      src/google/protobuf/compiler/objectivec/file.cc
  11. 4
      src/google/protobuf/compiler/objectivec/file.h
  12. 33
      src/google/protobuf/compiler/objectivec/generator.cc
  13. 1
      src/google/protobuf/compiler/objectivec/generator.h
  14. 25
      src/google/protobuf/compiler/objectivec/helpers.cc
  15. 4
      src/google/protobuf/compiler/objectivec/helpers.h
  16. 82
      src/google/protobuf/compiler/objectivec/import_writer.cc
  17. 9
      src/google/protobuf/compiler/objectivec/import_writer.h
  18. 26
      src/google/protobuf/compiler/objectivec/line_consumer.cc
  19. 3
      src/google/protobuf/compiler/objectivec/line_consumer.h
  20. 92
      src/google/protobuf/compiler/objectivec/line_consumer_unittest.cc
  21. 26
      src/google/protobuf/compiler/objectivec/map_field.cc
  22. 103
      src/google/protobuf/compiler/objectivec/message.cc
  23. 3
      src/google/protobuf/compiler/objectivec/message.h
  24. 27
      src/google/protobuf/compiler/objectivec/message_field.cc
  25. 3
      src/google/protobuf/compiler/objectivec/message_field.h
  26. 4
      src/google/protobuf/compiler/objectivec/method_dump.sh
  27. 426
      src/google/protobuf/compiler/objectivec/names.cc
  28. 16
      src/google/protobuf/compiler/objectivec/names.h
  29. 3
      src/google/protobuf/compiler/objectivec/names_unittest.cc
  30. 378
      src/google/protobuf/compiler/objectivec/nsobject_methods.h
  31. 30
      src/google/protobuf/compiler/objectivec/oneof.cc
  32. 2
      src/google/protobuf/compiler/objectivec/primitive_field.cc
  33. 3
      src/google/protobuf/compiler/objectivec/primitive_field.h
  34. 26
      src/google/protobuf/compiler/objectivec/text_format_decode_data.cc
  35. 1
      src/google/protobuf/compiler/objectivec/text_format_decode_data.h
  36. 1
      src/google/protobuf/compiler/objectivec/text_format_decode_data_unittest.cc

@ -56,8 +56,7 @@ static NSData *CheckedReadDataOfLength(NSFileHandle *handle, NSUInteger numBytes
return nil; // EOF.
}
if (dataLen != numBytes) {
Die(@"Failed to read the request length (%d), only got: %@",
numBytes, data);
Die(@"Failed to read the request length (%d), only got: %@", numBytes, data);
}
return data;
}
@ -76,7 +75,8 @@ static ConformanceResponse *DoTest(ConformanceRequest *request) {
Class msgClass = nil;
if ([request.messageType isEqual:@"protobuf_test_messages.proto3.TestAllTypesProto3"]) {
msgClass = [Proto3TestAllTypesProto3 class];
} else if ([request.messageType isEqual:@"protobuf_test_messages.proto2.TestAllTypesProto2"]) {
} else if ([request.messageType
isEqual:@"protobuf_test_messages.proto2.TestAllTypesProto2"]) {
msgClass = [Proto2TestAllTypesProto2 class];
} else {
response.runtimeError =
@ -87,8 +87,7 @@ static ConformanceResponse *DoTest(ConformanceRequest *request) {
NSError *error = nil;
testMessage = [msgClass parseFromData:request.protobufPayload error:&error];
if (!testMessage) {
response.parseError =
[NSString stringWithFormat:@"Parse error: %@", error];
response.parseError = [NSString stringWithFormat:@"Parse error: %@", error];
}
break;
}
@ -98,9 +97,8 @@ static ConformanceResponse *DoTest(ConformanceRequest *request) {
break;
case ConformanceRequest_Payload_OneOfCase_JspbPayload:
response.skipped =
@"ConformanceRequest had a jspb_payload ConformanceRequest.payload;"
" those aren't supposed to happen with opensource.";
response.skipped = @"ConformanceRequest had a jspb_payload ConformanceRequest.payload;"
" those aren't supposed to happen with opensource.";
break;
case ConformanceRequest_Payload_OneOfCase_TextPayload:
@ -120,7 +118,7 @@ static ConformanceResponse *DoTest(ConformanceRequest *request) {
response.protobufPayload = testMessage.data;
if (!response.protobufPayload) {
response.serializeError =
[NSString stringWithFormat:@"Failed to make data from: %@", testMessage];
[NSString stringWithFormat:@"Failed to make data from: %@", testMessage];
}
break;
@ -131,7 +129,7 @@ static ConformanceResponse *DoTest(ConformanceRequest *request) {
case ConformanceWireFormat_Jspb:
response.skipped =
@"ConformanceRequest had a requested_output_format of JSPB WireFormat; that"
" isn't supposed to happen with opensource.";
" isn't supposed to happen with opensource.";
break;
case ConformanceWireFormat_TextFormat:
@ -173,8 +171,7 @@ static BOOL DoTestIo(NSFileHandle *input, NSFileHandle *output) {
}
NSError *error = nil;
ConformanceRequest *request = [ConformanceRequest parseFromData:data
error:&error];
ConformanceRequest *request = [ConformanceRequest parseFromData:data error:&error];
if (!request) {
Die(@"Failed to parse the message data: %@", error);
}

@ -1,7 +1 @@
BasedOnStyle: Google
# Ignore pddm directives.
CommentPragmas: '^%'
# Following the rest of the protobuf code.
ColumnLimit: 80

@ -36,8 +36,8 @@
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/compiler/objectivec/helpers.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/compiler/objectivec/text_format_decode_data.h"
#include "google/protobuf/io/printer.h"
@ -58,8 +58,7 @@ std::string SafelyPrintIntToCode(int v) {
} // namespace
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor)
: descriptor_(descriptor),
name_(EnumName(descriptor_)) {
: descriptor_(descriptor), name_(EnumName(descriptor_)) {
// Track the names for the enum values, and if an alias overlaps a base
// value, skip making a name for it. Likewise if two alias overlap, the
// first one wins.
@ -121,25 +120,29 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) {
// doesn't have to bother with the `enum_extensibility` attribute, as the
// default will be what is needed.
printer->Print("$comments$typedef$deprecated_attribute$ GPB_ENUM($name$) {\n",
"comments", enum_comments,
"deprecated_attribute", GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file()),
"name", name_);
printer->Print(
"$comments$typedef$deprecated_attribute$ GPB_ENUM($name$) {\n",
"comments", enum_comments, "deprecated_attribute",
GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file()), "name",
name_);
printer->Indent();
if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
// Include the unknown value.
printer->Print(
"/**\n"
" * Value used if any message's field encounters a value that is not defined\n"
" * by this enum. The message will also have C functions to get/set the rawValue\n"
" * of the field.\n"
" **/\n"
"$name$_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,\n",
"name", name_);
// clang-format off
"/**\n"
" * Value used if any message's field encounters a value that is not defined\n"
" * by this enum. The message will also have C functions to get/set the rawValue\n"
" * of the field.\n"
" **/\n"
"$name$_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,\n",
// clang-format on
"name", name_);
}
for (int i = 0; i < all_values_.size(); i++) {
if (alias_values_to_skip_.find(all_values_[i]) != alias_values_to_skip_.end()) {
if (alias_values_to_skip_.find(all_values_[i]) !=
alias_values_to_skip_.end()) {
continue;
}
if (all_values_[i]->GetSourceLocation(&location)) {
@ -152,14 +155,14 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) {
}
}
printer->Print(
"$name$$deprecated_attribute$ = $value$,\n",
"name", EnumValueName(all_values_[i]),
"deprecated_attribute", GetOptionalDeprecatedAttribute(all_values_[i]),
"value", SafelyPrintIntToCode(all_values_[i]->number()));
printer->Print("$name$$deprecated_attribute$ = $value$,\n", "name",
EnumValueName(all_values_[i]), "deprecated_attribute",
GetOptionalDeprecatedAttribute(all_values_[i]), "value",
SafelyPrintIntToCode(all_values_[i]->number()));
}
printer->Outdent();
printer->Print(
// clang-format off
"};\n"
"\n"
"GPBEnumDescriptor *$name$_EnumDescriptor(void);\n"
@ -169,6 +172,7 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) {
" * the time this source was generated.\n"
" **/\n"
"BOOL $name$_IsValidValue(int32_t value);\n"
// clang-format on
"\n",
"name", name_);
}
@ -199,38 +203,42 @@ void EnumGenerator::GenerateSource(io::Printer* printer) {
}
printer->Print(
// clang-format off
"GPBEnumDescriptor *$name$_EnumDescriptor(void) {\n"
" static _Atomic(GPBEnumDescriptor*) descriptor = nil;\n"
" if (!descriptor) {\n",
// clang-format on
"name", name_);
static const int kBytesPerLine = 40; // allow for escaping
printer->Print(
" static const char *valueNames =");
printer->Print(" static const char *valueNames =");
for (int i = 0; i < text_blob.size(); i += kBytesPerLine) {
printer->Print(
"\n \"$data$\"",
"data", EscapeTrigraphs(absl::CEscape(text_blob.substr(i, kBytesPerLine))));
"\n \"$data$\"", "data",
EscapeTrigraphs(absl::CEscape(text_blob.substr(i, kBytesPerLine))));
}
printer->Print(
";\n"
" static const int32_t values[] = {\n");
for (int i = 0; i < all_values_.size(); i++) {
printer->Print(" $name$,\n", "name", EnumValueName(all_values_[i]));
printer->Print(" $name$,\n", "name", EnumValueName(all_values_[i]));
}
printer->Print(" };\n");
if (text_format_decode_data.num_entries() == 0) {
printer->Print(
// clang-format off
" GPBEnumDescriptor *worker =\n"
" [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
" valueNames:valueNames\n"
" values:values\n"
" count:(uint32_t)(sizeof(values) / sizeof(int32_t))\n"
" enumVerifier:$name$_IsValidValue];\n",
// clang-format on
"name", name_);
} else {
printer->Print(
} else {
printer->Print(
// clang-format off
" static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n"
" GPBEnumDescriptor *worker =\n"
" [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
@ -239,35 +247,41 @@ void EnumGenerator::GenerateSource(io::Printer* printer) {
" count:(uint32_t)(sizeof(values) / sizeof(int32_t))\n"
" enumVerifier:$name$_IsValidValue\n"
" extraTextFormatInfo:extraTextFormatInfo];\n",
"name", name_,
"extraTextFormatInfo", absl::CEscape(text_format_decode_data.Data()));
}
printer->Print(
" GPBEnumDescriptor *expected = nil;\n"
" if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {\n"
" [worker release];\n"
" }\n"
" }\n"
" return descriptor;\n"
"}\n\n");
// clang-format on
"name", name_, "extraTextFormatInfo",
absl::CEscape(text_format_decode_data.Data()));
}
// clang-format off
printer->Print(
" GPBEnumDescriptor *expected = nil;\n"
" if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {\n"
" [worker release];\n"
" }\n"
" }\n"
" return descriptor;\n"
"}\n\n");
// clang-format on
printer->Print(
// clang-format off
"BOOL $name$_IsValidValue(int32_t value__) {\n"
" switch (value__) {\n",
// clang-format on
"name", name_);
for (int i = 0; i < base_values_.size(); i++) {
printer->Print(
" case $name$:\n",
"name", EnumValueName(base_values_[i]));
printer->Print(" case $name$:\n", "name",
EnumValueName(base_values_[i]));
}
// clang-format off
printer->Print(
" return YES;\n"
" default:\n"
" return NO;\n"
" }\n"
"}\n\n");
// clang-format on
}
} // namespace objectivec
} // namespace compiler

@ -31,9 +31,10 @@
#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__
#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__
#include <string>
#include <set>
#include <string>
#include <vector>
#include "google/protobuf/descriptor.h"
#include "google/protobuf/io/printer.h"

@ -28,12 +28,13 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "google/protobuf/compiler/objectivec/enum_field.h"
#include <map>
#include <string>
#include "google/protobuf/compiler/objectivec/enum_field.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/compiler/objectivec/helpers.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/io/printer.h"
namespace google {
@ -78,6 +79,7 @@ void EnumFieldGenerator::GenerateCFunctionDeclarations(
return;
}
// clang-format off
printer->Print(
variables_,
"/**\n"
@ -92,12 +94,14 @@ void EnumFieldGenerator::GenerateCFunctionDeclarations(
" **/\n"
"void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value);\n"
"\n");
// clang-format on
}
void EnumFieldGenerator::GenerateCFunctionImplementations(
io::Printer* printer) const {
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) return;
// clang-format off
printer->Print(
variables_,
"int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message) {\n"
@ -112,13 +116,13 @@ void EnumFieldGenerator::GenerateCFunctionImplementations(
" GPBSetMessageRawEnumField(message, field, value);\n"
"}\n"
"\n");
// clang-format on
}
void EnumFieldGenerator::DetermineForwardDeclarations(
std::set<std::string>* fwd_decls,
bool include_external_types) const {
SingleFieldGenerator::DetermineForwardDeclarations(
fwd_decls, include_external_types);
std::set<std::string>* fwd_decls, bool include_external_types) const {
SingleFieldGenerator::DetermineForwardDeclarations(fwd_decls,
include_external_types);
// If it is an enum defined in a different file (and not a WKT), then we'll
// need a forward declaration for it. When it is in our file, all the enums
// are output before the message, so it will be declared before it is needed.
@ -142,8 +146,8 @@ RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
void RepeatedEnumFieldGenerator::FinishInitialization(void) {
RepeatedFieldGenerator::FinishInitialization();
variables_["array_comment"] =
"// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n";
variables_["array_comment"] = "// |" + variables_["name"] + "| contains |" +
variables_["storage_type"] + "|\n";
}
} // namespace objectivec

@ -33,6 +33,7 @@
#include <map>
#include <string>
#include "google/protobuf/compiler/objectivec/field.h"
namespace google {

@ -33,8 +33,8 @@
#include <iostream>
#include "absl/strings/str_cat.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/compiler/objectivec/helpers.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/io/printer.h"
@ -52,7 +52,7 @@ ExtensionGenerator::ExtensionGenerator(const std::string& root_class_name,
// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
// error cases, so it seems to be ok to use as a back door for errors.
std::cerr << "error: Extension is a map<>!"
<< " That used to be blocked by the compiler." << std::endl;
<< " That used to be blocked by the compiler." << std::endl;
std::cerr.flush();
abort();
}
@ -76,10 +76,14 @@ void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) {
}
// Unlike normal message fields, check if the file for the extension was
// deprecated.
vars["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file());
printer->Print(vars,
"$comments$"
"+ (GPBExtensionDescriptor *)$method_name$$storage_attribute$$deprecated_attribute$;\n");
vars["deprecated_attribute"] =
GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file());
// clang-format off
printer->Print(
vars,
"$comments$"
"+ (GPBExtensionDescriptor *)$method_name$$storage_attribute$$deprecated_attribute$;\n");
// clang-format on
}
void ExtensionGenerator::GenerateStaticVariablesInitialization(
@ -117,22 +121,25 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization(
if (objc_type == OBJECTIVECTYPE_ENUM) {
vars["enum_desc_func_name"] =
EnumName(descriptor_->enum_type()) + "_EnumDescriptor";
EnumName(descriptor_->enum_type()) + "_EnumDescriptor";
} else {
vars["enum_desc_func_name"] = "NULL";
}
printer->Print(vars,
"{\n"
" .defaultValue.$default_name$ = $default$,\n"
" .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n"
" .extendedClass.clazz = $extended_type$,\n"
" .messageOrGroupClass.clazz = $type$,\n"
" .enumDescriptorFunc = $enum_desc_func_name$,\n"
" .fieldNumber = $number$,\n"
" .dataType = $extension_type$,\n"
" .options = $options$,\n"
"},\n");
// clang-format off
printer->Print(
vars,
"{\n"
" .defaultValue.$default_name$ = $default$,\n"
" .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n"
" .extendedClass.clazz = $extended_type$,\n"
" .messageOrGroupClass.clazz = $type$,\n"
" .enumDescriptorFunc = $enum_desc_func_name$,\n"
" .fieldNumber = $number$,\n"
" .dataType = $extension_type$,\n"
" .options = $options$,\n"
"},\n");
// clang-format on
}
void ExtensionGenerator::DetermineObjectiveCClassDefinitions(
@ -147,9 +154,11 @@ void ExtensionGenerator::DetermineObjectiveCClassDefinitions(
}
void ExtensionGenerator::GenerateRegistrationSource(io::Printer* printer) {
// clang-format off
printer->Print(
"[registry addExtension:$root_class_and_method_name$];\n",
"root_class_and_method_name", root_class_and_method_name_);
// clang-format on
}
} // namespace objectivec

@ -34,10 +34,10 @@
#include "absl/strings/str_cat.h"
#include "google/protobuf/compiler/objectivec/enum_field.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/compiler/objectivec/helpers.h"
#include "google/protobuf/compiler/objectivec/map_field.h"
#include "google/protobuf/compiler/objectivec/message_field.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/compiler/objectivec/primitive_field.h"
#include "google/protobuf/io/printer.h"
@ -78,7 +78,8 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
classname + "_FieldNumber_" + capitalized_name;
(*variables)["field_number"] = absl::StrCat(descriptor->number());
(*variables)["field_type"] = GetCapitalizedType(descriptor);
(*variables)["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor);
(*variables)["deprecated_attribute"] =
GetOptionalDeprecatedAttribute(descriptor);
std::vector<std::string> field_flags;
if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated");
if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired");
@ -109,8 +110,8 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
(*variables)["dataTypeSpecific_name"] = "clazz";
(*variables)["dataTypeSpecific_value"] = "Nil";
(*variables)["storage_offset_value"] =
"(uint32_t)offsetof(" + classname + "__storage_, " + camel_case_name + ")";
(*variables)["storage_offset_value"] = "(uint32_t)offsetof(" + classname +
"__storage_, " + camel_case_name + ")";
(*variables)["storage_offset_comment"] = "";
// Clear some common things so they can be set just when needed.
@ -213,13 +214,10 @@ FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor)
FieldGenerator::~FieldGenerator() {}
void FieldGenerator::GenerateFieldNumberConstant(io::Printer* printer) const {
printer->Print(
variables_,
"$field_number_name$ = $field_number$,\n");
printer->Print(variables_, "$field_number_name$ = $field_number$,\n");
}
void FieldGenerator::GenerateCFunctionDeclarations(
io::Printer* printer) const {
void FieldGenerator::GenerateCFunctionDeclarations(io::Printer* printer) const {
// Nothing
}
@ -229,8 +227,7 @@ void FieldGenerator::GenerateCFunctionImplementations(
}
void FieldGenerator::DetermineForwardDeclarations(
std::set<std::string>* fwd_decls,
bool include_external_types) const {
std::set<std::string>* fwd_decls, bool include_external_types) const {
// Nothing
}
@ -239,10 +236,11 @@ void FieldGenerator::DetermineObjectiveCClassDefinitions(
// Nothing
}
void FieldGenerator::GenerateFieldDescription(
io::Printer* printer, bool include_default) const {
void FieldGenerator::GenerateFieldDescription(io::Printer* printer,
bool include_default) const {
// Printed in the same order as the structure decl.
if (include_default) {
// clang-format off
printer->Print(
variables_,
"{\n"
@ -255,7 +253,9 @@ void FieldGenerator::GenerateFieldDescription(
" .core.flags = $fieldflags$,\n"
" .core.dataType = GPBDataType$field_type$,\n"
"},\n");
// clang-format on
} else {
// clang-format off
printer->Print(
variables_,
"{\n"
@ -267,6 +267,7 @@ void FieldGenerator::GenerateFieldDescription(
" .flags = $fieldflags$,\n"
" .dataType = GPBDataType$field_type$,\n"
"},\n");
// clang-format on
}
}
@ -278,14 +279,13 @@ void FieldGenerator::SetNoHasBit(void) {
variables_["has_index"] = "GPBNoHasBit";
}
int FieldGenerator::ExtraRuntimeHasBitsNeeded(void) const {
return 0;
}
int FieldGenerator::ExtraRuntimeHasBitsNeeded(void) const { return 0; }
void FieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) {
// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
// error cases, so it seems to be ok to use as a back door for errors.
std::cerr << "Error: should have overridden SetExtraRuntimeHasBitsBase()." << std::endl;
std::cerr << "Error: should have overridden SetExtraRuntimeHasBitsBase()."
<< std::endl;
std::cerr.flush();
abort();
}
@ -326,14 +326,18 @@ void SingleFieldGenerator::GenerateFieldStorageDeclaration(
void SingleFieldGenerator::GeneratePropertyDeclaration(
io::Printer* printer) const {
printer->Print(variables_, "$comments$");
// clang-format off
printer->Print(
variables_,
"@property(nonatomic, readwrite) $property_type$ $name$$deprecated_attribute$;\n"
"\n");
// clang-format on
if (WantsHasProperty()) {
// clang-format off
printer->Print(
variables_,
"@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
// clang-format on
}
}
@ -371,26 +375,30 @@ void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration(
void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
io::Printer* printer) const {
// Differs from SingleFieldGenerator::GeneratePropertyDeclaration() in that
// it uses pointers and deals with Objective C's rules around storage name
// conventions (init*, new*, etc.)
printer->Print(variables_, "$comments$");
// clang-format off
printer->Print(
variables_,
"@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n");
// clang-format on
if (WantsHasProperty()) {
// clang-format off
printer->Print(
variables_,
"/** Test to see if @c $name$ has been set. */\n"
"@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
// clang-format on
}
if (IsInitName(variables_.find("name")->second)) {
// If property name starts with init we need to annotate it to get past ARC.
// http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
printer->Print(variables_,
"- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
"- ($property_type$ *)$name$ "
"GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
}
printer->Print("\n");
}
@ -423,13 +431,13 @@ void RepeatedFieldGenerator::GeneratePropertyImplementation(
void RepeatedFieldGenerator::GeneratePropertyDeclaration(
io::Printer* printer) const {
// Repeated fields don't need the has* properties, but they do expose a
// *Count (to check without autocreation). So for the field property we need
// the same logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for
// dealing with needing Objective C's rules around storage name conventions
// (init*, new*, etc.)
// clang-format off
printer->Print(
variables_,
"$comments$"
@ -437,11 +445,14 @@ void RepeatedFieldGenerator::GeneratePropertyDeclaration(
"@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n"
"/** The number of items in @c $name$ without causing the container to be created. */\n"
"@property(nonatomic, readonly) NSUInteger $name$_Count$deprecated_attribute$;\n");
// clang-format on
if (IsInitName(variables_.find("name")->second)) {
// If property name starts with init we need to annotate it to get past ARC.
// http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
// clang-format off
printer->Print(variables_,
"- ($array_property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
// clang-format on
}
printer->Print("\n");
}
@ -456,8 +467,7 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
extension_generators_(descriptor->extension_count()) {
// Construct all the FieldGenerators.
for (int i = 0; i < descriptor->field_count(); i++) {
field_generators_[i].reset(
FieldGenerator::Make(descriptor->field(i)));
field_generators_[i].reset(FieldGenerator::Make(descriptor->field(i)));
}
for (int i = 0; i < descriptor->extension_count(); i++) {
extension_generators_[i].reset(

@ -33,6 +33,7 @@
#include <map>
#include <string>
#include "google/protobuf/descriptor.h"
#include "google/protobuf/io/printer.h"
@ -63,15 +64,14 @@ class FieldGenerator {
virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
// Exposed for subclasses, should always call it on the parent class also.
virtual void DetermineForwardDeclarations(
std::set<std::string>* fwd_decls,
bool include_external_types) const;
virtual void DetermineForwardDeclarations(std::set<std::string>* fwd_decls,
bool include_external_types) const;
virtual void DetermineObjectiveCClassDefinitions(
std::set<std::string>* fwd_decls) const;
// Used during generation, not intended to be extended by subclasses.
void GenerateFieldDescription(
io::Printer* printer, bool include_default) const;
void GenerateFieldDescription(io::Printer* printer,
bool include_default) const;
void GenerateFieldNumberConstant(io::Printer* printer) const;
// Exposed to get and set the has bits information.
@ -111,10 +111,12 @@ class SingleFieldGenerator : public FieldGenerator {
SingleFieldGenerator(const SingleFieldGenerator&) = delete;
SingleFieldGenerator& operator=(const SingleFieldGenerator&) = delete;
virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
virtual void GenerateFieldStorageDeclaration(
io::Printer* printer) const override;
virtual void GeneratePropertyDeclaration(io::Printer* printer) const override;
virtual void GeneratePropertyImplementation(io::Printer* printer) const override;
virtual void GeneratePropertyImplementation(
io::Printer* printer) const override;
virtual bool RuntimeUsesHasBit(void) const override;
@ -130,7 +132,8 @@ class ObjCObjFieldGenerator : public SingleFieldGenerator {
ObjCObjFieldGenerator(const ObjCObjFieldGenerator&) = delete;
ObjCObjFieldGenerator& operator=(const ObjCObjFieldGenerator&) = delete;
virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
virtual void GenerateFieldStorageDeclaration(
io::Printer* printer) const override;
virtual void GeneratePropertyDeclaration(io::Printer* printer) const override;
protected:
@ -144,10 +147,12 @@ class RepeatedFieldGenerator : public ObjCObjFieldGenerator {
RepeatedFieldGenerator(const RepeatedFieldGenerator&) = delete;
RepeatedFieldGenerator& operator=(const RepeatedFieldGenerator&) = delete;
virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
virtual void GenerateFieldStorageDeclaration(
io::Printer* printer) const override;
virtual void GeneratePropertyDeclaration(io::Printer* printer) const override;
virtual void GeneratePropertyImplementation(io::Printer* printer) const override;
virtual void GeneratePropertyImplementation(
io::Printer* printer) const override;
virtual bool RuntimeUsesHasBit(void) const override;

@ -34,14 +34,14 @@
#include <iostream>
#include <sstream>
#include "google/protobuf/compiler/code_generator.h"
#include "absl/strings/str_cat.h"
#include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/compiler/objectivec/enum.h"
#include "google/protobuf/compiler/objectivec/extension.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/compiler/objectivec/helpers.h"
#include "google/protobuf/compiler/objectivec/import_writer.h"
#include "google/protobuf/compiler/objectivec/message.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/io/printer.h"
// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
@ -137,7 +137,7 @@ struct FileDescriptorsOrderedByName {
} // namespace
FileGenerator::CommonState::CommonState() { }
FileGenerator::CommonState::CommonState() {}
const FileGenerator::CommonState::MinDepsEntry&
FileGenerator::CommonState::CollectMinimalFileDepsContainingExtensionsInternal(
@ -156,20 +156,24 @@ FileGenerator::CommonState::CollectMinimalFileDepsContainingExtensionsInternal(
CollectMinimalFileDepsContainingExtensionsInternal(dep);
// Everything the dep covered, this file will also cover.
covered_deps_collector.insert(dep_info.covered_deps.begin(), dep_info.covered_deps.end());
covered_deps_collector.insert(dep_info.covered_deps.begin(),
dep_info.covered_deps.end());
// Prune everything from the dep's covered list in case another dep lists it
// as a min dep.
to_prune.insert(dep_info.covered_deps.begin(), dep_info.covered_deps.end());
// Does the dep have any extensions...
if (dep_info.has_extensions) {
// Yes -> Add this file, prune its min_deps and add them to the covered deps.
// Yes -> Add this file, prune its min_deps and add them to the covered
// deps.
min_deps_collector.insert(dep);
to_prune.insert(dep_info.min_deps.begin(), dep_info.min_deps.end());
covered_deps_collector.insert(dep_info.min_deps.begin(), dep_info.min_deps.end());
covered_deps_collector.insert(dep_info.min_deps.begin(),
dep_info.min_deps.end());
} else {
// No -> Just use its min_deps.
min_deps_collector.insert(dep_info.min_deps.begin(), dep_info.min_deps.end());
min_deps_collector.insert(dep_info.min_deps.begin(),
dep_info.min_deps.end());
}
}
@ -178,22 +182,25 @@ FileGenerator::CommonState::CollectMinimalFileDepsContainingExtensionsInternal(
// Fast path: if nothing to prune or there was only one dep, the prune work is
// a waste, skip it.
if (to_prune.empty() || file->dependency_count() == 1) {
return deps_info_cache_.insert(
{file, {file_has_exts, min_deps_collector, covered_deps_collector}}).first->second;
return deps_info_cache_
.insert(
{file, {file_has_exts, min_deps_collector, covered_deps_collector}})
.first->second;
}
std::unordered_set<const FileDescriptor*> min_deps;
std::copy_if(min_deps_collector.begin(), min_deps_collector.end(),
std::inserter(min_deps, min_deps.end()),
[&](const FileDescriptor* value){
return to_prune.find(value) == to_prune.end();
});
return deps_info_cache_.insert(
{file, {file_has_exts, min_deps, covered_deps_collector}}).first->second;
[&](const FileDescriptor* value) {
return to_prune.find(value) == to_prune.end();
});
return deps_info_cache_
.insert({file, {file_has_exts, min_deps, covered_deps_collector}})
.first->second;
}
// Collect the deps of the given file that contain extensions. This can be used to
// create the chain of roots that need to be wired together.
// Collect the deps of the given file that contain extensions. This can be used
// to create the chain of roots that need to be wired together.
//
// NOTE: If any changes are made to this and the supporting functions, you will
// need to manually validate what the generated code is for the test files:
@ -205,7 +212,7 @@ const std::vector<const FileDescriptor*>
FileGenerator::CommonState::CollectMinimalFileDepsContainingExtensions(
const FileDescriptor* file) {
std::unordered_set<const FileDescriptor*> min_deps =
CollectMinimalFileDepsContainingExtensionsInternal(file).min_deps;
CollectMinimalFileDepsContainingExtensionsInternal(file).min_deps;
// Sort the list since pointer order isn't stable across runs.
std::vector<const FileDescriptor*> result(min_deps.begin(), min_deps.end());
std::sort(result.begin(), result.end(), FileDescriptorsOrderedByName());
@ -261,6 +268,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
// compiled, since that will be the versions for the ObjC runtime at that
// time. The constants in the generated code will then get their values at
// at compile time (so checking against the headers being used to compile).
// clang-format off
printer->Print(
"#if GOOGLE_PROTOBUF_OBJC_VERSION < $google_protobuf_objc_version$\n"
"#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.\n"
@ -270,10 +278,12 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"#endif\n"
"\n",
"google_protobuf_objc_version", absl::StrCat(GOOGLE_PROTOBUF_OBJC_VERSION));
// clang-format on
// The bundled protos (WKTs) don't use of forward declarations.
bool headers_use_forward_declarations =
generation_options_.headers_use_forward_declarations && !is_bundled_proto_;
generation_options_.headers_use_forward_declarations &&
!is_bundled_proto_;
{
ImportWriter import_writer(
@ -299,6 +309,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
// deprecated-declarations suppression is only needed if some place in this
// proto file is something deprecated or if it references something from
// another file that is deprecated.
// clang-format off
printer->Print(
"// @@protoc_insertion_point(imports)\n"
"\n"
@ -307,6 +318,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"\n"
"CF_EXTERN_C_BEGIN\n"
"\n");
// clang-format on
std::set<std::string> fwd_decls;
for (const auto& generator : message_generators_) {
@ -338,6 +350,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
// For extensions to chain together, the Root gets created even if there
// are no extensions.
printer->Print(
// clang-format off
"#pragma mark - $root_class_name$\n"
"\n"
"/**\n"
@ -353,6 +366,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"GPB_FINAL @interface $root_class_name$ : GPBRootObject\n"
"@end\n"
"\n",
// clang-format off
"root_class_name", root_class_name_);
if (!extension_generators_.empty()) {
@ -372,6 +386,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
generator->GenerateMessageHeader(printer);
}
// clang-format off
printer->Print(
"NS_ASSUME_NONNULL_END\n"
"\n"
@ -382,6 +397,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"// @@protoc_insertion_point(global_scope)\n"
"\n"
"// clange-format on\n");
// clang-format on
}
void FileGenerator::GenerateSource(io::Printer* printer) {
@ -401,11 +417,12 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
}
std::vector<const FileDescriptor*> deps_with_extensions =
common_state_.CollectMinimalFileDepsContainingExtensions(file_);
common_state_.CollectMinimalFileDepsContainingExtensions(file_);
// The bundled protos (WKTs) don't use of forward declarations.
bool headers_use_forward_declarations =
generation_options_.headers_use_forward_declarations && !is_bundled_proto_;
generation_options_.headers_use_forward_declarations &&
!is_bundled_proto_;
{
ImportWriter import_writer(
@ -426,7 +443,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
public_import_names.insert(file_->public_dependency(i)->name());
}
for (int i = 0; i < file_->dependency_count(); i++) {
const FileDescriptor *dep = file_->dependency(i);
const FileDescriptor* dep = file_->dependency(i);
bool public_import = (public_import_names.count(dep->name()) != 0);
if (!public_import) {
import_writer.AddFile(dep, header_extension);
@ -471,11 +488,13 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
// another file that is deprecated.
// dollar-in-identifier-extension is needed because we use references to
// objc class names that have $ in identifiers.
// clang-format off
printer->Print(
"// @@protoc_insertion_point(imports)\n"
"\n"
"#pragma clang diagnostic push\n"
"#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n");
// clang-format on
if (includes_oneof) {
// The generated code for oneof's uses direct ivar access, suppress the
// warning in case developer turn that on in the context they compile the
@ -484,17 +503,20 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"#pragma clang diagnostic ignored \"-Wdirect-ivar-access\"\n");
}
if (!fwd_decls.empty()) {
// clang-format off
printer->Print(
"#pragma clang diagnostic ignored \"-Wdollar-in-identifier-extension\"\n");
"#pragma clang diagnostic ignored \"-Wdollar-in-identifier-extension\"\n");
// clang-format on
}
printer->Print(
"\n");
printer->Print("\n");
if (!fwd_decls.empty()) {
// clang-format off
printer->Print(
"#pragma mark - Objective C Class declarations\n"
"// Forward declarations of Objective C classes that we can use as\n"
"// static values in struct initializers.\n"
"// We don't use [Foo class] because it is not a static value.\n");
// clang-format on
}
for (const auto& i : fwd_decls) {
printer->Print("$value$\n", "value", i);
@ -503,9 +525,11 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
printer->Print("\n");
}
printer->Print(
// clang-format off
"#pragma mark - $root_class_name$\n"
"\n"
"@implementation $root_class_name$\n\n",
// clang-format on
"root_class_name", root_class_name_);
const bool file_contains_extensions = FileContainsExtensions(file_);
@ -513,6 +537,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
// If there were any extensions or this file has any dependencies, output
// a registry to override to create the file specific registry.
if (file_contains_extensions || !deps_with_extensions.empty()) {
// clang-format off
printer->Print(
"+ (GPBExtensionRegistry*)extensionRegistry {\n"
" // This is called by +initialize so there is no need to worry\n"
@ -521,13 +546,13 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
" if (!registry) {\n"
" GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n"
" registry = [[GPBExtensionRegistry alloc] init];\n");
// clang-format on
printer->Indent();
printer->Indent();
if (file_contains_extensions) {
printer->Print(
"static GPBExtensionDescription descriptions[] = {\n");
printer->Print("static GPBExtensionDescription descriptions[] = {\n");
printer->Indent();
for (const auto& generator : extension_generators_) {
generator->GenerateStaticVariablesInitialization(printer);
@ -536,6 +561,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
generator->GenerateStaticVariablesInitialization(printer);
}
printer->Outdent();
// clang-format off
printer->Print(
"};\n"
"for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n"
@ -546,15 +572,20 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
" [self globallyRegisterExtension:extension];\n"
" [extension release];\n"
"}\n");
// clang-format on
}
if (deps_with_extensions.empty()) {
// clang-format off
printer->Print(
"// None of the imports (direct or indirect) defined extensions, so no need to add\n"
"// them to this registry.\n");
// clang-format on
} else {
// clang-format off
printer->Print(
"// Merge in the imports (direct or indirect) that defined extensions.\n");
// clang-format on
for (std::vector<const FileDescriptor*>::iterator iter =
deps_with_extensions.begin();
iter != deps_with_extensions.end(); ++iter) {
@ -568,19 +599,25 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
printer->Outdent();
printer->Outdent();
// clang-format off
printer->Print(
" }\n"
" return registry;\n"
"}\n");
// clang-format on
} else {
if (file_->dependency_count() > 0) {
// clang-format off
printer->Print(
"// No extensions in the file and none of the imports (direct or indirect)\n"
"// defined extensions, so no need to generate +extensionRegistry.\n");
// clang-format on
} else {
// clang-format off
printer->Print(
"// No extensions in the file and no imports, so no need to generate\n"
"// +extensionRegistry.\n");
// clang-format on
}
}
@ -603,7 +640,9 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
vars["syntax"] = "GPBFileSyntaxProto3";
break;
}
printer->Print(vars,
// clang-format off
printer->Print(
vars,
"#pragma mark - $root_class_name$_FileDescriptor\n"
"\n"
"static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n"
@ -612,23 +651,30 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
" static GPBFileDescriptor *descriptor = NULL;\n"
" if (!descriptor) {\n"
" GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n");
// clang-format on
if (!vars["objc_prefix"].empty()) {
// clang-format off
printer->Print(
vars,
" descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
" objcPrefix:@\"$objc_prefix$\"\n"
" syntax:$syntax$];\n");
// clang-format on
} else {
// clang-format off
printer->Print(
vars,
" descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
" syntax:$syntax$];\n");
// clang-format on
}
// clang-format off
printer->Print(
" }\n"
" return descriptor;\n"
"}\n"
"\n");
// clang-format on
}
for (const auto& generator : enum_generators_) {
@ -638,13 +684,15 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
generator->GenerateSource(printer);
}
// clang-format off
printer->Print(
"\n"
"#pragma clang diagnostic pop\n"
"\n"
"// @@protoc_insertion_point(global_scope)\n"
"\n"
"// clang-format on\n");
"\n"
"#pragma clang diagnostic pop\n"
"\n"
"// @@protoc_insertion_point(global_scope)\n"
"\n"
"// clang-format on\n");
// clang-format on
}
// Helper to print the import of the runtime support at the top of generated
@ -669,14 +717,13 @@ void FileGenerator::PrintFileRuntimePreamble(
import_prefix += "/";
}
for (const auto& header : headers_to_import) {
printer->Print(
"#import \"$import_prefix$$header$\"\n",
"import_prefix", import_prefix,
"header", header);
printer->Print("#import \"$import_prefix$$header$\"\n", "import_prefix",
import_prefix, "header", header);
}
} else {
ImportWriter::PrintRuntimeImports(
printer, headers_to_import, generation_options_.runtime_import_prefix, true);
ImportWriter::PrintRuntimeImports(printer, headers_to_import,
generation_options_.runtime_import_prefix,
true);
}
printer->Print("\n");

@ -35,6 +35,7 @@
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "google/protobuf/compiler/objectivec/options.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/io/printer.h"
@ -66,7 +67,8 @@ class FileGenerator {
// have extensions.
std::unordered_set<const FileDescriptor*> covered_deps;
};
const MinDepsEntry& CollectMinimalFileDepsContainingExtensionsInternal(const FileDescriptor* file);
const MinDepsEntry& CollectMinimalFileDepsContainingExtensionsInternal(
const FileDescriptor* file);
std::unordered_map<const FileDescriptor*, MinDepsEntry> deps_info_cache_;
};

@ -39,8 +39,8 @@
#include "absl/strings/str_split.h"
#include "absl/strings/strip.h"
#include "google/protobuf/compiler/objectivec/file.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/compiler/objectivec/helpers.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/io/printer.h"
#include "google/protobuf/io/zero_copy_stream.h"
@ -75,9 +75,7 @@ ObjectiveCGenerator::ObjectiveCGenerator() {}
ObjectiveCGenerator::~ObjectiveCGenerator() {}
bool ObjectiveCGenerator::HasGenerateAll() const {
return true;
}
bool ObjectiveCGenerator::HasGenerateAll() const { return true; }
bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
const std::string& parameter,
@ -97,7 +95,8 @@ bool ObjectiveCGenerator::GenerateAll(
// options along with their values. If the option appears multiple times, only
// the last value will be considered.
//
// e.g. protoc ... --objc_opt=expected_prefixes=file.txt,generate_for_named_framework=MyFramework
// e.g. protoc ...
// --objc_opt=expected_prefixes=file.txt,generate_for_named_framework=MyFramework
Options validation_options;
GenerationOptions generation_options;
@ -127,8 +126,8 @@ bool ObjectiveCGenerator::GenerateAll(
// A semicolon delimited string that lists the paths of .proto files to
// exclude from the package prefix validations (expected_prefixes_path).
// This is provided as an "out", to skip some files being checked.
for (absl::string_view split_piece : absl::StrSplit(
options[i].second, ";", absl::SkipEmpty())) {
for (absl::string_view split_piece :
absl::StrSplit(options[i].second, ";", absl::SkipEmpty())) {
validation_options.expected_prefixes_suppressions.push_back(
std::string(split_piece));
}
@ -142,7 +141,8 @@ bool ObjectiveCGenerator::GenerateAll(
// Default is "no".
if (!StringToBool(options[i].second,
&validation_options.prefixes_must_be_registered)) {
*error = "error: Unknown value for prefixes_must_be_registered: " + options[i].second;
*error = "error: Unknown value for prefixes_must_be_registered: " +
options[i].second;
return false;
}
} else if (options[i].first == "require_prefixes") {
@ -154,7 +154,8 @@ bool ObjectiveCGenerator::GenerateAll(
// Default is "no".
if (!StringToBool(options[i].second,
&validation_options.require_prefixes)) {
*error = "error: Unknown value for require_prefixes: " + options[i].second;
*error =
"error: Unknown value for require_prefixes: " + options[i].second;
return false;
}
} else if (options[i].first == "generate_for_named_framework") {
@ -167,7 +168,8 @@ bool ObjectiveCGenerator::GenerateAll(
// the "default" framework name used for everything that wasn't mapped by
// the mapping file.
generation_options.generate_for_named_framework = options[i].second;
} else if (options[i].first == "named_framework_to_proto_path_mappings_path") {
} else if (options[i].first ==
"named_framework_to_proto_path_mappings_path") {
// Path to find a file containing the list of framework names and proto
// files. The generator uses this to decide if a proto file
// referenced should use a framework style import vs. a user level import
@ -188,7 +190,8 @@ bool ObjectiveCGenerator::GenerateAll(
// mappings file, it will use the default framework name if one was passed
// with generate_for_named_framework, or the relative path to it's include
// path otherwise.
generation_options.named_framework_to_proto_path_mappings_path = options[i].second;
generation_options.named_framework_to_proto_path_mappings_path =
options[i].second;
} else if (options[i].first == "runtime_import_prefix") {
// Path to use as a prefix on #imports of runtime provided headers in the
// generated files. When integrating ObjC protos into a build system,
@ -198,8 +201,9 @@ bool ObjectiveCGenerator::GenerateAll(
std::string(absl::StripSuffix(options[i].second, "/"));
} else if (options[i].first == "package_to_prefix_mappings_path") {
// Path to use for when loading the objc class prefix mappings to use.
// The `objc_class_prefix` file option is always honored first if one is present.
// This option also has precedent over the use_package_as_prefix option.
// The `objc_class_prefix` file option is always honored first if one is
// present. This option also has precedent over the use_package_as_prefix
// option.
//
// The format of the file is:
// - An entry is a line of "package=prefix".
@ -243,7 +247,8 @@ bool ObjectiveCGenerator::GenerateAll(
} else if (options[i].first == "headers_use_forward_declarations") {
if (!StringToBool(options[i].second,
&generation_options.headers_use_forward_declarations)) {
*error = "error: Unknown value for headers_use_forward_declarations: " + options[i].second;
*error = "error: Unknown value for headers_use_forward_declarations: " +
options[i].second;
return false;
}
} else {

@ -34,6 +34,7 @@
#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__
#include <string>
#include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/descriptor.h"

@ -28,17 +28,17 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/stubs/strutil.h"
#include "google/protobuf/compiler/objectivec/helpers.h"
#include "absl/strings/ascii.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_split.h"
#include "absl/strings/str_replace.h"
#include "google/protobuf/compiler/objectivec/helpers.h"
#include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/io/printer.h"
#include "google/protobuf/io/zero_copy_stream_impl.h"
#include "google/protobuf/stubs/common.h"
#include "google/protobuf/stubs/strutil.h"
// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
// error cases, so it seems to be ok to use as a back door for errors.
@ -55,7 +55,7 @@ std::string EscapeTrigraphs(absl::string_view to_escape) {
namespace {
std::string GetZeroEnumNameForFlagType(const FlagType flag_type) {
switch(flag_type) {
switch (flag_type) {
case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
return "GPBDescriptorInitializationFlag_None";
case FLAGTYPE_EXTENSION:
@ -69,7 +69,7 @@ std::string GetZeroEnumNameForFlagType(const FlagType flag_type) {
}
std::string GetEnumNameForFlagType(const FlagType flag_type) {
switch(flag_type) {
switch (flag_type) {
case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
return "GPBDescriptorInitializationFlags";
case FLAGTYPE_EXTENSION:
@ -82,8 +82,7 @@ std::string GetEnumNameForFlagType(const FlagType flag_type) {
}
}
std::string HandleExtremeFloatingPoint(std::string val,
bool add_float_suffix) {
std::string HandleExtremeFloatingPoint(std::string val, bool add_float_suffix) {
if (val == "nan") {
return "NAN";
} else if (val == "inf") {
@ -202,7 +201,7 @@ std::string GPBGenericValueFieldName(const FieldDescriptor* field) {
// Returns the field within the GPBGenericValue union to use for the given
// field.
if (field->is_repeated()) {
return "valueMessage";
return "valueMessage";
}
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32:
@ -237,7 +236,6 @@ std::string GPBGenericValueFieldName(const FieldDescriptor* field) {
return std::string();
}
std::string DefaultValue(const FieldDescriptor* field) {
// Repeated fields don't have defaults.
if (field->is_repeated()) {
@ -336,10 +334,10 @@ std::string ObjCClassDeclaration(const std::string& class_name) {
}
std::string BuildCommentsString(const SourceLocation& location,
bool prefer_single_line) {
bool prefer_single_line) {
const std::string& comments = location.leading_comments.empty()
? location.trailing_comments
: location.leading_comments;
? location.trailing_comments
: location.leading_comments;
std::vector<std::string> lines;
lines = absl::StrSplit(comments, "\n", absl::AllowEmpty());
while (!lines.empty() && lines.back().empty()) {
@ -388,7 +386,6 @@ std::string BuildCommentsString(const SourceLocation& location,
return final_comments;
}
} // namespace objectivec
} // namespace compiler
} // namespace protobuf

@ -104,7 +104,8 @@ inline bool IsReferenceType(const FieldDescriptor* field) {
std::string GPBGenericValueFieldName(const FieldDescriptor* field);
std::string DefaultValue(const FieldDescriptor* field);
std::string BuildFlagsString(const FlagType type, const std::vector<std::string>& strings);
std::string BuildFlagsString(const FlagType type,
const std::vector<std::string>& strings);
// Returns a symbol that can be used in C code to refer to an Objective C
// class without initializing the class.
@ -156,7 +157,6 @@ std::string GetOptionalDeprecatedAttribute(const TDescriptor* descriptor,
}
}
} // namespace objectivec
} // namespace compiler
} // namespace protobuf

@ -29,10 +29,11 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "google/protobuf/compiler/objectivec/import_writer.h"
#include "absl/strings/ascii.h"
#include "google/protobuf/compiler/objectivec/line_consumer.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/io/printer.h"
#include "absl/strings/ascii.h"
// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
// error cases, so it seems to be ok to use as a back door for errors.
@ -46,17 +47,19 @@ namespace {
class ProtoFrameworkCollector : public LineConsumer {
public:
ProtoFrameworkCollector(std::map<std::string, std::string>* inout_proto_file_to_framework_name)
ProtoFrameworkCollector(
std::map<std::string, std::string>* inout_proto_file_to_framework_name)
: map_(inout_proto_file_to_framework_name) {}
virtual bool ConsumeLine(const absl::string_view& line, std::string* out_error) override;
virtual bool ConsumeLine(const absl::string_view& line,
std::string* out_error) override;
private:
std::map<std::string, std::string>* map_;
};
bool ProtoFrameworkCollector::ConsumeLine(
const absl::string_view& line, std::string* out_error) {
bool ProtoFrameworkCollector::ConsumeLine(const absl::string_view& line,
std::string* out_error) {
int offset = line.find(':');
if (offset == absl::string_view::npos) {
*out_error =
@ -64,8 +67,10 @@ bool ProtoFrameworkCollector::ConsumeLine(
std::string(line) + "'.";
return false;
}
absl::string_view framework_name = absl::StripAsciiWhitespace(line.substr(0, offset));
absl::string_view proto_file_list = absl::StripAsciiWhitespace(line.substr(offset + 1));
absl::string_view framework_name =
absl::StripAsciiWhitespace(line.substr(0, offset));
absl::string_view proto_file_list =
absl::StripAsciiWhitespace(line.substr(offset + 1));
int start = 0;
while (start < proto_file_list.length()) {
@ -74,16 +79,17 @@ bool ProtoFrameworkCollector::ConsumeLine(
offset = proto_file_list.length();
}
absl::string_view proto_file =
absl::StripAsciiWhitespace(proto_file_list.substr(start, offset - start));
absl::string_view proto_file = absl::StripAsciiWhitespace(
proto_file_list.substr(start, offset - start));
if (!proto_file.empty()) {
std::map<std::string, std::string>::iterator existing_entry =
map_->find(std::string(proto_file));
if (existing_entry != map_->end()) {
std::cerr << "warning: duplicate proto file reference, replacing "
"framework entry for '"
<< std::string(proto_file) << "' with '" << std::string(framework_name)
<< "' (was '" << existing_entry->second << "')." << std::endl;
<< std::string(proto_file) << "' with '"
<< std::string(framework_name) << "' (was '"
<< existing_entry->second << "')." << std::endl;
std::cerr.flush();
}
@ -141,15 +147,14 @@ void ImportWriter::AddFile(const FileDescriptor* file,
proto_file_to_framework_name_.find(file->name());
if (proto_lookup != proto_file_to_framework_name_.end()) {
other_framework_imports_.push_back(
proto_lookup->second + "/" +
FilePathBasename(file) + header_extension);
proto_lookup->second + "/" + FilePathBasename(file) + header_extension);
return;
}
if (!generate_for_named_framework_.empty()) {
other_framework_imports_.push_back(
generate_for_named_framework_ + "/" +
FilePathBasename(file) + header_extension);
other_framework_imports_.push_back(generate_for_named_framework_ + "/" +
FilePathBasename(file) +
header_extension);
return;
}
@ -172,9 +177,7 @@ void ImportWriter::Print(io::Printer* printer) const {
for (std::vector<std::string>::const_iterator iter =
other_framework_imports_.begin();
iter != other_framework_imports_.end(); ++iter) {
printer->Print(
"#import <$header$>\n",
"header", *iter);
printer->Print("#import <$header$>\n", "header", *iter);
}
add_blank_line = true;
@ -187,9 +190,7 @@ void ImportWriter::Print(io::Printer* printer) const {
for (std::vector<std::string>::const_iterator iter = other_imports_.begin();
iter != other_imports_.end(); ++iter) {
printer->Print(
"#import \"$header$\"\n",
"header", *iter);
printer->Print("#import \"$header$\"\n", "header", *iter);
}
}
}
@ -200,10 +201,8 @@ void ImportWriter::PrintRuntimeImports(
// Given an override, use that.
if (!runtime_import_prefix.empty()) {
for (const auto& header : header_to_import) {
printer->Print(
" #import \"$import_prefix$/$header$\"\n",
"import_prefix", runtime_import_prefix,
"header", header);
printer->Print(" #import \"$import_prefix$/$header$\"\n", "import_prefix",
runtime_import_prefix, "header", header);
}
return;
}
@ -213,33 +212,27 @@ void ImportWriter::PrintRuntimeImports(
if (default_cpp_symbol) {
printer->Print(
// clang-format off
"// This CPP symbol can be defined to use imports that match up to the framework\n"
"// imports needed when using CocoaPods.\n"
"#if !defined($cpp_symbol$)\n"
" #define $cpp_symbol$ 0\n"
"#endif\n"
"\n",
// clang-format on
"cpp_symbol", cpp_symbol);
}
printer->Print(
"#if $cpp_symbol$\n",
"cpp_symbol", cpp_symbol);
printer->Print("#if $cpp_symbol$\n", "cpp_symbol", cpp_symbol);
for (const auto& header : header_to_import) {
printer->Print(
" #import <$framework_name$/$header$>\n",
"framework_name", framework_name,
"header", header);
printer->Print(" #import <$framework_name$/$header$>\n", "framework_name",
framework_name, "header", header);
}
printer->Print(
"#else\n");
printer->Print("#else\n");
for (const auto& header : header_to_import) {
printer->Print(
" #import \"$header$\"\n",
"header", header);
printer->Print(" #import \"$header$\"\n", "header", header);
}
printer->Print(
"#endif\n");
printer->Print("#endif\n");
}
void ImportWriter::ParseFrameworkMappings() {
@ -250,10 +243,11 @@ void ImportWriter::ParseFrameworkMappings() {
ProtoFrameworkCollector collector(&proto_file_to_framework_name_);
std::string parse_error;
if (!ParseSimpleFile(named_framework_to_proto_path_mappings_path_,
&collector, &parse_error)) {
std::cerr << "error parsing " << named_framework_to_proto_path_mappings_path_
<< " : " << parse_error << std::endl;
if (!ParseSimpleFile(named_framework_to_proto_path_mappings_path_, &collector,
&parse_error)) {
std::cerr << "error parsing "
<< named_framework_to_proto_path_mappings_path_ << " : "
<< parse_error << std::endl;
std::cerr.flush();
}
}

@ -55,10 +55,10 @@ class ImportWriter {
void AddFile(const FileDescriptor* file, const std::string& header_extension);
void Print(io::Printer* printer) const;
static void PrintRuntimeImports(io::Printer* printer,
const std::vector<std::string>& header_to_import,
const std::string& runtime_import_prefix,
bool default_cpp_symbol = false);
static void PrintRuntimeImports(
io::Printer* printer, const std::vector<std::string>& header_to_import,
const std::string& runtime_import_prefix,
bool default_cpp_symbol = false);
private:
void ParseFrameworkMappings();
@ -75,7 +75,6 @@ class ImportWriter {
std::vector<std::string> other_imports_;
};
} // namespace objectivec
} // namespace compiler
} // namespace protobuf

@ -61,16 +61,14 @@ namespace objectivec {
namespace posix {
#ifdef _WIN32
using google::protobuf::io::win32::open;
#else // !_WIN32
#else // !_WIN32
using ::open;
#endif // _WIN32
} // namespace posix
namespace {
bool ascii_isnewline(char c) {
return c == '\n' || c == '\r';
}
bool ascii_isnewline(char c) { return c == '\n' || c == '\r'; }
bool ReadLine(absl::string_view* input, absl::string_view* line) {
for (int len = 0; len < input->size(); ++len) {
@ -149,7 +147,8 @@ bool Parser::Finish(std::string* out_error) {
if (!leftover_.empty() && !ParseChunk("\n", out_error)) {
return false;
}
// This really should never fail if ParseChunk succeeded, but check to be sure.
// This really should never fail if ParseChunk succeeded, but check to be
// sure.
if (!leftover_.empty()) {
*out_error = "ParseSimple Internal error: finished with pending data.";
return false;
@ -157,8 +156,10 @@ bool Parser::Finish(std::string* out_error) {
return true;
}
std::string FullErrorString(const std::string& name, int line_num, const std::string& msg) {
return std::string("error: ") + name + " Line " + absl::StrCat(line_num) + ", " + msg;
std::string FullErrorString(const std::string& name, int line_num,
const std::string& msg) {
return std::string("error: ") + name + " Line " + absl::StrCat(line_num) +
", " + msg;
}
} // namespace
@ -186,8 +187,7 @@ bool ParseSimpleFile(const std::string& path, LineConsumer* line_consumer,
bool ParseSimpleStream(io::ZeroCopyInputStream& input_stream,
const std::string& stream_name,
LineConsumer* line_consumer,
std::string* out_error) {
LineConsumer* line_consumer, std::string* out_error) {
std::string local_error;
Parser parser(line_consumer);
const void* buf;
@ -197,9 +197,11 @@ bool ParseSimpleStream(io::ZeroCopyInputStream& input_stream,
continue;
}
if (!parser.ParseChunk(absl::string_view(static_cast<const char*>(buf), buf_len),
&local_error)) {
*out_error = FullErrorString(stream_name, parser.last_line(), local_error);
if (!parser.ParseChunk(
absl::string_view(static_cast<const char*>(buf), buf_len),
&local_error)) {
*out_error =
FullErrorString(stream_name, parser.last_line(), local_error);
return false;
}
}

@ -52,7 +52,8 @@ class PROTOC_EXPORT LineConsumer {
public:
LineConsumer();
virtual ~LineConsumer();
virtual bool ConsumeLine(const absl::string_view& line, std::string* out_error) = 0;
virtual bool ConsumeLine(const absl::string_view& line,
std::string* out_error) = 0;
};
bool PROTOC_EXPORT ParseSimpleFile(const std::string& path,

@ -29,11 +29,12 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "google/protobuf/compiler/objectivec/line_consumer.h"
#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
#include "absl/strings/str_cat.h"
#include <gtest/gtest.h>
#include "absl/strings/str_cat.h"
#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
namespace google {
namespace protobuf {
namespace compiler {
@ -43,11 +44,12 @@ namespace {
class TestLineCollector : public LineConsumer {
public:
explicit TestLineCollector(std::vector<std::string>* inout_lines,
const std::string* reject_line = nullptr,
bool skip_msg = false)
: lines_(inout_lines), reject_(reject_line), skip_msg_(skip_msg) {}
const std::string* reject_line = nullptr,
bool skip_msg = false)
: lines_(inout_lines), reject_(reject_line), skip_msg_(skip_msg) {}
bool ConsumeLine(const absl::string_view& line, std::string* out_error) override {
bool ConsumeLine(const absl::string_view& line,
std::string* out_error) override {
if (reject_ && *reject_ == line) {
if (!skip_msg_) {
*out_error = std::string("Rejected '") + *reject_ + "'";
@ -71,19 +73,20 @@ const int kBlockSizeCount = ABSL_ARRAYSIZE(kBlockSizes);
TEST(ObjCHelper, ParseSimple_BasicsSuccess) {
const std::vector<std::pair<std::string, std::vector<std::string>>> tests = {
{"", {}},
{"a", {"a"}},
{"a c", {"a c"}},
{" a c ", {"a c"}},
{"\ta c ", {"a c"}},
{"abc\n", {"abc"}},
{"abc\nd f", {"abc", "d f"}},
{"\n abc \n def \n\n", {"abc", "def"}},
{"", {}},
{"a", {"a"}},
{"a c", {"a c"}},
{" a c ", {"a c"}},
{"\ta c ", {"a c"}},
{"abc\n", {"abc"}},
{"abc\nd f", {"abc", "d f"}},
{"\n abc \n def \n\n", {"abc", "def"}},
};
for (const auto& test : tests) {
for (int i = 0; i < kBlockSizeCount; i++) {
io::ArrayInputStream input(test.first.data(), test.first.size(), kBlockSizes[i]);
io::ArrayInputStream input(test.first.data(), test.first.size(),
kBlockSizes[i]);
std::string err_str;
std::vector<std::string> lines;
TestLineCollector collector(&lines);
@ -96,22 +99,23 @@ TEST(ObjCHelper, ParseSimple_BasicsSuccess) {
TEST(ObjCHelper, ParseSimple_DropsComments) {
const std::vector<std::pair<std::string, std::vector<std::string>>> tests = {
{"# nothing", {}},
{"#", {}},
{"##", {}},
{"\n# nothing\n", {}},
{"a # same line", {"a"}},
{"a # same line\n", {"a"}},
{"a\n# line\nc", {"a", "c"}},
{"# n o t # h i n g #", {}},
{"## n o # t h i n g #", {}},
{"a# n o t # h i n g #", {"a"}},
{"a\n## n o # t h i n g #", {"a"}},
{"# nothing", {}},
{"#", {}},
{"##", {}},
{"\n# nothing\n", {}},
{"a # same line", {"a"}},
{"a # same line\n", {"a"}},
{"a\n# line\nc", {"a", "c"}},
{"# n o t # h i n g #", {}},
{"## n o # t h i n g #", {}},
{"a# n o t # h i n g #", {"a"}},
{"a\n## n o # t h i n g #", {"a"}},
};
for (const auto& test : tests) {
for (int i = 0; i < kBlockSizeCount; i++) {
io::ArrayInputStream input(test.first.data(), test.first.size(), kBlockSizes[i]);
io::ArrayInputStream input(test.first.data(), test.first.size(),
kBlockSizes[i]);
std::string err_str;
std::vector<std::string> lines;
TestLineCollector collector(&lines);
@ -124,21 +128,22 @@ TEST(ObjCHelper, ParseSimple_DropsComments) {
TEST(ObjCHelper, ParseSimple_RejectLines) {
const std::vector<std::tuple<std::string, std::string, int>> tests = {
std::make_tuple("a\nb\nc", "a", 1),
std::make_tuple("a\nb\nc", "b", 2),
std::make_tuple("a\nb\nc", "c", 3),
std::make_tuple("a\nb\nc\n", "c", 3),
std::make_tuple("a\nb\nc", "a", 1),
std::make_tuple("a\nb\nc", "b", 2),
std::make_tuple("a\nb\nc", "c", 3),
std::make_tuple("a\nb\nc\n", "c", 3),
};
for (const auto& test : tests) {
for (int i = 0; i < kBlockSizeCount; i++) {
io::ArrayInputStream input(std::get<0>(test).data(), std::get<0>(test).size(),
kBlockSizes[i]);
io::ArrayInputStream input(std::get<0>(test).data(),
std::get<0>(test).size(), kBlockSizes[i]);
std::string err_str;
TestLineCollector collector(nullptr, &std::get<1>(test));
EXPECT_FALSE(ParseSimpleStream(input, "dummy", &collector, &err_str));
std::string expected_err =
absl::StrCat("error: dummy Line ", std::get<2>(test), ", Rejected '", std::get<1>(test), "'");
absl::StrCat("error: dummy Line ", std::get<2>(test), ", Rejected '",
std::get<1>(test), "'");
EXPECT_EQ(err_str, expected_err);
}
}
@ -146,22 +151,23 @@ TEST(ObjCHelper, ParseSimple_RejectLines) {
TEST(ObjCHelper, ParseSimple_RejectLinesNoMessage) {
const std::vector<std::tuple<std::string, std::string, int>> tests = {
std::make_tuple("a\nb\nc", "a", 1),
std::make_tuple("a\nb\nc", "b", 2),
std::make_tuple("a\nb\nc", "c", 3),
std::make_tuple("a\nb\nc\n", "c", 3),
std::make_tuple("a\nb\nc", "a", 1),
std::make_tuple("a\nb\nc", "b", 2),
std::make_tuple("a\nb\nc", "c", 3),
std::make_tuple("a\nb\nc\n", "c", 3),
};
for (const auto& test : tests) {
for (int i = 0; i < kBlockSizeCount; i++) {
io::ArrayInputStream input(std::get<0>(test).data(), std::get<0>(test).size(),
kBlockSizes[i]);
io::ArrayInputStream input(std::get<0>(test).data(),
std::get<0>(test).size(), kBlockSizes[i]);
std::string err_str;
TestLineCollector collector(nullptr, &std::get<1>(test), true /* skip msg */);
TestLineCollector collector(nullptr, &std::get<1>(test),
true /* skip msg */);
EXPECT_FALSE(ParseSimpleStream(input, "dummy", &collector, &err_str));
std::string expected_err =
absl::StrCat("error: dummy Line ", std::get<2>(test),
", ConsumeLine failed without setting an error.");
absl::StrCat("error: dummy Line ", std::get<2>(test),
", ConsumeLine failed without setting an error.");
EXPECT_EQ(err_str, expected_err);
}
}

@ -28,12 +28,13 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "google/protobuf/compiler/objectivec/map_field.h"
#include <map>
#include <string>
#include "google/protobuf/compiler/objectivec/map_field.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/compiler/objectivec/helpers.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/io/printer.h"
namespace google {
@ -84,8 +85,7 @@ const char* MapEntryTypeName(const FieldDescriptor* descriptor, bool isKey) {
MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor)
: RepeatedFieldGenerator(descriptor) {
const FieldDescriptor* key_descriptor =
descriptor->message_type()->map_key();
const FieldDescriptor* key_descriptor = descriptor->message_type()->map_key();
const FieldDescriptor* value_descriptor =
descriptor->message_type()->map_value();
value_field_generator_.reset(FieldGenerator::Make(value_descriptor));
@ -135,8 +135,8 @@ MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor)
variables_["array_storage_type"] = class_name;
if (value_is_object_type) {
variables_["array_property_type"] =
class_name + "<" +
value_field_generator_->variable("storage_type") + "*>";
class_name + "<" + value_field_generator_->variable("storage_type") +
"*>";
}
}
@ -156,15 +156,15 @@ void MapFieldGenerator::FinishInitialization(void) {
descriptor_->message_type()->map_value();
if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_ENUM) {
variables_["array_comment"] =
"// |" + variables_["name"] + "| values are |" + value_field_generator_->variable("storage_type") + "|\n";
"// |" + variables_["name"] + "| values are |" +
value_field_generator_->variable("storage_type") + "|\n";
}
}
void MapFieldGenerator::DetermineForwardDeclarations(
std::set<std::string>* fwd_decls,
bool include_external_types) const {
RepeatedFieldGenerator::DetermineForwardDeclarations(
fwd_decls, include_external_types);
std::set<std::string>* fwd_decls, bool include_external_types) const {
RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls,
include_external_types);
const FieldDescriptor* value_descriptor =
descriptor_->message_type()->map_value();
// Within a file there is no requirement on the order of the messages, so
@ -186,8 +186,8 @@ void MapFieldGenerator::DetermineObjectiveCClassDefinitions(
const FieldDescriptor* value_descriptor =
descriptor_->message_type()->map_value();
if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE) {
fwd_decls->insert(ObjCClassDeclaration(
value_field_generator_->variable("storage_type")));
fwd_decls->insert(
ObjCClassDeclaration(value_field_generator_->variable("storage_type")));
}
}

@ -38,8 +38,8 @@
#include "absl/strings/str_cat.h"
#include "google/protobuf/compiler/objectivec/enum.h"
#include "google/protobuf/compiler/objectivec/extension.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/compiler/objectivec/helpers.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/compiler/objectivec/text_format_decode_data.h"
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/io/printer.h"
@ -152,11 +152,12 @@ struct ExtensionRangeOrdering {
// and return it.
const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
const FieldDescriptor** fields =
new const FieldDescriptor* [descriptor->field_count()];
new const FieldDescriptor*[descriptor->field_count()];
for (int i = 0; i < descriptor->field_count(); i++) {
fields[i] = descriptor->field(i);
}
std::sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber());
std::sort(fields, fields + descriptor->field_count(),
FieldOrderingByNumber());
return fields;
}
@ -164,12 +165,12 @@ const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
// array and return it.
const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) {
const FieldDescriptor** fields =
new const FieldDescriptor* [descriptor->field_count()];
new const FieldDescriptor*[descriptor->field_count()];
for (int i = 0; i < descriptor->field_count(); i++) {
fields[i] = descriptor->field(i);
}
std::sort(fields, fields + descriptor->field_count(),
FieldOrderingByStorageSize());
FieldOrderingByStorageSize());
return fields;
}
@ -200,8 +201,7 @@ MessageGenerator::MessageGenerator(const std::string& root_classname,
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
MessageGenerator* generator =
new MessageGenerator(root_classname_,
descriptor_->nested_type(i));
new MessageGenerator(root_classname_, descriptor_->nested_type(i));
nested_message_generators_.emplace_back(generator);
}
}
@ -220,8 +220,7 @@ void MessageGenerator::GenerateStaticVariablesInitialization(
}
void MessageGenerator::DetermineForwardDeclarations(
std::set<std::string>* fwd_decls,
bool include_external_types) {
std::set<std::string>* fwd_decls, bool include_external_types) {
if (!IsMapEntryMessage(descriptor_)) {
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
@ -305,16 +304,18 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
}
printer->Print(
// clang-format off
"#pragma mark - $classname$\n"
"\n",
// clang-format on
"classname", class_name_);
if (descriptor_->field_count()) {
std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
SortFieldsByNumber(descriptor_));
printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n",
"classname", class_name_);
printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n", "classname",
class_name_);
printer->Indent();
for (int i = 0; i < descriptor_->field_count(); i++) {
@ -339,9 +340,10 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
}
printer->Print(
// clang-format off
"$comments$$deprecated_attribute$GPB_FINAL @interface $classname$ : GPBMessage\n\n",
"classname", class_name_,
"deprecated_attribute", deprecated_attribute_,
// clang-format on
"classname", class_name_, "deprecated_attribute", deprecated_attribute_,
"comments", message_comments);
std::vector<char> seen_oneofs(oneof_generators_.size(), 0);
@ -374,8 +376,8 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
}
if (descriptor_->extension_count() > 0) {
printer->Print("@interface $classname$ (DynamicMethods)\n\n",
"classname", class_name_);
printer->Print("@interface $classname$ (DynamicMethods)\n\n", "classname",
class_name_);
for (const auto& generator : extension_generators_) {
generator->GenerateMembersHeader(printer);
}
@ -390,20 +392,23 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
void MessageGenerator::GenerateSource(io::Printer* printer) {
if (!IsMapEntryMessage(descriptor_)) {
printer->Print(
// clang-format off
"#pragma mark - $classname$\n"
"\n",
// clang-format on
"classname", class_name_);
if (!deprecated_attribute_.empty()) {
// No warnings when compiling the impl of this deprecated class.
// clang-format off
printer->Print(
"#pragma clang diagnostic push\n"
"#pragma clang diagnostic ignored \"-Wdeprecated-implementations\"\n"
"\n");
// clang-format on
}
printer->Print("@implementation $classname$\n\n",
"classname", class_name_);
printer->Print("@implementation $classname$\n\n", "classname", class_name_);
for (const auto& generator : oneof_generators_) {
generator->GeneratePropertyImplementation(printer);
@ -426,7 +431,7 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
}
std::sort(sorted_extensions.begin(), sorted_extensions.end(),
ExtensionRangeOrdering());
ExtensionRangeOrdering());
// Assign has bits:
// 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing
@ -452,11 +457,13 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
sizeof_has_storage += oneof_generators_.size();
printer->Print(
// clang-format off
"\n"
"typedef struct $classname$__storage_ {\n"
" uint32_t _has_storage_[$sizeof_has_storage$];\n",
"classname", class_name_,
"sizeof_has_storage", absl::StrCat(sizeof_has_storage));
// clang-format on
"classname", class_name_, "sizeof_has_storage",
absl::StrCat(sizeof_has_storage));
printer->Indent();
for (int i = 0; i < descriptor_->field_count(); i++) {
@ -467,13 +474,14 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
printer->Print("} $classname$__storage_;\n\n", "classname", class_name_);
// clang-format off
printer->Print(
"// This method is threadsafe because it is initially called\n"
"// in +initialize for each subclass.\n"
"+ (GPBDescriptor *)descriptor {\n"
" static GPBDescriptor *descriptor = nil;\n"
" if (!descriptor) {\n");
// clang-format on
TextFormatDecodeData text_format_decode_data;
bool has_fields = descriptor_->field_count() > 0;
@ -487,23 +495,21 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
if (has_fields) {
printer->Indent();
printer->Indent();
printer->Print(
"static $field_description_type$ fields[] = {\n",
"field_description_type", field_description_type);
printer->Print("static $field_description_type$ fields[] = {\n",
"field_description_type", field_description_type);
printer->Indent();
for (int i = 0; i < descriptor_->field_count(); ++i) {
const FieldGenerator& field_generator =
field_generators_.get(sorted_fields[i]);
field_generator.GenerateFieldDescription(printer, need_defaults);
if (field_generator.needs_textformat_name_support()) {
text_format_decode_data.AddString(sorted_fields[i]->number(),
field_generator.generated_objc_name(),
field_generator.raw_field_name());
text_format_decode_data.AddString(
sorted_fields[i]->number(), field_generator.generated_objc_name(),
field_generator.raw_field_name());
}
}
printer->Outdent();
printer->Print(
"};\n");
printer->Print("};\n");
printer->Outdent();
printer->Outdent();
}
@ -528,9 +534,10 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
if (descriptor_->options().message_set_wire_format()) {
init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat");
}
vars["init_flags"] = BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION,
init_flags);
vars["init_flags"] =
BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION, init_flags);
// clang-format off
printer->Print(
vars,
" GPBDescriptor *localDescriptor =\n"
@ -541,55 +548,63 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
" fieldCount:$fields_count$\n"
" storageSize:sizeof($classname$__storage_)\n"
" flags:$init_flags$];\n");
// clang-format on
if (!oneof_generators_.empty()) {
printer->Print(
" static const char *oneofs[] = {\n");
printer->Print(" static const char *oneofs[] = {\n");
for (const auto& generator : oneof_generators_) {
printer->Print(" \"$name$\",\n", "name",
generator->DescriptorName());
}
printer->Print(
// clang-format off
" };\n"
" [localDescriptor setupOneofs:oneofs\n"
" count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n"
" firstHasIndex:$first_has_index$];\n",
// clang-format on
"first_has_index", oneof_generators_[0]->HasIndexAsString());
}
if (text_format_decode_data.num_entries() != 0) {
const std::string text_format_data_str(text_format_decode_data.Data());
// clang-format off
printer->Print(
"#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
" static const char *extraTextFormatInfo =");
// clang-format on
static const int kBytesPerLine = 40; // allow for escaping
for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) {
printer->Print(
"\n \"$data$\"",
"data", EscapeTrigraphs(
absl::CEscape(text_format_data_str.substr(i, kBytesPerLine))));
printer->Print("\n \"$data$\"", "data",
EscapeTrigraphs(absl::CEscape(
text_format_data_str.substr(i, kBytesPerLine))));
}
// clang-format off
printer->Print(
";\n"
" [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n"
"#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n");
// clang-format on
}
if (!sorted_extensions.empty()) {
printer->Print(
" static const GPBExtensionRange ranges[] = {\n");
printer->Print(" static const GPBExtensionRange ranges[] = {\n");
for (int i = 0; i < sorted_extensions.size(); i++) {
printer->Print(" { .start = $start$, .end = $end$ },\n",
"start", absl::StrCat(sorted_extensions[i]->start),
"end", absl::StrCat(sorted_extensions[i]->end));
printer->Print(" { .start = $start$, .end = $end$ },\n", "start",
absl::StrCat(sorted_extensions[i]->start), "end",
absl::StrCat(sorted_extensions[i]->end));
}
// clang-format off
printer->Print(
" };\n"
" [localDescriptor setupExtensionRanges:ranges\n"
" count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
// clang-format on
}
if (descriptor_->containing_type() != NULL) {
std::string containing_class = ClassName(descriptor_->containing_type());
std::string parent_class_ref = ObjCClass(containing_class);
printer->Print(
// clang-format off
" [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n",
// clang-format on
"parent_class_ref", parent_class_ref);
}
std::string suffix_added;
@ -599,6 +614,7 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
" [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n",
"suffix", suffix_added);
}
// clang-format off
printer->Print(
" #if defined(DEBUG) && DEBUG\n"
" NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
@ -608,11 +624,14 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
" return descriptor;\n"
"}\n\n"
"@end\n\n");
// clang-format on
if (!deprecated_attribute_.empty()) {
// clang-format off
printer->Print(
"#pragma clang diagnostic pop\n"
"\n");
// clang-format on
}
for (int i = 0; i < descriptor_->field_count(); i++) {

@ -31,9 +31,10 @@
#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
#include <string>
#include <set>
#include <string>
#include <vector>
#include "google/protobuf/compiler/objectivec/field.h"
#include "google/protobuf/compiler/objectivec/oneof.h"
#include "google/protobuf/descriptor.h"

@ -28,12 +28,13 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "google/protobuf/compiler/objectivec/message_field.h"
#include <map>
#include <string>
#include "google/protobuf/compiler/objectivec/message_field.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/compiler/objectivec/helpers.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/io/printer.h"
namespace google {
@ -66,15 +67,14 @@ MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor)
MessageFieldGenerator::~MessageFieldGenerator() {}
void MessageFieldGenerator::DetermineForwardDeclarations(
std::set<std::string>* fwd_decls,
bool include_external_types) const {
ObjCObjFieldGenerator::DetermineForwardDeclarations(
fwd_decls, include_external_types);
std::set<std::string>* fwd_decls, bool include_external_types) const {
ObjCObjFieldGenerator::DetermineForwardDeclarations(fwd_decls,
include_external_types);
// Within a file there is no requirement on the order of the messages, so
// local references need a forward declaration. External files (not WKTs),
// need one when requested.
if ((include_external_types &&
!IsProtobufLibraryBundledProtoFile(descriptor_->message_type()->file())) ||
if ((include_external_types && !IsProtobufLibraryBundledProtoFile(
descriptor_->message_type()->file())) ||
descriptor_->file() == descriptor_->message_type()->file()) {
// Class name is already in "storage_type".
fwd_decls->insert("@class " + variable("storage_type"));
@ -98,15 +98,14 @@ RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
void RepeatedMessageFieldGenerator::DetermineForwardDeclarations(
std::set<std::string>* fwd_decls,
bool include_external_types) const {
RepeatedFieldGenerator::DetermineForwardDeclarations(
fwd_decls, include_external_types);
std::set<std::string>* fwd_decls, bool include_external_types) const {
RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls,
include_external_types);
// Within a file there is no requirement on the order of the messages, so
// local references need a forward declaration. External files (not WKTs),
// need one when requested.
if ((include_external_types &&
!IsProtobufLibraryBundledProtoFile(descriptor_->message_type()->file())) ||
if ((include_external_types && !IsProtobufLibraryBundledProtoFile(
descriptor_->message_type()->file())) ||
descriptor_->file() == descriptor_->message_type()->file()) {
// Class name is already in "storage_type".
fwd_decls->insert("@class " + variable("storage_type"));

@ -68,7 +68,8 @@ class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator {
virtual ~RepeatedMessageFieldGenerator();
RepeatedMessageFieldGenerator(const RepeatedMessageFieldGenerator&) = delete;
RepeatedMessageFieldGenerator operator=(const RepeatedMessageFieldGenerator&) = delete;
RepeatedMessageFieldGenerator operator=(
const RepeatedMessageFieldGenerator&) = delete;
public:
virtual void DetermineForwardDeclarations(

@ -82,9 +82,9 @@ int main(int argc, const char * argv[]) {
for (NSString *item in array) {
// Some items with _ in them get returned in quotes, so do not add more.
if ([item hasPrefix:@"\""]) {
printf("\t%s,\n", item.UTF8String);
printf(" %s,\n", item.UTF8String);
} else {
printf("\t\"%s\",\n", item.UTF8String);
printf(" \"%s\",\n", item.UTF8String);
}
}
}

@ -28,6 +28,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "google/protobuf/compiler/objectivec/names.h"
#include <climits>
#include <fstream>
#include <iostream>
@ -35,11 +37,10 @@
#include <unordered_set>
#include <vector>
#include "google/protobuf/compiler/code_generator.h"
#include "absl/strings/ascii.h"
#include "absl/strings/str_split.h"
#include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/compiler/objectivec/line_consumer.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/compiler/objectivec/nsobject_methods.h"
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/io/zero_copy_stream_impl.h"
@ -67,7 +68,8 @@ class SimpleLineCollector : public LineConsumer {
explicit SimpleLineCollector(std::unordered_set<std::string>* inout_set)
: set_(inout_set) {}
virtual bool ConsumeLine(const absl::string_view& line, std::string* out_error) override {
virtual bool ConsumeLine(const absl::string_view& line,
std::string* out_error) override {
set_->insert(std::string(line));
return true;
}
@ -78,11 +80,13 @@ class SimpleLineCollector : public LineConsumer {
class PackageToPrefixesCollector : public LineConsumer {
public:
PackageToPrefixesCollector(const std::string &usage,
std::map<std::string, std::string>* inout_package_to_prefix_map)
PackageToPrefixesCollector(
const std::string& usage,
std::map<std::string, std::string>* inout_package_to_prefix_map)
: usage_(usage), prefix_map_(inout_package_to_prefix_map) {}
virtual bool ConsumeLine(const absl::string_view& line, std::string* out_error) override;
virtual bool ConsumeLine(const absl::string_view& line,
std::string* out_error) override;
private:
const std::string usage_;
@ -93,7 +97,9 @@ class PrefixModeStorage {
public:
PrefixModeStorage();
std::string package_to_prefix_mappings_path() const { return package_to_prefix_mappings_path_; }
std::string package_to_prefix_mappings_path() const {
return package_to_prefix_mappings_path_;
}
void set_package_to_prefix_mappings_path(const std::string& path) {
package_to_prefix_mappings_path_ = path;
package_to_prefix_map_.clear();
@ -115,7 +121,9 @@ class PrefixModeStorage {
// When using a proto package as the prefix, this should be added as the
// prefix in front of it.
const std::string& forced_package_prefix() const { return forced_prefix_; }
void set_forced_package_prefix(const std::string& prefix) { forced_prefix_ = prefix; }
void set_forced_package_prefix(const std::string& prefix) {
forced_prefix_ = prefix;
}
private:
bool use_package_name_;
@ -132,7 +140,8 @@ PrefixModeStorage::PrefixModeStorage() {
use_package_name_ = BoolFromEnvVar("GPB_OBJC_USE_PACKAGE_AS_PREFIX", false);
const char* exception_path = getenv("GPB_OBJC_PACKAGE_PREFIX_EXCEPTIONS_PATH");
const char* exception_path =
getenv("GPB_OBJC_PACKAGE_PREFIX_EXCEPTIONS_PATH");
if (exception_path) {
exception_path_ = exception_path;
}
@ -143,21 +152,25 @@ PrefixModeStorage::PrefixModeStorage() {
}
}
std::string PrefixModeStorage::prefix_from_proto_package_mappings(const FileDescriptor* file) {
std::string PrefixModeStorage::prefix_from_proto_package_mappings(
const FileDescriptor* file) {
if (!file) {
return "";
}
if (package_to_prefix_map_.empty() && !package_to_prefix_mappings_path_.empty()) {
if (package_to_prefix_map_.empty() &&
!package_to_prefix_mappings_path_.empty()) {
std::string error_str;
// Re use the same collector as we use for expected_prefixes_path since the file
// format is the same.
PackageToPrefixesCollector collector("Package to prefixes", &package_to_prefix_map_);
if (!ParseSimpleFile(package_to_prefix_mappings_path_, &collector, &error_str)) {
// Re use the same collector as we use for expected_prefixes_path since the
// file format is the same.
PackageToPrefixesCollector collector("Package to prefixes",
&package_to_prefix_map_);
if (!ParseSimpleFile(package_to_prefix_mappings_path_, &collector,
&error_str)) {
if (error_str.empty()) {
error_str = std::string("protoc:0: warning: Failed to parse")
+ std::string(" prefix to proto package mappings file: ")
+ package_to_prefix_mappings_path_;
error_str = std::string("protoc:0: warning: Failed to parse") +
std::string(" prefix to proto package mappings file: ") +
package_to_prefix_mappings_path_;
}
std::cerr << error_str << std::endl;
std::cerr.flush();
@ -169,7 +182,8 @@ std::string PrefixModeStorage::prefix_from_proto_package_mappings(const FileDesc
// For files without packages, the can be registered as "no_package:PATH",
// allowing the expected prefixes file.
static const std::string no_package_prefix("no_package:");
const std::string lookup_key = package.empty() ? no_package_prefix + file->name() : package;
const std::string lookup_key =
package.empty() ? no_package_prefix + file->name() : package;
std::map<std::string, std::string>::const_iterator prefix_lookup =
package_to_prefix_map_.find(lookup_key);
@ -187,9 +201,9 @@ bool PrefixModeStorage::is_package_exempted(const std::string& package) {
SimpleLineCollector collector(&exceptions_);
if (!ParseSimpleFile(exception_path_, &collector, &error_str)) {
if (error_str.empty()) {
error_str = std::string("protoc:0: warning: Failed to parse")
+ std::string(" package prefix exceptions file: ")
+ exception_path_;
error_str = std::string("protoc:0: warning: Failed to parse") +
std::string(" package prefix exceptions file: ") +
exception_path_;
}
std::cerr << error_str << std::endl;
std::cerr.flush();
@ -320,8 +334,7 @@ std::string UnderscoresToCamelCase(const std::string& input,
}
result += value;
}
if ((result.length() != 0) &&
!first_capitalized &&
if ((result.length() != 0) && !first_capitalized &&
!first_segment_forces_upper) {
result[0] = absl::ascii_tolower(result[0]);
}
@ -329,72 +342,193 @@ std::string UnderscoresToCamelCase(const std::string& input,
}
const char* const kReservedWordList[] = {
// Note NSObject Methods:
// These are brought in from nsobject_methods.h that is generated
// using method_dump.sh. See kNSObjectMethods below.
// Objective C "keywords" that aren't in C
// From
// http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c
// with some others added on.
"id", "_cmd", "super", "in", "out", "inout", "bycopy", "byref", "oneway",
"self", "instancetype", "nullable", "nonnull", "nil", "Nil",
"YES", "NO", "weak",
// C/C++ keywords (Incl C++ 0x11)
// From http://en.cppreference.com/w/cpp/keywords
"and", "and_eq", "alignas", "alignof", "asm", "auto", "bitand", "bitor",
"bool", "break", "case", "catch", "char", "char16_t", "char32_t", "class",
"compl", "const", "constexpr", "const_cast", "continue", "decltype",
"default", "delete", "double", "dynamic_cast", "else", "enum", "explicit",
"export", "extern ", "false", "float", "for", "friend", "goto", "if",
"inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not",
"not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected",
"public", "register", "reinterpret_cast", "return", "short", "signed",
"sizeof", "static", "static_assert", "static_cast", "struct", "switch",
"template", "this", "thread_local", "throw", "true", "try", "typedef",
"typeid", "typename", "union", "unsigned", "using", "virtual", "void",
"volatile", "wchar_t", "while", "xor", "xor_eq",
// C99 keywords
// From
// http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyw.htm
"restrict",
// GCC/Clang extension
"typeof",
// Not a keyword, but will break you
"NULL",
// C88+ specs call for these to be macros, so depending on what they are
// defined to be it can lead to odd errors for some Xcode/SDK versions.
"stdin", "stdout", "stderr",
// Objective-C Runtime typedefs
// From <obc/runtime.h>
"Category", "Ivar", "Method", "Protocol",
// GPBMessage Methods
// Only need to add instance methods that may conflict with
// method declared in protos. The main cases are methods
// that take no arguments, or setFoo:/hasFoo: type methods.
"clear", "data", "delimitedData", "descriptor", "extensionRegistry",
"extensionsCurrentlySet", "initialized", "isInitialized", "serializedSize",
"sortedExtensionsInUse", "unknownFields",
// MacTypes.h names
"Fixed", "Fract", "Size", "LogicalAddress", "PhysicalAddress", "ByteCount",
"ByteOffset", "Duration", "AbsoluteTime", "OptionBits", "ItemCount",
"PBVersion", "ScriptCode", "LangCode", "RegionCode", "OSType",
"ProcessSerialNumber", "Point", "Rect", "FixedPoint", "FixedRect", "Style",
"StyleParameter", "StyleField", "TimeScale", "TimeBase", "TimeRecord",
// Note NSObject Methods:
// These are brought in from nsobject_methods.h that is generated
// using method_dump.sh. See kNSObjectMethods below.
// Objective C "keywords" that aren't in C
// From
// http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c
// with some others added on.
"id",
"_cmd",
"super",
"in",
"out",
"inout",
"bycopy",
"byref",
"oneway",
"self",
"instancetype",
"nullable",
"nonnull",
"nil",
"Nil",
"YES",
"NO",
"weak",
// C/C++ keywords (Incl C++ 0x11)
// From http://en.cppreference.com/w/cpp/keywords
"and",
"and_eq",
"alignas",
"alignof",
"asm",
"auto",
"bitand",
"bitor",
"bool",
"break",
"case",
"catch",
"char",
"char16_t",
"char32_t",
"class",
"compl",
"const",
"constexpr",
"const_cast",
"continue",
"decltype",
"default",
"delete",
"double",
"dynamic_cast",
"else",
"enum",
"explicit",
"export",
"extern ",
"false",
"float",
"for",
"friend",
"goto",
"if",
"inline",
"int",
"long",
"mutable",
"namespace",
"new",
"noexcept",
"not",
"not_eq",
"nullptr",
"operator",
"or",
"or_eq",
"private",
"protected",
"public",
"register",
"reinterpret_cast",
"return",
"short",
"signed",
"sizeof",
"static",
"static_assert",
"static_cast",
"struct",
"switch",
"template",
"this",
"thread_local",
"throw",
"true",
"try",
"typedef",
"typeid",
"typename",
"union",
"unsigned",
"using",
"virtual",
"void",
"volatile",
"wchar_t",
"while",
"xor",
"xor_eq",
// C99 keywords
// From
// http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyw.htm
"restrict",
// GCC/Clang extension
"typeof",
// Not a keyword, but will break you
"NULL",
// C88+ specs call for these to be macros, so depending on what they are
// defined to be it can lead to odd errors for some Xcode/SDK versions.
"stdin",
"stdout",
"stderr",
// Objective-C Runtime typedefs
// From <obc/runtime.h>
"Category",
"Ivar",
"Method",
"Protocol",
// GPBMessage Methods
// Only need to add instance methods that may conflict with
// method declared in protos. The main cases are methods
// that take no arguments, or setFoo:/hasFoo: type methods.
"clear",
"data",
"delimitedData",
"descriptor",
"extensionRegistry",
"extensionsCurrentlySet",
"initialized",
"isInitialized",
"serializedSize",
"sortedExtensionsInUse",
"unknownFields",
// MacTypes.h names
"Fixed",
"Fract",
"Size",
"LogicalAddress",
"PhysicalAddress",
"ByteCount",
"ByteOffset",
"Duration",
"AbsoluteTime",
"OptionBits",
"ItemCount",
"PBVersion",
"ScriptCode",
"LangCode",
"RegionCode",
"OSType",
"ProcessSerialNumber",
"Point",
"Rect",
"FixedPoint",
"FixedRect",
"Style",
"StyleParameter",
"StyleField",
"TimeScale",
"TimeBase",
"TimeRecord",
};
// returns true is input starts with __ or _[A-Z] which are reserved identifiers
// in C/ C++. All calls should go through UnderscoresToCamelCase before getting here
// but this verifies and allows for future expansion if we decide to redefine what a
// reserved C identifier is (for example the GNU list
// in C/ C++. All calls should go through UnderscoresToCamelCase before getting
// here but this verifies and allows for future expansion if we decide to
// redefine what a reserved C identifier is (for example the GNU list
// https://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html )
bool IsReservedCIdentifier(const std::string& input) {
if (input.length() > 2) {
@ -422,7 +556,8 @@ std::string SanitizeNameForObjC(const std::string& prefix,
// b) Isn't equivalent to the prefix or
// c) Has the prefix, but the letter after the prefix is lowercase
if (absl::StartsWith(input, prefix)) {
if (input.length() == prefix.length() || !absl::ascii_isupper(input[prefix.length()])) {
if (input.length() == prefix.length() ||
!absl::ascii_isupper(input[prefix.length()])) {
sanitized = prefix + input;
} else {
sanitized = input;
@ -469,8 +604,7 @@ void PathSplit(const std::string& path, std::string* directory,
}
bool IsSpecialNamePrefix(const std::string& name,
const std::string* special_names,
size_t count) {
const std::string* special_names, size_t count) {
for (size_t i = 0; i < count; ++i) {
const size_t length = special_names[i].length();
if (name.compare(0, length, special_names[i]) == 0) {
@ -503,8 +637,8 @@ bool IsRetainedName(const std::string& name) {
// http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
static const std::string retained_names[] = {"new", "alloc", "copy",
"mutableCopy"};
return IsSpecialNamePrefix(name, retained_names,
sizeof(retained_names) / sizeof(retained_names[0]));
return IsSpecialNamePrefix(
name, retained_names, sizeof(retained_names) / sizeof(retained_names[0]));
}
bool IsInitName(const std::string& name) {
@ -557,8 +691,10 @@ std::string FileClassPrefix(const FileDescriptor* file) {
return file->options().objc_class_prefix();
}
// If package prefix is specified in an prefix to proto mappings file then use that.
std::string objc_class_prefix = g_prefix_mode.prefix_from_proto_package_mappings(file);
// If package prefix is specified in an prefix to proto mappings file then use
// that.
std::string objc_class_prefix =
g_prefix_mode.prefix_from_proto_package_mappings(file);
if (!objc_class_prefix.empty()) {
return objc_class_prefix;
}
@ -577,7 +713,8 @@ std::string FileClassPrefix(const FileDescriptor* file) {
// camelcase each one and then join them with underscores, and add an
// underscore at the end.
std::string result;
const std::vector<std::string> segments = absl::StrSplit(file->package(), ".", absl::SkipEmpty());
const std::vector<std::string> segments =
absl::StrSplit(file->package(), ".", absl::SkipEmpty());
for (const auto& segment : segments) {
const std::string part = UnderscoresToCamelCase(segment, true);
if (part.empty()) {
@ -780,7 +917,8 @@ std::string OneofNameCapitalized(const OneofDescriptor* descriptor) {
return result;
}
std::string UnCamelCaseFieldName(const std::string& name, const FieldDescriptor* field) {
std::string UnCamelCaseFieldName(const std::string& name,
const FieldDescriptor* field) {
absl::string_view worker(name);
if (absl::EndsWith(worker, "_p")) {
worker = absl::StripSuffix(worker, "_p");
@ -850,15 +988,18 @@ bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file) {
namespace {
bool PackageToPrefixesCollector::ConsumeLine(
const absl::string_view& line, std::string* out_error) {
bool PackageToPrefixesCollector::ConsumeLine(const absl::string_view& line,
std::string* out_error) {
int offset = line.find('=');
if (offset == absl::string_view::npos) {
*out_error = usage_ + " file line without equal sign: '" + absl::StrCat(line) + "'.";
*out_error =
usage_ + " file line without equal sign: '" + absl::StrCat(line) + "'.";
return false;
}
absl::string_view package = absl::StripAsciiWhitespace(line.substr(0, offset));
absl::string_view prefix = absl::StripAsciiWhitespace(line.substr(offset + 1));
absl::string_view package =
absl::StripAsciiWhitespace(line.substr(0, offset));
absl::string_view prefix =
absl::StripAsciiWhitespace(line.substr(offset + 1));
MaybeUnQuote(&prefix);
// Don't really worry about error checking the package/prefix for
// being valid. Assume the file is validated when it is created/edited.
@ -874,8 +1015,7 @@ bool LoadExpectedPackagePrefixes(const std::string& expected_prefixes_path,
}
PackageToPrefixesCollector collector("Expected prefixes", prefix_map);
return ParseSimpleFile(
expected_prefixes_path, &collector, out_error);
return ParseSimpleFile(expected_prefixes_path, &collector, out_error);
}
bool ValidateObjCClassPrefix(
@ -929,9 +1069,9 @@ bool ValidateObjCClassPrefix(
// If there was no prefix option, we're done at this point.
if (!has_prefix) {
if (require_prefixes) {
*out_error =
"error: '" + file->name() + "' does not have a required 'option" +
" objc_class_prefix'.";
*out_error = "error: '" + file->name() +
"' does not have a required 'option" +
" objc_class_prefix'.";
return false;
}
return true;
@ -958,9 +1098,9 @@ bool ValidateObjCClassPrefix(
// package (overlap is allowed, but it has to be listed as an expected
// overlap).
if (!other_package_for_prefix.empty()) {
*out_error =
"error: Found 'option objc_class_prefix = \"" + prefix +
"\";' in '" + file->name() + "'; that prefix is already used for ";
*out_error = "error: Found 'option objc_class_prefix = \"" + prefix +
"\";' in '" + file->name() +
"'; that prefix is already used for ";
if (absl::StartsWith(other_package_for_prefix, no_package_prefix)) {
absl::StrAppend(
out_error, "file '",
@ -976,26 +1116,24 @@ bool ValidateObjCClassPrefix(
expected_prefixes_path, ").");
return false; // Only report first usage of the prefix.
}
} // !prefix.empty() && have_expected_prefix_file
} // !prefix.empty() && have_expected_prefix_file
// Check: Warning - Make sure the prefix is is a reasonable value according
// to Apple's rules (the checks above implicitly whitelist anything that
// doesn't meet these rules).
if (!prefix.empty() && !absl::ascii_isupper(prefix[0])) {
std::cerr
<< "protoc:0: warning: Invalid 'option objc_class_prefix = \""
<< prefix << "\";' in '" << file->name() << "';"
<< " it should start with a capital letter." << std::endl;
std::cerr << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
<< prefix << "\";' in '" << file->name() << "';"
<< " it should start with a capital letter." << std::endl;
std::cerr.flush();
}
if (!prefix.empty() && prefix.length() < 3) {
// Apple reserves 2 character prefixes for themselves. They do use some
// 3 character prefixes, but they haven't updated the rules/docs.
std::cerr
<< "protoc:0: warning: Invalid 'option objc_class_prefix = \""
<< prefix << "\";' in '" << file->name() << "';"
<< " Apple recommends they should be at least 3 characters long."
<< std::endl;
std::cerr << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
<< prefix << "\";' in '" << file->name() << "';"
<< " Apple recommends they should be at least 3 characters long."
<< std::endl;
std::cerr.flush();
}
@ -1004,19 +1142,19 @@ bool ValidateObjCClassPrefix(
if (have_expected_prefix_file) {
if (prefixes_must_be_registered) {
*out_error =
"error: '" + file->name() + "' has 'option objc_class_prefix = \"" +
prefix + "\";', but it is not registered. Add '" + lookup_key + " = " +
(prefix.empty() ? "\"\"" : prefix) +
"' to the expected prefixes file (" + expected_prefixes_path + ").";
"error: '" + file->name() + "' has 'option objc_class_prefix = \"" +
prefix + "\";', but it is not registered. Add '" + lookup_key +
" = " + (prefix.empty() ? "\"\"" : prefix) +
"' to the expected prefixes file (" + expected_prefixes_path + ").";
return false;
}
std::cerr
<< "protoc:0: warning: Found unexpected 'option objc_class_prefix = \""
<< prefix << "\";' in '" << file->name() << "'; consider adding '"
<< lookup_key << " = " << (prefix.empty() ? "\"\"" : prefix)
<< "' to the expected prefixes file (" << expected_prefixes_path
<< ")." << std::endl;
<< "protoc:0: warning: Found unexpected 'option objc_class_prefix = \""
<< prefix << "\";' in '" << file->name() << "'; consider adding '"
<< lookup_key << " = " << (prefix.empty() ? "\"\"" : prefix)
<< "' to the expected prefixes file (" << expected_prefixes_path << ")."
<< std::endl;
std::cerr.flush();
}
@ -1033,7 +1171,8 @@ Options::Options() {
if (file_path) {
expected_prefixes_path = file_path;
}
const char* suppressions = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES_SUPPRESSIONS");
const char* suppressions =
getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES_SUPPRESSIONS");
if (suppressions) {
expected_prefixes_suppressions =
absl::StrSplit(suppressions, ";", absl::SkipEmpty());
@ -1045,9 +1184,9 @@ Options::Options() {
bool ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files,
std::string* out_error) {
// Options's ctor load from the environment.
Options options;
return ValidateObjCClassPrefixes(files, options, out_error);
// Options's ctor load from the environment.
Options options;
return ValidateObjCClassPrefixes(files, options, out_error);
}
bool ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files,
@ -1062,28 +1201,25 @@ bool ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files,
// Load the expected package prefixes, if available, to validate against.
std::map<std::string, std::string> expected_package_prefixes;
if (!LoadExpectedPackagePrefixes(generation_options.expected_prefixes_path,
&expected_package_prefixes,
out_error)) {
&expected_package_prefixes, out_error)) {
return false;
}
for (int i = 0; i < files.size(); i++) {
bool should_skip =
(std::find(generation_options.expected_prefixes_suppressions.begin(),
generation_options.expected_prefixes_suppressions.end(),
files[i]->name())
!= generation_options.expected_prefixes_suppressions.end());
(std::find(generation_options.expected_prefixes_suppressions.begin(),
generation_options.expected_prefixes_suppressions.end(),
files[i]->name()) !=
generation_options.expected_prefixes_suppressions.end());
if (should_skip) {
continue;
}
bool is_valid =
ValidateObjCClassPrefix(files[i],
generation_options.expected_prefixes_path,
expected_package_prefixes,
generation_options.prefixes_must_be_registered,
generation_options.require_prefixes,
out_error);
bool is_valid = ValidateObjCClassPrefix(
files[i], generation_options.expected_prefixes_path,
expected_package_prefixes,
generation_options.prefixes_must_be_registered,
generation_options.require_prefixes, out_error);
if (!is_valid) {
return false;
}

@ -49,8 +49,7 @@ namespace objectivec {
// Get/Set the path to a file to load for objc class prefix lookups.
std::string PROTOC_EXPORT GetPackageToPrefixMappingsPath();
void PROTOC_EXPORT SetPackageToPrefixMappingsPath(
const std::string& file_path);
void PROTOC_EXPORT SetPackageToPrefixMappingsPath(const std::string& file_path);
// Get/Set if the proto package should be used to make the default prefix for
// symbols. This will then impact most of the type naming apis below. It is done
// as a global to not break any other generator reusing the methods since they
@ -61,8 +60,8 @@ void PROTOC_EXPORT SetUseProtoPackageAsDefaultPrefix(bool on_or_off);
// `UseProtoPackageAsDefaultPrefix()` is `true`. An empty string means there
// should be no exceptions.
std::string PROTOC_EXPORT GetProtoPackagePrefixExceptionList();
void PROTOC_EXPORT SetProtoPackagePrefixExceptionList(
const std::string& file_path);
void PROTOC_EXPORT
SetProtoPackagePrefixExceptionList(const std::string& file_path);
// Get/Set a prefix to add before the prefix generated from the package name.
// This is only used when UseProtoPackageAsDefaultPrefix() is True.
std::string PROTOC_EXPORT GetForcedPackagePrefix();
@ -108,14 +107,16 @@ std::string PROTOC_EXPORT EnumName(const EnumDescriptor* descriptor);
std::string PROTOC_EXPORT EnumValueName(const EnumValueDescriptor* descriptor);
// Returns the name of the enum value corresponding to the descriptor.
std::string PROTOC_EXPORT EnumValueShortName(const EnumValueDescriptor* descriptor);
std::string PROTOC_EXPORT
EnumValueShortName(const EnumValueDescriptor* descriptor);
// Reverse what an enum does.
std::string PROTOC_EXPORT UnCamelCaseEnumShortName(const std::string& name);
// Returns the name to use for the extension (used as the method off the file's
// Root class).
std::string PROTOC_EXPORT ExtensionMethodName(const FieldDescriptor* descriptor);
std::string PROTOC_EXPORT
ExtensionMethodName(const FieldDescriptor* descriptor);
// Returns the transformed field name.
std::string PROTOC_EXPORT FieldName(const FieldDescriptor* field);
@ -124,7 +125,8 @@ std::string PROTOC_EXPORT FieldNameCapitalized(const FieldDescriptor* field);
// Returns the transformed oneof name.
std::string PROTOC_EXPORT OneofEnumName(const OneofDescriptor* descriptor);
std::string PROTOC_EXPORT OneofName(const OneofDescriptor* descriptor);
std::string PROTOC_EXPORT OneofNameCapitalized(const OneofDescriptor* descriptor);
std::string PROTOC_EXPORT
OneofNameCapitalized(const OneofDescriptor* descriptor);
// Reverse of the above.
std::string PROTOC_EXPORT UnCamelCaseFieldName(const std::string& name,

@ -29,10 +29,11 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
#include <gtest/gtest.h>
#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
namespace google {
namespace protobuf {
namespace compiler {

@ -35,193 +35,193 @@
// iOS: iPhoneSimulator12.1.sdk
const char* const kNSObjectMethodsList[] = {
"CAMLType",
"CA_copyRenderValue",
"CA_prepareRenderValue",
"NS_copyCGImage",
"NS_tiledLayerVisibleRect",
"___tryRetain_OA",
"__autorelease_OA",
"__dealloc_zombie",
"__release_OA",
"__retain_OA",
"_accessibilityFinalize",
"_accessibilityIsTableViewDescendant",
"_accessibilityUIElementSpecifier",
"_accessibilityUseConvenienceAPI",
"_allowsDirectEncoding",
"_asScriptTerminologyNameArray",
"_asScriptTerminologyNameString",
"_bindingAdaptor",
"_cfTypeID",
"_copyDescription",
"_destroyObserverList",
"_didEndKeyValueObserving",
"_implicitObservationInfo",
"_internalAccessibilityAttributedHint",
"_internalAccessibilityAttributedLabel",
"_internalAccessibilityAttributedValue",
"_isAXConnector",
"_isAccessibilityContainerSectionCandidate",
"_isAccessibilityContentNavigatorSectionCandidate",
"_isAccessibilityContentSectionCandidate",
"_isAccessibilityTopLevelNavigatorSectionCandidate",
"_isDeallocating",
"_isKVOA",
"_isToManyChangeInformation",
"_ivarDescription",
"_localClassNameForClass",
"_methodDescription",
"_observerStorage",
"_overrideUseFastBlockObservers",
"_propertyDescription",
"_releaseBindingAdaptor",
"_scriptingCount",
"_scriptingCountNonrecursively",
"_scriptingDebugDescription",
"_scriptingExists",
"_scriptingShouldCheckObjectIndexes",
"_shortMethodDescription",
"_shouldSearchChildrenForSection",
"_traitStorageList",
"_tryRetain",
"_ui_descriptionBuilder",
"_uikit_variesByTraitCollections",
"_web_description",
"_webkit_invokeOnMainThread",
"_willBeginKeyValueObserving",
"accessibilityActivate",
"accessibilityActivationPoint",
"accessibilityAllowsOverriddenAttributesWhenIgnored",
"accessibilityAssistiveTechnologyFocusedIdentifiers",
"accessibilityAttributedHint",
"accessibilityAttributedLabel",
"accessibilityAttributedValue",
"accessibilityContainer",
"accessibilityContainerType",
"accessibilityCustomActions",
"accessibilityCustomRotors",
"accessibilityDecrement",
"accessibilityDragSourceDescriptors",
"accessibilityDropPointDescriptors",
"accessibilityElementCount",
"accessibilityElementDidBecomeFocused",
"accessibilityElementDidLoseFocus",
"accessibilityElementIsFocused",
"accessibilityElements",
"accessibilityElementsHidden",
"accessibilityFrame",
"accessibilityHeaderElements",
"accessibilityHint",
"accessibilityIdentification",
"accessibilityIdentifier",
"accessibilityIncrement",
"accessibilityLabel",
"accessibilityLanguage",
"accessibilityLocalizedStringKey",
"accessibilityNavigationStyle",
"accessibilityOverriddenAttributes",
"accessibilityParameterizedAttributeNames",
"accessibilityPath",
"accessibilityPerformEscape",
"accessibilityPerformMagicTap",
"accessibilityPresenterProcessIdentifier",
"accessibilityShouldUseUniqueId",
"accessibilitySupportsNotifications",
"accessibilitySupportsOverriddenAttributes",
"accessibilityTemporaryChildren",
"accessibilityTraits",
"accessibilityValue",
"accessibilityViewIsModal",
"accessibilityVisibleArea",
"allPropertyKeys",
"allowsWeakReference",
"attributeKeys",
"autoContentAccessingProxy",
"autorelease",
"awakeFromNib",
"boolValueSafe",
"bs_encoded",
"bs_isPlistableType",
"bs_secureEncoded",
"cl_json_serializeKey",
"class",
"classCode",
"classDescription",
"classForArchiver",
"classForCoder",
"classForKeyedArchiver",
"classForPortCoder",
"className",
"clearProperties",
"copy",
"dealloc",
"debugDescription",
"defaultAccessibilityTraits",
"description",
"doubleValueSafe",
"entityName",
"exposedBindings",
"finalize",
"finishObserving",
"flushKeyBindings",
"hash",
"init",
"int64ValueSafe",
"isAccessibilityElement",
"isAccessibilityElementByDefault",
"isElementAccessibilityExposedToInterfaceBuilder",
"isFault",
"isNSArray__",
"isNSCFConstantString__",
"isNSData__",
"isNSDate__",
"isNSDictionary__",
"isNSNumber__",
"isNSObject__",
"isNSOrderedSet__",
"isNSSet__",
"isNSString__",
"isNSTimeZone__",
"isNSValue__",
"isProxy",
"mutableCopy",
"nilValueForKey",
"objectSpecifier",
"observationInfo",
"pep_onDetachedThread",
"pep_onMainThread",
"pep_onMainThreadIfNecessary",
"prepareForInterfaceBuilder",
"release",
"releaseOnMainThread",
"retain",
"retainCount",
"retainWeakReference",
"scriptingProperties",
"self",
"shouldGroupAccessibilityChildren",
"storedAccessibilityActivationPoint",
"storedAccessibilityContainerType",
"storedAccessibilityElementsHidden",
"storedAccessibilityFrame",
"storedAccessibilityNavigationStyle",
"storedAccessibilityTraits",
"storedAccessibilityViewIsModal",
"storedIsAccessibilityElement",
"storedShouldGroupAccessibilityChildren",
"stringValueSafe",
"superclass",
"toManyRelationshipKeys",
"toOneRelationshipKeys",
"traitStorageList",
"un_safeBoolValue",
"userInterfaceItemIdentifier",
"utf8ValueSafe",
"valuesForKeysWithDictionary",
"zone",
// Protocol: CAAnimatableValue
// Protocol: CARenderValue
// Protocol: NSObject
// Protocol: ROCKRemoteInvocationInterface
"CAMLType",
"CA_copyRenderValue",
"CA_prepareRenderValue",
"NS_copyCGImage",
"NS_tiledLayerVisibleRect",
"___tryRetain_OA",
"__autorelease_OA",
"__dealloc_zombie",
"__release_OA",
"__retain_OA",
"_accessibilityFinalize",
"_accessibilityIsTableViewDescendant",
"_accessibilityUIElementSpecifier",
"_accessibilityUseConvenienceAPI",
"_allowsDirectEncoding",
"_asScriptTerminologyNameArray",
"_asScriptTerminologyNameString",
"_bindingAdaptor",
"_cfTypeID",
"_copyDescription",
"_destroyObserverList",
"_didEndKeyValueObserving",
"_implicitObservationInfo",
"_internalAccessibilityAttributedHint",
"_internalAccessibilityAttributedLabel",
"_internalAccessibilityAttributedValue",
"_isAXConnector",
"_isAccessibilityContainerSectionCandidate",
"_isAccessibilityContentNavigatorSectionCandidate",
"_isAccessibilityContentSectionCandidate",
"_isAccessibilityTopLevelNavigatorSectionCandidate",
"_isDeallocating",
"_isKVOA",
"_isToManyChangeInformation",
"_ivarDescription",
"_localClassNameForClass",
"_methodDescription",
"_observerStorage",
"_overrideUseFastBlockObservers",
"_propertyDescription",
"_releaseBindingAdaptor",
"_scriptingCount",
"_scriptingCountNonrecursively",
"_scriptingDebugDescription",
"_scriptingExists",
"_scriptingShouldCheckObjectIndexes",
"_shortMethodDescription",
"_shouldSearchChildrenForSection",
"_traitStorageList",
"_tryRetain",
"_ui_descriptionBuilder",
"_uikit_variesByTraitCollections",
"_web_description",
"_webkit_invokeOnMainThread",
"_willBeginKeyValueObserving",
"accessibilityActivate",
"accessibilityActivationPoint",
"accessibilityAllowsOverriddenAttributesWhenIgnored",
"accessibilityAssistiveTechnologyFocusedIdentifiers",
"accessibilityAttributedHint",
"accessibilityAttributedLabel",
"accessibilityAttributedValue",
"accessibilityContainer",
"accessibilityContainerType",
"accessibilityCustomActions",
"accessibilityCustomRotors",
"accessibilityDecrement",
"accessibilityDragSourceDescriptors",
"accessibilityDropPointDescriptors",
"accessibilityElementCount",
"accessibilityElementDidBecomeFocused",
"accessibilityElementDidLoseFocus",
"accessibilityElementIsFocused",
"accessibilityElements",
"accessibilityElementsHidden",
"accessibilityFrame",
"accessibilityHeaderElements",
"accessibilityHint",
"accessibilityIdentification",
"accessibilityIdentifier",
"accessibilityIncrement",
"accessibilityLabel",
"accessibilityLanguage",
"accessibilityLocalizedStringKey",
"accessibilityNavigationStyle",
"accessibilityOverriddenAttributes",
"accessibilityParameterizedAttributeNames",
"accessibilityPath",
"accessibilityPerformEscape",
"accessibilityPerformMagicTap",
"accessibilityPresenterProcessIdentifier",
"accessibilityShouldUseUniqueId",
"accessibilitySupportsNotifications",
"accessibilitySupportsOverriddenAttributes",
"accessibilityTemporaryChildren",
"accessibilityTraits",
"accessibilityValue",
"accessibilityViewIsModal",
"accessibilityVisibleArea",
"allPropertyKeys",
"allowsWeakReference",
"attributeKeys",
"autoContentAccessingProxy",
"autorelease",
"awakeFromNib",
"boolValueSafe",
"bs_encoded",
"bs_isPlistableType",
"bs_secureEncoded",
"cl_json_serializeKey",
"class",
"classCode",
"classDescription",
"classForArchiver",
"classForCoder",
"classForKeyedArchiver",
"classForPortCoder",
"className",
"clearProperties",
"copy",
"dealloc",
"debugDescription",
"defaultAccessibilityTraits",
"description",
"doubleValueSafe",
"entityName",
"exposedBindings",
"finalize",
"finishObserving",
"flushKeyBindings",
"hash",
"init",
"int64ValueSafe",
"isAccessibilityElement",
"isAccessibilityElementByDefault",
"isElementAccessibilityExposedToInterfaceBuilder",
"isFault",
"isNSArray__",
"isNSCFConstantString__",
"isNSData__",
"isNSDate__",
"isNSDictionary__",
"isNSNumber__",
"isNSObject__",
"isNSOrderedSet__",
"isNSSet__",
"isNSString__",
"isNSTimeZone__",
"isNSValue__",
"isProxy",
"mutableCopy",
"nilValueForKey",
"objectSpecifier",
"observationInfo",
"pep_onDetachedThread",
"pep_onMainThread",
"pep_onMainThreadIfNecessary",
"prepareForInterfaceBuilder",
"release",
"releaseOnMainThread",
"retain",
"retainCount",
"retainWeakReference",
"scriptingProperties",
"self",
"shouldGroupAccessibilityChildren",
"storedAccessibilityActivationPoint",
"storedAccessibilityContainerType",
"storedAccessibilityElementsHidden",
"storedAccessibilityFrame",
"storedAccessibilityNavigationStyle",
"storedAccessibilityTraits",
"storedAccessibilityViewIsModal",
"storedIsAccessibilityElement",
"storedShouldGroupAccessibilityChildren",
"stringValueSafe",
"superclass",
"toManyRelationshipKeys",
"toOneRelationshipKeys",
"traitStorageList",
"un_safeBoolValue",
"userInterfaceItemIdentifier",
"utf8ValueSafe",
"valuesForKeysWithDictionary",
"zone",
// Protocol: CAAnimatableValue
// Protocol: CARenderValue
// Protocol: NSObject
// Protocol: ROCKRemoteInvocationInterface
};

@ -34,8 +34,8 @@
#include <string>
#include "absl/strings/str_cat.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/compiler/objectivec/helpers.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/io/printer.h"
namespace google {
@ -71,54 +71,53 @@ void OneofGenerator::SetOneofIndexBase(int index_base) {
}
void OneofGenerator::GenerateCaseEnum(io::Printer* printer) {
printer->Print(
variables_,
"typedef GPB_ENUM($enum_name$) {\n");
printer->Print(variables_, "typedef GPB_ENUM($enum_name$) {\n");
printer->Indent();
printer->Print(
variables_,
"$enum_name$_GPBUnsetOneOfCase = 0,\n");
printer->Print(variables_, "$enum_name$_GPBUnsetOneOfCase = 0,\n");
std::string enum_name = variables_["enum_name"];
for (int j = 0; j < descriptor_->field_count(); j++) {
const FieldDescriptor* field = descriptor_->field(j);
std::string field_name = FieldNameCapitalized(field);
printer->Print(
"$enum_name$_$field_name$ = $field_number$,\n",
"enum_name", enum_name,
"field_name", field_name,
"field_number", absl::StrCat(field->number()));
printer->Print("$enum_name$_$field_name$ = $field_number$,\n", "enum_name",
enum_name, "field_name", field_name, "field_number",
absl::StrCat(field->number()));
}
printer->Outdent();
// clang-format off
printer->Print(
"};\n"
"\n");
// clang-format on
}
void OneofGenerator::GeneratePublicCasePropertyDeclaration(
io::Printer* printer) {
// clang-format off
printer->Print(
variables_,
"$comments$"
"@property(nonatomic, readonly) $enum_name$ $name$OneOfCase;\n"
"\n");
// clang-format on
}
void OneofGenerator::GenerateClearFunctionDeclaration(io::Printer* printer) {
// clang-format off
printer->Print(
variables_,
"/**\n"
" * Clears whatever value was set for the oneof '$name$'.\n"
" **/\n"
"void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message);\n");
// clang-format on
}
void OneofGenerator::GeneratePropertyImplementation(io::Printer* printer) {
printer->Print(
variables_,
"@dynamic $name$OneOfCase;\n");
printer->Print(variables_, "@dynamic $name$OneOfCase;\n");
}
void OneofGenerator::GenerateClearFunctionImplementation(io::Printer* printer) {
// clang-format off
printer->Print(
variables_,
"void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message) {\n"
@ -126,6 +125,7 @@ void OneofGenerator::GenerateClearFunctionImplementation(io::Printer* printer) {
" GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:$raw_index$];\n"
" GPBClearOneof(message, oneof);\n"
"}\n");
// clang-format on
}
std::string OneofGenerator::DescriptorName(void) const {

@ -34,8 +34,8 @@
#include <string>
#include "absl/strings/str_cat.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/compiler/objectivec/helpers.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/io/printer.h"
namespace google {

@ -48,7 +48,8 @@ class PrimitiveFieldGenerator : public SingleFieldGenerator {
PrimitiveFieldGenerator(const PrimitiveFieldGenerator&) = delete;
PrimitiveFieldGenerator& operator=(const PrimitiveFieldGenerator&) = delete;
virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
virtual void GenerateFieldStorageDeclaration(
io::Printer* printer) const override;
virtual int ExtraRuntimeHasBitsNeeded(void) const override;
virtual void SetExtraRuntimeHasBitsBase(int index_base) override;

@ -28,16 +28,18 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/compiler/objectivec/text_format_decode_data.h"
#include "absl/strings/ascii.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_split.h"
#include "absl/strings/str_replace.h"
#include "google/protobuf/compiler/objectivec/text_format_decode_data.h"
#include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/io/printer.h"
#include "google/protobuf/io/zero_copy_stream_impl.h"
#include "google/protobuf/stubs/strutil.h"
// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
// error cases, so it seems to be ok to use as a back door for errors.
@ -166,9 +168,9 @@ std::string DirectDecodeString(const std::string& str) {
} // namespace
TextFormatDecodeData::TextFormatDecodeData() { }
TextFormatDecodeData::TextFormatDecodeData() {}
TextFormatDecodeData::~TextFormatDecodeData() { }
TextFormatDecodeData::~TextFormatDecodeData() {}
void TextFormatDecodeData::AddString(int32_t key,
const std::string& input_for_decode,
@ -177,8 +179,8 @@ void TextFormatDecodeData::AddString(int32_t key,
i != entries_.end(); ++i) {
if (i->first == key) {
std::cerr << "error: duplicate key (" << key
<< ") making TextFormat data, input: \"" << input_for_decode
<< "\", desired: \"" << desired_output << "\"." << std::endl;
<< ") making TextFormat data, input: \"" << input_for_decode
<< "\", desired: \"" << desired_output << "\"." << std::endl;
std::cerr.flush();
abort();
}
@ -213,16 +215,17 @@ std::string TextFormatDecodeData::DecodeDataForString(
const std::string& input_for_decode, const std::string& desired_output) {
if (input_for_decode.empty() || desired_output.empty()) {
std::cerr << "error: got empty string for making TextFormat data, input: \""
<< input_for_decode << "\", desired: \"" << desired_output << "\"."
<< std::endl;
<< input_for_decode << "\", desired: \"" << desired_output
<< "\"." << std::endl;
std::cerr.flush();
abort();
}
if ((input_for_decode.find('\0') != std::string::npos) ||
(desired_output.find('\0') != std::string::npos)) {
std::cerr << "error: got a null char in a string for making TextFormat data,"
<< " input: \"" << absl::CEscape(input_for_decode) << "\", desired: \""
<< absl::CEscape(desired_output) << "\"." << std::endl;
std::cerr
<< "error: got a null char in a string for making TextFormat data,"
<< " input: \"" << absl::CEscape(input_for_decode) << "\", desired: \""
<< absl::CEscape(desired_output) << "\"." << std::endl;
std::cerr.flush();
abort();
}
@ -259,7 +262,6 @@ std::string TextFormatDecodeData::DecodeDataForString(
return builder.Finish() + (char)'\0';
}
} // namespace objectivec
} // namespace compiler
} // namespace protobuf

@ -68,7 +68,6 @@ class PROTOC_EXPORT TextFormatDecodeData {
std::vector<DataEntry> entries_;
};
} // namespace objectivec
} // namespace compiler
} // namespace protobuf

@ -212,7 +212,6 @@ TEST(ObjCHelper, TextFormatDecodeData_ByteCodes) {
EXPECT_EQ(expected, decode_data.Data());
}
// Death tests do not work on Windows as of yet.
#ifdef PROTOBUF_HAS_DEATH_TEST
TEST(ObjCHelperDeathTest, TextFormatDecodeData_Failures) {

Loading…
Cancel
Save