diff options
author | Thomas Van Lenten <thomasvl@google.com> | 2015-11-30 14:38:04 -0500 |
---|---|---|
committer | Thomas Van Lenten <thomasvl@google.com> | 2016-02-18 13:55:59 -0500 |
commit | 2480acb6d974a2cfc1da5b1ea8cc14f2415e6dfe (patch) | |
tree | 3e95be3eae1e7d0ff8dce89951b167843127fb94 /src | |
parent | 9ab11c6561abd5fe997a999f21799d160b0d14cf (diff) | |
download | protobuf-2480acb6d974a2cfc1da5b1ea8cc14f2415e6dfe.tar.gz protobuf-2480acb6d974a2cfc1da5b1ea8cc14f2415e6dfe.tar.bz2 protobuf-2480acb6d974a2cfc1da5b1ea8cc14f2415e6dfe.zip |
Support ObjC Generic Collections
- Extend GPB*ObjectDictionary to support generic syntax.
- Update the generator to output generics so the enclosed type is exposed for compiler checks.
- Use generics in a the public interfaces.
- Update the generated sources that are checked in.
Diffstat (limited to 'src')
18 files changed, 237 insertions, 132 deletions
diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc index 97df536e..66ad13b7 100644 --- a/src/google/protobuf/compiler/main.cc +++ b/src/google/protobuf/compiler/main.cc @@ -78,7 +78,7 @@ int main(int argc, char* argv[]) { // Objective C google::protobuf::compiler::objectivec::ObjectiveCGenerator objc_generator; - cli.RegisterGenerator("--objc_out", &objc_generator, + cli.RegisterGenerator("--objc_out", "--objc_opt", &objc_generator, "Generate Objective C header and source."); // JavaScript diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc index 30a13ddb..ecc77f6b 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc @@ -44,6 +44,7 @@ namespace compiler { namespace objectivec { namespace { + void SetEnumVariables(const FieldDescriptor* descriptor, map<string, string>* variables) { string type = EnumName(descriptor->enum_type()); @@ -63,8 +64,9 @@ void SetEnumVariables(const FieldDescriptor* descriptor, } } // namespace -EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor) - : SingleFieldGenerator(descriptor) { +EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : SingleFieldGenerator(descriptor, options) { SetEnumVariables(descriptor, &variables_); } @@ -112,6 +114,7 @@ void EnumFieldGenerator::GenerateCFunctionImplementations( void EnumFieldGenerator::DetermineForwardDeclarations( set<string>* fwd_decls) const { + SingleFieldGenerator::DetermineForwardDeclarations(fwd_decls); // If it is an enum defined in a different file, 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. @@ -123,14 +126,20 @@ void EnumFieldGenerator::DetermineForwardDeclarations( } RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator( - const FieldDescriptor* descriptor) - : RepeatedFieldGenerator(descriptor) { + const FieldDescriptor* descriptor, const Options& options) + : RepeatedFieldGenerator(descriptor, options) { SetEnumVariables(descriptor, &variables_); variables_["array_storage_type"] = "GPBEnumArray"; } RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} +void RepeatedEnumFieldGenerator::FinishInitialization(void) { + RepeatedFieldGenerator::FinishInitialization(); + variables_["array_comment"] = + "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n"; +} + void RepeatedEnumFieldGenerator::GenerateFieldDescriptionTypeSpecific( io::Printer* printer) const { printer->Print( diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h index b629eae8..ae2f57e3 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h @@ -41,7 +41,8 @@ namespace compiler { namespace objectivec { class EnumFieldGenerator : public SingleFieldGenerator { - friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options); public: virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const; @@ -50,7 +51,7 @@ class EnumFieldGenerator : public SingleFieldGenerator { virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const; protected: - explicit EnumFieldGenerator(const FieldDescriptor* descriptor); + EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options); virtual ~EnumFieldGenerator(); private: @@ -58,13 +59,16 @@ class EnumFieldGenerator : public SingleFieldGenerator { }; class RepeatedEnumFieldGenerator : public RepeatedFieldGenerator { - friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options); public: + virtual void FinishInitialization(); virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const; protected: - RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor); + RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); virtual ~RepeatedEnumFieldGenerator(); private: diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc index cf5d8cfb..09341820 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc @@ -45,6 +45,7 @@ namespace compiler { namespace objectivec { namespace { + void SetCommonFieldVariables(const FieldDescriptor* descriptor, map<string, string>* variables) { string camel_case_name = FieldName(descriptor); @@ -117,39 +118,40 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, } // namespace -FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) { +FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options) { FieldGenerator* result = NULL; if (field->is_repeated()) { switch (GetObjectiveCType(field)) { case OBJECTIVECTYPE_MESSAGE: { if (field->is_map()) { - result = new MapFieldGenerator(field); + result = new MapFieldGenerator(field, options); } else { - result = new RepeatedMessageFieldGenerator(field); + result = new RepeatedMessageFieldGenerator(field, options); } break; } case OBJECTIVECTYPE_ENUM: - result = new RepeatedEnumFieldGenerator(field); + result = new RepeatedEnumFieldGenerator(field, options); break; default: - result = new RepeatedPrimitiveFieldGenerator(field); + result = new RepeatedPrimitiveFieldGenerator(field, options); break; } } else { switch (GetObjectiveCType(field)) { case OBJECTIVECTYPE_MESSAGE: { - result = new MessageFieldGenerator(field); + result = new MessageFieldGenerator(field, options); break; } case OBJECTIVECTYPE_ENUM: - result = new EnumFieldGenerator(field); + result = new EnumFieldGenerator(field, options); break; default: if (IsReferenceType(field)) { - result = new PrimitiveObjFieldGenerator(field); + result = new PrimitiveObjFieldGenerator(field, options); } else { - result = new PrimitiveFieldGenerator(field); + result = new PrimitiveFieldGenerator(field, options); } break; } @@ -158,8 +160,8 @@ FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) { return result; } - -FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor) +FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor, + const Options& options) : descriptor_(descriptor) { SetCommonFieldVariables(descriptor, &variables_); } @@ -252,9 +254,9 @@ void FieldGenerator::FinishInitialization(void) { } } -SingleFieldGenerator::SingleFieldGenerator( - const FieldDescriptor* descriptor) - : FieldGenerator(descriptor) { +SingleFieldGenerator::SingleFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : FieldGenerator(descriptor, options) { // Nothing } @@ -300,9 +302,9 @@ bool SingleFieldGenerator::WantsHasProperty(void) const { return false; } -ObjCObjFieldGenerator::ObjCObjFieldGenerator( - const FieldDescriptor* descriptor) - : SingleFieldGenerator(descriptor) { +ObjCObjFieldGenerator::ObjCObjFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : SingleFieldGenerator(descriptor, options) { variables_["property_storage_attribute"] = "strong"; if (IsRetainedName(variables_["name"])) { variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED"; @@ -342,18 +344,21 @@ void ObjCObjFieldGenerator::GeneratePropertyDeclaration( } RepeatedFieldGenerator::RepeatedFieldGenerator( - const FieldDescriptor* descriptor) - : ObjCObjFieldGenerator(descriptor) { + const FieldDescriptor* descriptor, const Options& options) + : ObjCObjFieldGenerator(descriptor, options) { // Repeated fields don't use the has index. variables_["has_index"] = "GPBNoHasBit"; + // Default to no comment and let the cases needing it fill it in. + variables_["array_comment"] = ""; } RepeatedFieldGenerator::~RepeatedFieldGenerator() {} void RepeatedFieldGenerator::FinishInitialization(void) { FieldGenerator::FinishInitialization(); - variables_["array_comment"] = - "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n"; + if (variables_.find("array_property_type") == variables_.end()) { + variables_["array_property_type"] = variable("array_storage_type"); + } } void RepeatedFieldGenerator::GenerateFieldStorageDeclaration( @@ -379,13 +384,13 @@ void RepeatedFieldGenerator::GeneratePropertyDeclaration( variables_, "$comments$" "$array_comment$" - "@property(nonatomic, readwrite, strong, null_resettable) $array_storage_type$ *$name$$storage_attribute$;\n" + "@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$;\n" "@property(nonatomic, readonly) NSUInteger $name$_Count;\n"); 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_, - "- ($array_storage_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n"); + "- ($array_property_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n"); } printer->Print("\n"); } @@ -395,7 +400,8 @@ bool RepeatedFieldGenerator::WantsHasProperty(void) const { return false; } -FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor) +FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, + const Options& options) : descriptor_(descriptor), field_generators_( new scoped_ptr<FieldGenerator>[descriptor->field_count()]), @@ -403,10 +409,12 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor) new scoped_ptr<FieldGenerator>[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), options)); } for (int i = 0; i < descriptor->extension_count(); i++) { - extension_generators_[i].reset(FieldGenerator::Make(descriptor->extension(i))); + extension_generators_[i].reset( + FieldGenerator::Make(descriptor->extension(i), options)); } } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.h b/src/google/protobuf/compiler/objectivec/objectivec_field.h index 130a52dd..e8a20a72 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.h @@ -49,24 +49,31 @@ namespace objectivec { class FieldGenerator { public: - static FieldGenerator* Make(const FieldDescriptor* field); + static FieldGenerator* Make(const FieldDescriptor* field, + const Options& options); virtual ~FieldGenerator(); + // Exposed for subclasses to fill in. virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const = 0; virtual void GeneratePropertyDeclaration(io::Printer* printer) const = 0; - virtual void GeneratePropertyImplementation(io::Printer* printer) const = 0; - virtual void GenerateFieldDescription(io::Printer* printer) const; + // Called by GenerateFieldDescription, exposed for classes that need custom + // generation. virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const; - virtual void GenerateFieldNumberConstant(io::Printer* printer) const; + // Exposed for subclasses to extend, base does nothing. virtual void GenerateCFunctionDeclarations(io::Printer* printer) const; virtual void GenerateCFunctionImplementations(io::Printer* printer) const; + // Exposed for subclasses, should always call it on the parent class also. virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const; + // Used during generation, not intended to be extended by subclasses. + void GenerateFieldDescription(io::Printer* printer) const; + void GenerateFieldNumberConstant(io::Printer* printer) const; + void SetOneofIndexBase(int index_base); string variable(const char* key) const { @@ -81,7 +88,7 @@ class FieldGenerator { string raw_field_name() const { return variable("raw_field_name"); } protected: - explicit FieldGenerator(const FieldDescriptor* descriptor); + FieldGenerator(const FieldDescriptor* descriptor, const Options& options); virtual void FinishInitialization(void); virtual bool WantsHasProperty(void) const = 0; @@ -103,7 +110,8 @@ class SingleFieldGenerator : public FieldGenerator { virtual void GeneratePropertyImplementation(io::Printer* printer) const; protected: - explicit SingleFieldGenerator(const FieldDescriptor* descriptor); + SingleFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); virtual bool WantsHasProperty(void) const; private: @@ -119,7 +127,8 @@ class ObjCObjFieldGenerator : public SingleFieldGenerator { virtual void GeneratePropertyDeclaration(io::Printer* printer) const; protected: - explicit ObjCObjFieldGenerator(const FieldDescriptor* descriptor); + ObjCObjFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjCObjFieldGenerator); @@ -135,7 +144,8 @@ class RepeatedFieldGenerator : public ObjCObjFieldGenerator { virtual void GeneratePropertyImplementation(io::Printer* printer) const; protected: - explicit RepeatedFieldGenerator(const FieldDescriptor* descriptor); + RepeatedFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); virtual void FinishInitialization(void); virtual bool WantsHasProperty(void) const; @@ -146,7 +156,7 @@ class RepeatedFieldGenerator : public ObjCObjFieldGenerator { // Convenience class which constructs FieldGenerators for a Descriptor. class FieldGeneratorMap { public: - explicit FieldGeneratorMap(const Descriptor* descriptor); + FieldGeneratorMap(const Descriptor* descriptor, const Options& options); ~FieldGeneratorMap(); const FieldGenerator& get(const FieldDescriptor* field) const; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index 228c66f0..cdf9ebbc 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -50,17 +50,18 @@ const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30000; namespace compiler { namespace objectivec { -FileGenerator::FileGenerator(const FileDescriptor *file) +FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options) : file_(file), root_class_name_(FileClassName(file)), - is_public_dep_(false) { + is_public_dep_(false), + options_(options) { for (int i = 0; i < file_->enum_type_count(); i++) { EnumGenerator *generator = new EnumGenerator(file_->enum_type(i)); enum_generators_.push_back(generator); } for (int i = 0; i < file_->message_type_count(); i++) { MessageGenerator *generator = - new MessageGenerator(root_class_name_, file_->message_type(i)); + new MessageGenerator(root_class_name_, file_->message_type(i), options_); message_generators_.push_back(generator); } for (int i = 0; i < file_->extension_count(); i++) { @@ -352,7 +353,8 @@ const vector<FileGenerator *> &FileGenerator::DependencyGenerators() { public_import_names.insert(file_->public_dependency(i)->name()); } for (int i = 0; i < file_->dependency_count(); i++) { - FileGenerator *generator = new FileGenerator(file_->dependency(i)); + FileGenerator *generator = + new FileGenerator(file_->dependency(i), options_); const string& name = file_->dependency(i)->name(); bool public_import = (public_import_names.count(name) != 0); generator->SetIsPublicDependency(public_import); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h index 1bb4f0ea..4c0fcd3f 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h @@ -55,7 +55,7 @@ class MessageGenerator; class FileGenerator { public: - explicit FileGenerator(const FileDescriptor* file); + FileGenerator(const FileDescriptor* file, const Options& options); ~FileGenerator(); void GenerateSource(io::Printer* printer); @@ -84,6 +84,8 @@ class FileGenerator { vector<ExtensionGenerator*> extension_generators_; bool is_public_dep_; + const Options options_; + const vector<FileGenerator*>& DependencyGenerators(); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc index 375b4e0f..72e295de 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc @@ -49,21 +49,31 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file, const string& parameter, OutputDirectory* output_directory, string* error) const { - // ObjC doesn't have any options at the moment, error if passed one. + // ----------------------------------------------------------------- + // Parse generator options. + + Options generation_options; + vector<pair<string, string> > options; ParseGeneratorParameter(parameter, &options); for (int i = 0; i < options.size(); i++) { - *error = "error:: Unknown generator option: " + options[i].first; - return false; + if (options[i].first == "expected_prefixes_path") { + generation_options.expected_prefixes_path = options[i].second; + } else { + *error = "error: Unknown generator option: " + options[i].first; + return false; + } } + // ----------------------------------------------------------------- + // Validate the objc prefix/package pairing. - if (!ValidateObjCClassPrefix(file, error)) { + if (!ValidateObjCClassPrefix(file, generation_options, error)) { // *error will have been filled in. return false; } - FileGenerator file_generator(file); + FileGenerator file_generator(file, generation_options); string filepath = FilePath(file); // Generate header. diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc index 8527b74b..77a378c8 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -58,6 +58,14 @@ namespace protobuf { namespace compiler { namespace objectivec { +Options::Options() { + // Default is the value of the env for the package prefixes. + const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES"); + if (file_path) { + expected_prefixes_path = file_path; + } +} + namespace { hash_set<string> MakeWordsMap(const char* const words[], size_t num_words) { @@ -890,26 +898,26 @@ bool Parser::ParseLoop() { return true; } -bool LoadExpectedPackagePrefixes(map<string, string>* prefix_map, - string* out_expect_file_path, +bool LoadExpectedPackagePrefixes(const Options &generation_options, + map<string, string>* prefix_map, string* out_error) { - const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES"); - if (file_path == NULL) { + if (generation_options.expected_prefixes_path.empty()) { return true; } int fd; do { - fd = open(file_path, O_RDONLY); + fd = open(generation_options.expected_prefixes_path.c_str(), O_RDONLY); } while (fd < 0 && errno == EINTR); if (fd < 0) { *out_error = - string(file_path) + ":0:0: error: Unable to open." + strerror(errno); + string("error: Unable to open \"") + + generation_options.expected_prefixes_path + + "\", " + strerror(errno); return false; } io::FileInputStream file_stream(fd); file_stream.SetCloseOnDelete(true); - *out_expect_file_path = file_path; Parser parser(prefix_map); const void* buf; @@ -920,8 +928,9 @@ bool LoadExpectedPackagePrefixes(map<string, string>* prefix_map, } if (!parser.ParseChunk(StringPiece(static_cast<const char*>(buf), buf_len))) { - *out_error = string(file_path) + ":" + SimpleItoa(parser.last_line()) + - ":0: error: " + parser.error_str(); + *out_error = + string("error: ") + generation_options.expected_prefixes_path + + " Line " + SimpleItoa(parser.last_line()) + ", " + parser.error_str(); return false; } } @@ -930,7 +939,9 @@ bool LoadExpectedPackagePrefixes(map<string, string>* prefix_map, } // namespace -bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) { +bool ValidateObjCClassPrefix(const FileDescriptor* file, + const Options& generation_options, + string* out_error) { const string prefix = file->options().objc_class_prefix(); const string package = file->package(); @@ -939,11 +950,10 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) { // Load any expected package prefixes to validate against those. map<string, string> expected_package_prefixes; - string expect_file_path; - if (!LoadExpectedPackagePrefixes(&expected_package_prefixes, - &expect_file_path, out_error)) { - // Any error, clear the entries that were read. - expected_package_prefixes.clear(); + if (!LoadExpectedPackagePrefixes(generation_options, + &expected_package_prefixes, + out_error)) { + return false; } // Check: Error - See if there was an expected prefix for the package and @@ -957,7 +967,7 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) { return true; } else { // ...it didn't match! - *out_error = "protoc:0: error: Expected 'option objc_class_prefix = \"" + + *out_error = "error: Expected 'option objc_class_prefix = \"" + package_match->second + "\";' in '" + file->name() + "'"; if (prefix.length()) { *out_error += "; but found '" + prefix + "' instead"; @@ -980,11 +990,11 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) { i != expected_package_prefixes.end(); ++i) { if (i->second == prefix) { *out_error = - "protoc:0: error: Found 'option objc_class_prefix = \"" + prefix + + "error: Found 'option objc_class_prefix = \"" + prefix + "\";' in '" + file->name() + "'; that prefix is already used for 'package " + i->first + ";'. It can only be reused by listing it in the expected file (" + - expect_file_path + ")."; + generation_options.expected_prefixes_path + ")."; return false; // Only report first usage of the prefix. } } @@ -1017,7 +1027,7 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) { << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \"" << prefix << "\";' in '" << file->name() << "';" << " consider adding it to the expected prefixes file (" - << expect_file_path << ")." << endl; + << generation_options.expected_prefixes_path << ")." << endl; cerr.flush(); } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h index 85744862..5b2dd190 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -42,6 +42,12 @@ namespace protobuf { namespace compiler { namespace objectivec { +// Generator options (see objectivec_generator.cc for a description of each): +struct Options { + Options(); + string expected_prefixes_path; +}; + // Strips ".proto" or ".protodevel" from the end of a filename. string StripProto(const string& filename); @@ -145,7 +151,9 @@ string BuildCommentsString(const SourceLocation& location); // Checks the prefix for a given file and outputs any warnings needed, if // there are flat out errors, then out_error is filled in and the result is // false. -bool ValidateObjCClassPrefix(const FileDescriptor* file, string *out_error); +bool ValidateObjCClassPrefix(const FileDescriptor* file, + const Options& generation_options, + string* out_error); // Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform // the input into the expected output. diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc index 2987f3db..2751e936 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc @@ -84,13 +84,14 @@ const char* MapEntryTypeName(const FieldDescriptor* descriptor, bool isKey) { } // namespace -MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor) - : RepeatedFieldGenerator(descriptor) { +MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : RepeatedFieldGenerator(descriptor, options) { const FieldDescriptor* key_descriptor = descriptor->message_type()->FindFieldByName("key"); const FieldDescriptor* value_descriptor = descriptor->message_type()->FindFieldByName("value"); - value_field_generator_.reset(FieldGenerator::Make(value_descriptor)); + value_field_generator_.reset(FieldGenerator::Make(value_descriptor, options)); // Pull over some variables_ from the value. variables_["field_type"] = value_field_generator_->variable("field_type"); @@ -117,16 +118,27 @@ MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor) variables_["fieldflags"] = BuildFlagsString(field_flags); ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor); - if ((GetObjectiveCType(key_descriptor) == OBJECTIVECTYPE_STRING) && + const bool value_is_object_type = ((value_objc_type == OBJECTIVECTYPE_STRING) || (value_objc_type == OBJECTIVECTYPE_DATA) || - (value_objc_type == OBJECTIVECTYPE_MESSAGE))) { + (value_objc_type == OBJECTIVECTYPE_MESSAGE)); + if ((GetObjectiveCType(key_descriptor) == OBJECTIVECTYPE_STRING) && + value_is_object_type) { variables_["array_storage_type"] = "NSMutableDictionary"; + variables_["array_property_type"] = + "NSMutableDictionary<NSString*, " + + value_field_generator_->variable("storage_type") + "*>"; } else { - string base_name = MapEntryTypeName(key_descriptor, true); - base_name += MapEntryTypeName(value_descriptor, false); - base_name += "Dictionary"; - variables_["array_storage_type"] = "GPB" + base_name; + string class_name("GPB"); + class_name += MapEntryTypeName(key_descriptor, true); + class_name += MapEntryTypeName(value_descriptor, false); + class_name += "Dictionary"; + variables_["array_storage_type"] = class_name; + if (value_is_object_type) { + variables_["array_property_type"] = + class_name + "<" + + value_field_generator_->variable("storage_type") + "*>"; + } } } @@ -138,15 +150,9 @@ void MapFieldGenerator::FinishInitialization(void) { // values in the map are. const FieldDescriptor* value_descriptor = descriptor_->message_type()->FindFieldByName("value"); - ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor); - if ((value_objc_type == OBJECTIVECTYPE_MESSAGE) || - (value_objc_type == OBJECTIVECTYPE_DATA) || - (value_objc_type == OBJECTIVECTYPE_STRING) || - (value_objc_type == OBJECTIVECTYPE_ENUM)) { + if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_ENUM) { variables_["array_comment"] = "// |" + variables_["name"] + "| values are |" + value_field_generator_->variable("storage_type") + "|\n"; - } else { - variables_["array_comment"] = ""; } } @@ -157,6 +163,19 @@ void MapFieldGenerator::GenerateFieldDescriptionTypeSpecific( value_field_generator_->GenerateFieldDescriptionTypeSpecific(printer); } +void MapFieldGenerator::DetermineForwardDeclarations( + set<string>* fwd_decls) const { + RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls); + const FieldDescriptor* value_descriptor = + descriptor_->message_type()->FindFieldByName("value"); + if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE) { + const string& value_storage_type = + value_field_generator_->variable("storage_type"); + fwd_decls->insert("@class " + value_storage_type); + } +} + + } // namespace objectivec } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h index 173541f2..7351ea05 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h @@ -41,18 +41,22 @@ namespace compiler { namespace objectivec { class MapFieldGenerator : public RepeatedFieldGenerator { - friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options); public: virtual void FinishInitialization(void); virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const; protected: - explicit MapFieldGenerator(const FieldDescriptor* descriptor); + MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options); virtual ~MapFieldGenerator(); + virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const; + private: scoped_ptr<FieldGenerator> value_field_generator_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator); }; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc index 32671d42..e0ea8bd2 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc @@ -174,10 +174,11 @@ const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) { } // namespace MessageGenerator::MessageGenerator(const string& root_classname, - const Descriptor* descriptor) + const Descriptor* descriptor, + const Options& options) : root_classname_(root_classname), descriptor_(descriptor), - field_generators_(descriptor), + field_generators_(descriptor, options), class_name_(ClassName(descriptor_)) { for (int i = 0; i < descriptor_->extension_count(); i++) { extension_generators_.push_back( @@ -196,7 +197,9 @@ MessageGenerator::MessageGenerator(const 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), + options); nested_message_generators_.push_back(generator); } } @@ -230,11 +233,6 @@ void MessageGenerator::DetermineForwardDeclarations(set<string>* fwd_decls) { if (!IsMapEntryMessage(descriptor_)) { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* fieldDescriptor = descriptor_->field(i); - // If it is a the field is repeated, the type will be and *Array, and we - // don't need any forward decl. - if (fieldDescriptor->is_repeated()) { - continue; - } field_generators_.get(fieldDescriptor) .DetermineForwardDeclarations(fwd_decls); } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/objectivec_message.h index 06b536ff..8565e76f 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.h @@ -54,7 +54,9 @@ class EnumGenerator; class MessageGenerator { public: - MessageGenerator(const string& root_classname, const Descriptor* descriptor); + MessageGenerator(const string& root_classname, + const Descriptor* descriptor, + const Options& options); ~MessageGenerator(); void GenerateStaticVariablesInitialization(io::Printer* printer); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc index f2ce4e5b..d6ccd6d1 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc @@ -58,8 +58,9 @@ void SetMessageVariables(const FieldDescriptor* descriptor, } // namespace -MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor) - : ObjCObjFieldGenerator(descriptor) { +MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : ObjCObjFieldGenerator(descriptor, options) { SetMessageVariables(descriptor, &variables_); } @@ -67,6 +68,7 @@ MessageFieldGenerator::~MessageFieldGenerator() {} void MessageFieldGenerator::DetermineForwardDeclarations( set<string>* fwd_decls) const { + ObjCObjFieldGenerator::DetermineForwardDeclarations(fwd_decls); // Class name is already in "storage_type". fwd_decls->insert("@class " + variable("storage_type")); } @@ -82,14 +84,24 @@ bool MessageFieldGenerator::WantsHasProperty(void) const { } RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( - const FieldDescriptor* descriptor) - : RepeatedFieldGenerator(descriptor) { + const FieldDescriptor* descriptor, const Options& options) + : RepeatedFieldGenerator(descriptor, options) { SetMessageVariables(descriptor, &variables_); variables_["array_storage_type"] = "NSMutableArray"; + variables_["array_property_type"] = + "NSMutableArray<" + variables_["storage_type"] + "*>"; } RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} +void RepeatedMessageFieldGenerator::DetermineForwardDeclarations( + set<string>* fwd_decls) const { + RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls); + // Class name is already in "storage_type". + fwd_decls->insert("@class " + variable("storage_type")); +} + + } // namespace objectivec } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h index 708ea566..d2dba153 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h @@ -41,10 +41,12 @@ namespace compiler { namespace objectivec { class MessageFieldGenerator : public ObjCObjFieldGenerator { - friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options); protected: - explicit MessageFieldGenerator(const FieldDescriptor* descriptor); + MessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); virtual ~MessageFieldGenerator(); virtual bool WantsHasProperty(void) const; @@ -56,12 +58,17 @@ class MessageFieldGenerator : public ObjCObjFieldGenerator { }; class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator { - friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options); protected: - explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor); + RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); virtual ~RepeatedMessageFieldGenerator(); + public: + virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); }; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc index c185b66d..ea7f1b91 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc @@ -74,7 +74,7 @@ const char* PrimitiveTypeName(const FieldDescriptor* descriptor) { case OBJECTIVECTYPE_ENUM: return "int32_t"; case OBJECTIVECTYPE_MESSAGE: - return NULL; + return NULL; // Messages go through objectivec_message_field.cc|h. } // Some compilers report reaching end of function even though all cases of @@ -107,7 +107,8 @@ const char* PrimitiveArrayTypeName(const FieldDescriptor* descriptor) { case OBJECTIVECTYPE_ENUM: return "Enum"; case OBJECTIVECTYPE_MESSAGE: - return ""; // Want NSArray + // Want NSArray (but goes through objectivec_message_field.cc|h). + return ""; } // Some compilers report reaching end of function even though all cases of @@ -126,16 +127,16 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, } // namespace PrimitiveFieldGenerator::PrimitiveFieldGenerator( - const FieldDescriptor* descriptor) - : SingleFieldGenerator(descriptor) { + const FieldDescriptor* descriptor, const Options& options) + : SingleFieldGenerator(descriptor, options) { SetPrimitiveVariables(descriptor, &variables_); } PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator( - const FieldDescriptor* descriptor) - : ObjCObjFieldGenerator(descriptor) { + const FieldDescriptor* descriptor, const Options& options) + : ObjCObjFieldGenerator(descriptor, options) { SetPrimitiveVariables(descriptor, &variables_); variables_["property_storage_attribute"] = "copy"; } @@ -143,8 +144,8 @@ PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator( PrimitiveObjFieldGenerator::~PrimitiveObjFieldGenerator() {} RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( - const FieldDescriptor* descriptor) - : RepeatedFieldGenerator(descriptor) { + const FieldDescriptor* descriptor, const Options& options) + : RepeatedFieldGenerator(descriptor, options) { SetPrimitiveVariables(descriptor, &variables_); string base_name = PrimitiveArrayTypeName(descriptor); @@ -152,19 +153,13 @@ RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( variables_["array_storage_type"] = "GPB" + base_name + "Array"; } else { variables_["array_storage_type"] = "NSMutableArray"; + variables_["array_property_type"] = + "NSMutableArray<" + variables_["storage_type"] + "*>"; } } RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} -void RepeatedPrimitiveFieldGenerator::FinishInitialization(void) { - RepeatedFieldGenerator::FinishInitialization(); - if (IsPrimitiveType(descriptor_)) { - // No comment needed for primitive types. - variables_["array_comment"] = ""; - } -} - } // namespace objectivec } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h index 9bb79343..87139afb 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h @@ -41,10 +41,12 @@ namespace compiler { namespace objectivec { class PrimitiveFieldGenerator : public SingleFieldGenerator { - friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options); protected: - explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor); + PrimitiveFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); virtual ~PrimitiveFieldGenerator(); private: @@ -52,10 +54,12 @@ class PrimitiveFieldGenerator : public SingleFieldGenerator { }; class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator { - friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options); protected: - explicit PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor); + PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); virtual ~PrimitiveObjFieldGenerator(); private: @@ -63,12 +67,13 @@ class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator { }; class RepeatedPrimitiveFieldGenerator : public RepeatedFieldGenerator { - friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options); protected: - explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor); + RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); virtual ~RepeatedPrimitiveFieldGenerator(); - virtual void FinishInitialization(void); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); |