[ObjC] Scrub "syntax" references and editions prep

Scrub all the objc related sources for references to "syntax"
and update them to no longer tie things accordingly.

The ObjC Protos `GPBFileDescriptor` concept still exposes the
`syntax`, but it was already marked as deprecated. This will be
removed in the future as nothing should need to look at the value.

Validate that all generation calls are on the helpers to get the
editions support from the C++ code.

PiperOrigin-RevId: 555971288
pull/13521/head
Thomas Van Lenten 2023-08-11 08:59:53 -07:00 committed by Copybara-Service
parent 2eee41224e
commit ff259f71c5
10 changed files with 33 additions and 48 deletions

View File

@ -47,6 +47,8 @@ typedef NS_ENUM(uint8_t, GPBFileSyntax) {
GPBFileSyntaxProto2 = 2,
/** Proto3 syntax. */
GPBFileSyntaxProto3 = 3,
/** Editions syntax. */
GPBFileSyntaxProtoEditions = 99,
};
/** Type of proto field. */
@ -135,16 +137,9 @@ __attribute__((objc_subclassing_restricted))
@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.
*
* This should not be used for making decisions about support
* features/behaviors, what proto2 vs. proto3 syntax has meant has evolved over
* time, and not more specific methods on the descriptors should be used
* instead.
*/
/** The syntax of the proto file, this property will be removed in the future. */
@property(nonatomic, readonly) GPBFileSyntax syntax
__attribute__((deprecated("Syntax is not a good way to decide things about behaviors.")));
__attribute__((deprecated("Syntax will be removed in the future.")));
@end

View File

@ -275,7 +275,7 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, NSArray *allMessageField
// only wrong in the rare cases an enum is declared in a proto3 syntax
// file but used for a field in the proto2 syntax file.
BOOL isClosedEnum =
(coreDesc->dataType == GPBDataTypeEnum && fileSyntax != GPBFileSyntaxProto3);
(coreDesc->dataType == GPBDataTypeEnum && fileSyntax == GPBFileSyntaxProto2);
if (isClosedEnum) {
coreDesc->flags |= GPBFieldClosedEnum;
}

View File

