in cdk/extra/protobuf/protobuf-3.19.6/src/google/protobuf/compiler/js/js_generator.cc [2544:2897]
void Generator::GenerateClassField(const GeneratorOptions& options,
io::Printer* printer,
const FieldDescriptor* field) const {
if (field->is_map()) {
const FieldDescriptor* key_field = MapFieldKey(field);
const FieldDescriptor* value_field = MapFieldValue(field);
// Map field: special handling to instantiate the map object on demand.
std::string key_type =
JSFieldTypeAnnotation(options, key_field,
/* is_setter_argument = */ false,
/* force_present = */ true,
/* singular_if_not_packed = */ false);
std::string value_type =
JSFieldTypeAnnotation(options, value_field,
/* is_setter_argument = */ false,
/* force_present = */ true,
/* singular_if_not_packed = */ false);
printer->Print(
"/**\n"
" * $fielddef$\n"
" * @param {boolean=} opt_noLazyCreate Do not create the map if\n"
" * empty, instead returning `undefined`\n"
" * @return {!jspb.Map<$keytype$,$valuetype$>}\n"
" */\n",
"fielddef", FieldDefinition(options, field), "keytype", key_type,
"valuetype", value_type);
printer->Print(
"$class$.prototype.$gettername$ = function(opt_noLazyCreate) {\n"
" return /** @type {!jspb.Map<$keytype$,$valuetype$>} */ (\n",
"class", GetMessagePath(options, field->containing_type()),
"gettername", "get" + JSGetterName(options, field), "keytype", key_type,
"valuetype", value_type);
printer->Annotate("gettername", field);
printer->Print(
" jspb.Message.getMapField(this, $index$, opt_noLazyCreate",
"index", JSFieldIndex(field));
if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
printer->Print(
",\n"
" $messageType$",
"messageType", GetMessagePath(options, value_field->message_type()));
} else {
printer->Print(
",\n"
" null");
}
printer->Print("));\n");
printer->Print(
"};\n"
"\n"
"\n");
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
// Message field: special handling in order to wrap the underlying data
// array with a message object.
printer->Print(
"/**\n"
" * $fielddef$\n"
"$comment$"
" * @return {$type$}\n"
" */\n",
"fielddef", FieldDefinition(options, field), "comment",
FieldComments(field, BYTES_DEFAULT), "type",
JSFieldTypeAnnotation(options, field,
/* is_setter_argument = */ false,
/* force_present = */ false,
/* singular_if_not_packed = */ false));
printer->Print(
"$class$.prototype.$gettername$ = function() {\n"
" return /** @type{$type$} */ (\n"
" jspb.Message.get$rpt$WrapperField(this, $wrapperclass$, "
"$index$$required$));\n"
"};\n"
"\n"
"\n",
"class", GetMessagePath(options, field->containing_type()),
"gettername", "get" + JSGetterName(options, field), "type",
JSFieldTypeAnnotation(options, field,
/* is_setter_argument = */ false,
/* force_present = */ false,
/* singular_if_not_packed = */ false),
"rpt", (field->is_repeated() ? "Repeated" : ""), "index",
JSFieldIndex(field), "wrapperclass", SubmessageTypeRef(options, field),
"required",
(field->label() == FieldDescriptor::LABEL_REQUIRED ? ", 1" : ""));
printer->Annotate("gettername", field);
printer->Print(
"/**\n"
" * @param {$optionaltype$} value\n"
" * @return {!$class$} returns this\n"
"*/\n"
"$class$.prototype.$settername$ = function(value) {\n"
" return jspb.Message.set$oneoftag$$repeatedtag$WrapperField(",
"optionaltype",
JSFieldTypeAnnotation(options, field,
/* is_setter_argument = */ true,
/* force_present = */ false,
/* singular_if_not_packed = */ false),
"class", GetMessagePath(options, field->containing_type()),
"settername", "set" + JSGetterName(options, field), "oneoftag",
(InRealOneof(field) ? "Oneof" : ""), "repeatedtag",
(field->is_repeated() ? "Repeated" : ""));
printer->Annotate("settername", field);
printer->Print(
"this, $index$$oneofgroup$, value);\n"
"};\n"
"\n"
"\n",
"index", JSFieldIndex(field), "oneofgroup",
(InRealOneof(field) ? (", " + JSOneofArray(options, field)) : ""));
if (field->is_repeated()) {
GenerateRepeatedMessageHelperMethods(options, printer, field);
}
} else {
bool untyped = false;
// Simple (primitive) field, either singular or repeated.
// TODO(b/26173701): Always use BYTES_DEFAULT for the getter return type;
// at this point we "lie" to non-binary users and tell the return
// type is always base64 string, pending a LSC to migrate to typed getters.
BytesMode bytes_mode =
field->type() == FieldDescriptor::TYPE_BYTES && !options.binary
? BYTES_B64
: BYTES_DEFAULT;
std::string typed_annotation =
JSFieldTypeAnnotation(options, field,
/* is_setter_argument = */ false,
/* force_present = */ false,
/* singular_if_not_packed = */ false,
/* bytes_mode = */ bytes_mode);
if (untyped) {
printer->Print(
"/**\n"
" * @return {?} Raw field, untyped.\n"
" */\n");
} else {
printer->Print(
"/**\n"
" * $fielddef$\n"
"$comment$"
" * @return {$type$}\n"
" */\n",
"fielddef", FieldDefinition(options, field), "comment",
FieldComments(field, bytes_mode), "type", typed_annotation);
}
printer->Print("$class$.prototype.$gettername$ = function() {\n", "class",
GetMessagePath(options, field->containing_type()),
"gettername", "get" + JSGetterName(options, field));
printer->Annotate("gettername", field);
if (untyped) {
printer->Print(" return ");
} else {
printer->Print(" return /** @type {$type$} */ (", "type",
typed_annotation);
}
bool use_default = !ReturnsNullWhenUnset(options, field);
// Raw fields with no default set should just return undefined.
if (untyped && !field->has_default_value()) {
use_default = false;
}
// Repeated fields get initialized to their default in the constructor
// (why?), so we emit a plain getField() call for them.
if (field->is_repeated()) {
use_default = false;
}
GenerateFieldValueExpression(printer, "this", field, use_default);
if (untyped) {
printer->Print(
";\n"
"};\n"
"\n"
"\n");
} else {
printer->Print(
");\n"
"};\n"
"\n"
"\n");
}
if (field->type() == FieldDescriptor::TYPE_BYTES && !untyped) {
GenerateBytesWrapper(options, printer, field, BYTES_B64);
GenerateBytesWrapper(options, printer, field, BYTES_U8);
}
printer->Print(
"/**\n"
" * @param {$optionaltype$} value\n"
" * @return {!$class$} returns this\n"
" */\n",
"class", GetMessagePath(options, field->containing_type()),
"optionaltype",
untyped ? "*"
: JSFieldTypeAnnotation(options, field,
/* is_setter_argument = */ true,
/* force_present = */ false,
/* singular_if_not_packed = */ false));
if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
!field->is_repeated() && !field->is_map() &&
!HasFieldPresence(options, field)) {
// Proto3 non-repeated and non-map fields without presence use the
// setProto3*Field function.
printer->Print(
"$class$.prototype.$settername$ = function(value) {\n"
" return jspb.Message.setProto3$typetag$Field(this, $index$, "
"value);"
"\n"
"};\n"
"\n"
"\n",
"class", GetMessagePath(options, field->containing_type()),
"settername", "set" + JSGetterName(options, field), "typetag",
JSTypeTag(field), "index", JSFieldIndex(field));
printer->Annotate("settername", field);
} else {
// Otherwise, use the regular setField function.
printer->Print(
"$class$.prototype.$settername$ = function(value) {\n"
" return jspb.Message.set$oneoftag$Field(this, $index$",
"class", GetMessagePath(options, field->containing_type()),
"settername", "set" + JSGetterName(options, field), "oneoftag",
(InRealOneof(field) ? "Oneof" : ""), "index", JSFieldIndex(field));
printer->Annotate("settername", field);
printer->Print(
"$oneofgroup$, $type$value$rptvalueinit$$typeclose$);\n"
"};\n"
"\n"
"\n",
"type",
untyped ? "/** @type{string|number|boolean|Array|undefined} */(" : "",
"typeclose", untyped ? ")" : "", "oneofgroup",
(InRealOneof(field) ? (", " + JSOneofArray(options, field)) : ""),
"rptvalueinit", (field->is_repeated() ? " || []" : ""));
}
if (untyped) {
printer->Print(
"/**\n"
" * Clears the value.\n"
" * @return {!$class$} returns this\n"
" */\n",
"class", GetMessagePath(options, field->containing_type()));
}
if (field->is_repeated()) {
GenerateRepeatedPrimitiveHelperMethods(options, printer, field, untyped);
}
}
// Generate clearFoo() method for map fields, repeated fields, and other
// fields with presence.
if (field->is_map()) {
// clang-format off
printer->Print(
"/**\n"
" * Clears values from the map. The map will be non-null.\n"
" * @return {!$class$} returns this\n"
" */\n"
"$class$.prototype.$clearername$ = function() {\n"
" this.$gettername$().clear();\n"
" return this;"
"};\n"
"\n"
"\n",
"class", GetMessagePath(options, field->containing_type()),
"clearername", "clear" + JSGetterName(options, field),
"gettername", "get" + JSGetterName(options, field));
// clang-format on
printer->Annotate("clearername", field);
} else if (field->is_repeated() ||
(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
!field->is_required())) {
// Fields where we can delegate to the regular setter.
// clang-format off
printer->Print(
"/**\n"
" * $jsdoc$\n"
" * @return {!$class$} returns this\n"
" */\n"
"$class$.prototype.$clearername$ = function() {\n"
" return this.$settername$($clearedvalue$);\n"
"};\n"
"\n"
"\n",
"jsdoc", field->is_repeated()
? "Clears the list making it empty but non-null."
: "Clears the message field making it undefined.",
"class", GetMessagePath(options, field->containing_type()),
"clearername", "clear" + JSGetterName(options, field),
"settername", "set" + JSGetterName(options, field),
"clearedvalue", (field->is_repeated() ? "[]" : "undefined"));
// clang-format on
printer->Annotate("clearername", field);
} else if (HasFieldPresence(options, field)) {
// Fields where we can't delegate to the regular setter because it doesn't
// accept "undefined" as an argument.
// clang-format off
printer->Print(
"/**\n"
" * Clears the field making it undefined.\n"
" * @return {!$class$} returns this\n"
" */\n"
"$class$.prototype.$clearername$ = function() {\n"
" return jspb.Message.set$maybeoneof$Field(this, "
"$index$$maybeoneofgroup$, ",
"class", GetMessagePath(options, field->containing_type()),
"clearername", "clear" + JSGetterName(options, field),
"maybeoneof", (InRealOneof(field) ? "Oneof" : ""),
"maybeoneofgroup", (InRealOneof(field)
? (", " + JSOneofArray(options, field))
: ""),
"index", JSFieldIndex(field));
// clang-format on
printer->Annotate("clearername", field);
printer->Print(
"$clearedvalue$);\n"
"};\n"
"\n"
"\n",
"clearedvalue", (field->is_repeated() ? "[]" : "undefined"));
}
if (HasFieldPresence(options, field)) {
printer->Print(
"/**\n"
" * Returns whether this field is set.\n"
" * @return {boolean}\n"
" */\n"
"$class$.prototype.$hasername$ = function() {\n"
" return jspb.Message.getField(this, $index$) != null;\n"
"};\n"
"\n"
"\n",
"class", GetMessagePath(options, field->containing_type()), "hasername",
"has" + JSGetterName(options, field), "index", JSFieldIndex(field));
printer->Annotate("hasername", field);
}
}