aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Brent Shaffer <betterbrent@google.com>2018-05-02 14:40:15 -0700
committerGravatar Paul Yang <TeBoring@users.noreply.github.com>2018-05-24 13:39:41 -0700
commitf1911f37f817fb2dddbb07478bdcda526488fc55 (patch)
tree402d04901ea74eef1e161aca8a370439760bdb1e
parentb625aabbe75f91bb4974b5c75106233ed2761dbb (diff)
PHP array constructors for protobuf messages (#4530)
* PHP array constructors for protobuf messages * removes Descriptor from error message * allows mergeFrom to accept an array * only use initWithDescriptor if instanceof MapEntry * adds doc comments * removes ability for constructors to take arrays for submessages * Revert "allows mergeFrom to accept an array" This reverts commit b7b72182d561634af12c5c5c56a7cda3b33241f9. * makes mergeFromArray protected and fixes mergeFrom whitespace * Separates merging from JSON and merging from PHP array * removes well-known types and json keys from array construction * Addresses PR review comments * cleans up tests * fixes exception messages
-rw-r--r--php/src/Google/Protobuf/Internal/DescriptorProto.php24
-rw-r--r--php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php15
-rw-r--r--php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php16
-rw-r--r--php/src/Google/Protobuf/Internal/EnumDescriptorProto.php22
-rw-r--r--php/src/Google/Protobuf/Internal/EnumDescriptorProto_EnumReservedRange.php16
-rw-r--r--php/src/Google/Protobuf/Internal/EnumOptions.php22
-rw-r--r--php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php15
-rw-r--r--php/src/Google/Protobuf/Internal/EnumValueOptions.php19
-rw-r--r--php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php14
-rw-r--r--php/src/Google/Protobuf/Internal/FieldDescriptorProto.php42
-rw-r--r--php/src/Google/Protobuf/Internal/FieldOptions.php68
-rw-r--r--php/src/Google/Protobuf/Internal/FileDescriptorProto.php37
-rw-r--r--php/src/Google/Protobuf/Internal/FileDescriptorSet.php13
-rw-r--r--php/src/Google/Protobuf/Internal/FileOptions.php87
-rw-r--r--php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php15
-rw-r--r--php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php24
-rw-r--r--php/src/Google/Protobuf/Internal/Message.php248
-rw-r--r--php/src/Google/Protobuf/Internal/MessageOptions.php58
-rw-r--r--php/src/Google/Protobuf/Internal/MethodDescriptorProto.php22
-rw-r--r--php/src/Google/Protobuf/Internal/MethodOptions.php20
-rw-r--r--php/src/Google/Protobuf/Internal/OneofDescriptorProto.php14
-rw-r--r--php/src/Google/Protobuf/Internal/OneofOptions.php14
-rw-r--r--php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php15
-rw-r--r--php/src/Google/Protobuf/Internal/ServiceOptions.php19
-rw-r--r--php/src/Google/Protobuf/Internal/SourceCodeInfo.php54
-rw-r--r--php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php79
-rw-r--r--php/src/Google/Protobuf/Internal/UninterpretedOption.php21
-rw-r--r--php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php14
-rw-r--r--php/tests/generated_phpdoc_test.php8
-rw-r--r--php/tests/php_implementation_test.php154
-rw-r--r--src/google/protobuf/compiler/php/php_generator.cc54
31 files changed, 1082 insertions, 161 deletions
diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto.php b/php/src/Google/Protobuf/Internal/DescriptorProto.php
index 1d6959b7..4676269e 100644
--- a/php/src/Google/Protobuf/Internal/DescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/DescriptorProto.php
@@ -71,9 +71,29 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message
private $reserved_name;
private $has_reserved_name = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $name
+ * @type \Google\Protobuf\Internal\FieldDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $field
+ * @type \Google\Protobuf\Internal\FieldDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $extension
+ * @type \Google\Protobuf\Internal\DescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $nested_type
+ * @type \Google\Protobuf\Internal\EnumDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $enum_type
+ * @type \Google\Protobuf\Internal\DescriptorProto_ExtensionRange[]|\Google\Protobuf\Internal\RepeatedField $extension_range
+ * @type \Google\Protobuf\Internal\OneofDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $oneof_decl
+ * @type \Google\Protobuf\Internal\MessageOptions $options
+ * @type \Google\Protobuf\Internal\DescriptorProto_ReservedRange[]|\Google\Protobuf\Internal\RepeatedField $reserved_range
+ * @type string[]|\Google\Protobuf\Internal\RepeatedField $reserved_name
+ * Reserved field names, which may not be used by fields in the same message.
+ * A given name may only be reserved once.
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php b/php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php
index 1d455995..d926ee6e 100644
--- a/php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php
+++ b/php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php
@@ -31,9 +31,20 @@ class DescriptorProto_ExtensionRange extends \Google\Protobuf\Internal\Message
private $options = null;
private $has_options = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type int $start
+ * @type int $end
+ * @type \Google\Protobuf\Internal\ExtensionRangeOptions $options
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php b/php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php
index b1022d61..302eaaa9 100644
--- a/php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php
+++ b/php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php
@@ -34,9 +34,21 @@ class DescriptorProto_ReservedRange extends \Google\Protobuf\Internal\Message
private $end = 0;
private $has_end = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type int $start
+ * Inclusive.
+ * @type int $end
+ * Exclusive.
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php b/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php
index 930f26ef..406bb5b5 100644
--- a/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php
@@ -50,9 +50,27 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message
private $reserved_name;
private $has_reserved_name = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $name
+ * @type \Google\Protobuf\Internal\EnumValueDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $value
+ * @type \Google\Protobuf\Internal\EnumOptions $options
+ * @type \Google\Protobuf\Internal\EnumDescriptorProto_EnumReservedRange[]|\Google\Protobuf\Internal\RepeatedField $reserved_range
+ * Range of reserved numeric values. Reserved numeric values may not be used
+ * by enum values in the same enum declaration. Reserved ranges may not
+ * overlap.
+ * @type string[]|\Google\Protobuf\Internal\RepeatedField $reserved_name
+ * Reserved enum value names, which may not be reused. A given name may only
+ * be reserved once.
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/EnumDescriptorProto_EnumReservedRange.php b/php/src/Google/Protobuf/Internal/EnumDescriptorProto_EnumReservedRange.php
index 6b2449fa..3d7b008e 100644
--- a/php/src/Google/Protobuf/Internal/EnumDescriptorProto_EnumReservedRange.php
+++ b/php/src/Google/Protobuf/Internal/EnumDescriptorProto_EnumReservedRange.php
@@ -36,9 +36,21 @@ class EnumDescriptorProto_EnumReservedRange extends \Google\Protobuf\Internal\Me
private $end = 0;
private $has_end = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type int $start
+ * Inclusive.
+ * @type int $end
+ * Inclusive.
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/EnumOptions.php b/php/src/Google/Protobuf/Internal/EnumOptions.php
index 3f598a41..3d74c81c 100644
--- a/php/src/Google/Protobuf/Internal/EnumOptions.php
+++ b/php/src/Google/Protobuf/Internal/EnumOptions.php
@@ -41,9 +41,27 @@ class EnumOptions extends \Google\Protobuf\Internal\Message
private $uninterpreted_option;
private $has_uninterpreted_option = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type bool $allow_alias
+ * Set this option to true to allow mapping different tag names to the same
+ * value.
+ * @type bool $deprecated
+ * Is this enum deprecated?
+ * Depending on the target platform, this can emit Deprecated annotations
+ * for the enum, or it will be completely ignored; in the very least, this
+ * is a formalization for deprecating enums.
+ * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option
+ * The parser stores options it doesn't recognize here. See above.
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php b/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php
index e363220f..50bda008 100644
--- a/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php
@@ -33,9 +33,20 @@ class EnumValueDescriptorProto extends \Google\Protobuf\Internal\Message
private $options = null;
private $has_options = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $name
+ * @type int $number
+ * @type \Google\Protobuf\Internal\EnumValueOptions $options
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/EnumValueOptions.php b/php/src/Google/Protobuf/Internal/EnumValueOptions.php
index db8de174..a267c6d5 100644
--- a/php/src/Google/Protobuf/Internal/EnumValueOptions.php
+++ b/php/src/Google/Protobuf/Internal/EnumValueOptions.php
@@ -33,9 +33,24 @@ class EnumValueOptions extends \Google\Protobuf\Internal\Message
private $uninterpreted_option;
private $has_uninterpreted_option = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type bool $deprecated
+ * Is this enum value deprecated?
+ * Depending on the target platform, this can emit Deprecated annotations
+ * for the enum value, or it will be completely ignored; in the very least,
+ * this is a formalization for deprecating enum values.
+ * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option
+ * The parser stores options it doesn't recognize here. See above.
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php b/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php
index ee9e38bb..00fbebec 100644
--- a/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php
+++ b/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php
@@ -23,9 +23,19 @@ class ExtensionRangeOptions extends \Google\Protobuf\Internal\Message
private $uninterpreted_option;
private $has_uninterpreted_option = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option
+ * The parser stores options it doesn't recognize here. See above.
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php b/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php
index 10c27593..e5781975 100644
--- a/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php
@@ -94,9 +94,47 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
private $options = null;
private $has_options = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $name
+ * @type int $number
+ * @type int $label
+ * @type int $type
+ * If type_name is set, this need not be set. If both this and type_name
+ * are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
+ * @type string $type_name
+ * For message and enum types, this is the name of the type. If the name
+ * starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
+ * rules are used to find the type (i.e. first the nested types within this
+ * message are searched, then within the parent, on up to the root
+ * namespace).
+ * @type string $extendee
+ * For extensions, this is the name of the type being extended. It is
+ * resolved in the same manner as type_name.
+ * @type string $default_value
+ * For numeric types, contains the original text representation of the value.
+ * For booleans, "true" or "false".
+ * For strings, contains the default text contents (not escaped in any way).
+ * For bytes, contains the C escaped value. All bytes >= 128 are escaped.
+ * TODO(kenton): Base-64 encode?
+ * @type int $oneof_index
+ * If set, gives the index of a oneof in the containing type's oneof_decl
+ * list. This field is a member of that oneof.
+ * @type string $json_name
+ * JSON name of this field. The value is set by protocol compiler. If the
+ * user has set a "json_name" option on this field, that option's value
+ * will be used. Otherwise, it's deduced from the field's name by converting
+ * it to camelCase.
+ * @type \Google\Protobuf\Internal\FieldOptions $options
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/FieldOptions.php b/php/src/Google/Protobuf/Internal/FieldOptions.php
index 169f860b..751c278d 100644
--- a/php/src/Google/Protobuf/Internal/FieldOptions.php
+++ b/php/src/Google/Protobuf/Internal/FieldOptions.php
@@ -107,9 +107,73 @@ class FieldOptions extends \Google\Protobuf\Internal\Message
private $uninterpreted_option;
private $has_uninterpreted_option = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type int $ctype
+ * The ctype option instructs the C++ code generator to use a different
+ * representation of the field than it normally would. See the specific
+ * options below. This option is not yet implemented in the open source
+ * release -- sorry, we'll try to include it in a future version!
+ * @type bool $packed
+ * The packed option can be enabled for repeated primitive fields to enable
+ * a more efficient representation on the wire. Rather than repeatedly
+ * writing the tag and type for each element, the entire array is encoded as
+ * a single length-delimited blob. In proto3, only explicit setting it to
+ * false will avoid using packed encoding.
+ * @type int $jstype
+ * The jstype option determines the JavaScript type used for values of the
+ * field. The option is permitted only for 64 bit integral and fixed types
+ * (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING
+ * is represented as JavaScript string, which avoids loss of precision that
+ * can happen when a large value is converted to a floating point JavaScript.
+ * Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
+ * use the JavaScript "number" type. The behavior of the default option
+ * JS_NORMAL is implementation dependent.
+ * This option is an enum to permit additional types to be added, e.g.
+ * goog.math.Integer.
+ * @type bool $lazy
+ * Should this field be parsed lazily? Lazy applies only to message-type
+ * fields. It means that when the outer message is initially parsed, the
+ * inner message's contents will not be parsed but instead stored in encoded
+ * form. The inner message will actually be parsed when it is first accessed.
+ * This is only a hint. Implementations are free to choose whether to use
+ * eager or lazy parsing regardless of the value of this option. However,
+ * setting this option true suggests that the protocol author believes that
+ * using lazy parsing on this field is worth the additional bookkeeping
+ * overhead typically needed to implement it.
+ * This option does not affect the public interface of any generated code;
+ * all method signatures remain the same. Furthermore, thread-safety of the
+ * interface is not affected by this option; const methods remain safe to
+ * call from multiple threads concurrently, while non-const methods continue
+ * to require exclusive access.
+ * Note that implementations may choose not to check required fields within
+ * a lazy sub-message. That is, calling IsInitialized() on the outer message
+ * may return true even if the inner message has missing required fields.
+ * This is necessary because otherwise the inner message would have to be
+ * parsed in order to perform the check, defeating the purpose of lazy
+ * parsing. An implementation which chooses not to check required fields
+ * must be consistent about it. That is, for any particular sub-message, the
+ * implementation must either *always* check its required fields, or *never*
+ * check its required fields, regardless of whether or not the message has
+ * been parsed.
+ * @type bool $deprecated
+ * Is this field deprecated?
+ * Depending on the target platform, this can emit Deprecated annotations
+ * for accessors, or it will be completely ignored; in the very least, this
+ * is a formalization for deprecating fields.
+ * @type bool $weak
+ * For Google-internal migration only. Do not use.
+ * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option
+ * The parser stores options it doesn't recognize here. See above.
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/FileDescriptorProto.php b/php/src/Google/Protobuf/Internal/FileDescriptorProto.php
index 9ee222d1..cb10aa79 100644
--- a/php/src/Google/Protobuf/Internal/FileDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/FileDescriptorProto.php
@@ -99,9 +99,42 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message
private $syntax = '';
private $has_syntax = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $name
+ * file name, relative to root of source tree
+ * @type string $package
+ * e.g. "foo", "foo.bar", etc.
+ * @type string[]|\Google\Protobuf\Internal\RepeatedField $dependency
+ * Names of files imported by this file.
+ * @type int[]|\Google\Protobuf\Internal\RepeatedField $public_dependency
+ * Indexes of the public imported files in the dependency list above.
+ * @type int[]|\Google\Protobuf\Internal\RepeatedField $weak_dependency
+ * Indexes of the weak imported files in the dependency list.
+ * For Google-internal migration only. Do not use.
+ * @type \Google\Protobuf\Internal\DescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $message_type
+ * All top-level definitions in this file.
+ * @type \Google\Protobuf\Internal\EnumDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $enum_type
+ * @type \Google\Protobuf\Internal\ServiceDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $service
+ * @type \Google\Protobuf\Internal\FieldDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $extension
+ * @type \Google\Protobuf\Internal\FileOptions $options
+ * @type \Google\Protobuf\Internal\SourceCodeInfo $source_code_info
+ * This field contains optional information about the original source code.
+ * You may safely remove this entire field without harming runtime
+ * functionality of the descriptors -- the information is needed only by
+ * development tools.
+ * @type string $syntax
+ * The syntax of the proto file.
+ * The supported values are "proto2" and "proto3".
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/FileDescriptorSet.php b/php/src/Google/Protobuf/Internal/FileDescriptorSet.php
index 0b2cf957..9907b17d 100644
--- a/php/src/Google/Protobuf/Internal/FileDescriptorSet.php
+++ b/php/src/Google/Protobuf/Internal/FileDescriptorSet.php
@@ -24,9 +24,18 @@ class FileDescriptorSet extends \Google\Protobuf\Internal\Message
private $file;
private $has_file = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type \Google\Protobuf\Internal\FileDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $file
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/FileOptions.php b/php/src/Google/Protobuf/Internal/FileOptions.php
index 18e9455c..2315ed5e 100644
--- a/php/src/Google/Protobuf/Internal/FileOptions.php
+++ b/php/src/Google/Protobuf/Internal/FileOptions.php
@@ -200,9 +200,92 @@ class FileOptions extends \Google\Protobuf\Internal\Message
private $uninterpreted_option;
private $has_uninterpreted_option = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $java_package
+ * Sets the Java package where classes generated from this .proto will be
+ * placed. By default, the proto package is used, but this is often
+ * inappropriate because proto packages do not normally start with backwards
+ * domain names.
+ * @type string $java_outer_classname
+ * If set, all the classes from the .proto file are wrapped in a single
+ * outer class with the given name. This applies to both Proto1
+ * (equivalent to the old "--one_java_file" option) and Proto2 (where
+ * a .proto always translates to a single class, but you may want to
+ * explicitly choose the class name).
+ * @type bool $java_multiple_files
+ * If set true, then the Java code generator will generate a separate .java
+ * file for each top-level message, enum, and service defined in the .proto
+ * file. Thus, these types will *not* be nested inside the outer class
+ * named by java_outer_classname. However, the outer class will still be
+ * generated to contain the file's getDescriptor() method as well as any
+ * top-level extensions defined in the file.
+ * @type bool $java_generate_equals_and_hash
+ * This option does nothing.
+ * @type bool $java_string_check_utf8
+ * If set true, then the Java2 code generator will generate code that
+ * throws an exception whenever an attempt is made to assign a non-UTF-8
+ * byte sequence to a string field.
+ * Message reflection will do the same.
+ * However, an extension field still accepts non-UTF-8 byte sequences.
+ * This option has no effect on when used with the lite runtime.
+ * @type int $optimize_for
+ * @type string $go_package
+ * Sets the Go package where structs generated from this .proto will be
+ * placed. If omitted, the Go package will be derived from the following:
+ * - The basename of the package import path, if provided.
+ * - Otherwise, the package statement in the .proto file, if present.
+ * - Otherwise, the basename of the .proto file, without extension.
+ * @type bool $cc_generic_services
+ * Should generic services be generated in each language? "Generic" services
+ * are not specific to any particular RPC system. They are generated by the
+ * main code generators in each language (without additional plugins).
+ * Generic services were the only kind of service generation supported by
+ * early versions of google.protobuf.
+ * Generic services are now considered deprecated in favor of using plugins
+ * that generate code specific to your particular RPC system. Therefore,
+ * these default to false. Old code which depends on generic services should
+ * explicitly set them to true.
+ * @type bool $java_generic_services
+ * @type bool $py_generic_services
+ * @type bool $php_generic_services
+ * @type bool $deprecated
+ * Is this file deprecated?
+ * Depending on the target platform, this can emit Deprecated annotations
+ * for everything in the file, or it will be completely ignored; in the very
+ * least, this is a formalization for deprecating files.
+ * @type bool $cc_enable_arenas
+ * Enables the use of arenas for the proto messages in this file. This applies
+ * only to generated classes for C++.
+ * @type string $objc_class_prefix
+ * Sets the objective c class prefix which is prepended to all objective c
+ * generated classes from this .proto. There is no default.
+ * @type string $csharp_namespace
+ * Namespace for generated classes; defaults to the package.
+ * @type string $swift_prefix
+ * By default Swift generators will take the proto package and CamelCase it
+ * replacing '.' with underscore and use that to prefix the types/symbols
+ * defined. When this options is provided, they will use this value instead
+ * to prefix the types/symbols defined.
+ * @type string $php_class_prefix
+ * Sets the php class prefix which is prepended to all php generated classes
+ * from this .proto. Default is empty.
+ * @type string $php_namespace
+ * Use this option to change the namespace of php generated classes. Default
+ * is empty. When this option is empty, the package name will be used for
+ * determining the namespace.
+ * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option
+ * The parser stores options it doesn't recognize here.
+ * See the documentation for the "Options" section above.
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php
index ae2ad745..c2b41a29 100644
--- a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php
+++ b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php
@@ -28,9 +28,20 @@ class GeneratedCodeInfo extends \Google\Protobuf\Internal\Message
private $annotation;
private $has_annotation = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation[]|\Google\Protobuf\Internal\RepeatedField $annotation
+ * An Annotation connects some span of text in generated code to an element
+ * of its generating .proto file.
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php
index 22ac2337..75182007 100644
--- a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php
+++ b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php
@@ -48,9 +48,29 @@ class GeneratedCodeInfo_Annotation extends \Google\Protobuf\Internal\Message
private $end = 0;
private $has_end = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type int[]|\Google\Protobuf\Internal\RepeatedField $path
+ * Identifies the element in the original source .proto file. This field
+ * is formatted the same as SourceCodeInfo.Location.path.
+ * @type string $source_file
+ * Identifies the filesystem path to the original source .proto.
+ * @type int $begin
+ * Identifies the starting offset in bytes in the generated code
+ * that relates to the identified object.
+ * @type int $end
+ * Identifies the ending offset in bytes in the generated code that
+ * relates to the identified offset. The end offset should be one past
+ * the last relevant byte (so the length of the text = end - begin).
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/Message.php b/php/src/Google/Protobuf/Internal/Message.php
index 3aff7bd6..73ac375e 100644
--- a/php/src/Google/Protobuf/Internal/Message.php
+++ b/php/src/Google/Protobuf/Internal/Message.php
@@ -66,19 +66,30 @@ class Message
/**
* @ignore
*/
- public function __construct($desc = NULL)
+ public function __construct($data = NULL)
{
// MapEntry message is shared by all types of map fields, whose
// descriptors are different from each other. Thus, we cannot find a
// specific descriptor from the descriptor pool.
- if (get_class($this) === 'Google\Protobuf\Internal\MapEntry') {
- $this->desc = $desc;
- foreach ($desc->getField() as $field) {
- $setter = $field->getSetter();
- $this->$setter($this->defaultValue($field));
+ if ($this instanceof MapEntry) {
+ $this->initWithDescriptor($data);
+ } else {
+ $this->initWithGeneratedPool();
+ if (is_array($data)) {
+ $this->mergeFromArray($data);
+ } else if (!empty($data)) {
+ throw new \InvalidArgumentException(
+ 'Message constructor must be an array or null.'
+ );
}
- return;
}
+ }
+
+ /**
+ * @ignore
+ */
+ private function initWithGeneratedPool()
+ {
$pool = DescriptorPool::getGeneratedPool();
$this->desc = $pool->getDescriptorByClassName(get_class($this));
if (is_null($this->desc)) {
@@ -151,6 +162,19 @@ class Message
}
}
+ /**
+ * @ignore
+ */
+ private function initWithDescriptor(Descriptor $desc)
+ {
+ $this->desc = $desc;
+ foreach ($desc->getField() as $field) {
+ $setter = $field->getSetter();
+ $defaultValue = $this->defaultValue($field);
+ $this->$setter($defaultValue);
+ }
+ }
+
protected function readOneof($number)
{
$field = $this->desc->getFieldByNumber($number);
@@ -628,58 +652,58 @@ class Message
*/
public function mergeFrom($msg)
{
- if (get_class($this) !== get_class($msg)) {
- user_error("Cannot merge messages with different class.");
- return;
- }
-
- foreach ($this->desc->getField() as $field) {
- $setter = $field->getSetter();
- $getter = $field->getGetter();
- if ($field->isMap()) {
- if (count($msg->$getter()) != 0) {
- $value_field = $field->getMessageType()->getFieldByNumber(2);
- foreach ($msg->$getter() as $key => $value) {
- if ($value_field->getType() == GPBType::MESSAGE) {
- $klass = $value_field->getMessageType()->getClass();
- $copy = new $klass;
- $copy->mergeFrom($value);
-
- $this->kvUpdateHelper($field, $key, $copy);
- } else {
- $this->kvUpdateHelper($field, $key, $value);
- }
- }
- }
- } else if ($field->getLabel() === GPBLabel::REPEATED) {
- if (count($msg->$getter()) != 0) {
- foreach ($msg->$getter() as $tmp) {
- if ($field->getType() == GPBType::MESSAGE) {
- $klass = $field->getMessageType()->getClass();
- $copy = new $klass;
- $copy->mergeFrom($tmp);
- $this->appendHelper($field, $copy);
- } else {
- $this->appendHelper($field, $tmp);
- }
- }
- }
- } else if ($field->getLabel() === GPBLabel::OPTIONAL) {
- if($msg->$getter() !== $this->defaultValue($field)) {
- $tmp = $msg->$getter();
- if ($field->getType() == GPBType::MESSAGE) {
- if (is_null($this->$getter())) {
- $klass = $field->getMessageType()->getClass();
- $new_msg = new $klass;
- $this->$setter($new_msg);
- }
- $this->$getter()->mergeFrom($tmp);
- } else {
- $this->$setter($tmp);
- }
- }
- }
- }
+ if (get_class($this) !== get_class($msg)) {
+ user_error("Cannot merge messages with different class.");
+ return;
+ }
+
+ foreach ($this->desc->getField() as $field) {
+ $setter = $field->getSetter();
+ $getter = $field->getGetter();
+ if ($field->isMap()) {
+ if (count($msg->$getter()) != 0) {
+ $value_field = $field->getMessageType()->getFieldByNumber(2);
+ foreach ($msg->$getter() as $key => $value) {
+ if ($value_field->getType() == GPBType::MESSAGE) {
+ $klass = $value_field->getMessageType()->getClass();
+ $copy = new $klass;
+ $copy->mergeFrom($value);
+
+ $this->kvUpdateHelper($field, $key, $copy);
+ } else {
+ $this->kvUpdateHelper($field, $key, $value);
+ }
+ }
+ }
+ } else if ($field->getLabel() === GPBLabel::REPEATED) {
+ if (count($msg->$getter()) != 0) {
+ foreach ($msg->$getter() as $tmp) {
+ if ($field->getType() == GPBType::MESSAGE) {
+ $klass = $field->getMessageType()->getClass();
+ $copy = new $klass;
+ $copy->mergeFrom($tmp);
+ $this->appendHelper($field, $copy);
+ } else {
+ $this->appendHelper($field, $tmp);
+ }
+ }
+ }
+ } else if ($field->getLabel() === GPBLabel::OPTIONAL) {
+ if($msg->$getter() !== $this->defaultValue($field)) {
+ $tmp = $msg->$getter();
+ if ($field->getType() == GPBType::MESSAGE) {
+ if (is_null($this->$getter())) {
+ $klass = $field->getMessageType()->getClass();
+ $new_msg = new $klass;
+ $this->$setter($new_msg);
+ }
+ $this->$getter()->mergeFrom($tmp);
+ } else {
+ $this->$setter($tmp);
+ }
+ }
+ }
+ }
}
/**
@@ -763,7 +787,8 @@ class Message
try {
$timestamp = GPBUtil::parseTimestamp($value);
} catch (\Exception $e) {
- throw new GPBDecodeException("Invalid RFC 3339 timestamp: ".$e->getMessage());
+ throw new GPBDecodeException(
+ "Invalid RFC 3339 timestamp: ".$e->getMessage());
}
$submsg->setSeconds($timestamp->getSeconds());
@@ -775,7 +800,8 @@ class Message
try {
return GPBUtil::parseFieldMask($value);
} catch (\Exception $e) {
- throw new GPBDecodeException("Invalid FieldMask: ".$e->getMessage());
+ throw new GPBDecodeException(
+ "Invalid FieldMask: ".$e->getMessage());
}
} else {
if (is_null($value) &&
@@ -792,21 +818,23 @@ class Message
case GPBType::ENUM:
if (is_null($value)) {
return $this->defaultValue($field);
- } else if (is_integer($value)) {
+ }
+ if (is_integer($value)) {
return $value;
- } else {
- $enum_value =
- $field->getEnumType()->getValueByName($value);
}
+ $enum_value = $field->getEnumType()->getValueByName($value);
if (!is_null($enum_value)) {
return $enum_value->getNumber();
}
+ throw new GPBDecodeException(
+ "Enum field only accepts integer or enum value name");
case GPBType::STRING:
if (is_null($value)) {
return $this->defaultValue($field);
}
if (!is_string($value)) {
- throw new GPBDecodeException("Expect string");
+ throw new GPBDecodeException(
+ "String field only accepts string value");
}
return $value;
case GPBType::BYTES:
@@ -814,12 +842,12 @@ class Message
return $this->defaultValue($field);
}
if (!is_string($value)) {
- throw new GPBDecodeException("Expect string");
+ throw new GPBDecodeException(
+ "Byte field only accepts string value");
}
$proto_value = base64_decode($value, true);
if ($proto_value === false) {
- throw new GPBDecodeException(
- "Invalid base64 characters");
+ throw new GPBDecodeException("Invalid base64 characters");
}
return $proto_value;
case GPBType::BOOL:
@@ -834,27 +862,14 @@ class Message
return false;
}
throw new GPBDecodeException(
- "Bool field only accept bool value");
+ "Bool field only accepts bool value");
}
if (!is_bool($value)) {
throw new GPBDecodeException(
- "Bool field only accept bool value");
+ "Bool field only accepts bool value");
}
return $value;
case GPBType::FLOAT:
- if (is_null($value)) {
- return $this->defaultValue($field);
- }
- if ($value === "Infinity") {
- return INF;
- }
- if ($value === "-Infinity") {
- return -INF;
- }
- if ($value === "NaN") {
- return NAN;
- }
- return $value;
case GPBType::DOUBLE:
if (is_null($value)) {
return $this->defaultValue($field);
@@ -943,6 +958,39 @@ class Message
}
}
+ /**
+ * Populates the message from a user-supplied PHP array. Array keys
+ * correspond to Message properties and nested message properties.
+ *
+ * Example:
+ * ```
+ * $message->mergeFromArray([
+ * 'name' => 'This is a message name',
+ * 'interval' => [
+ * 'startTime' => time() - 60,
+ * 'endTime' => time(),
+ * ]
+ * ]);
+ * ```
+ *
+ * @param array $array An array containing message properties and values.
+ * @return null.
+ * @throws Exception Invalid data.
+ */
+ protected function mergeFromArray(array $array)
+ {
+ // Just call the setters for the field names
+ foreach ($array as $key => $value) {
+ $field = $this->desc->getFieldByName($key);
+ if (is_null($field)) {
+ throw new \UnexpectedValueException(
+ 'Invalid message property: ' . $key);
+ }
+ $setter = $field->getSetter();
+ $this->$setter($value);
+ }
+ }
+
protected function mergeFromJsonArray($array)
{
if (is_a($this, "Google\Protobuf\Any")) {
@@ -1035,6 +1083,11 @@ class Message
}
return;
}
+ $this->mergeFromArrayJsonImpl($array);
+ }
+
+ private function mergeFromArrayJsonImpl($array)
+ {
foreach ($array as $key => $value) {
$field = $this->desc->getFieldByJsonName($key);
if (is_null($field)) {
@@ -1043,7 +1096,6 @@ class Message
continue;
}
}
- $setter = $field->getSetter();
if ($field->isMap()) {
if (is_null($value)) {
continue;
@@ -1055,15 +1107,13 @@ class Message
throw new \Exception(
"Map value field element cannot be null.");
}
- $proto_key =
- $this->convertJsonValueToProtoValue(
- $tmp_key,
- $key_field,
- true);
- $proto_value =
- $this->convertJsonValueToProtoValue(
- $tmp_value,
- $value_field);
+ $proto_key = $this->convertJsonValueToProtoValue(
+ $tmp_key,
+ $key_field,
+ true);
+ $proto_value = $this->convertJsonValueToProtoValue(
+ $tmp_value,
+ $value_field);
self::kvUpdateHelper($field, $proto_key, $proto_value);
}
} else if ($field->isRepeated()) {
@@ -1075,14 +1125,16 @@ class Message
throw new \Exception(
"Repeated field elements cannot be null.");
}
- $proto_value =
- $this->convertJsonValueToProtoValue($tmp, $field);
+ $proto_value = $this->convertJsonValueToProtoValue(
+ $tmp,
+ $field);
self::appendHelper($field, $proto_value);
}
} else {
$setter = $field->getSetter();
- $proto_value =
- $this->convertJsonValueToProtoValue($value, $field);
+ $proto_value = $this->convertJsonValueToProtoValue(
+ $value,
+ $field);
if ($field->getType() === GPBType::MESSAGE) {
if (is_null($proto_value)) {
continue;
diff --git a/php/src/Google/Protobuf/Internal/MessageOptions.php b/php/src/Google/Protobuf/Internal/MessageOptions.php
index 99ff3d0e..bf490de6 100644
--- a/php/src/Google/Protobuf/Internal/MessageOptions.php
+++ b/php/src/Google/Protobuf/Internal/MessageOptions.php
@@ -87,9 +87,63 @@ class MessageOptions extends \Google\Protobuf\Internal\Message
private $uninterpreted_option;
private $has_uninterpreted_option = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type bool $message_set_wire_format
+ * Set true to use the old proto1 MessageSet wire format for extensions.
+ * This is provided for backwards-compatibility with the MessageSet wire
+ * format. You should not use this for any other reason: It's less
+ * efficient, has fewer features, and is more complicated.
+ * The message must be defined exactly as follows:
+ * message Foo {
+ * option message_set_wire_format = true;
+ * extensions 4 to max;
+ * }
+ * Note that the message cannot have any defined fields; MessageSets only
+ * have extensions.
+ * All extensions of your type must be singular messages; e.g. they cannot
+ * be int32s, enums, or repeated messages.
+ * Because this is an option, the above two restrictions are not enforced by
+ * the protocol compiler.
+ * @type bool $no_standard_descriptor_accessor
+ * Disables the generation of the standard "descriptor()" accessor, which can
+ * conflict with a field of the same name. This is meant to make migration
+ * from proto1 easier; new code should avoid fields named "descriptor".
+ * @type bool $deprecated
+ * Is this message deprecated?
+ * Depending on the target platform, this can emit Deprecated annotations
+ * for the message, or it will be completely ignored; in the very least,
+ * this is a formalization for deprecating messages.
+ * @type bool $map_entry
+ * Whether the message is an automatically generated map entry type for the
+ * maps field.
+ * For maps fields:
+ * map<KeyType, ValueType> map_field = 1;
+ * The parsed descriptor looks like:
+ * message MapFieldEntry {
+ * option map_entry = true;
+ * optional KeyType key = 1;
+ * optional ValueType value = 2;
+ * }
+ * repeated MapFieldEntry map_field = 1;
+ * Implementations may choose not to generate the map_entry=true message, but
+ * use a native map in the target language to hold the keys and values.
+ * The reflection APIs in such implementions still need to work as
+ * if the field is a repeated message field.
+ * NOTE: Do not set the option in .proto files. Always use the maps syntax
+ * instead. The option should only be implicitly set by the proto compiler
+ * parser.
+ * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option
+ * The parser stores options it doesn't recognize here. See above.
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php b/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php
index ccfce2db..1bd5dd3e 100644
--- a/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php
@@ -55,9 +55,27 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message
private $server_streaming = false;
private $has_server_streaming = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $name
+ * @type string $input_type
+ * Input and output type names. These are resolved in the same way as
+ * FieldDescriptorProto.type_name, but must refer to a message type.
+ * @type string $output_type
+ * @type \Google\Protobuf\Internal\MethodOptions $options
+ * @type bool $client_streaming
+ * Identifies if client streams multiple client messages
+ * @type bool $server_streaming
+ * Identifies if server streams multiple server messages
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/MethodOptions.php b/php/src/Google/Protobuf/Internal/MethodOptions.php
index baa806b7..a2c729a9 100644
--- a/php/src/Google/Protobuf/Internal/MethodOptions.php
+++ b/php/src/Google/Protobuf/Internal/MethodOptions.php
@@ -38,9 +38,25 @@ class MethodOptions extends \Google\Protobuf\Internal\Message
private $uninterpreted_option;
private $has_uninterpreted_option = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type bool $deprecated
+ * Is this method deprecated?
+ * Depending on the target platform, this can emit Deprecated annotations
+ * for the method, or it will be completely ignored; in the very least,
+ * this is a formalization for deprecating methods.
+ * @type int $idempotency_level
+ * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option
+ * The parser stores options it doesn't recognize here. See above.
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php b/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php
index 15ff0610..9ecfe5cb 100644
--- a/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php
@@ -28,9 +28,19 @@ class OneofDescriptorProto extends \Google\Protobuf\Internal\Message
private $options = null;
private $has_options = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $name
+ * @type \Google\Protobuf\Internal\OneofOptions $options
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/OneofOptions.php b/php/src/Google/Protobuf/Internal/OneofOptions.php
index e5b4633d..46b516f3 100644
--- a/php/src/Google/Protobuf/Internal/OneofOptions.php
+++ b/php/src/Google/Protobuf/Internal/OneofOptions.php
@@ -23,9 +23,19 @@ class OneofOptions extends \Google\Protobuf\Internal\Message
private $uninterpreted_option;
private $has_uninterpreted_option = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option
+ * The parser stores options it doesn't recognize here. See above.
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php b/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php
index da88e9c4..8de7afd0 100644
--- a/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php
@@ -33,9 +33,20 @@ class ServiceDescriptorProto extends \Google\Protobuf\Internal\Message
private $options = null;
private $has_options = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $name
+ * @type \Google\Protobuf\Internal\MethodDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $method
+ * @type \Google\Protobuf\Internal\ServiceOptions $options
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/ServiceOptions.php b/php/src/Google/Protobuf/Internal/ServiceOptions.php
index 3e7214a1..67162f37 100644
--- a/php/src/Google/Protobuf/Internal/ServiceOptions.php
+++ b/php/src/Google/Protobuf/Internal/ServiceOptions.php
@@ -33,9 +33,24 @@ class ServiceOptions extends \Google\Protobuf\Internal\Message
private $uninterpreted_option;
private $has_uninterpreted_option = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type bool $deprecated
+ * Is this service deprecated?
+ * Depending on the target platform, this can emit Deprecated annotations
+ * for the service, or it will be completely ignored; in the very least,
+ * this is a formalization for deprecating services.
+ * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option
+ * The parser stores options it doesn't recognize here. See above.
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/SourceCodeInfo.php b/php/src/Google/Protobuf/Internal/SourceCodeInfo.php
index 6ce05ed4..2305a792 100644
--- a/php/src/Google/Protobuf/Internal/SourceCodeInfo.php
+++ b/php/src/Google/Protobuf/Internal/SourceCodeInfo.php
@@ -66,9 +66,59 @@ class SourceCodeInfo extends \Google\Protobuf\Internal\Message
private $location;
private $has_location = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type \Google\Protobuf\Internal\SourceCodeInfo_Location[]|\Google\Protobuf\Internal\RepeatedField $location
+ * A Location identifies a piece of source code in a .proto file which
+ * corresponds to a particular definition. This information is intended
+ * to be useful to IDEs, code indexers, documentation generators, and similar
+ * tools.
+ * For example, say we have a file like:
+ * message Foo {
+ * optional string foo = 1;
+ * }
+ * Let's look at just the field definition:
+ * optional string foo = 1;
+ * ^ ^^ ^^ ^ ^^^
+ * a bc de f ghi
+ * We have the following locations:
+ * span path represents
+ * [a,i) [ 4, 0, 2, 0 ] The whole field definition.
+ * [a,b) [ 4, 0, 2, 0, 4 ] The label (optional).
+ * [c,d) [ 4, 0, 2, 0, 5 ] The type (string).
+ * [e,f) [ 4, 0, 2, 0, 1 ] The name (foo).
+ * [g,h) [ 4, 0, 2, 0, 3 ] The number (1).
+ * Notes:
+ * - A location may refer to a repeated field itself (i.e. not to any
+ * particular index within it). This is used whenever a set of elements are
+ * logically enclosed in a single code segment. For example, an entire
+ * extend block (possibly containing multiple extension definitions) will
+ * have an outer location whose path refers to the "extensions" repeated
+ * field without an index.
+ * - Multiple locations may have the same path. This happens when a single
+ * logical declaration is spread out across multiple places. The most
+ * obvious example is the "extend" block again -- there may be multiple
+ * extend blocks in the same scope, each of which will have the same path.
+ * - A location's span is not always a subset of its parent's span. For
+ * example, the "extendee" of an extension declaration appears at the
+ * beginning of the "extend" block and is shared by all extensions within
+ * the block.
+ * - Just because a location's span is a subset of some other location's span
+ * does not mean that it is a descendent. For example, a "group" defines
+ * both a type and a field in a single declaration. Thus, the locations
+ * corresponding to the type and field and their components will overlap.
+ * - Code which tries to interpret locations should probably be designed to
+ * ignore those that it doesn't understand, as more types of locations could
+ * be recorded in the future.
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php b/php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php
index 19ed2bc2..f930aac1 100644
--- a/php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php
+++ b/php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php
@@ -106,9 +106,84 @@ class SourceCodeInfo_Location extends \Google\Protobuf\Internal\Message
private $leading_detached_comments;
private $has_leading_detached_comments = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type int[]|\Google\Protobuf\Internal\RepeatedField $path
+ * Identifies which part of the FileDescriptorProto was defined at this
+ * location.
+ * Each element is a field number or an index. They form a path from
+ * the root FileDescriptorProto to the place where the definition. For
+ * example, this path:
+ * [ 4, 3, 2, 7, 1 ]
+ * refers to:
+ * file.message_type(3) // 4, 3
+ * .field(7) // 2, 7
+ * .name() // 1
+ * This is because FileDescriptorProto.message_type has field number 4:
+ * repeated DescriptorProto message_type = 4;
+ * and DescriptorProto.field has field number 2:
+ * repeated FieldDescriptorProto field = 2;
+ * and FieldDescriptorProto.name has field number 1:
+ * optional string name = 1;
+ * Thus, the above path gives the location of a field name. If we removed
+ * the last element:
+ * [ 4, 3, 2, 7 ]
+ * this path refers to the whole field declaration (from the beginning
+ * of the label to the terminating semicolon).
+ * @type int[]|\Google\Protobuf\Internal\RepeatedField $span
+ * Always has exactly three or four elements: start line, start column,
+ * end line (optional, otherwise assumed same as start line), end column.
+ * These are packed into a single field for efficiency. Note that line
+ * and column numbers are zero-based -- typically you will want to add
+ * 1 to each before displaying to a user.
+ * @type string $leading_comments
+ * If this SourceCodeInfo represents a complete declaration, these are any
+ * comments appearing before and after the declaration which appear to be
+ * attached to the declaration.
+ * A series of line comments appearing on consecutive lines, with no other
+ * tokens appearing on those lines, will be treated as a single comment.
+ * leading_detached_comments will keep paragraphs of comments that appear
+ * before (but not connected to) the current element. Each paragraph,
+ * separated by empty lines, will be one comment element in the repeated
+ * field.
+ * Only the comment content is provided; comment markers (e.g. //) are
+ * stripped out. For block comments, leading whitespace and an asterisk
+ * will be stripped from the beginning of each line other than the first.
+ * Newlines are included in the output.
+ * Examples:
+ * optional int32 foo = 1; // Comment attached to foo.
+ * // Comment attached to bar.
+ * optional int32 bar = 2;
+ * optional string baz = 3;
+ * // Comment attached to baz.
+ * // Another line attached to baz.
+ * // Comment attached to qux.
+ * //
+ * // Another line attached to qux.
+ * optional double qux = 4;
+ * // Detached comment for corge. This is not leading or trailing comments
+ * // to qux or corge because there are blank lines separating it from
+ * // both.
+ * // Detached comment for corge paragraph 2.
+ * optional string corge = 5;
+ * /&#42; Block comment attached
+ * * to corge. Leading asterisks
+ * * will be removed. *&#47;
+ * /&#42; Block comment attached to
+ * * grault. *&#47;
+ * optional int32 grault = 6;
+ * // ignored detached comments.
+ * @type string $trailing_comments
+ * @type string[]|\Google\Protobuf\Internal\RepeatedField $leading_detached_comments
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/UninterpretedOption.php b/php/src/Google/Protobuf/Internal/UninterpretedOption.php
index 4d342eb3..36a18688 100644
--- a/php/src/Google/Protobuf/Internal/UninterpretedOption.php
+++ b/php/src/Google/Protobuf/Internal/UninterpretedOption.php
@@ -61,9 +61,26 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message
private $aggregate_value = '';
private $has_aggregate_value = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type \Google\Protobuf\Internal\UninterpretedOption_NamePart[]|\Google\Protobuf\Internal\RepeatedField $name
+ * @type string $identifier_value
+ * The value of the uninterpreted option, in whatever type the tokenizer
+ * identified it as during parsing. Exactly one of these should be set.
+ * @type int|string $positive_int_value
+ * @type int|string $negative_int_value
+ * @type float $double_value
+ * @type string $string_value
+ * @type string $aggregate_value
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php b/php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php
index c9a6fc3c..d4369fda 100644
--- a/php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php
+++ b/php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php
@@ -32,9 +32,19 @@ class UninterpretedOption_NamePart extends \Google\Protobuf\Internal\Message
private $is_extension = false;
private $has_is_extension = false;
- public function __construct() {
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $name_part
+ * @type bool $is_extension
+ * }
+ */
+ public function __construct($data = NULL) {
\GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
- parent::__construct();
+ parent::__construct($data);
}
/**
diff --git a/php/tests/generated_phpdoc_test.php b/php/tests/generated_phpdoc_test.php
index 6c1a26f7..505dafea 100644
--- a/php/tests/generated_phpdoc_test.php
+++ b/php/tests/generated_phpdoc_test.php
@@ -16,6 +16,14 @@ class GeneratedPhpdocTest extends TestBase
$this->assertContains('foo.TestMessage', $doc);
}
+ public function testPhpDocForConstructor()
+ {
+ $class = new ReflectionClass('Foo\TestMessage');
+ $doc = $class->getMethod('__construct')->getDocComment();
+ $this->assertContains('@param array $data', $doc);
+ $this->assertContains('@type int $optional_int32', $doc);
+ }
+
/**
* @dataProvider providePhpDocForGettersAndSetters
*/
diff --git a/php/tests/php_implementation_test.php b/php/tests/php_implementation_test.php
index 5dbc9233..720af132 100644
--- a/php/tests/php_implementation_test.php
+++ b/php/tests/php_implementation_test.php
@@ -3,6 +3,7 @@
require_once('test_base.php');
require_once('test_util.php');
+use Foo\TestEnum;
use Foo\TestMessage;
use Foo\TestMessage_Sub;
use Foo\TestPackedMessage;
@@ -15,7 +16,6 @@ use Google\Protobuf\Internal\CodedOutputStream;
class ImplementationTest extends TestBase
{
-
public function testReadInt32()
{
$value = null;
@@ -513,4 +513,156 @@ class ImplementationTest extends TestBase
TestUtil::setTestPackedMessage($m);
$this->assertSame(166, $m->byteSize());
}
+
+ public function testArrayConstructor()
+ {
+ $m = new TestMessage([
+ 'optional_int32' => -42,
+ 'optional_int64' => -43,
+ 'optional_uint32' => 42,
+ 'optional_uint64' => 43,
+ 'optional_sint32' => -44,
+ 'optional_sint64' => -45,
+ 'optional_fixed32' => 46,
+ 'optional_fixed64' => 47,
+ 'optional_sfixed32' => -46,
+ 'optional_sfixed64' => -47,
+ 'optional_float' => 1.5,
+ 'optional_double' => 1.6,
+ 'optional_bool' => true,
+ 'optional_string' => 'a',
+ 'optional_bytes' => 'b',
+ 'optional_enum' => TestEnum::ONE,
+ 'optional_message' => new TestMessage_Sub([
+ 'a' => 33
+ ]),
+ 'repeated_int32' => [-42, -52],
+ 'repeated_int64' => [-43, -53],
+ 'repeated_uint32' => [42, 52],
+ 'repeated_uint64' => [43, 53],
+ 'repeated_sint32' => [-44, -54],
+ 'repeated_sint64' => [-45, -55],
+ 'repeated_fixed32' => [46, 56],
+ 'repeated_fixed64' => [47, 57],
+ 'repeated_sfixed32' => [-46, -56],
+ 'repeated_sfixed64' => [-47, -57],
+ 'repeated_float' => [1.5, 2.5],
+ 'repeated_double' => [1.6, 2.6],
+ 'repeated_bool' => [true, false],
+ 'repeated_string' => ['a', 'c'],
+ 'repeated_bytes' => ['b', 'd'],
+ 'repeated_enum' => [TestEnum::ZERO, TestEnum::ONE],
+ 'repeated_message' => [
+ new TestMessage_Sub(['a' => 34]),
+ new TestMessage_Sub(['a' => 35]),
+ ],
+ 'map_int32_int32' => [-62 => -62],
+ 'map_int64_int64' => [-63 => -63],
+ 'map_uint32_uint32' => [62 => 62],
+ 'map_uint64_uint64' => [63 => 63],
+ 'map_sint32_sint32' => [-64 => -64],
+ 'map_sint64_sint64' => [-65 => -65],
+ 'map_fixed32_fixed32' => [66 => 66],
+ 'map_fixed64_fixed64' => [67 => 67],
+ 'map_sfixed32_sfixed32' => [-68 => -68],
+ 'map_sfixed64_sfixed64' => [-69 => -69],
+ 'map_int32_float' => [1 => 3.5],
+ 'map_int32_double' => [1 => 3.6],
+ 'map_bool_bool' => [true => true],
+ 'map_string_string' => ['e' => 'e'],
+ 'map_int32_bytes' => [1 => 'f'],
+ 'map_int32_enum' => [1 => TestEnum::ONE],
+ 'map_int32_message' => [1 => new TestMessage_Sub(['a' => 36])],
+ ]);
+
+ TestUtil::assertTestMessage($m);
+
+ // Using message objects
+ $m = new TestMessage([
+ 'optional_message' => new TestMessage_Sub(['a' => 33]),
+ 'repeated_message' => [
+ new TestMessage_Sub(['a' => 34]),
+ new TestMessage_Sub(['a' => 35]),
+ ],
+ 'map_int32_message' => [
+ 1 => new TestMessage_Sub(['a' => 36])
+ ],
+ ]);
+
+ $this->assertEquals(33, $m->getOptionalMessage()->getA());
+ $this->assertEquals(34, $m->getRepeatedMessage()[0]->getA());
+ $this->assertEquals(35, $m->getRepeatedMessage()[1]->getA());
+ $this->assertEquals(36, $m->getMapInt32Message()[1]->getA());
+ }
+
+ /**
+ * @expectedException UnexpectedValueException
+ * @expectedExceptionMessage Invalid message property: optionalInt32
+ */
+ public function testArrayConstructorJsonCaseThrowsException()
+ {
+ $m = new TestMessage([
+ 'optionalInt32' => -42,
+ ]);
+ }
+
+ /**
+ * @expectedException Exception
+ * @expectedExceptionMessage Expect message.
+ */
+ public function testArraysForMessagesThrowsException()
+ {
+ $m = new TestMessage([
+ 'optional_message' => [
+ 'a' => 33
+ ]
+ ]);
+ }
+
+ public function testArrayConstructorWithNullValues()
+ {
+ $requestData = [
+ 'optional_bool' => null,
+ 'optional_string' => null,
+ 'optional_bytes' => null,
+ 'optional_message' => null,
+ ];
+
+ $m = new TestMessage($requestData);
+
+ $this->assertSame(false, $m->getOptionalBool());
+ $this->assertSame('', $m->getOptionalString());
+ $this->assertSame('', $m->getOptionalBytes());
+ $this->assertSame(null, $m->getOptionalMessage());
+ }
+
+ /**
+ * @dataProvider provideArrayConstructorWithNullValuesThrowsException
+ * @expectedException Exception
+ */
+ public function testArrayConstructorWithNullValuesThrowsException($requestData)
+ {
+ $m = new TestMessage($requestData);
+ }
+
+ public function provideArrayConstructorWithNullValuesThrowsException()
+ {
+ return [
+ [['optional_int32' => null]],
+ [['optional_int64' => null]],
+ [['optional_uint32' => null]],
+ [['optional_uint64' => null]],
+ [['optional_sint32' => null]],
+ [['optional_sint64' => null]],
+ [['optional_fixed32' => null]],
+ [['optional_fixed64' => null]],
+ [['optional_sfixed32' => null]],
+ [['optional_sfixed64' => null]],
+ [['optional_float' => null]],
+ [['optional_double' => null]],
+ [['optional_enum' => null]],
+ [['repeated_int32' => null]],
+ [['map_int32_int32' => null]],
+ ];
+ }
}
diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc
index a37380e3..34d0f9ef 100644
--- a/src/google/protobuf/compiler/php/php_generator.cc
+++ b/src/google/protobuf/compiler/php/php_generator.cc
@@ -94,6 +94,9 @@ void Indent(io::Printer* printer);
void Outdent(io::Printer* printer);
void GenerateMessageDocComment(io::Printer* printer, const Descriptor* message,
int is_descriptor);
+void GenerateMessageConstructorDocComment(io::Printer* printer,
+ const Descriptor* message,
+ int is_descriptor);
void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field,
int is_descriptor, int function_type);
void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
@@ -1109,8 +1112,9 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
}
printer.Print("\n");
+ GenerateMessageConstructorDocComment(&printer, message, is_descriptor);
printer.Print(
- "public function __construct() {\n");
+ "public function __construct($data = NULL) {\n");
Indent(&printer);
std::string metadata_filename =
@@ -1118,7 +1122,7 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
std::string metadata_fullname = FilenameToClassname(metadata_filename);
printer.Print(
"\\^fullname^::initOnce();\n"
- "parent::__construct();\n",
+ "parent::__construct($data);\n",
"fullname", metadata_fullname);
Outdent(&printer);
@@ -1271,7 +1275,8 @@ static string EscapePhpdoc(const string& input) {
}
static void GenerateDocCommentBodyForLocation(
- io::Printer* printer, const SourceLocation& location) {
+ io::Printer* printer, const SourceLocation& location, bool trailingNewline,
+ int indentCount) {
string comments = location.leading_comments.empty() ?
location.trailing_comments : location.leading_comments;
if (!comments.empty()) {
@@ -1292,14 +1297,16 @@ static void GenerateDocCommentBodyForLocation(
// Most lines should start with a space. Watch out for lines that start
// with a /, since putting that right after the leading asterisk will
// close the comment.
- if (!lines[i].empty() && lines[i][0] == '/') {
+ if (indentCount == 0 && !lines[i].empty() && lines[i][0] == '/') {
printer->Print(" * ^line^\n", "line", lines[i]);
} else {
- printer->Print(" *^line^\n", "line", lines[i]);
+ std::string indent = std::string(indentCount, ' ');
+ printer->Print(" *^ind^^line^\n", "ind", indent, "line", lines[i]);
}
}
- printer->Print(
- " *\n");
+ if (trailingNewline) {
+ printer->Print(" *\n");
+ }
}
}
@@ -1308,7 +1315,7 @@ static void GenerateDocCommentBody(
io::Printer* printer, const DescriptorType* descriptor) {
SourceLocation location;
if (descriptor->GetSourceLocation(&location)) {
- GenerateDocCommentBodyForLocation(printer, location);
+ GenerateDocCommentBodyForLocation(printer, location, true, 0);
}
}
@@ -1334,6 +1341,37 @@ void GenerateMessageDocComment(io::Printer* printer,
"messagename", EscapePhpdoc(message->full_name()));
}
+void GenerateMessageConstructorDocComment(io::Printer* printer,
+ const Descriptor* message,
+ int is_descriptor) {
+ // In theory we should have slightly different comments for setters, getters,
+ // etc., but in practice everyone already knows the difference between these
+ // so it's redundant information.
+
+ // We start the comment with the main body based on the comments from the
+ // .proto file (if present). We then end with the field declaration, e.g.:
+ // optional string foo = 5;
+ // If the field is a group, the debug string might end with {.
+ printer->Print("/**\n");
+ printer->Print(" * Constructor.\n");
+ printer->Print(" *\n");
+ printer->Print(" * @param array $data {\n");
+ printer->Print(" * Optional. Data for populating the Message object.\n");
+ printer->Print(" *\n");
+ for (int i = 0; i < message->field_count(); i++) {
+ const FieldDescriptor* field = message->field(i);
+ printer->Print(" * @type ^php_type^ $^var^\n",
+ "php_type", PhpSetterTypeName(field, is_descriptor),
+ "var", field->name());
+ SourceLocation location;
+ if (field->GetSourceLocation(&location)) {
+ GenerateDocCommentBodyForLocation(printer, location, false, 10);
+ }
+ }
+ printer->Print(" * }\n");
+ printer->Print(" */\n");
+}
+
void GenerateServiceDocComment(io::Printer* printer,
const ServiceDescriptor* service) {
printer->Print("/**\n");