Commit a989501f authored by Sergio Campamá's avatar Sergio Campamá Committed by Jisi Liu

Adds support for appledoc in generated code. (#1928)

Convert mapping of proto comments to appledoc format so they show up in Xcode and cocoadocs.

Fixes https://github.com/google/protobuf/issues/1866
parent 42ab9b44
......@@ -34,6 +34,15 @@ import "google/protobuf/unittest.proto";
package protobuf_unittest;
// Used to check that Headerdocs and appledoc work correctly. If these comments
// are not handled correctly, Xcode will fail to build the tests.
message TestGeneratedComments {
// This is a string that could contain stuff like
// mime types as image/* or */plain. Maybe twitter usernames
// like @protobuf, @google or @something.
optional string string_field = 1;
}
// Using the messages in unittest.proto, setup for recursive cases for testing
// extensions at various depths.
extend TestAllExtensions {
......
......@@ -28,14 +28,16 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - GPBAnyRoot
/// Exposes the extension registry for this file.
///
/// The base class provides:
/// @code
/// + (GPBExtensionRegistry *)extensionRegistry;
/// @endcode
/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
/// this file and all files that it depends on.
/**
* Exposes the extension registry for this file.
*
* The base class provides:
* @code
* + (GPBExtensionRegistry *)extensionRegistry;
* @endcode
* which is a @c GPBExtensionRegistry that includes all the extensions defined by
* this file and all files that it depends on.
**/
@interface GPBAnyRoot : GPBRootObject
@end
......@@ -46,101 +48,105 @@ typedef GPB_ENUM(GPBAny_FieldNumber) {
GPBAny_FieldNumber_Value = 2,
};
/// `Any` contains an arbitrary serialized protocol buffer message along with a
/// URL that describes the type of the serialized message.
///
/// Protobuf library provides support to pack/unpack Any values in the form
/// of utility functions or additional generated methods of the Any type.
///
/// Example 1: Pack and unpack a message in C++.
///
/// Foo foo = ...;
/// Any any;
/// any.PackFrom(foo);
/// ...
/// if (any.UnpackTo(&foo)) {
/// ...
/// }
///
/// Example 2: Pack and unpack a message in Java.
///
/// Foo foo = ...;
/// Any any = Any.pack(foo);
/// ...
/// if (any.is(Foo.class)) {
/// foo = any.unpack(Foo.class);
/// }
///
/// Example 3: Pack and unpack a message in Python.
///
/// foo = Foo(...)
/// any = Any()
/// any.Pack(foo)
/// ...
/// if any.Is(Foo.DESCRIPTOR):
/// any.Unpack(foo)
/// ...
///
/// The pack methods provided by protobuf library will by default use
/// 'type.googleapis.com/full.type.name' as the type URL and the unpack
/// methods only use the fully qualified type name after the last '/'
/// in the type URL, for example "foo.bar.com/x/y.z" will yield type
/// name "y.z".
///
///
/// JSON
/// ====
/// The JSON representation of an `Any` value uses the regular
/// representation of the deserialized, embedded message, with an
/// additional field `\@type` which contains the type URL. Example:
///
/// package google.profile;
/// message Person {
/// string first_name = 1;
/// string last_name = 2;
/// }
///
/// {
/// "\@type": "type.googleapis.com/google.profile.Person",
/// "firstName": <string>,
/// "lastName": <string>
/// }
///
/// If the embedded message type is well-known and has a custom JSON
/// representation, that representation will be embedded adding a field
/// `value` which holds the custom JSON in addition to the `\@type`
/// field. Example (for message [google.protobuf.Duration][]):
///
/// {
/// "\@type": "type.googleapis.com/google.protobuf.Duration",
/// "value": "1.212s"
/// }
/**
* `Any` contains an arbitrary serialized protocol buffer message along with a
* URL that describes the type of the serialized message.
*
* Protobuf library provides support to pack/unpack Any values in the form
* of utility functions or additional generated methods of the Any type.
*
* Example 1: Pack and unpack a message in C++.
*
* Foo foo = ...;
* Any any;
* any.PackFrom(foo);
* ...
* if (any.UnpackTo(&foo)) {
* ...
* }
*
* Example 2: Pack and unpack a message in Java.
*
* Foo foo = ...;
* Any any = Any.pack(foo);
* ...
* if (any.is(Foo.class)) {
* foo = any.unpack(Foo.class);
* }
*
* Example 3: Pack and unpack a message in Python.
*
* foo = Foo(...)
* any = Any()
* any.Pack(foo)
* ...
* if any.Is(Foo.DESCRIPTOR):
* any.Unpack(foo)
* ...
*
* The pack methods provided by protobuf library will by default use
* 'type.googleapis.com/full.type.name' as the type URL and the unpack
* methods only use the fully qualified type name after the last '/'
* in the type URL, for example "foo.bar.com/x/y.z" will yield type
* name "y.z".
*
*
* JSON
* ====
* The JSON representation of an `Any` value uses the regular
* representation of the deserialized, embedded message, with an
* additional field `\@type` which contains the type URL. Example:
*
* package google.profile;
* message Person {
* string first_name = 1;
* string last_name = 2;
* }
*
* {
* "\@type": "type.googleapis.com/google.profile.Person",
* "firstName": <string>,
* "lastName": <string>
* }
*
* If the embedded message type is well-known and has a custom JSON
* representation, that representation will be embedded adding a field
* `value` which holds the custom JSON in addition to the `\@type`
* field. Example (for message [google.protobuf.Duration][]):
*
* {
* "\@type": "type.googleapis.com/google.protobuf.Duration",
* "value": "1.212s"
* }
**/
@interface GPBAny : GPBMessage
/// A URL/resource name whose content describes the type of the
/// serialized protocol buffer message.
///
/// For URLs which use the scheme `http`, `https`, or no scheme, the
/// following restrictions and interpretations apply:
///
/// * If no scheme is provided, `https` is assumed.
/// * The last segment of the URL's path must represent the fully
/// qualified name of the type (as in `path/google.protobuf.Duration`).
/// The name should be in a canonical form (e.g., leading "." is
/// not accepted).
/// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
/// value in binary format, or produce an error.
/// * Applications are allowed to cache lookup results based on the
/// URL, or have them precompiled into a binary to avoid any
/// lookup. Therefore, binary compatibility needs to be preserved
/// on changes to types. (Use versioned type names to manage
/// breaking changes.)
///
/// Schemes other than `http`, `https` (or the empty scheme) might be
/// used with implementation specific semantics.
/**
* A URL/resource name whose content describes the type of the
* serialized protocol buffer message.
*
* For URLs which use the scheme `http`, `https`, or no scheme, the
* following restrictions and interpretations apply:
*
* * If no scheme is provided, `https` is assumed.
* * The last segment of the URL's path must represent the fully
* qualified name of the type (as in `path/google.protobuf.Duration`).
* The name should be in a canonical form (e.g., leading "." is
* not accepted).
* * An HTTP GET on the URL must yield a [google.protobuf.Type][]
* value in binary format, or produce an error.
* * Applications are allowed to cache lookup results based on the
* URL, or have them precompiled into a binary to avoid any
* lookup. Therefore, binary compatibility needs to be preserved
* on changes to types. (Use versioned type names to manage
* breaking changes.)
*
* Schemes other than `http`, `https` (or the empty scheme) might be
* used with implementation specific semantics.
**/
@property(nonatomic, readwrite, copy, null_resettable) NSString *typeURL;
/// Must be a valid serialized protocol buffer of the above specified type.
/** Must be a valid serialized protocol buffer of the above specified type. */
@property(nonatomic, readwrite, copy, null_resettable) NSData *value;
@end
......
This diff is collapsed.
......@@ -28,14 +28,16 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - GPBDurationRoot
/// Exposes the extension registry for this file.
///
/// The base class provides:
/// @code
/// + (GPBExtensionRegistry *)extensionRegistry;
/// @endcode
/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
/// this file and all files that it depends on.
/**
* Exposes the extension registry for this file.
*
* The base class provides:
* @code
* + (GPBExtensionRegistry *)extensionRegistry;
* @endcode
* which is a @c GPBExtensionRegistry that includes all the extensions defined by
* this file and all files that it depends on.
**/
@interface GPBDurationRoot : GPBRootObject
@end
......@@ -46,58 +48,64 @@ typedef GPB_ENUM(GPBDuration_FieldNumber) {
GPBDuration_FieldNumber_Nanos = 2,
};
/// A Duration represents a signed, fixed-length span of time represented
/// as a count of seconds and fractions of seconds at nanosecond
/// resolution. It is independent of any calendar and concepts like "day"
/// or "month". It is related to Timestamp in that the difference between
/// two Timestamp values is a Duration and it can be added or subtracted
/// from a Timestamp. Range is approximately +-10,000 years.
///
/// Example 1: Compute Duration from two Timestamps in pseudo code.
///
/// Timestamp start = ...;
/// Timestamp end = ...;
/// Duration duration = ...;
///
/// duration.seconds = end.seconds - start.seconds;
/// duration.nanos = end.nanos - start.nanos;
///
/// if (duration.seconds < 0 && duration.nanos > 0) {
/// duration.seconds += 1;
/// duration.nanos -= 1000000000;
/// } else if (durations.seconds > 0 && duration.nanos < 0) {
/// duration.seconds -= 1;
/// duration.nanos += 1000000000;
/// }
///
/// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
///
/// Timestamp start = ...;
/// Duration duration = ...;
/// Timestamp end = ...;
///
/// end.seconds = start.seconds + duration.seconds;
/// end.nanos = start.nanos + duration.nanos;
///
/// if (end.nanos < 0) {
/// end.seconds -= 1;
/// end.nanos += 1000000000;
/// } else if (end.nanos >= 1000000000) {
/// end.seconds += 1;
/// end.nanos -= 1000000000;
/// }
/**
* A Duration represents a signed, fixed-length span of time represented
* as a count of seconds and fractions of seconds at nanosecond
* resolution. It is independent of any calendar and concepts like "day"
* or "month". It is related to Timestamp in that the difference between
* two Timestamp values is a Duration and it can be added or subtracted
* from a Timestamp. Range is approximately +-10,000 years.
*
* Example 1: Compute Duration from two Timestamps in pseudo code.
*
* Timestamp start = ...;
* Timestamp end = ...;
* Duration duration = ...;
*
* duration.seconds = end.seconds - start.seconds;
* duration.nanos = end.nanos - start.nanos;
*
* if (duration.seconds < 0 && duration.nanos > 0) {
* duration.seconds += 1;
* duration.nanos -= 1000000000;
* } else if (durations.seconds > 0 && duration.nanos < 0) {
* duration.seconds -= 1;
* duration.nanos += 1000000000;
* }
*
* Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
*
* Timestamp start = ...;
* Duration duration = ...;
* Timestamp end = ...;
*
* end.seconds = start.seconds + duration.seconds;
* end.nanos = start.nanos + duration.nanos;
*
* if (end.nanos < 0) {
* end.seconds -= 1;
* end.nanos += 1000000000;
* } else if (end.nanos >= 1000000000) {
* end.seconds += 1;
* end.nanos -= 1000000000;
* }
**/
@interface GPBDuration : GPBMessage
/// Signed seconds of the span of time. Must be from -315,576,000,000
/// to +315,576,000,000 inclusive.
/**
* Signed seconds of the span of time. Must be from -315,576,000,000
* to +315,576,000,000 inclusive.
**/
@property(nonatomic, readwrite) int64_t seconds;
/// Signed fractions of a second at nanosecond resolution of the span
/// of time. Durations less than one second are represented with a 0
/// `seconds` field and a positive or negative `nanos` field. For durations
/// of one second or more, a non-zero value for the `nanos` field must be
/// of the same sign as the `seconds` field. Must be from -999,999,999
/// to +999,999,999 inclusive.
/**
* Signed fractions of a second at nanosecond resolution of the span
* of time. Durations less than one second are represented with a 0
* `seconds` field and a positive or negative `nanos` field. For durations
* of one second or more, a non-zero value for the `nanos` field must be
* of the same sign as the `seconds` field. Must be from -999,999,999
* to +999,999,999 inclusive.
**/
@property(nonatomic, readwrite) int32_t nanos;
@end
......
......@@ -28,28 +28,32 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - GPBEmptyRoot
/// Exposes the extension registry for this file.
///
/// The base class provides:
/// @code
/// + (GPBExtensionRegistry *)extensionRegistry;
/// @endcode
/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
/// this file and all files that it depends on.
/**
* Exposes the extension registry for this file.
*
* The base class provides:
* @code
* + (GPBExtensionRegistry *)extensionRegistry;
* @endcode
* which is a @c GPBExtensionRegistry that includes all the extensions defined by
* this file and all files that it depends on.
**/
@interface GPBEmptyRoot : GPBRootObject
@end
#pragma mark - GPBEmpty
/// A generic empty message that you can re-use to avoid defining duplicated
/// empty messages in your APIs. A typical example is to use it as the request
/// or the response type of an API method. For instance:
///
/// service Foo {
/// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
/// }
///
/// The JSON representation for `Empty` is empty JSON object `{}`.
/**
* A generic empty message that you can re-use to avoid defining duplicated
* empty messages in your APIs. A typical example is to use it as the request
* or the response type of an API method. For instance:
*
* service Foo {
* rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
* }
*
* The JSON representation for `Empty` is empty JSON object `{}`.
**/
@interface GPBEmpty : GPBMessage
@end
......
......@@ -28,14 +28,16 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - GPBSourceContextRoot
/// Exposes the extension registry for this file.
///
/// The base class provides:
/// @code
/// + (GPBExtensionRegistry *)extensionRegistry;
/// @endcode
/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
/// this file and all files that it depends on.
/**
* Exposes the extension registry for this file.
*
* The base class provides:
* @code
* + (GPBExtensionRegistry *)extensionRegistry;
* @endcode
* which is a @c GPBExtensionRegistry that includes all the extensions defined by
* this file and all files that it depends on.
**/
@interface GPBSourceContextRoot : GPBRootObject
@end
......@@ -45,12 +47,16 @@ typedef GPB_ENUM(GPBSourceContext_FieldNumber) {
GPBSourceContext_FieldNumber_FileName = 1,
};
/// `SourceContext` represents information about the source of a
/// protobuf element, like the file in which it is defined.
/**
* `SourceContext` represents information about the source of a
* protobuf element, like the file in which it is defined.
**/
@interface GPBSourceContext : GPBMessage
/// The path-qualified name of the .proto file that contained the associated
/// protobuf element. For example: `"google/protobuf/source_context.proto"`.
/**
* The path-qualified name of the .proto file that contained the associated
* protobuf element. For example: `"google/protobuf/source_context.proto"`.
**/
@property(nonatomic, readwrite, copy, null_resettable) NSString *fileName;
@end
......
......@@ -32,35 +32,43 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Enum GPBNullValue
/// `NullValue` is a singleton enumeration to represent the null value for the
/// `Value` type union.
///
/// The JSON representation for `NullValue` is JSON `null`.
/**
* `NullValue` is a singleton enumeration to represent the null value for the
* `Value` type union.
*
* The JSON representation for `NullValue` is JSON `null`.
**/
typedef GPB_ENUM(GPBNullValue) {
/// Value used if any message's field encounters a value that is not defined
/// by this enum. The message will also have C functions to get/set the rawValue
/// of the field.
/**
* Value used if any message's field encounters a value that is not defined
* by this enum. The message will also have C functions to get/set the rawValue
* of the field.
**/
GPBNullValue_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,
/// Null value.
/** Null value. */
GPBNullValue_NullValue = 0,
};
GPBEnumDescriptor *GPBNullValue_EnumDescriptor(void);
/// Checks to see if the given value is defined by the enum or was not known at
/// the time this source was generated.
/**
* Checks to see if the given value is defined by the enum or was not known at
* the time this source was generated.
**/
BOOL GPBNullValue_IsValidValue(int32_t value);
#pragma mark - GPBStructRoot
/// Exposes the extension registry for this file.
///
/// The base class provides:
/// @code
/// + (GPBExtensionRegistry *)extensionRegistry;
/// @endcode
/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
/// this file and all files that it depends on.
/**
* Exposes the extension registry for this file.
*
* The base class provides:
* @code
* + (GPBExtensionRegistry *)extensionRegistry;
* @endcode
* which is a @c GPBExtensionRegistry that includes all the extensions defined by
* this file and all files that it depends on.
**/
@interface GPBStructRoot : GPBRootObject
@end
......@@ -70,19 +78,21 @@ typedef GPB_ENUM(GPBStruct_FieldNumber) {
GPBStruct_FieldNumber_Fields = 1,
};
/// `Struct` represents a structured data value, consisting of fields
/// which map to dynamically typed values. In some languages, `Struct`
/// might be supported by a native representation. For example, in
/// scripting languages like JS a struct is represented as an
/// object. The details of that representation are described together
/// with the proto support for the language.
///
/// The JSON representation for `Struct` is JSON object.
/**
* `Struct` represents a structured data value, consisting of fields
* which map to dynamically typed values. In some languages, `Struct`
* might be supported by a native representation. For example, in
* scripting languages like JS a struct is represented as an
* object. The details of that representation are described together
* with the proto support for the language.
*
* The JSON representation for `Struct` is JSON object.
**/
@interface GPBStruct : GPBMessage
/// Unordered map of dynamically typed values.
/** Unordered map of dynamically typed values. */
@property(nonatomic, readwrite, strong, null_resettable) NSMutableDictionary<NSString*, GPBValue*> *fields;
/// The number of items in @c fields without causing the array to be created.
/** The number of items in @c fields without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger fields_Count;
@end
......@@ -108,46 +118,54 @@ typedef GPB_ENUM(GPBValue_Kind_OneOfCase) {
GPBValue_Kind_OneOfCase_ListValue = 6,
};
/// `Value` represents a dynamically typed value which can be either
/// null, a number, a string, a boolean, a recursive struct value, or a
/// list of values. A producer of value is expected to set one of that
/// variants, absence of any variant indicates an error.
///
/// The JSON representation for `Value` is JSON value.
/**
* `Value` represents a dynamically typed value which can be either
* null, a number, a string, a boolean, a recursive struct value, or a
* list of values. A producer of value is expected to set one of that
* variants, absence of any variant indicates an error.
*
* The JSON representation for `Value` is JSON value.
**/
@interface GPBValue : GPBMessage
/// The kind of value.
/** The kind of value. */
@property(nonatomic, readonly) GPBValue_Kind_OneOfCase kindOneOfCase;
/// Represents a null value.
/** Represents a null value. */
@property(nonatomic, readwrite) GPBNullValue nullValue;
/// Represents a double value.
/** Represents a double value. */
@property(nonatomic, readwrite) double numberValue;
/// Represents a string value.
/** Represents a string value. */
@property(nonatomic, readwrite, copy, null_resettable) NSString *stringValue;
/// Represents a boolean value.
/** Represents a boolean value. */
@property(nonatomic, readwrite) BOOL boolValue;
/// Represents a structured value.
/** Represents a structured value. */
@property(nonatomic, readwrite, strong, null_resettable) GPBStruct *structValue;
/// Represents a repeated `Value`.
/** Represents a repeated `Value`. */
@property(nonatomic, readwrite, strong, null_resettable) GPBListValue *listValue;
@end
/// Fetches the raw value of a @c GPBValue's @c nullValue property, even
/// if the value was not defined by the enum at the time the code was generated.
/**
* Fetches the raw value of a @c GPBValue's @c nullValue property, even
* if the value was not defined by the enum at the time the code was generated.
**/
int32_t GPBValue_NullValue_RawValue(GPBValue *message);
/// Sets the raw value of an @c GPBValue's @c nullValue property, allowing
/// it to be set to a value that was not defined by the enum at the time the code
/// was generated.
/**
* Sets the raw value of an @c GPBValue's @c nullValue property, allowing
* it to be set to a value that was not defined by the enum at the time the code
* was generated.
**/
void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value);
/// Clears whatever value was set for the oneof 'kind'.
/**
* Clears whatever value was set for the oneof 'kind'.
**/
void GPBValue_ClearKindOneOfCase(GPBValue *message);
#pragma mark - GPBListValue
......@@ -156,14 +174,16 @@ typedef GPB_ENUM(GPBListValue_FieldNumber) {
GPBListValue_FieldNumber_ValuesArray = 1,
};
/// `ListValue` is a wrapper around a repeated field of values.
///
/// The JSON representation for `ListValue` is JSON array.
/**
* `ListValue` is a wrapper around a repeated field of values.
*
* The JSON representation for `ListValue` is JSON array.
**/
@interface GPBListValue : GPBMessage
/// Repeated field of dynamically typed values.
/** Repeated field of dynamically typed values. */
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBValue*> *valuesArray;
/// The number of items in @c valuesArray without causing the array to be created.
/** The number of items in @c valuesArray without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger valuesArray_Count;
@end
......
......@@ -28,14 +28,16 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - GPBTimestampRoot
/// Exposes the extension registry for this file.
///
/// The base class provides:
/// @code
/// + (GPBExtensionRegistry *)extensionRegistry;
/// @endcode
/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
/// this file and all files that it depends on.
/**
* Exposes the extension registry for this file.
*
* The base class provides:
* @code
* + (GPBExtensionRegistry *)extensionRegistry;
* @endcode
* which is a @c GPBExtensionRegistry that includes all the extensions defined by
* this file and all files that it depends on.
**/
@interface GPBTimestampRoot : GPBRootObject
@end
......@@ -46,70 +48,76 @@ typedef GPB_ENUM(GPBTimestamp_FieldNumber) {
GPBTimestamp_FieldNumber_Nanos = 2,
};
/// A Timestamp represents a point in time independent of any time zone
/// or calendar, represented as seconds and fractions of seconds at
/// nanosecond resolution in UTC Epoch time. It is encoded using the
/// Proleptic Gregorian Calendar which extends the Gregorian calendar
/// backwards to year one. It is encoded assuming all minutes are 60
/// seconds long, i.e. leap seconds are "smeared" so that no leap second
/// table is needed for interpretation. Range is from
/// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
/// By restricting to that range, we ensure that we can convert to
/// and from RFC 3339 date strings.
/// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
///
/// Example 1: Compute Timestamp from POSIX `time()`.
///
/// Timestamp timestamp;
/// timestamp.set_seconds(time(NULL));
/// timestamp.set_nanos(0);
///
/// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
///
/// struct timeval tv;
/// gettimeofday(&tv, NULL);
///
/// Timestamp timestamp;
/// timestamp.set_seconds(tv.tv_sec);
/// timestamp.set_nanos(tv.tv_usec * 1000);
///
/// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
///
/// FILETIME ft;
/// GetSystemTimeAsFileTime(&ft);
/// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
///
/// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
/// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
/// Timestamp timestamp;
/// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
/// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
///
/// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
///
/// long millis = System.currentTimeMillis();
///
/// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
/// .setNanos((int) ((millis % 1000) * 1000000)).build();
///
///
/// Example 5: Compute Timestamp from current time in Python.
///
/// now = time.time()
/// seconds = int(now)
/// nanos = int((now - seconds) * 10**9)
/// timestamp = Timestamp(seconds=seconds, nanos=nanos)
/**
* A Timestamp represents a point in time independent of any time zone
* or calendar, represented as seconds and fractions of seconds at
* nanosecond resolution in UTC Epoch time. It is encoded using the
* Proleptic Gregorian Calendar which extends the Gregorian calendar
* backwards to year one. It is encoded assuming all minutes are 60
* seconds long, i.e. leap seconds are "smeared" so that no leap second
* table is needed for interpretation. Range is from
* 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
* By restricting to that range, we ensure that we can convert to
* and from RFC 3339 date strings.
* See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
*
* Example 1: Compute Timestamp from POSIX `time()`.
*
* Timestamp timestamp;
* timestamp.set_seconds(time(NULL));
* timestamp.set_nanos(0);
*
* Example 2: Compute Timestamp from POSIX `gettimeofday()`.
*
* struct timeval tv;
* gettimeofday(&tv, NULL);
*
* Timestamp timestamp;
* timestamp.set_seconds(tv.tv_sec);
* timestamp.set_nanos(tv.tv_usec * 1000);
*
* Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
*
* FILETIME ft;
* GetSystemTimeAsFileTime(&ft);
* UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
*
* // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
* // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
* Timestamp timestamp;
* timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
* timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
*
* Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
*
* long millis = System.currentTimeMillis();
*
* Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
* .setNanos((int) ((millis % 1000) * 1000000)).build();
*
*
* Example 5: Compute Timestamp from current time in Python.
*
* now = time.time()
* seconds = int(now)
* nanos = int((now - seconds) * 10**9)
* timestamp = Timestamp(seconds=seconds, nanos=nanos)
**/
@interface GPBTimestamp : GPBMessage
/// Represents seconds of UTC time since Unix epoch
/// 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to
/// 9999-12-31T23:59:59Z inclusive.
/**
* Represents seconds of UTC time since Unix epoch
* 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to
* 9999-12-31T23:59:59Z inclusive.
**/
@property(nonatomic, readwrite) int64_t seconds;
/// Non-negative fractions of a second at nanosecond resolution. Negative
/// second values with fractions must still have non-negative nanos values
/// that count forward in time. Must be from 0 to 999,999,999
/// inclusive.
/**
* Non-negative fractions of a second at nanosecond resolution. Negative
* second values with fractions must still have non-negative nanos values
* that count forward in time. Must be from 0 to 999,999,999
* inclusive.
**/
@property(nonatomic, readwrite) int32_t nanos;
@end
......
This diff is collapsed.
......@@ -28,14 +28,16 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - GPBWrappersRoot
/// Exposes the extension registry for this file.
///
/// The base class provides:
/// @code
/// + (GPBExtensionRegistry *)extensionRegistry;
/// @endcode
/// which is a @c GPBExtensionRegistry that includes all the extensions defined by
/// this file and all files that it depends on.
/**
* Exposes the extension registry for this file.
*
* The base class provides:
* @code
* + (GPBExtensionRegistry *)extensionRegistry;
* @endcode
* which is a @c GPBExtensionRegistry that includes all the extensions defined by
* this file and all files that it depends on.
**/
@interface GPBWrappersRoot : GPBRootObject
@end
......@@ -45,12 +47,14 @@ typedef GPB_ENUM(GPBDoubleValue_FieldNumber) {
GPBDoubleValue_FieldNumber_Value = 1,
};
/// Wrapper message for `double`.
///
/// The JSON representation for `DoubleValue` is JSON number.
/**
* Wrapper message for `double`.
*
* The JSON representation for `DoubleValue` is JSON number.
**/
@interface GPBDoubleValue : GPBMessage
/// The double value.
/** The double value. */
@property(nonatomic, readwrite) double value;
@end
......@@ -61,12 +65,14 @@ typedef GPB_ENUM(GPBFloatValue_FieldNumber) {
GPBFloatValue_FieldNumber_Value = 1,
};
/// Wrapper message for `float`.
///
/// The JSON representation for `FloatValue` is JSON number.
/**
* Wrapper message for `float`.
*
* The JSON representation for `FloatValue` is JSON number.
**/
@interface GPBFloatValue : GPBMessage
/// The float value.
/** The float value. */
@property(nonatomic, readwrite) float value;
@end
......@@ -77,12 +83,14 @@ typedef GPB_ENUM(GPBInt64Value_FieldNumber) {
GPBInt64Value_FieldNumber_Value = 1,
};
/// Wrapper message for `int64`.
///
/// The JSON representation for `Int64Value` is JSON string.
/**
* Wrapper message for `int64`.
*
* The JSON representation for `Int64Value` is JSON string.
**/
@interface GPBInt64Value : GPBMessage
/// The int64 value.
/** The int64 value. */
@property(nonatomic, readwrite) int64_t value;
@end
......@@ -93,12 +101,14 @@ typedef GPB_ENUM(GPBUInt64Value_FieldNumber) {
GPBUInt64Value_FieldNumber_Value = 1,
};
/// Wrapper message for `uint64`.
///
/// The JSON representation for `UInt64Value` is JSON string.
/**
* Wrapper message for `uint64`.
*
* The JSON representation for `UInt64Value` is JSON string.
**/
@interface GPBUInt64Value : GPBMessage
/// The uint64 value.
/** The uint64 value. */
@property(nonatomic, readwrite) uint64_t value;
@end
......@@ -109,12 +119,14 @@ typedef GPB_ENUM(GPBInt32Value_FieldNumber) {
GPBInt32Value_FieldNumber_Value = 1,
};
/// Wrapper message for `int32`.
///
/// The JSON representation for `Int32Value` is JSON number.
/**
* Wrapper message for `int32`.
*
* The JSON representation for `Int32Value` is JSON number.
**/
@interface GPBInt32Value : GPBMessage
/// The int32 value.
/** The int32 value. */
@property(nonatomic, readwrite) int32_t value;
@end
......@@ -125,12 +137,14 @@ typedef GPB_ENUM(GPBUInt32Value_FieldNumber) {
GPBUInt32Value_FieldNumber_Value = 1,
};
/// Wrapper message for `uint32`.
///
/// The JSON representation for `UInt32Value` is JSON number.
/**
* Wrapper message for `uint32`.
*
* The JSON representation for `UInt32Value` is JSON number.
**/
@interface GPBUInt32Value : GPBMessage
/// The uint32 value.
/** The uint32 value. */
@property(nonatomic, readwrite) uint32_t value;
@end
......@@ -141,12 +155,14 @@ typedef GPB_ENUM(GPBBoolValue_FieldNumber) {
GPBBoolValue_FieldNumber_Value = 1,
};
/// Wrapper message for `bool`.
///
/// The JSON representation for `BoolValue` is JSON `true` and `false`.
/**
* Wrapper message for `bool`.
*
* The JSON representation for `BoolValue` is JSON `true` and `false`.
**/
@interface GPBBoolValue : GPBMessage
/// The bool value.
/** The bool value. */
@property(nonatomic, readwrite) BOOL value;
@end
......@@ -157,12 +173,14 @@ typedef GPB_ENUM(GPBStringValue_FieldNumber) {
GPBStringValue_FieldNumber_Value = 1,
};
/// Wrapper message for `string`.
///
/// The JSON representation for `StringValue` is JSON string.
/**
* Wrapper message for `string`.
*
* The JSON representation for `StringValue` is JSON string.
**/
@interface GPBStringValue : GPBMessage
/// The string value.
/** The string value. */
@property(nonatomic, readwrite, copy, null_resettable) NSString *value;
@end
......@@ -173,12 +191,14 @@ typedef GPB_ENUM(GPBBytesValue_FieldNumber) {
GPBBytesValue_FieldNumber_Value = 1,
};
/// Wrapper message for `bytes`.
///
/// The JSON representation for `BytesValue` is JSON string.
/**
* Wrapper message for `bytes`.
*
* The JSON representation for `BytesValue` is JSON string.
**/
@interface GPBBytesValue : GPBMessage
/// The bytes value.
/** The bytes value. */
@property(nonatomic, readwrite, copy, null_resettable) NSData *value;
@end
......
......@@ -62,7 +62,7 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) {
string enum_comments;
SourceLocation location;
if (descriptor_->GetSourceLocation(&location)) {
enum_comments = BuildCommentsString(location);
enum_comments = BuildCommentsString(location, true);
} else {
enum_comments = "";
}
......@@ -81,16 +81,18 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) {
if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
// Include the unknown value.
printer->Print(
"/// Value used if any message's field encounters a value that is not defined\n"
"/// by this enum. The message will also have C functions to get/set the rawValue\n"
"/// of the field.\n"
"/**\n"
" * Value used if any message's field encounters a value that is not defined\n"
" * by this enum. The message will also have C functions to get/set the rawValue\n"
" * of the field.\n"
" **/\n"
"$name$_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,\n",
"name", name_);
}
for (int i = 0; i < all_values_.size(); i++) {
SourceLocation location;
if (all_values_[i]->GetSourceLocation(&location)) {
string comments = BuildCommentsString(location).c_str();
string comments = BuildCommentsString(location, true).c_str();
if (comments.length() > 0) {
if (i > 0) {
printer->Print("\n");
......@@ -111,8 +113,10 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) {
"\n"
"GPBEnumDescriptor *$name$_EnumDescriptor(void);\n"
"\n"
"/// Checks to see if the given value is defined by the enum or was not known at\n"
"/// the time this source was generated.\n"
"/**\n"
" * Checks to see if the given value is defined by the enum or was not known at\n"
" * the time this source was generated.\n"
" **/\n"
"BOOL $name$_IsValidValue(int32_t value);\n"
"\n",
"name", name_);
......
......@@ -83,12 +83,16 @@ void EnumFieldGenerator::GenerateCFunctionDeclarations(
printer->Print(
variables_,
"/// Fetches the raw value of a @c $owning_message_class$'s @c $name$ property, even\n"
"/// if the value was not defined by the enum at the time the code was generated.\n"
"/**\n"
" * Fetches the raw value of a @c $owning_message_class$'s @c $name$ property, even\n"
" * if the value was not defined by the enum at the time the code was generated.\n"
" **/\n"
"int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message);\n"
"/// Sets the raw value of an @c $owning_message_class$'s @c $name$ property, allowing\n"
"/// it to be set to a value that was not defined by the enum at the time the code\n"
"/// was generated.\n"
"/**\n"
" * Sets the raw value of an @c $owning_message_class$'s @c $name$ property, allowing\n"
" * it to be set to a value that was not defined by the enum at the time the code\n"
" * was generated.\n"
" **/\n"
"void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value);\n"
"\n");
}
......
......@@ -63,7 +63,7 @@ void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) {
vars["method_name"] = method_name_;
SourceLocation location;
if (descriptor_->GetSourceLocation(&location)) {
vars["comments"] = BuildCommentsString(location);
vars["comments"] = BuildCommentsString(location, true);
} else {
vars["comments"] = "";
}
......
......@@ -64,7 +64,7 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
SourceLocation location;
if (descriptor->GetSourceLocation(&location)) {
(*variables)["comments"] = BuildCommentsString(location);
(*variables)["comments"] = BuildCommentsString(location, true);
} else {
(*variables)["comments"] = "\n";
}
......@@ -335,7 +335,7 @@ void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
if (WantsHasProperty()) {
printer->Print(
variables_,
"/// Test to see if @c $name$ has been set.\n"
"/** Test to see if @c $name$ has been set. */\n"
"@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
}
if (IsInitName(variables_.find("name")->second)) {
......@@ -387,7 +387,7 @@ void RepeatedFieldGenerator::GeneratePropertyDeclaration(
"$comments$"
"$array_comment$"
"@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n"
"/// The number of items in @c $name$ without causing the array to be created.\n"
"/** The number of items in @c $name$ without causing the array to be created. */\n"
"@property(nonatomic, readonly) NSUInteger $name$_Count$deprecated_attribute$;\n");
if (IsInitName(variables_.find("name")->second)) {
// If property name starts with init we need to annotate it to get past ARC.
......
......@@ -357,14 +357,16 @@ void FileGenerator::GenerateHeader(io::Printer *printer) {
printer->Print(
"#pragma mark - $root_class_name$\n"
"\n"
"/// Exposes the extension registry for this file.\n"
"///\n"
"/// The base class provides:\n"
"/// @code\n"
"/// + (GPBExtensionRegistry *)extensionRegistry;\n"
"/// @endcode\n"
"/// which is a @c GPBExtensionRegistry that includes all the extensions defined by\n"
"/// this file and all files that it depends on.\n"
"/**\n"
" * Exposes the extension registry for this file.\n"
" *\n"
" * The base class provides:\n"
" * @code\n"
" * + (GPBExtensionRegistry *)extensionRegistry;\n"
" * @endcode\n"
" * which is a @c GPBExtensionRegistry that includes all the extensions defined by\n"
" * this file and all files that it depends on.\n"
" **/\n"
"@interface $root_class_name$ : GPBRootObject\n"
"@end\n"
"\n",
......
......@@ -830,7 +830,8 @@ string BuildFlagsString(const vector<string>& strings) {
return string;
}
string BuildCommentsString(const SourceLocation& location) {
string BuildCommentsString(const SourceLocation& location,
bool prefer_single_line) {
const string& comments = location.leading_comments.empty()
? location.trailing_comments
: location.leading_comments;
......@@ -839,15 +840,37 @@ string BuildCommentsString(const SourceLocation& location) {
while (!lines.empty() && lines.back().empty()) {
lines.pop_back();
}
string prefix("///");
string suffix("\n");
// If there are no comments, just return an empty string.
if (lines.size() == 0) {
return "";
}
string prefix;
string suffix;
string final_comments;
for (int i = 0; i < lines.size(); i++) {
// HeaderDoc uses '\' and '@' for markers; escape them.
const string line = StringReplace(lines[i], "\\", "\\\\", true);
final_comments +=
prefix + StringReplace(line, "@", "\\@", true) + suffix;
string epilogue;
if (prefer_single_line && lines.size() == 1) {
prefix = "/** ";
suffix = " */\n";
} else {
prefix = " * ";
suffix = "\n";
final_comments += "/**\n";
epilogue = " **/\n";
}
for (int i = 0; i < lines.size(); i++) {
string line = StripPrefixString(lines[i], " ");
// HeaderDoc and appledoc use '\' and '@' for markers; escape them.
line = StringReplace(line, "\\", "\\\\", true);
line = StringReplace(line, "@", "\\@", true);
// Decouple / from * to not have inline comments inside comments.
line = StringReplace(line, "/*", "/\\*", true);
line = StringReplace(line, "*/", "*\\/", true);
final_comments += prefix + line + suffix;
}
final_comments += epilogue;
return final_comments;
}
......
......@@ -172,8 +172,10 @@ bool HasNonZeroDefaultValue(const FieldDescriptor* field);
string BuildFlagsString(const vector<string>& strings);
// Builds a HeaderDoc style comment out of the comments in the .proto file.
string BuildCommentsString(const SourceLocation& location);
// Builds HeaderDoc/appledoc style comments out of the comments in the .proto
// file.
string BuildCommentsString(const SourceLocation& location,
bool prefer_single_line);
// The name the commonly used by the library when built as a framework.
// This lines up to the name used in the CocoaPod.
......
......@@ -331,7 +331,7 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
string message_comments;
SourceLocation location;
if (descriptor_->GetSourceLocation(&location)) {
message_comments = BuildCommentsString(location);
message_comments = BuildCommentsString(location, false);
} else {
message_comments = "";
}
......
......@@ -53,7 +53,7 @@ OneofGenerator::OneofGenerator(const OneofDescriptor* descriptor)
string comments;
SourceLocation location;
if (descriptor_->GetSourceLocation(&location)) {
comments = BuildCommentsString(location);
comments = BuildCommentsString(location, true);
} else {
comments = "";
}
......@@ -104,7 +104,9 @@ void OneofGenerator::GeneratePublicCasePropertyDeclaration(
void OneofGenerator::GenerateClearFunctionDeclaration(io::Printer* printer) {
printer->Print(
variables_,
"/// Clears whatever value was set for the oneof '$name$'.\n"
"/**\n"
" * Clears whatever value was set for the oneof '$name$'.\n"
" **/\n"
"void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message);\n");
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment