From 5977fb0a0558646d2d44d1e4c6bc33173122c22c Mon Sep 17 00:00:00 2001 From: Yuki Yugui Sonoda Date: Wed, 1 Jun 2016 16:23:15 +0900 Subject: Generalize plugin support in Bazel Skylark rule It helps users to support their own plugins in a manner consistent to cc_proto_library and py_proto_libary in their skylark rules --- protobuf.bzl | 54 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/protobuf.bzl b/protobuf.bzl index c5555fde..0b8f5e7d 100644 --- a/protobuf.bzl +++ b/protobuf.bzl @@ -62,9 +62,19 @@ def _proto_gen_impl(ctx): if ctx.attr.gen_py: args += ["--python_out=" + ctx.var["GENDIR"] + "/" + gen_dir] - if ctx.executable.grpc_cpp_plugin: - args += ["--plugin=protoc-gen-grpc=" + ctx.executable.grpc_cpp_plugin.path] - args += ["--grpc_out=" + ctx.var["GENDIR"] + "/" + gen_dir] + if ctx.executable.plugin: + plugin = ctx.executable.plugin + lang = ctx.attr.plugin_language + if not lang and plugin.basename.startswith('protoc-gen-'): + lang = plugin.basename[len('protoc-gen-'):] + if not lang: + fail("cannot infer the target language of plugin", "plugin_language") + + outdir = ctx.var["GENDIR"] + "/" + gen_dir + if ctx.attr.plugin_options: + outdir = ",".join(ctx.attr.plugin_options) + ":" + outdir + args += ["--plugin=protoc-gen-%s=%s" % (lang, plugin.path)] + args += ["--%s_out=%s" % (lang, outdir)] if args: ctx.action( @@ -72,6 +82,7 @@ def _proto_gen_impl(ctx): outputs=ctx.outputs.outs, arguments=args + import_flags + [s.path for s in srcs], executable=ctx.executable.protoc, + mnemonic="ProtoCompile", ) return struct( @@ -82,7 +93,7 @@ def _proto_gen_impl(ctx): ), ) -_proto_gen = rule( +proto_gen = rule( attrs = { "srcs": attr.label_list(allow_files = True), "deps": attr.label_list(providers = ["proto"]), @@ -93,11 +104,13 @@ _proto_gen = rule( single_file = True, mandatory = True, ), - "grpc_cpp_plugin": attr.label( + "plugin": attr.label( cfg = HOST_CFG, + allow_files = True, executable = True, - single_file = True, ), + "plugin_language": attr.string(), + "plugin_options": attr.string_list(), "gen_cc": attr.bool(), "gen_py": attr.bool(), "outs": attr.output_list(), @@ -105,6 +118,26 @@ _proto_gen = rule( output_to_genfiles = True, implementation = _proto_gen_impl, ) +"""Generates codes from Protocol Buffers definitions. + +This rule helps you to implement Skylark macros specific to the target +language. You should prefer more specific `cc_proto_library `, +`py_proto_library` and others unless you are adding such wrapper macros. + +Args: + srcs: Protocol Buffers definition files (.proto) to run the protocol compiler + against. + deps: a list of dependency labels; must be other proto libraries. + includes: a list of include paths to .proto files. + protoc: the label of the protocol compiler to generate the sources. + plugin: the label of the protocol compiler plugin to be passed to the protocol + compiler. + plugin_language: the language of the generated sources + plugin_options: a list of options to be passed to the plugin + gen_cc: generates C++ sources in addition to the ones from the plugin. + gen_py: generates Python sources in addition to the ones from the plugin. + outs: a list of labels of the expected outputs from the protocol compiler. +""" def cc_proto_library( name, @@ -150,7 +183,7 @@ def cc_proto_library( if internal_bootstrap_hack: # For pre-checked-in generated files, we add the internal_bootstrap_hack # which will skip the codegen action. - _proto_gen( + proto_gen( name=name + "_genproto", srcs=srcs, deps=[s + "_genproto" for s in deps], @@ -170,13 +203,14 @@ def cc_proto_library( outs = _CcOuts(srcs, use_grpc_plugin) - _proto_gen( + proto_gen( name=name + "_genproto", srcs=srcs, deps=[s + "_genproto" for s in deps], includes=includes, protoc=protoc, - grpc_cpp_plugin=grpc_cpp_plugin, + plugin=grpc_cpp_plugin, + plugin_language="grpc", gen_cc=1, outs=outs, visibility=["//visibility:public"], @@ -286,7 +320,7 @@ def py_proto_library( if include != None: includes = [include] - _proto_gen( + proto_gen( name=name + "_genproto", srcs=srcs, deps=[s + "_genproto" for s in deps], -- cgit v1.2.3 From 588a803d586447582b8398a92c3d93808f80e285 Mon Sep 17 00:00:00 2001 From: "Wei-Yin Chen (陳威尹)" Date: Fri, 19 Aug 2016 15:25:54 -0700 Subject: Support Unicode build on Windows --- appveyor.bat | 2 +- appveyor.yml | 1 + cmake/CMakeLists.txt | 4 ++++ src/google/protobuf/testing/file.cc | 16 ++++++++-------- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/appveyor.bat b/appveyor.bat index 0e6dd520..58cc9355 100644 --- a/appveyor.bat +++ b/appveyor.bat @@ -10,7 +10,7 @@ goto :error echo Building C++ mkdir build_msvc cd build_msvc -cmake -G "%generator%" -Dprotobuf_BUILD_SHARED_LIBS=%BUILD_DLL% ../cmake +cmake -G "%generator%" -Dprotobuf_BUILD_SHARED_LIBS=%BUILD_DLL% -DUNICODE=%UNICODE% ../cmake msbuild protobuf.sln /p:Platform=%vcplatform% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" || goto error cd %configuration% tests.exe || goto error diff --git a/appveyor.yml b/appveyor.yml index 2ea3cb78..20fc8ade 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,6 +11,7 @@ environment: matrix: - language: cpp BUILD_DLL: ON + UNICODE: ON - language: csharp diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index f947b741..8c374b7e 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -159,6 +159,10 @@ else (MSVC) set(LIB_PREFIX) endif (MSVC) +if (UNICODE) + add_definitions(-DUNICODE -D_UNICODE) +endif (UNICODE) + include(libprotobuf-lite.cmake) include(libprotobuf.cmake) include(libprotoc.cmake) diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc index bc76c844..470512ed 100644 --- a/src/google/protobuf/testing/file.cc +++ b/src/google/protobuf/testing/file.cc @@ -141,12 +141,12 @@ void File::DeleteRecursively(const string& name, #ifdef _MSC_VER // This interface is so weird. - WIN32_FIND_DATA find_data; - HANDLE find_handle = FindFirstFile((name + "/*").c_str(), &find_data); + WIN32_FIND_DATAA find_data; + HANDLE find_handle = FindFirstFileA((name + "/*").c_str(), &find_data); if (find_handle == INVALID_HANDLE_VALUE) { // Just delete it, whatever it is. - DeleteFile(name.c_str()); - RemoveDirectory(name.c_str()); + DeleteFileA(name.c_str()); + RemoveDirectoryA(name.c_str()); return; } @@ -156,15 +156,15 @@ void File::DeleteRecursively(const string& name, string path = name + "/" + entry_name; if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { DeleteRecursively(path, NULL, NULL); - RemoveDirectory(path.c_str()); + RemoveDirectoryA(path.c_str()); } else { - DeleteFile(path.c_str()); + DeleteFileA(path.c_str()); } } - } while(FindNextFile(find_handle, &find_data)); + } while(FindNextFileA(find_handle, &find_data)); FindClose(find_handle); - RemoveDirectory(name.c_str()); + RemoveDirectoryA(name.c_str()); #else // Use opendir()! Yay! // lstat = Don't follow symbolic links. -- cgit v1.2.3 From 11d6cb56d0df8427dd1a768d39a9717c2c4a7e70 Mon Sep 17 00:00:00 2001 From: "Wei-Yin Chen (陳威尹)" Date: Fri, 19 Aug 2016 16:40:57 -0700 Subject: Add test for Win32ErrorMessage --- src/google/protobuf/compiler/command_line_interface_unittest.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index 0ebf9b6a..dee438c6 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -719,6 +719,11 @@ TEST_F(CommandLineInterfaceTest, TrailingBackslash) { ExpectGenerated("test_generator", "", "foo.proto", "Foo"); } +TEST_F(CommandLineInterfaceTest, Win32ErrorMessage) { + EXPECT_EQ("The system cannot find the file specified.\r\n", + Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND)); +} + #endif // defined(_WIN32) || defined(__CYGWIN__) TEST_F(CommandLineInterfaceTest, PathLookup) { -- cgit v1.2.3 From 48811b2eddadf723b0685934025735163c74362f Mon Sep 17 00:00:00 2001 From: "Wei-Yin Chen (陳威尹)" Date: Fri, 19 Aug 2016 16:41:55 -0700 Subject: Fix Win32ErrorMessage on Unicode build --- src/google/protobuf/compiler/subprocess.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc index 6e258664..e929e4fb 100644 --- a/src/google/protobuf/compiler/subprocess.cc +++ b/src/google/protobuf/compiler/subprocess.cc @@ -261,12 +261,12 @@ string Subprocess::Win32ErrorMessage(DWORD error_code) { char* message; // WTF? - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, error_code, 0, - (LPTSTR)&message, // NOT A BUG! - 0, NULL); + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error_code, 0, + (LPSTR)&message, // NOT A BUG! + 0, NULL); string result = message; LocalFree(message); -- cgit v1.2.3 From a7eaf3696725d22e40ef2689bd2e8f32749d2df0 Mon Sep 17 00:00:00 2001 From: "Wei-Yin Chen (陳威尹)" Date: Thu, 1 Sep 2016 17:12:49 -0700 Subject: Rename UNICODE to protobuf_UNICODE --- appveyor.bat | 2 +- cmake/CMakeLists.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.bat b/appveyor.bat index 58cc9355..916f4434 100644 --- a/appveyor.bat +++ b/appveyor.bat @@ -10,7 +10,7 @@ goto :error echo Building C++ mkdir build_msvc cd build_msvc -cmake -G "%generator%" -Dprotobuf_BUILD_SHARED_LIBS=%BUILD_DLL% -DUNICODE=%UNICODE% ../cmake +cmake -G "%generator%" -Dprotobuf_BUILD_SHARED_LIBS=%BUILD_DLL% -Dprotobuf_UNICODE=%UNICODE% ../cmake msbuild protobuf.sln /p:Platform=%vcplatform% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" || goto error cd %configuration% tests.exe || goto error diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 8c374b7e..df3b2012 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -159,9 +159,9 @@ else (MSVC) set(LIB_PREFIX) endif (MSVC) -if (UNICODE) +if (protobuf_UNICODE) add_definitions(-DUNICODE -D_UNICODE) -endif (UNICODE) +endif (protobuf_UNICODE) include(libprotobuf-lite.cmake) include(libprotobuf.cmake) -- cgit v1.2.3 From 82133ba00b199e659b703852d7570fe3e62fd5df Mon Sep 17 00:00:00 2001 From: Guo Xiao Date: Thu, 8 Sep 2016 21:33:18 +0800 Subject: include std::find() --- src/google/protobuf/compiler/objectivec/objectivec_file.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index f70d4d5f..72fe8f91 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -37,6 +37,7 @@ #include #include #include +#include // std::find() #include #include -- cgit v1.2.3 From 337ec3065f98d6f048f92b3a864f65383a2549d8 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Tue, 16 Aug 2016 11:26:49 -0400 Subject: Add ObjC helpers for Any WKT. - Capture the ObjC prefix used when generating the the file. - Track the containing type on descriptors. - Mark descriptors where the message class name got a suffix added to it. - Expose a fullName property on Descriptors. - Add helpers for packing/unpacking Any messages. - Bump the ObjC runtime version number. Since we added methods and invoke them in the generated code, ensure the code is running against a matching version. Otherwise, someone could compile against headers, but run with a framework that is older and get unknown selector failures. This should trip clearer messaging. Fixes https://github.com/google/protobuf/issues/1674 --- objectivec/DevTools/compile_testing_protos.sh | 1 + objectivec/GPBBootstrap.h | 2 +- objectivec/GPBDescriptor.h | 9 ++ objectivec/GPBDescriptor.m | 114 ++++++++++++++++- objectivec/GPBDescriptor_PackagePrivate.h | 5 + objectivec/GPBWellKnownTypes.h | 125 +++++++++++++++++++ objectivec/GPBWellKnownTypes.m | 135 +++++++++++++++++++++ objectivec/Tests/GPBDescriptorTests.m | 29 +++++ objectivec/Tests/GPBUnittestProtos.m | 1 + objectivec/Tests/GPBWellKnownTypesTest.m | 56 +++++++++ objectivec/google/protobuf/Any.pbobjc.h | 2 +- objectivec/google/protobuf/Any.pbobjc.m | 1 + objectivec/google/protobuf/Api.pbobjc.h | 2 +- objectivec/google/protobuf/Api.pbobjc.m | 1 + objectivec/google/protobuf/Duration.pbobjc.h | 2 +- objectivec/google/protobuf/Duration.pbobjc.m | 1 + objectivec/google/protobuf/Empty.pbobjc.h | 2 +- objectivec/google/protobuf/Empty.pbobjc.m | 1 + objectivec/google/protobuf/FieldMask.pbobjc.h | 2 +- objectivec/google/protobuf/FieldMask.pbobjc.m | 1 + objectivec/google/protobuf/SourceContext.pbobjc.h | 2 +- objectivec/google/protobuf/SourceContext.pbobjc.m | 1 + objectivec/google/protobuf/Struct.pbobjc.h | 2 +- objectivec/google/protobuf/Struct.pbobjc.m | 1 + objectivec/google/protobuf/Timestamp.pbobjc.h | 2 +- objectivec/google/protobuf/Timestamp.pbobjc.m | 1 + objectivec/google/protobuf/Type.pbobjc.h | 2 +- objectivec/google/protobuf/Type.pbobjc.m | 1 + objectivec/google/protobuf/Wrappers.pbobjc.h | 2 +- objectivec/google/protobuf/Wrappers.pbobjc.m | 1 + .../compiler/objectivec/objectivec_file.cc | 37 ++++-- .../compiler/objectivec/objectivec_helpers.cc | 34 ++++-- .../compiler/objectivec/objectivec_helpers.h | 4 + .../compiler/objectivec/objectivec_message.cc | 13 ++ 34 files changed, 557 insertions(+), 38 deletions(-) diff --git a/objectivec/DevTools/compile_testing_protos.sh b/objectivec/DevTools/compile_testing_protos.sh index 35a85046..6cc32da9 100755 --- a/objectivec/DevTools/compile_testing_protos.sh +++ b/objectivec/DevTools/compile_testing_protos.sh @@ -93,6 +93,7 @@ compile_protos() { # sources can be generated from them. CORE_PROTO_FILES=( + src/google/protobuf/any_test.proto src/google/protobuf/unittest_arena.proto src/google/protobuf/unittest_custom_options.proto src/google/protobuf/unittest_enormous_descriptor.proto diff --git a/objectivec/GPBBootstrap.h b/objectivec/GPBBootstrap.h index 2e5bdc71..7dc943d4 100644 --- a/objectivec/GPBBootstrap.h +++ b/objectivec/GPBBootstrap.h @@ -99,4 +99,4 @@ // regenerated. // // Meant to be used internally by generated code. -#define GOOGLE_PROTOBUF_OBJC_GEN_VERSION 30001 +#define GOOGLE_PROTOBUF_OBJC_GEN_VERSION 30002 diff --git a/objectivec/GPBDescriptor.h b/objectivec/GPBDescriptor.h index 36fb4eae..651f4de0 100644 --- a/objectivec/GPBDescriptor.h +++ b/objectivec/GPBDescriptor.h @@ -81,6 +81,13 @@ typedef NS_ENUM(uint8_t, GPBFieldType) { @property(nonatomic, readonly, getter=isWireFormat) BOOL wireFormat; /** The class of this message. */ @property(nonatomic, readonly) Class messageClass; +/** Containing message descriptor if this message is nested, or nil otherwise. */ +@property(readonly, nullable) GPBDescriptor *containingType; +/** + * Fully qualified name for this message (package.message). Can be nil if the + * value is unable to be computed. + */ +@property(readonly, nullable) NSString *fullName; /** * Gets the field for the given number. @@ -118,6 +125,8 @@ typedef NS_ENUM(uint8_t, GPBFieldType) { /** The package declared in the proto file. */ @property(nonatomic, readonly, copy) NSString *package; +/** The objc prefix declared in the proto file. */ +@property(nonatomic, readonly, copy, nullable) NSString *objcPrefix; /** The syntax of the proto file. */ @property(nonatomic, readonly) GPBFileSyntax syntax; diff --git a/objectivec/GPBDescriptor.m b/objectivec/GPBDescriptor.m index dccb9bc8..0753a948 100644 --- a/objectivec/GPBDescriptor.m +++ b/objectivec/GPBDescriptor.m @@ -42,8 +42,10 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdirect-ivar-access" -// The address of this variable is used as a key for obj_getAssociatedObject. +// The addresses of these variables are used as keys for objc_getAssociatedObject. static const char kTextFormatExtraValueKey = 0; +static const char kParentClassNameValueKey = 0; +static const char kClassNameSuffixKey = 0; // Utility function to generate selectors on the fly. static SEL SelFromStrings(const char *prefix, const char *middle, @@ -215,10 +217,102 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, extensionRangesCount_ = count; } +- (void)setupContainingMessageClassName:(const char *)msgClassName { + // Note: Only fetch the class here, can't send messages to it because + // that could cause cycles back to this class within +initialize if + // two messages have each other in fields (i.e. - they build a graph). + NSAssert(objc_getClass(msgClassName), @"Class %s not defined", msgClassName); + NSValue *parentNameValue = [NSValue valueWithPointer:msgClassName]; + objc_setAssociatedObject(self, &kParentClassNameValueKey, + parentNameValue, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (void)setupMessageClassNameSuffix:(NSString *)suffix { + if (suffix.length) { + objc_setAssociatedObject(self, &kClassNameSuffixKey, + suffix, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } +} + - (NSString *)name { return NSStringFromClass(messageClass_); } +- (GPBDescriptor *)containingType { + NSValue *parentNameValue = + objc_getAssociatedObject(self, &kParentClassNameValueKey); + if (!parentNameValue) { + return nil; + } + const char *parentName = [parentNameValue pointerValue]; + Class parentClass = objc_getClass(parentName); + NSAssert(parentClass, @"Class %s not defined", parentName); + return [parentClass descriptor]; +} + +- (NSString *)fullName { + NSString *className = NSStringFromClass(self.messageClass); + GPBFileDescriptor *file = self.file; + NSString *objcPrefix = file.objcPrefix; + if (objcPrefix && ![className hasPrefix:objcPrefix]) { + NSAssert(0, + @"Class didn't have correct prefix? (%@ - %@)", + className, objcPrefix); + return nil; + } + GPBDescriptor *parent = self.containingType; + + NSString *name = nil; + if (parent) { + NSString *parentClassName = NSStringFromClass(parent.messageClass); + // The generator will add _Class to avoid reserved words, drop it. + NSString *suffix = objc_getAssociatedObject(parent, &kClassNameSuffixKey); + if (suffix) { + if (![parentClassName hasSuffix:suffix]) { + NSAssert(0, + @"ParentMessage class didn't have correct suffix? (%@ - %@)", + className, suffix); + return nil; + } + parentClassName = + [parentClassName substringToIndex:(parentClassName.length - suffix.length)]; + } + NSString *parentPrefix = [parentClassName stringByAppendingString:@"_"]; + if (![className hasPrefix:parentPrefix]) { + NSAssert(0, + @"Class didn't have the correct parent name prefix? (%@ - %@)", + parentPrefix, className); + return nil; + } + name = [className substringFromIndex:parentPrefix.length]; + } else { + name = [className substringFromIndex:objcPrefix.length]; + } + + // The generator will add _Class to avoid reserved words, drop it. + NSString *suffix = objc_getAssociatedObject(self, &kClassNameSuffixKey); + if (suffix) { + if (![name hasSuffix:suffix]) { + NSAssert(0, + @"Message class didn't have correct suffix? (%@ - %@)", + name, suffix); + return nil; + } + name = [name substringToIndex:(name.length - suffix.length)]; + } + + NSString *prefix = (parent != nil ? parent.fullName : file.package); + NSString *result; + if (prefix.length > 0) { + result = [NSString stringWithFormat:@"%@.%@", prefix, name]; + } else { + result = name; + } + return result; +} + - (id)copyWithZone:(NSZone *)zone { #pragma unused(zone) return [self retain]; @@ -255,12 +349,26 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, @implementation GPBFileDescriptor { NSString *package_; + NSString *objcPrefix_; GPBFileSyntax syntax_; } @synthesize package = package_; +@synthesize objcPrefix = objcPrefix_; @synthesize syntax = syntax_; +- (instancetype)initWithPackage:(NSString *)package + objcPrefix:(NSString *)objcPrefix + syntax:(GPBFileSyntax)syntax { + self = [super init]; + if (self) { + package_ = [package copy]; + objcPrefix_ = [objcPrefix copy]; + syntax_ = syntax; + } + return self; +} + - (instancetype)initWithPackage:(NSString *)package syntax:(GPBFileSyntax)syntax { self = [super init]; @@ -273,6 +381,7 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, - (void)dealloc { [package_ release]; + [objcPrefix_ release]; [super dealloc]; } @@ -416,6 +525,9 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) { // Extra type specific data. if (isMessage) { const char *className = coreDesc->dataTypeSpecific.className; + // Note: Only fetch the class here, can't send messages to it because + // that could cause cycles back to this class within +initialize if + // two messages have each other in fields (i.e. - they build a graph). msgClass_ = objc_getClass(className); NSAssert(msgClass_, @"Class %s not defined", className); } else if (dataType == GPBDataTypeEnum) { diff --git a/objectivec/GPBDescriptor_PackagePrivate.h b/objectivec/GPBDescriptor_PackagePrivate.h index c20ff6b0..66a4db77 100644 --- a/objectivec/GPBDescriptor_PackagePrivate.h +++ b/objectivec/GPBDescriptor_PackagePrivate.h @@ -165,10 +165,15 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { firstHasIndex:(int32_t)firstHasIndex; - (void)setupExtraTextInfo:(const char *)extraTextFormatInfo; - (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count; +- (void)setupContainingMessageClassName:(const char *)msgClassName; +- (void)setupMessageClassNameSuffix:(NSString *)suffix; @end @interface GPBFileDescriptor () +- (instancetype)initWithPackage:(NSString *)package + objcPrefix:(NSString *)objcPrefix + syntax:(GPBFileSyntax)syntax; - (instancetype)initWithPackage:(NSString *)package syntax:(GPBFileSyntax)syntax; @end diff --git a/objectivec/GPBWellKnownTypes.h b/objectivec/GPBWellKnownTypes.h index 96d51d9e..9ea57297 100644 --- a/objectivec/GPBWellKnownTypes.h +++ b/objectivec/GPBWellKnownTypes.h @@ -37,15 +37,32 @@ #endif #if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import #import #import #else + #import "google/protobuf/Any.pbobjc.h" #import "google/protobuf/Duration.pbobjc.h" #import "google/protobuf/Timestamp.pbobjc.h" #endif NS_ASSUME_NONNULL_BEGIN +#pragma mark - Errors + +/** NSError domain used for errors. */ +extern NSString *const GPBWellKnownTypesErrorDomain; + +/** Error code for NSError with GPBWellKnownTypesErrorDomain. */ +typedef NS_ENUM(NSInteger, GPBWellKnownTypesErrorCode) { + /** The type_url could not be computed for the requested GPBMessage class. */ + GPBWellKnownTypesErrorCodeFailedToComputeTypeURL = -100, + /** type_url in a Any doesn’t match that of the requested GPBMessage class. */ + GPBWellKnownTypesErrorCodeTypeURLMismatch = -101, +}; + +#pragma mark - GPBTimestamp + /** * Category for GPBTimestamp to work with standard Foundation time/date types. **/ @@ -77,6 +94,8 @@ NS_ASSUME_NONNULL_BEGIN @end +#pragma mark - GPBDuration + /** * Category for GPBDuration to work with standard Foundation time type. **/ @@ -96,4 +115,110 @@ NS_ASSUME_NONNULL_BEGIN @end +#pragma mark - GPBAny + +/** + * Category for GPBAny to help work with the message within the object. + **/ +@interface GPBAny (GBPWellKnownTypes) + +/** + * Convenience method to create a GPBAny containing the serialized message. + * This uses type.googleapis.com/ as the type_url's prefix. + * + * @param message The message to be packed into the GPBAny. + * @param errorPtr Pointer to an error that will be populated if something goes + * wrong. + * + * @return A newly configured GPBAny with the given message, or nil on failure. + */ ++ (nullable instancetype)anyWithMessage:(nonnull GPBMessage *)message + error:(NSError **)errorPtr; + +/** + * Convenience method to create a GPBAny containing the serialized message. + * + * @param message The message to be packed into the GPBAny. + * @param typeURLPrefix The URL prefix to apply for type_url. + * @param errorPtr Pointer to an error that will be populated if something + * goes wrong. + * + * @return A newly configured GPBAny with the given message, or nil on failure. + */ ++ (nullable instancetype)anyWithMessage:(nonnull GPBMessage *)message + typeURLPrefix:(nonnull NSString *)typeURLPrefix + error:(NSError **)errorPtr; + +/** + * Initializes a GPBAny to contain the serialized message. This uses + * type.googleapis.com/ as the type_url's prefix. + * + * @param message The message to be packed into the GPBAny. + * @param errorPtr Pointer to an error that will be populated if something goes + * wrong. + * + * @return A newly configured GPBAny with the given message, or nil on failure. + */ +- (nullable instancetype)initWithMessage:(nonnull GPBMessage *)message + error:(NSError **)errorPtr; + +/** + * Initializes a GPBAny to contain the serialized message. + * + * @param message The message to be packed into the GPBAny. + * @param typeURLPrefix The URL prefix to apply for type_url. + * @param errorPtr Pointer to an error that will be populated if something + * goes wrong. + * + * @return A newly configured GPBAny with the given message, or nil on failure. + */ +- (nullable instancetype)initWithMessage:(nonnull GPBMessage *)message + typeURLPrefix:(nonnull NSString *)typeURLPrefix + error:(NSError **)errorPtr; + +/** + * Packs the serialized message into this GPBAny. This uses + * type.googleapis.com/ as the type_url's prefix. + * + * @param message The message to be packed into the GPBAny. + * @param errorPtr Pointer to an error that will be populated if something goes + * wrong. + * + * @return Whether the packing was successful or not. + */ +- (BOOL)packWithMessage:(nonnull GPBMessage *)message + error:(NSError **)errorPtr; + +/** + * Packs the serialized message into this GPBAny. + * + * @param message The message to be packed into the GPBAny. + * @param typeURLPrefix The URL prefix to apply for type_url. + * @param errorPtr Pointer to an error that will be populated if something + * goes wrong. + * + * @return Whether the packing was successful or not. + */ +- (BOOL)packWithMessage:(nonnull GPBMessage *)message + typeURLPrefix:(nonnull NSString *)typeURLPrefix + error:(NSError **)errorPtr; + +/** + * Unpacks the serialized message as if it was an instance of the given class. + * + * @note When checking type_url, the base URL is not checked, only the fully + * qualified name. + * + * @param messageClass The class to use to deserialize the contained message. + * @param errorPtr Pointer to an error that will be populated if something + * goes wrong. + * + * @return An instance of the given class populated with the contained data, or + * nil on failure. + */ +- (nullable GPBMessage *)unpackMessageClass:(Class)messageClass + error:(NSError **)errorPtr; + +@end + NS_ASSUME_NONNULL_END diff --git a/objectivec/GPBWellKnownTypes.m b/objectivec/GPBWellKnownTypes.m index 5cdd62d5..ed798a2e 100644 --- a/objectivec/GPBWellKnownTypes.m +++ b/objectivec/GPBWellKnownTypes.m @@ -34,6 +34,13 @@ #import "GPBWellKnownTypes.h" +#import "GPBUtilities_PackagePrivate.h" + +NSString *const GPBWellKnownTypesErrorDomain = + GPBNSStringifySymbol(GPBWellKnownTypesErrorDomain); + +static NSString *kTypePrefixGoogleApisCom = @"type.googleapis.com/"; + static NSTimeInterval TimeIntervalSince1970FromSecondsAndNanos(int64_t seconds, int32_t nanos) { return seconds + (NSTimeInterval)nanos / 1e9; @@ -48,6 +55,30 @@ static int32_t SecondsAndNanosFromTimeIntervalSince1970(NSTimeInterval time, return (int32_t)nanos; } +static NSString *BuildTypeURL(NSString *typeURLPrefix, NSString *fullName) { + if (typeURLPrefix.length == 0) { + return fullName; + } + + if ([typeURLPrefix hasSuffix:@"/"]) { + return [typeURLPrefix stringByAppendingString:fullName]; + } + + return [NSString stringWithFormat:@"%@/%@", typeURLPrefix, fullName]; +} + +static NSString *ParseTypeFromURL(NSString *typeURLString) { + NSRange range = [typeURLString rangeOfString:@"/" options:NSBackwardsSearch]; + if ((range.location == NSNotFound) || + (NSMaxRange(range) == typeURLString.length)) { + return nil; + } + NSString *result = [typeURLString substringFromIndex:range.location + 1]; + return result; +} + +#pragma mark - GPBTimestamp + @implementation GPBTimestamp (GBPWellKnownTypes) - (instancetype)initWithDate:(NSDate *)date { @@ -87,6 +118,8 @@ static int32_t SecondsAndNanosFromTimeIntervalSince1970(NSTimeInterval time, @end +#pragma mark - GPBDuration + @implementation GPBDuration (GBPWellKnownTypes) - (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { @@ -113,3 +146,105 @@ static int32_t SecondsAndNanosFromTimeIntervalSince1970(NSTimeInterval time, } @end + +#pragma mark - GPBAny + +@implementation GPBAny (GBPWellKnownTypes) + ++ (instancetype)anyWithMessage:(GPBMessage *)message + error:(NSError **)errorPtr { + return [self anyWithMessage:message + typeURLPrefix:kTypePrefixGoogleApisCom + error:errorPtr]; +} + ++ (instancetype)anyWithMessage:(GPBMessage *)message + typeURLPrefix:(NSString *)typeURLPrefix + error:(NSError **)errorPtr { + return [[[self alloc] initWithMessage:message + typeURLPrefix:typeURLPrefix + error:errorPtr] autorelease]; +} + +- (instancetype)initWithMessage:(GPBMessage *)message + error:(NSError **)errorPtr { + return [self initWithMessage:message + typeURLPrefix:kTypePrefixGoogleApisCom + error:errorPtr]; +} + +- (instancetype)initWithMessage:(GPBMessage *)message + typeURLPrefix:(NSString *)typeURLPrefix + error:(NSError **)errorPtr { + self = [self init]; + if (self) { + if (![self packWithMessage:message + typeURLPrefix:typeURLPrefix + error:errorPtr]) { + [self release]; + self = nil; + } + } + return self; +} + +- (BOOL)packWithMessage:(GPBMessage *)message + error:(NSError **)errorPtr { + return [self packWithMessage:message + typeURLPrefix:kTypePrefixGoogleApisCom + error:errorPtr]; +} + +- (BOOL)packWithMessage:(GPBMessage *)message + typeURLPrefix:(NSString *)typeURLPrefix + error:(NSError **)errorPtr { + NSString *fullName = [message descriptor].fullName; + if (fullName.length == 0) { + if (errorPtr) { + *errorPtr = + [NSError errorWithDomain:GPBWellKnownTypesErrorDomain + code:GPBWellKnownTypesErrorCodeFailedToComputeTypeURL + userInfo:nil]; + } + return NO; + } + if (errorPtr) { + *errorPtr = nil; + } + self.typeURL = BuildTypeURL(typeURLPrefix, fullName); + self.value = message.data; + return YES; +} + +- (GPBMessage *)unpackMessageClass:(Class)messageClass + error:(NSError **)errorPtr { + NSString *fullName = [messageClass descriptor].fullName; + if (fullName.length == 0) { + if (errorPtr) { + *errorPtr = + [NSError errorWithDomain:GPBWellKnownTypesErrorDomain + code:GPBWellKnownTypesErrorCodeFailedToComputeTypeURL + userInfo:nil]; + } + return nil; + } + + NSString *expectedFullName = ParseTypeFromURL(self.typeURL); + if ((expectedFullName == nil) || ![expectedFullName isEqual:fullName]) { + if (errorPtr) { + *errorPtr = + [NSError errorWithDomain:GPBWellKnownTypesErrorDomain + code:GPBWellKnownTypesErrorCodeTypeURLMismatch + userInfo:nil]; + } + return nil; + } + + // Any is proto3, which means no extensions, so this assumes anything put + // within an any also won't need extensions. A second helper could be added + // if needed. + return [messageClass parseFromData:self.value + error:errorPtr]; +} + +@end diff --git a/objectivec/Tests/GPBDescriptorTests.m b/objectivec/Tests/GPBDescriptorTests.m index 74e3172b..1e1c3de8 100644 --- a/objectivec/Tests/GPBDescriptorTests.m +++ b/objectivec/Tests/GPBDescriptorTests.m @@ -34,12 +34,41 @@ #import "GPBDescriptor.h" #import "google/protobuf/Unittest.pbobjc.h" +#import "google/protobuf/UnittestObjc.pbobjc.h" +#import "google/protobuf/Descriptor.pbobjc.h" @interface DescriptorTests : GPBTestCase @end @implementation DescriptorTests +- (void)testDescriptor_containingType { + GPBDescriptor *testAllTypesDesc = [TestAllTypes descriptor]; + GPBDescriptor *nestedMessageDesc = [TestAllTypes_NestedMessage descriptor]; + XCTAssertNil(testAllTypesDesc.containingType); + XCTAssertNotNil(nestedMessageDesc.containingType); + XCTAssertEqual(nestedMessageDesc.containingType, testAllTypesDesc); // Ptr comparison +} + +- (void)testDescriptor_fullName { + GPBDescriptor *testAllTypesDesc = [TestAllTypes descriptor]; + XCTAssertEqualObjects(testAllTypesDesc.fullName, @"protobuf_unittest.TestAllTypes"); + GPBDescriptor *nestedMessageDesc = [TestAllTypes_NestedMessage descriptor]; + XCTAssertEqualObjects(nestedMessageDesc.fullName, @"protobuf_unittest.TestAllTypes.NestedMessage"); + + // Prefixes removed. + GPBDescriptor *descDesc = [GPBDescriptorProto descriptor]; + XCTAssertEqualObjects(descDesc.fullName, @"google.protobuf.DescriptorProto"); + GPBDescriptor *descExtRngDesc = [GPBDescriptorProto_ExtensionRange descriptor]; + XCTAssertEqualObjects(descExtRngDesc.fullName, @"google.protobuf.DescriptorProto.ExtensionRange"); + + // Things that get "_Class" added. + GPBDescriptor *pointDesc = [Point_Class descriptor]; + XCTAssertEqualObjects(pointDesc.fullName, @"protobuf_unittest.Point"); + GPBDescriptor *pointRectDesc = [Point_Rect descriptor]; + XCTAssertEqualObjects(pointRectDesc.fullName, @"protobuf_unittest.Point.Rect"); +} + - (void)testFieldDescriptor { GPBDescriptor *descriptor = [TestAllTypes descriptor]; diff --git a/objectivec/Tests/GPBUnittestProtos.m b/objectivec/Tests/GPBUnittestProtos.m index 7b938e72..8d2948bf 100644 --- a/objectivec/Tests/GPBUnittestProtos.m +++ b/objectivec/Tests/GPBUnittestProtos.m @@ -36,6 +36,7 @@ // a descriptor as it doesn't use the classes/enums. #import "google/protobuf/Descriptor.pbobjc.m" +#import "google/protobuf/AnyTest.pbobjc.m" #import "google/protobuf/MapProto2Unittest.pbobjc.m" #import "google/protobuf/MapUnittest.pbobjc.m" #import "google/protobuf/Unittest.pbobjc.m" diff --git a/objectivec/Tests/GPBWellKnownTypesTest.m b/objectivec/Tests/GPBWellKnownTypesTest.m index 78f4e637..041841dd 100644 --- a/objectivec/Tests/GPBWellKnownTypesTest.m +++ b/objectivec/Tests/GPBWellKnownTypesTest.m @@ -32,6 +32,8 @@ #import +#import "google/protobuf/AnyTest.pbobjc.h" + // A basically random interval into the future for testing with. static const NSTimeInterval kFutureOffsetInterval = 15000; @@ -99,4 +101,58 @@ static const NSTimeInterval kTimeAccuracy = 1e-9; [duration2 release]; } +- (void)testAnyHelpers { + + // Set and extract covers most of the code. + + TestAny *subMessage = [TestAny message]; + subMessage.int32Value = 12345; + TestAny *message = [TestAny message]; + NSError *err = nil; + message.anyValue = [GPBAny anyWithMessage:subMessage error:&err]; + XCTAssertNil(err); + + NSData *data = message.data; + XCTAssertNotNil(data); + + TestAny *message2 = [TestAny parseFromData:data error:&err]; + XCTAssertNil(err); + XCTAssertNotNil(message2); + XCTAssertTrue(message2.hasAnyValue); + + TestAny *subMessage2 = + (TestAny *)[message.anyValue unpackMessageClass:[TestAny class] + error:&err]; + XCTAssertNil(err); + XCTAssertNotNil(subMessage2); + XCTAssertEqual(subMessage2.int32Value, 12345); + + // NULL errorPtr in the two calls. + + message.anyValue = [GPBAny anyWithMessage:subMessage error:NULL]; + NSData *data2 = message.data; + XCTAssertEqualObjects(data2, data); + + TestAny *subMessage3 = + (TestAny *)[message.anyValue unpackMessageClass:[TestAny class] + error:NULL]; + XCTAssertNotNil(subMessage3); + XCTAssertEqualObjects(subMessage2, subMessage3); + + // Try to extract wrong type. + + GPBTimestamp *wrongMessage = + (GPBTimestamp *)[message.anyValue unpackMessageClass:[GPBTimestamp class] + error:&err]; + XCTAssertNotNil(err); + XCTAssertNil(wrongMessage); + XCTAssertEqualObjects(err.domain, GPBWellKnownTypesErrorDomain); + XCTAssertEqual(err.code, GPBWellKnownTypesErrorCodeTypeURLMismatch); + + wrongMessage = + (GPBTimestamp *)[message.anyValue unpackMessageClass:[GPBTimestamp class] + error:NULL]; + XCTAssertNil(wrongMessage); +} + @end diff --git a/objectivec/google/protobuf/Any.pbobjc.h b/objectivec/google/protobuf/Any.pbobjc.h index 842052fe..b88b786a 100644 --- a/objectivec/google/protobuf/Any.pbobjc.h +++ b/objectivec/google/protobuf/Any.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/Any.pbobjc.m b/objectivec/google/protobuf/Any.pbobjc.m index deaedc16..50448cb1 100644 --- a/objectivec/google/protobuf/Any.pbobjc.m +++ b/objectivec/google/protobuf/Any.pbobjc.m @@ -41,6 +41,7 @@ static GPBFileDescriptor *GPBAnyRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; diff --git a/objectivec/google/protobuf/Api.pbobjc.h b/objectivec/google/protobuf/Api.pbobjc.h index 182e866c..3750e093 100644 --- a/objectivec/google/protobuf/Api.pbobjc.h +++ b/objectivec/google/protobuf/Api.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/Api.pbobjc.m b/objectivec/google/protobuf/Api.pbobjc.m index e73ecf85..5736c818 100644 --- a/objectivec/google/protobuf/Api.pbobjc.m +++ b/objectivec/google/protobuf/Api.pbobjc.m @@ -45,6 +45,7 @@ static GPBFileDescriptor *GPBApiRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; diff --git a/objectivec/google/protobuf/Duration.pbobjc.h b/objectivec/google/protobuf/Duration.pbobjc.h index fa91e223..090eb002 100644 --- a/objectivec/google/protobuf/Duration.pbobjc.h +++ b/objectivec/google/protobuf/Duration.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/Duration.pbobjc.m b/objectivec/google/protobuf/Duration.pbobjc.m index 79fbe007..70792768 100644 --- a/objectivec/google/protobuf/Duration.pbobjc.m +++ b/objectivec/google/protobuf/Duration.pbobjc.m @@ -41,6 +41,7 @@ static GPBFileDescriptor *GPBDurationRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; diff --git a/objectivec/google/protobuf/Empty.pbobjc.h b/objectivec/google/protobuf/Empty.pbobjc.h index 4d36174d..e0ed3e16 100644 --- a/objectivec/google/protobuf/Empty.pbobjc.h +++ b/objectivec/google/protobuf/Empty.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/Empty.pbobjc.m b/objectivec/google/protobuf/Empty.pbobjc.m index 83cede25..f4f21f65 100644 --- a/objectivec/google/protobuf/Empty.pbobjc.m +++ b/objectivec/google/protobuf/Empty.pbobjc.m @@ -41,6 +41,7 @@ static GPBFileDescriptor *GPBEmptyRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.h b/objectivec/google/protobuf/FieldMask.pbobjc.h index 491463f9..14ed5379 100644 --- a/objectivec/google/protobuf/FieldMask.pbobjc.h +++ b/objectivec/google/protobuf/FieldMask.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.m b/objectivec/google/protobuf/FieldMask.pbobjc.m index 906e3cbd..d4cceee9 100644 --- a/objectivec/google/protobuf/FieldMask.pbobjc.m +++ b/objectivec/google/protobuf/FieldMask.pbobjc.m @@ -41,6 +41,7 @@ static GPBFileDescriptor *GPBFieldMaskRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.h b/objectivec/google/protobuf/SourceContext.pbobjc.h index d9450057..417562c0 100644 --- a/objectivec/google/protobuf/SourceContext.pbobjc.h +++ b/objectivec/google/protobuf/SourceContext.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.m b/objectivec/google/protobuf/SourceContext.pbobjc.m index 5c6ca6c0..d80231a5 100644 --- a/objectivec/google/protobuf/SourceContext.pbobjc.m +++ b/objectivec/google/protobuf/SourceContext.pbobjc.m @@ -41,6 +41,7 @@ static GPBFileDescriptor *GPBSourceContextRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; diff --git a/objectivec/google/protobuf/Struct.pbobjc.h b/objectivec/google/protobuf/Struct.pbobjc.h index a5b31cd0..163b39ba 100644 --- a/objectivec/google/protobuf/Struct.pbobjc.h +++ b/objectivec/google/protobuf/Struct.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/Struct.pbobjc.m b/objectivec/google/protobuf/Struct.pbobjc.m index 55c135e6..02f7d24a 100644 --- a/objectivec/google/protobuf/Struct.pbobjc.m +++ b/objectivec/google/protobuf/Struct.pbobjc.m @@ -42,6 +42,7 @@ static GPBFileDescriptor *GPBStructRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.h b/objectivec/google/protobuf/Timestamp.pbobjc.h index ebfa670f..094e9b6b 100644 --- a/objectivec/google/protobuf/Timestamp.pbobjc.h +++ b/objectivec/google/protobuf/Timestamp.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.m b/objectivec/google/protobuf/Timestamp.pbobjc.m index 5e4d5cc1..7c57b4f5 100644 --- a/objectivec/google/protobuf/Timestamp.pbobjc.m +++ b/objectivec/google/protobuf/Timestamp.pbobjc.m @@ -41,6 +41,7 @@ static GPBFileDescriptor *GPBTimestampRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; diff --git a/objectivec/google/protobuf/Type.pbobjc.h b/objectivec/google/protobuf/Type.pbobjc.h index 05411958..da923c30 100644 --- a/objectivec/google/protobuf/Type.pbobjc.h +++ b/objectivec/google/protobuf/Type.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/Type.pbobjc.m b/objectivec/google/protobuf/Type.pbobjc.m index b48f4d0f..dfe11860 100644 --- a/objectivec/google/protobuf/Type.pbobjc.m +++ b/objectivec/google/protobuf/Type.pbobjc.m @@ -45,6 +45,7 @@ static GPBFileDescriptor *GPBTypeRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.h b/objectivec/google/protobuf/Wrappers.pbobjc.h index e397c480..2bf6fd29 100644 --- a/objectivec/google/protobuf/Wrappers.pbobjc.h +++ b/objectivec/google/protobuf/Wrappers.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.m b/objectivec/google/protobuf/Wrappers.pbobjc.m index ebf8e228..73a13842 100644 --- a/objectivec/google/protobuf/Wrappers.pbobjc.m +++ b/objectivec/google/protobuf/Wrappers.pbobjc.m @@ -41,6 +41,7 @@ static GPBFileDescriptor *GPBWrappersRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index f70d4d5f..685ed56d 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -53,7 +53,7 @@ namespace { // This is also found in GPBBootstrap.h, and needs to be kept in sync. It // is the version check done to ensure generated code works with the current // runtime being used. -const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30001; +const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30002; const char* kHeaderExtension = ".pbobjc.h"; @@ -463,19 +463,22 @@ void FileGenerator::GenerateSource(io::Printer *printer) { // File descriptor only needed if there are messages to use it. if (message_generators_.size() > 0) { - string syntax; + map vars; + vars["root_class_name"] = root_class_name_; + vars["package"] = file_->package(); + vars["objc_prefix"] = FileClassPrefix(file_); switch (file_->syntax()) { case FileDescriptor::SYNTAX_UNKNOWN: - syntax = "GPBFileSyntaxUnknown"; + vars["syntax"] = "GPBFileSyntaxUnknown"; break; case FileDescriptor::SYNTAX_PROTO2: - syntax = "GPBFileSyntaxProto2"; + vars["syntax"] = "GPBFileSyntaxProto2"; break; case FileDescriptor::SYNTAX_PROTO3: - syntax = "GPBFileSyntaxProto3"; + vars["syntax"] = "GPBFileSyntaxProto3"; break; } - printer->Print( + printer->Print(vars, "#pragma mark - $root_class_name$_FileDescriptor\n" "\n" "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n" @@ -483,16 +486,24 @@ void FileGenerator::GenerateSource(io::Printer *printer) { " // about thread safety of the singleton.\n" " static GPBFileDescriptor *descriptor = NULL;\n" " if (!descriptor) {\n" - " GPBDebugCheckRuntimeVersion();\n" - " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" - " syntax:$syntax$];\n" + " GPBDebugCheckRuntimeVersion();\n"); + if (vars["objc_prefix"].size() > 0) { + printer->Print( + vars, + " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" + " objcPrefix:@\"$objc_prefix$\"\n" + " syntax:$syntax$];\n"); + } else { + printer->Print( + vars, + " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" + " syntax:$syntax$];\n"); + } + printer->Print( " }\n" " return descriptor;\n" "}\n" - "\n", - "root_class_name", root_class_name_, - "package", file_->package(), - "syntax", syntax); + "\n"); } for (vector::iterator iter = enum_generators_.begin(); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc index 847be983..2fe0016a 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -210,10 +210,14 @@ const char* const kReservedWordList[] = { hash_set kReservedWords = MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList)); -string SanitizeNameForObjC(const string& input, const string& extension) { +string SanitizeNameForObjC(const string& input, + const string& extension, + string* out_suffix_added) { if (kReservedWords.count(input) > 0) { + if (out_suffix_added) *out_suffix_added = extension; return input + extension; } + if (out_suffix_added) out_suffix_added->clear(); return input; } @@ -308,6 +312,12 @@ string BaseFileName(const FileDescriptor* file) { return basename; } +string FileClassPrefix(const FileDescriptor* file) { + // Default is empty string, no need to check has_objc_class_prefix. + string result = file->options().objc_class_prefix(); + return result; +} + string FilePath(const FileDescriptor* file) { string output; string basename; @@ -338,19 +348,13 @@ string FilePathBasename(const FileDescriptor* file) { return output; } -string FileClassPrefix(const FileDescriptor* file) { - // Default is empty string, no need to check has_objc_class_prefix. - string result = file->options().objc_class_prefix(); - return result; -} - string FileClassName(const FileDescriptor* file) { string name = FileClassPrefix(file); name += UnderscoresToCamelCase(StripProto(BaseFileName(file)), true); name += "Root"; // There aren't really any reserved words that end in "Root", but playing // it safe and checking. - return SanitizeNameForObjC(name, "_RootClass"); + return SanitizeNameForObjC(name, "_RootClass", NULL); } string ClassNameWorker(const Descriptor* descriptor) { @@ -372,11 +376,15 @@ string ClassNameWorker(const EnumDescriptor* descriptor) { } string ClassName(const Descriptor* descriptor) { + return ClassName(descriptor, NULL); +} + +string ClassName(const Descriptor* descriptor, string* out_suffix_added) { // 1. Message names are used as is (style calls for CamelCase, trust it). // 2. Check for reserved word at the very end and then suffix things. string prefix = FileClassPrefix(descriptor->file()); string name = ClassNameWorker(descriptor); - return SanitizeNameForObjC(prefix + name, "_Class"); + return SanitizeNameForObjC(prefix + name, "_Class", out_suffix_added); } string EnumName(const EnumDescriptor* descriptor) { @@ -390,7 +398,7 @@ string EnumName(const EnumDescriptor* descriptor) { // yields Fixed_Class, Fixed_Size. string name = FileClassPrefix(descriptor->file()); name += ClassNameWorker(descriptor); - return SanitizeNameForObjC(name, "_Enum"); + return SanitizeNameForObjC(name, "_Enum", NULL); } string EnumValueName(const EnumValueDescriptor* descriptor) { @@ -405,7 +413,7 @@ string EnumValueName(const EnumValueDescriptor* descriptor) { const string& name = class_name + "_" + value_str; // There aren't really any reserved words with an underscore and a leading // capital letter, but playing it safe and checking. - return SanitizeNameForObjC(name, "_Value"); + return SanitizeNameForObjC(name, "_Value", NULL); } string EnumValueShortName(const EnumValueDescriptor* descriptor) { @@ -442,7 +450,7 @@ string UnCamelCaseEnumShortName(const string& name) { string ExtensionMethodName(const FieldDescriptor* descriptor) { const string& name = NameFromFieldDescriptor(descriptor); const string& result = UnderscoresToCamelCase(name, false); - return SanitizeNameForObjC(result, "_Extension"); + return SanitizeNameForObjC(result, "_Extension", NULL); } string FieldName(const FieldDescriptor* field) { @@ -457,7 +465,7 @@ string FieldName(const FieldDescriptor* field) { result += "_p"; } } - return SanitizeNameForObjC(result, "_p"); + return SanitizeNameForObjC(result, "_p", NULL); } string FieldNameCapitalized(const FieldDescriptor* field) { diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h index b05983df..022b7a1b 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -67,6 +67,9 @@ bool IsRetainedName(const string& name); // handling under ARC. bool IsInitName(const string& name); +// Gets the objc_class_prefix. +string FileClassPrefix(const FileDescriptor* file); + // Gets the path of the file we're going to generate (sans the .pb.h // extension). The path will be dependent on the objectivec package // declared in the proto package. @@ -83,6 +86,7 @@ string FileClassName(const FileDescriptor* file); // These return the fully-qualified class name corresponding to the given // descriptor. string ClassName(const Descriptor* descriptor); +string ClassName(const Descriptor* descriptor, string* out_suffix_added); string EnumName(const EnumDescriptor* descriptor); // Returns the fully-qualified name of the enum value corresponding to the diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc index 822da893..7c5fe311 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc @@ -579,6 +579,19 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { " [localDescriptor setupExtensionRanges:ranges\n" " count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n"); } + if (descriptor_->containing_type() != NULL) { + string parent_class_name = ClassName(descriptor_->containing_type()); + printer->Print( + " [localDescriptor setupContainingMessageClassName:GPBStringifySymbol($parent_name$)];\n", + "parent_name", parent_class_name); + } + string suffix_added; + ClassName(descriptor_, &suffix_added); + if (suffix_added.size() > 0) { + printer->Print( + " [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n", + "suffix", suffix_added); + } printer->Print( " NSAssert(descriptor == nil, @\"Startup recursed!\");\n" " descriptor = localDescriptor;\n" -- cgit v1.2.3 From 1327e6f4700f31c09d427230e8fa6b5bdb7df6cc Mon Sep 17 00:00:00 2001 From: Adrian Ludwin Date: Fri, 9 Sep 2016 12:45:37 -0400 Subject: Update repo to use google test --- WORKSPACE | 24 ++++++++++++------------ gmock.BUILD | 20 ++++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index 065dc819..df919ad1 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -1,15 +1,15 @@ -new_http_archive( - name = "gmock_archive", - url = "https://googlemock.googlecode.com/files/gmock-1.7.0.zip", - sha256 = "26fcbb5925b74ad5fc8c26b0495dfc96353f4d553492eb97e85a8a6d2f43095b", +new_git_repository( + name = "googletest", build_file = "gmock.BUILD", + remote = "https://github.com/google/googletest", + tag = "release-1.8.0", ) new_http_archive( name = "six_archive", - url = "https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz#md5=34eed507548117b2ab523ab14b2f8b55", - sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a", build_file = "six.BUILD", + sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a", + url = "https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz#md5=34eed507548117b2ab523ab14b2f8b55", ) bind( @@ -19,12 +19,12 @@ bind( bind( name = "gtest", - actual = "@gmock_archive//:gtest", + actual = "@googletest//:gtest", ) bind( name = "gtest_main", - actual = "@gmock_archive//:gtest_main", + actual = "@googletest//:gtest_main", ) bind( @@ -33,8 +33,8 @@ bind( ) maven_jar( - name = "guava_maven", - artifact = "com.google.guava:guava:18.0", + name = "guava_maven", + artifact = "com.google.guava:guava:18.0", ) bind( @@ -43,8 +43,8 @@ bind( ) maven_jar( - name = "gson_maven", - artifact = "com.google.code.gson:gson:2.3", + name = "gson_maven", + artifact = "com.google.code.gson:gson:2.3", ) bind( diff --git a/gmock.BUILD b/gmock.BUILD index 82abf275..b1ae15a9 100644 --- a/gmock.BUILD +++ b/gmock.BUILD @@ -1,19 +1,19 @@ cc_library( name = "gtest", srcs = [ - "gmock-1.7.0/gtest/src/gtest-all.cc", - "gmock-1.7.0/src/gmock-all.cc", + "googletest/src/gtest-all.cc", + "googlemock/src/gmock-all.cc", ], hdrs = glob([ - "gmock-1.7.0/**/*.h", - "gmock-1.7.0/gtest/src/*.cc", - "gmock-1.7.0/src/*.cc", + "**/*.h", + "googletest/src/*.cc", + "googlemock/src/*.cc", ]), includes = [ - "gmock-1.7.0", - "gmock-1.7.0/gtest", - "gmock-1.7.0/gtest/include", - "gmock-1.7.0/include", + "googlemock", + "googletest", + "googletest/include", + "googlemock/include", ], linkopts = ["-pthread"], visibility = ["//visibility:public"], @@ -21,7 +21,7 @@ cc_library( cc_library( name = "gtest_main", - srcs = ["gmock-1.7.0/src/gmock_main.cc"], + srcs = ["googlemock/src/gmock_main.cc"], linkopts = ["-pthread"], visibility = ["//visibility:public"], deps = [":gtest"], -- cgit v1.2.3