From 237f321e338b50503eb38728afa6ad29bea6076a Mon Sep 17 00:00:00 2001 From: Sergio Campamá Date: Tue, 9 Aug 2016 05:26:24 -0700 Subject: 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 --- .../compiler/objectivec/objectivec_enum.cc | 18 ++++++---- .../compiler/objectivec/objectivec_enum_field.cc | 14 +++++--- .../compiler/objectivec/objectivec_extension.cc | 2 +- .../compiler/objectivec/objectivec_field.cc | 6 ++-- .../compiler/objectivec/objectivec_file.cc | 18 +++++----- .../compiler/objectivec/objectivec_helpers.cc | 39 +++++++++++++++++----- .../compiler/objectivec/objectivec_helpers.h | 6 ++-- .../compiler/objectivec/objectivec_message.cc | 2 +- .../compiler/objectivec/objectivec_oneof.cc | 6 ++-- 9 files changed, 74 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc index e76f8e99..34e17823 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc @@ -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_); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc index b63bc0de..7a774a09 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc @@ -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"); } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc index 3f7ab9d3..c0e7253a 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc @@ -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"] = ""; } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc index 812b4a1c..d2a6e882 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc @@ -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. diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index b864ef12..438f4113 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -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", diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc index 22c7a883..28b3f5ae 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -830,7 +830,8 @@ string BuildFlagsString(const vector& 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; } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h index be20beee..998c6281 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -170,8 +170,10 @@ bool HasNonZeroDefaultValue(const FieldDescriptor* field); string BuildFlagsString(const vector& 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. diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc index e1a78619..822da893 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc @@ -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 = ""; } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc index 3dda903b..5531ae24 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc @@ -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"); } -- cgit v1.2.3