@ -128,8 +128,8 @@ typedef struct GPBMessageFieldDescription {
GPBDataType dataType;
} GPBMessageFieldDescription;
// Fields in messages defined in a 'proto2' syntax file can provide a default
// value. This struct provides the default along with the field info.
// If a message uses fields where they provide default values that are non zero, then this
// struct is used to provide the values along with the field info.
typedef struct GPBMessageFieldDescriptionWithDefault {
// Default value for the ivar.
GPBGenericValue defaultValue;

View File

@ -94,9 +94,6 @@ CF_EXTERN_C_END
/**
* The set of unknown fields for this message.
*
* Only messages from proto files declared with "proto2" syntax support unknown
* fields.
**/
@property(nonatomic, copy, nullable) GPBUnknownFieldSet *unknownFields;

View File

@ -992,8 +992,6 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
static GPBDescriptor *descriptor = NULL;
static GPBFileDescriptor *fileDescriptor = NULL;
if (!descriptor) {
// Use a dummy file that marks it as proto2 syntax so when used generically
// it supports unknowns/etc.
fileDescriptor = [[GPBFileDescriptor alloc] initWithPackage:@"internal"
syntax:GPBFileSyntaxProto2];

View File

@ -36,8 +36,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
* A collection of unknown fields. Fields parsed from the binary representation
* of a message that are unknown end up in an instance of this set. This only
* applies for files declared with the "proto2" syntax.
* of a message that are unknown end up in an instance of this set.
**/
__attribute__((objc_subclassing_restricted))
@interface GPBUnknownFieldSet : NSObject<NSCopying>

View File

@ -112,15 +112,13 @@ causing it to be created for you. For this, there is always a `\[NAME\]_Count`
property also provided that can return zero or the real count, but won't trigger
the creation.
For primitive type fields (ints, floats, bools, enum) in messages defined in a
`.proto` file that use *proto2* syntax there are conceptual differences between
having an *explicit* and *default* value. You can always get the value of the
property. In the case that it hasn't been set you will get the default. In
cases where you need to know whether it was set explicitly or you are just
getting the default, you can use the `has\[NAME\]` property. If the value has
been set, and you want to clear it, you can set the `has\[NAME\]` to `NO`.
*proto3* syntax messages do away with this concept, thus the default values are
never included when the message is encoded.
All message fields *always* have a value when accessed. For primitive type
fields (ints, floats, bools, enum) there the concept of *presence*, that allows
you to tell the difference between when the field is the *default* value because
it *was not* set and when it *was* set, but *explicitly* to the *default*
value for the field. For fields with that do support *presence*, you can test
if the value was *explicitly* set via the `has\[NAME\]` property. If the value
has been set, and you want to clear it, you can set the `has\[NAME\]` to `NO`.
The Objective C classes/enums can be used from Swift code.

View File

@ -91,16 +91,16 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) const {
// Swift 5 included SE0192 "Handling Future Enum Cases"
// https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
// Since a .proto file can get new values added to an enum at any time, they
// are effectively "non-frozen". Even in a proto3 syntax file where there is
// support for the unknown value, an edit to the file can always add a new
// value moving something from unknown to known. Since Swift is now ABI
// stable, it also means a binary could contain Swift compiled against one
// version of the .pbobjc.h file, but finally linked against an enum with
// more cases. So the Swift code will always have to treat ObjC Proto Enums
// as "non-frozen". The default behavior in SE0192 is for all objc enums to
// be "non-frozen" unless marked as otherwise, so this means this generation
// doesn't have to bother with the `enum_extensibility` attribute, as the
// default will be what is needed.
// are effectively "non-frozen". Even with an EnumType::Open there is support
// for the unknown value, an edit to the file can always add a new value
// moving something from unknown to known. Since Swift is ABI stable, it also
// means a binary could contain Swift compiled against one version of the
// .pbobjc.h file, but finally linked against an enum with more cases. So the
// Swift code will always have to treat ObjC Proto Enums as "non-frozen". The
// default behavior in SE0192 is for all objc enums to be "non-frozen" unless
// marked as otherwise, so this means this generation doesn't have to bother
// with the `enum_extensibility` clang attribute, as the default will be what
// is needed.
printer->Emit(
{

View File

@ -126,14 +126,9 @@ bool HasNonZeroDefaultValue(const FieldDescriptor* field) {
return false;
}
// As much as checking field->has_default_value() seems useful, it isn't
// because of enums. proto2 syntax allows the first item in an enum (the
// default) to be non zero. So checking field->has_default_value() would
// result in missing this non zero default. See MessageWithOneBasedEnum in
// objectivec/Tests/unittest_objc.proto for a test Message to confirm this.
// Some proto file set the default to the zero value, so make sure the value
// isn't the zero case.
// Some proto files set the default to the zero value, so make sure the value
// isn't the zero case instead of relying on has_default_value() to tell when
// non zero.
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32:
return field->default_value_int32() != 0;
@ -151,9 +146,12 @@ bool HasNonZeroDefaultValue(const FieldDescriptor* field) {
return field->default_value_bool();
case FieldDescriptor::CPPTYPE_STRING: {
const std::string& default_string = field->default_value_string();
return default_string.length() != 0;
return !default_string.empty();
}
case FieldDescriptor::CPPTYPE_ENUM:
// The default value for an enum field is the first enum value, so there
// even more reason we can't use has_default_value() for checking for
// zero.
return field->default_value_enum()->number() != 0;
case FieldDescriptor::CPPTYPE_MESSAGE:
return false;

View File

@ -223,7 +223,7 @@ MessageGenerator::MessageGenerator(const std::string& file_description_name,
GetOptionalDeprecatedAttribute(descriptor, descriptor->file())) {
for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
oneof_generators_.push_back(
std::make_unique<OneofGenerator>(descriptor_->oneof_decl(i)));
std::make_unique<OneofGenerator>(descriptor_->real_oneof_decl(i)));
}
// Assign has bits: