diff options
author | lokken <lokken@yandex-team.ru> | 2022-02-10 16:47:33 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:47:33 +0300 |
commit | b0fa6d4befe59be301b94f957505510e247c5c10 (patch) | |
tree | c0e726f55449209dcc36fe5d3866ea8b00e5baca | |
parent | 91627ad918ce331c6d185aaaef1e5d1353c390b0 (diff) | |
download | ydb-b0fa6d4befe59be301b94f957505510e247c5c10.tar.gz |
Restoring authorship annotation for <lokken@yandex-team.ru>. Commit 1 of 2.
5 files changed, 2894 insertions, 2894 deletions
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/js/js_generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/js/js_generator.cc index 521bcd0226..1af8fff095 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/js/js_generator.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/js/js_generator.cc @@ -1,33 +1,33 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + #include <assert.h> #include <google/protobuf/compiler/js/js_generator.h> #include <google/protobuf/compiler/js/well_known_types_embed.h> @@ -40,23 +40,23 @@ #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/stringprintf.h> #include <google/protobuf/stubs/strutil.h> - -#include <algorithm> -#include <limits> -#include <map> -#include <memory> -#include <string> -#include <utility> -#include <vector> - -namespace google { -namespace protobuf { -namespace compiler { -namespace js { - -// Sorted list of JavaScript keywords. These cannot be used as names. If they -// appear, we prefix them with "pb_". -const char* kKeyword[] = { + +#include <algorithm> +#include <limits> +#include <map> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +namespace google { +namespace protobuf { +namespace compiler { +namespace js { + +// Sorted list of JavaScript keywords. These cannot be used as names. If they +// appear, we prefix them with "pb_". +const char* kKeyword[] = { "abstract", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "debugger", "default", "delete", "do", "double", @@ -69,131 +69,131 @@ const char* kKeyword[] = { "switch", "synchronized", "this", "throw", "throws", "transient", "try", "typeof", "var", "void", "volatile", "while", "with", -}; - -static const int kNumKeyword = sizeof(kKeyword) / sizeof(char*); - -namespace { - -// The mode of operation for bytes fields. Historically JSPB always carried -// bytes as JS {string}, containing base64 content by convention. With binary -// and proto3 serialization the new convention is to represent it as binary -// data in Uint8Array. See b/26173701 for background on the migration. -enum BytesMode { - BYTES_DEFAULT, // Default type for getBytesField to return. - BYTES_B64, // Explicitly coerce to base64 string where needed. - BYTES_U8, // Explicitly coerce to Uint8Array where needed. -}; - +}; + +static const int kNumKeyword = sizeof(kKeyword) / sizeof(char*); + +namespace { + +// The mode of operation for bytes fields. Historically JSPB always carried +// bytes as JS {string}, containing base64 content by convention. With binary +// and proto3 serialization the new convention is to represent it as binary +// data in Uint8Array. See b/26173701 for background on the migration. +enum BytesMode { + BYTES_DEFAULT, // Default type for getBytesField to return. + BYTES_B64, // Explicitly coerce to base64 string where needed. + BYTES_U8, // Explicitly coerce to Uint8Array where needed. +}; + bool IsReserved(const TProtoStringType& ident) { - for (int i = 0; i < kNumKeyword; i++) { - if (ident == kKeyword[i]) { - return true; - } - } - return false; -} - -bool StrEndsWith(StringPiece sp, StringPiece x) { - return sp.size() >= x.size() && sp.substr(sp.size() - x.size()) == x; -} - + for (int i = 0; i < kNumKeyword; i++) { + if (ident == kKeyword[i]) { + return true; + } + } + return false; +} + +bool StrEndsWith(StringPiece sp, StringPiece x) { + return sp.size() >= x.size() && sp.substr(sp.size() - x.size()) == x; +} + TProtoStringType GetSnakeFilename(const TProtoStringType& filename) { TProtoStringType snake_name = filename; ReplaceCharacters(&snake_name, "/", '_'); return snake_name; -} - -// Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript -// file foo/bar/baz.js. +} + +// Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript +// file foo/bar/baz.js. TProtoStringType GetJSFilename(const GeneratorOptions& options, const TProtoStringType& filename) { - return StripProto(filename) + options.GetFileNameExtension(); -} - -// Given a filename like foo/bar/baz.proto, returns the root directory -// path ../../ + return StripProto(filename) + options.GetFileNameExtension(); +} + +// Given a filename like foo/bar/baz.proto, returns the root directory +// path ../../ TProtoStringType GetRootPath(const TProtoStringType& from_filename, const TProtoStringType& to_filename) { - if (to_filename.find("google/protobuf") == 0) { - // Well-known types (.proto files in the google/protobuf directory) are - // assumed to come from the 'google-protobuf' npm package. We may want to - // generalize this exception later by letting others put generated code in - // their own npm packages. - return "google-protobuf/"; - } - - size_t slashes = std::count(from_filename.begin(), from_filename.end(), '/'); - if (slashes == 0) { - return "./"; - } + if (to_filename.find("google/protobuf") == 0) { + // Well-known types (.proto files in the google/protobuf directory) are + // assumed to come from the 'google-protobuf' npm package. We may want to + // generalize this exception later by letting others put generated code in + // their own npm packages. + return "google-protobuf/"; + } + + size_t slashes = std::count(from_filename.begin(), from_filename.end(), '/'); + if (slashes == 0) { + return "./"; + } TProtoStringType result = ""; - for (size_t i = 0; i < slashes; i++) { - result += "../"; - } - return result; -} - -// Returns the alias we assign to the module of the given .proto filename -// when importing. + for (size_t i = 0; i < slashes; i++) { + result += "../"; + } + return result; +} + +// Returns the alias we assign to the module of the given .proto filename +// when importing. TProtoStringType ModuleAlias(const TProtoStringType& filename) { - // This scheme could technically cause problems if a file includes any 2 of: - // foo/bar_baz.proto - // foo_bar_baz.proto - // foo_bar/baz.proto - // - // We'll worry about this problem if/when we actually see it. This name isn't - // exposed to users so we can change it later if we need to. + // This scheme could technically cause problems if a file includes any 2 of: + // foo/bar_baz.proto + // foo_bar_baz.proto + // foo_bar/baz.proto + // + // We'll worry about this problem if/when we actually see it. This name isn't + // exposed to users so we can change it later if we need to. TProtoStringType basename = StripProto(filename); ReplaceCharacters(&basename, "-", '$'); ReplaceCharacters(&basename, "/", '_'); ReplaceCharacters(&basename, ".", '_'); - return basename + "_pb"; -} - + return basename + "_pb"; +} + // Returns the fully normalized JavaScript namespace for the given -// file descriptor's package. +// file descriptor's package. TProtoStringType GetNamespace(const GeneratorOptions& options, const FileDescriptor* file) { - if (!options.namespace_prefix.empty()) { - return options.namespace_prefix; - } else if (!file->package().empty()) { - return "proto." + file->package(); - } else { - return "proto"; - } -} - -// Returns the name of the message with a leading dot and taking into account -// nesting, for example ".OuterMessage.InnerMessage", or returns empty if -// descriptor is null. This function does not handle namespacing, only message -// nesting. + if (!options.namespace_prefix.empty()) { + return options.namespace_prefix; + } else if (!file->package().empty()) { + return "proto." + file->package(); + } else { + return "proto"; + } +} + +// Returns the name of the message with a leading dot and taking into account +// nesting, for example ".OuterMessage.InnerMessage", or returns empty if +// descriptor is null. This function does not handle namespacing, only message +// nesting. TProtoStringType GetNestedMessageName(const Descriptor* descriptor) { - if (descriptor == NULL) { - return ""; - } + if (descriptor == NULL) { + return ""; + } TProtoStringType result = - StripPrefixString(descriptor->full_name(), descriptor->file()->package()); - // Add a leading dot if one is not already present. - if (!result.empty() && result[0] != '.') { - result = "." + result; - } - return result; -} - -// Returns the path prefix for a message or enumeration that -// lives under the given file and containing type. + StripPrefixString(descriptor->full_name(), descriptor->file()->package()); + // Add a leading dot if one is not already present. + if (!result.empty() && result[0] != '.') { + result = "." + result; + } + return result; +} + +// Returns the path prefix for a message or enumeration that +// lives under the given file and containing type. TProtoStringType GetPrefix(const GeneratorOptions& options, const FileDescriptor* file_descriptor, const Descriptor* containing_type) { TProtoStringType prefix = GetNamespace(options, file_descriptor) + GetNestedMessageName(containing_type); - if (!prefix.empty()) { - prefix += "."; - } - return prefix; -} - + if (!prefix.empty()) { + prefix += "."; + } + return prefix; +} + // Returns the fully normalized JavaScript path prefix for the given // message descriptor. TProtoStringType GetMessagePathPrefix(const GeneratorOptions& options, @@ -201,13 +201,13 @@ TProtoStringType GetMessagePathPrefix(const GeneratorOptions& options, return GetPrefix(options, descriptor->file(), descriptor->containing_type()); } -// Returns the fully normalized JavaScript path for the given -// message descriptor. +// Returns the fully normalized JavaScript path for the given +// message descriptor. TProtoStringType GetMessagePath(const GeneratorOptions& options, const Descriptor* descriptor) { return GetMessagePathPrefix(options, descriptor) + descriptor->name(); -} - +} + // Returns the fully normalized JavaScript path prefix for the given // enumeration descriptor. TProtoStringType GetEnumPathPrefix(const GeneratorOptions& options, @@ -216,149 +216,149 @@ TProtoStringType GetEnumPathPrefix(const GeneratorOptions& options, enum_descriptor->containing_type()); } -// Returns the fully normalized JavaScript path for the given -// enumeration descriptor. +// Returns the fully normalized JavaScript path for the given +// enumeration descriptor. TProtoStringType GetEnumPath(const GeneratorOptions& options, const EnumDescriptor* enum_descriptor) { return GetEnumPathPrefix(options, enum_descriptor) + enum_descriptor->name(); -} - +} + TProtoStringType MaybeCrossFileRef(const GeneratorOptions& options, const FileDescriptor* from_file, const Descriptor* to_message) { if ((options.import_style == GeneratorOptions::kImportCommonJs || options.import_style == GeneratorOptions::kImportCommonJsStrict) && - from_file != to_message->file()) { - // Cross-file ref in CommonJS needs to use the module alias instead of - // the global name. - return ModuleAlias(to_message->file()->name()) + - GetNestedMessageName(to_message->containing_type()) + "." + - to_message->name(); - } else { - // Within a single file we use a full name. - return GetMessagePath(options, to_message); - } -} - + from_file != to_message->file()) { + // Cross-file ref in CommonJS needs to use the module alias instead of + // the global name. + return ModuleAlias(to_message->file()->name()) + + GetNestedMessageName(to_message->containing_type()) + "." + + to_message->name(); + } else { + // Within a single file we use a full name. + return GetMessagePath(options, to_message); + } +} + TProtoStringType SubmessageTypeRef(const GeneratorOptions& options, const FieldDescriptor* field) { - GOOGLE_CHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE); - return MaybeCrossFileRef(options, field->file(), field->message_type()); -} - -// - Object field name: LOWER_UNDERSCORE -> LOWER_CAMEL, except for group fields -// (UPPER_CAMEL -> LOWER_CAMEL), with "List" (or "Map") appended if appropriate, -// and with reserved words triggering a "pb_" prefix. -// - Getters/setters: LOWER_UNDERSCORE -> UPPER_CAMEL, except for group fields -// (use the name directly), then append "List" if appropriate, then append "$" -// if resulting name is equal to a reserved word. -// - Enums: just uppercase. - -// Locale-independent version of ToLower that deals only with ASCII A-Z. -char ToLowerASCII(char c) { - if (c >= 'A' && c <= 'Z') { - return (c - 'A') + 'a'; - } else { - return c; - } -} - + GOOGLE_CHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE); + return MaybeCrossFileRef(options, field->file(), field->message_type()); +} + +// - Object field name: LOWER_UNDERSCORE -> LOWER_CAMEL, except for group fields +// (UPPER_CAMEL -> LOWER_CAMEL), with "List" (or "Map") appended if appropriate, +// and with reserved words triggering a "pb_" prefix. +// - Getters/setters: LOWER_UNDERSCORE -> UPPER_CAMEL, except for group fields +// (use the name directly), then append "List" if appropriate, then append "$" +// if resulting name is equal to a reserved word. +// - Enums: just uppercase. + +// Locale-independent version of ToLower that deals only with ASCII A-Z. +char ToLowerASCII(char c) { + if (c >= 'A' && c <= 'Z') { + return (c - 'A') + 'a'; + } else { + return c; + } +} + std::vector<TProtoStringType> ParseLowerUnderscore(const TProtoStringType& input) { std::vector<TProtoStringType> words; TProtoStringType running = ""; - for (int i = 0; i < input.size(); i++) { - if (input[i] == '_') { - if (!running.empty()) { - words.push_back(running); - running.clear(); - } - } else { - running += ToLowerASCII(input[i]); - } - } - if (!running.empty()) { - words.push_back(running); - } - return words; -} - + for (int i = 0; i < input.size(); i++) { + if (input[i] == '_') { + if (!running.empty()) { + words.push_back(running); + running.clear(); + } + } else { + running += ToLowerASCII(input[i]); + } + } + if (!running.empty()) { + words.push_back(running); + } + return words; +} + std::vector<TProtoStringType> ParseUpperCamel(const TProtoStringType& input) { std::vector<TProtoStringType> words; TProtoStringType running = ""; - for (int i = 0; i < input.size(); i++) { - if (input[i] >= 'A' && input[i] <= 'Z' && !running.empty()) { - words.push_back(running); - running.clear(); - } - running += ToLowerASCII(input[i]); - } - if (!running.empty()) { - words.push_back(running); - } - return words; -} - + for (int i = 0; i < input.size(); i++) { + if (input[i] >= 'A' && input[i] <= 'Z' && !running.empty()) { + words.push_back(running); + running.clear(); + } + running += ToLowerASCII(input[i]); + } + if (!running.empty()) { + words.push_back(running); + } + return words; +} + TProtoStringType ToLowerCamel(const std::vector<TProtoStringType>& words) { TProtoStringType result; - for (int i = 0; i < words.size(); i++) { + for (int i = 0; i < words.size(); i++) { TProtoStringType word = words[i]; - if (i == 0 && (word[0] >= 'A' && word[0] <= 'Z')) { - word[0] = (word[0] - 'A') + 'a'; - } else if (i != 0 && (word[0] >= 'a' && word[0] <= 'z')) { - word[0] = (word[0] - 'a') + 'A'; - } - result += word; - } - return result; -} - + if (i == 0 && (word[0] >= 'A' && word[0] <= 'Z')) { + word[0] = (word[0] - 'A') + 'a'; + } else if (i != 0 && (word[0] >= 'a' && word[0] <= 'z')) { + word[0] = (word[0] - 'a') + 'A'; + } + result += word; + } + return result; +} + TProtoStringType ToUpperCamel(const std::vector<TProtoStringType>& words) { TProtoStringType result; - for (int i = 0; i < words.size(); i++) { + for (int i = 0; i < words.size(); i++) { TProtoStringType word = words[i]; - if (word[0] >= 'a' && word[0] <= 'z') { - word[0] = (word[0] - 'a') + 'A'; - } - result += word; - } - return result; -} - -// Based on code from descriptor.cc (Thanks Kenton!) -// Uppercases the entire string, turning ValueName into -// VALUENAME. + if (word[0] >= 'a' && word[0] <= 'z') { + word[0] = (word[0] - 'a') + 'A'; + } + result += word; + } + return result; +} + +// Based on code from descriptor.cc (Thanks Kenton!) +// Uppercases the entire string, turning ValueName into +// VALUENAME. TProtoStringType ToEnumCase(const TProtoStringType& input) { TProtoStringType result; - result.reserve(input.size()); - - for (int i = 0; i < input.size(); i++) { - if ('a' <= input[i] && input[i] <= 'z') { - result.push_back(input[i] - 'a' + 'A'); - } else { - result.push_back(input[i]); - } - } - - return result; -} - + result.reserve(input.size()); + + for (int i = 0; i < input.size(); i++) { + if ('a' <= input[i] && input[i] <= 'z') { + result.push_back(input[i] - 'a' + 'A'); + } else { + result.push_back(input[i]); + } + } + + return result; +} + TProtoStringType ToLower(const TProtoStringType& input) { TProtoStringType result; - result.reserve(input.size()); - - for (int i = 0; i < input.size(); i++) { - if ('A' <= input[i] && input[i] <= 'Z') { - result.push_back(input[i] - 'A' + 'a'); - } else { - result.push_back(input[i]); - } - } - - return result; -} - + result.reserve(input.size()); + + for (int i = 0; i < input.size(); i++) { + if ('A' <= input[i] && input[i] <= 'Z') { + result.push_back(input[i] - 'A' + 'a'); + } else { + result.push_back(input[i]); + } + } + + return result; +} + // When we're generating one output file per SCC, this is the filename -// that top-level extensions should go in. +// that top-level extensions should go in. // e.g. one proto file (test.proto): // package a; // extends Foo { @@ -372,8 +372,8 @@ TProtoStringType GetExtensionFileName(const GeneratorOptions& options, TProtoStringType snake_name = StripProto(GetSnakeFilename(file->name())); return options.output_dir + "/" + ToLower(GetNamespace(options, file)) + (with_filename ? ("_" + snake_name + "_extensions") : "") + - options.GetFileNameExtension(); -} + options.GetFileNameExtension(); +} // When we're generating one output file per SCC, this is the filename // that all messages in the SCC should go in. // If with_package equals true, filename will have package prefix, @@ -415,10 +415,10 @@ TProtoStringType GetMessagesFileName(const GeneratorOptions& options, const SCC* filename_base = (*long_name_dict)[scc->GetRepresentative()]; } return options.output_dir + "/" + package_base + filename_base + - options.GetFileNameExtension(); -} - -// When we're generating one output file per type name, this is the filename + options.GetFileNameExtension(); +} + +// When we're generating one output file per type name, this is the filename // that a top-level enum should go in. // If with_package equals true, filename will have package prefix. TProtoStringType GetEnumFileName(const GeneratorOptions& options, @@ -427,91 +427,91 @@ TProtoStringType GetEnumFileName(const GeneratorOptions& options, (with_package ? ToLower(GetNamespace(options, desc->file()) + "_") : "") + ToLower(desc->name()) + options.GetFileNameExtension(); -} - -// Returns the message/response ID, if set. +} + +// Returns the message/response ID, if set. TProtoStringType GetMessageId(const Descriptor* desc) { return TProtoStringType(); } - -bool IgnoreExtensionField(const FieldDescriptor* field) { - // Exclude descriptor extensions from output "to avoid clutter" (from original - // codegen). + +bool IgnoreExtensionField(const FieldDescriptor* field) { + // Exclude descriptor extensions from output "to avoid clutter" (from original + // codegen). if (!field->is_extension()) return false; const FileDescriptor* file = field->containing_type()->file(); return file->name() == "net/proto2/proto/descriptor.proto" || file->name() == "google/protobuf/descriptor.proto"; -} - -// Used inside Google only -- do not remove. -bool IsResponse(const Descriptor* desc) { return false; } - -bool IgnoreField(const FieldDescriptor* field) { - return IgnoreExtensionField(field); -} - -// Do we ignore this message type? +} + +// Used inside Google only -- do not remove. +bool IsResponse(const Descriptor* desc) { return false; } + +bool IgnoreField(const FieldDescriptor* field) { + return IgnoreExtensionField(field); +} + +// Do we ignore this message type? bool IgnoreMessage(const Descriptor* d) { return d->options().map_entry(); } - -// Does JSPB ignore this entire oneof? True only if all fields are ignored. -bool IgnoreOneof(const OneofDescriptor* oneof) { + +// Does JSPB ignore this entire oneof? True only if all fields are ignored. +bool IgnoreOneof(const OneofDescriptor* oneof) { if (oneof->is_synthetic()) return true; - for (int i = 0; i < oneof->field_count(); i++) { - if (!IgnoreField(oneof->field(i))) { - return false; - } - } - return true; -} - + for (int i = 0; i < oneof->field_count(); i++) { + if (!IgnoreField(oneof->field(i))) { + return false; + } + } + return true; +} + TProtoStringType JSIdent(const GeneratorOptions& options, const FieldDescriptor* field, bool is_upper_camel, bool is_map, bool drop_list) { TProtoStringType result; - if (field->type() == FieldDescriptor::TYPE_GROUP) { + if (field->type() == FieldDescriptor::TYPE_GROUP) { result = is_upper_camel ? ToUpperCamel(ParseUpperCamel(field->message_type()->name())) : ToLowerCamel(ParseUpperCamel(field->message_type()->name())); - } else { + } else { result = is_upper_camel ? ToUpperCamel(ParseLowerUnderscore(field->name())) : ToLowerCamel(ParseLowerUnderscore(field->name())); - } + } if (is_map || field->is_map()) { - // JSPB-style or proto3-style map. - result += "Map"; - } else if (!drop_list && field->is_repeated()) { - // Repeated field. - result += "List"; - } - return result; -} - + // JSPB-style or proto3-style map. + result += "Map"; + } else if (!drop_list && field->is_repeated()) { + // Repeated field. + result += "List"; + } + return result; +} + TProtoStringType JSObjectFieldName(const GeneratorOptions& options, const FieldDescriptor* field) { TProtoStringType name = JSIdent(options, field, /* is_upper_camel = */ false, /* is_map = */ false, /* drop_list = */ false); - if (IsReserved(name)) { - name = "pb_" + name; - } - return name; -} - + if (IsReserved(name)) { + name = "pb_" + name; + } + return name; +} + TProtoStringType JSByteGetterSuffix(BytesMode bytes_mode) { - switch (bytes_mode) { - case BYTES_DEFAULT: - return ""; - case BYTES_B64: - return "B64"; - case BYTES_U8: - return "U8"; - default: - assert(false); - } - return ""; -} - -// Returns the field name as a capitalized portion of a getter/setter method -// name, e.g. MyField for .getMyField(). + switch (bytes_mode) { + case BYTES_DEFAULT: + return ""; + case BYTES_B64: + return "B64"; + case BYTES_U8: + return "U8"; + default: + assert(false); + } + return ""; +} + +// Returns the field name as a capitalized portion of a getter/setter method +// name, e.g. MyField for .getMyField(). TProtoStringType JSGetterName(const GeneratorOptions& options, const FieldDescriptor* field, BytesMode bytes_mode = BYTES_DEFAULT, @@ -519,91 +519,91 @@ TProtoStringType JSGetterName(const GeneratorOptions& options, TProtoStringType name = JSIdent(options, field, /* is_upper_camel = */ true, /* is_map = */ false, drop_list); - if (field->type() == FieldDescriptor::TYPE_BYTES) { + if (field->type() == FieldDescriptor::TYPE_BYTES) { TProtoStringType suffix = JSByteGetterSuffix(bytes_mode); - if (!suffix.empty()) { - name += "_as" + suffix; - } - } - if (name == "Extension" || name == "JsPbMessageId") { - // Avoid conflicts with base-class names. - name += "$"; - } - return name; -} - + if (!suffix.empty()) { + name += "_as" + suffix; + } + } + if (name == "Extension" || name == "JsPbMessageId") { + // Avoid conflicts with base-class names. + name += "$"; + } + return name; +} + TProtoStringType JSOneofName(const OneofDescriptor* oneof) { - return ToUpperCamel(ParseLowerUnderscore(oneof->name())); -} - -// Returns the index corresponding to this field in the JSPB array (underlying -// data storage array). + return ToUpperCamel(ParseLowerUnderscore(oneof->name())); +} + +// Returns the index corresponding to this field in the JSPB array (underlying +// data storage array). TProtoStringType JSFieldIndex(const FieldDescriptor* field) { - // Determine whether this field is a member of a group. Group fields are a bit - // wonky: their "containing type" is a message type created just for the - // group, and that type's parent type has a field with the group-message type - // as its message type and TYPE_GROUP as its field type. For such fields, the - // index we use is relative to the field number of the group submessage field. - // For all other fields, we just use the field number. - const Descriptor* containing_type = field->containing_type(); - const Descriptor* parent_type = containing_type->containing_type(); - if (parent_type != NULL) { - for (int i = 0; i < parent_type->field_count(); i++) { - if (parent_type->field(i)->type() == FieldDescriptor::TYPE_GROUP && - parent_type->field(i)->message_type() == containing_type) { + // Determine whether this field is a member of a group. Group fields are a bit + // wonky: their "containing type" is a message type created just for the + // group, and that type's parent type has a field with the group-message type + // as its message type and TYPE_GROUP as its field type. For such fields, the + // index we use is relative to the field number of the group submessage field. + // For all other fields, we just use the field number. + const Descriptor* containing_type = field->containing_type(); + const Descriptor* parent_type = containing_type->containing_type(); + if (parent_type != NULL) { + for (int i = 0; i < parent_type->field_count(); i++) { + if (parent_type->field(i)->type() == FieldDescriptor::TYPE_GROUP && + parent_type->field(i)->message_type() == containing_type) { return StrCat(field->number() - parent_type->field(i)->number()); - } - } - } + } + } + } return StrCat(field->number()); -} - +} + TProtoStringType JSOneofIndex(const OneofDescriptor* oneof) { - int index = -1; - for (int i = 0; i < oneof->containing_type()->oneof_decl_count(); i++) { - const OneofDescriptor* o = oneof->containing_type()->oneof_decl(i); + int index = -1; + for (int i = 0; i < oneof->containing_type()->oneof_decl_count(); i++) { + const OneofDescriptor* o = oneof->containing_type()->oneof_decl(i); if (o->is_synthetic()) continue; - // If at least one field in this oneof is not JSPB-ignored, count the oneof. - for (int j = 0; j < o->field_count(); j++) { - const FieldDescriptor* f = o->field(j); - if (!IgnoreField(f)) { - index++; - break; // inner loop - } - } - if (o == oneof) { - break; - } - } + // If at least one field in this oneof is not JSPB-ignored, count the oneof. + for (int j = 0; j < o->field_count(); j++) { + const FieldDescriptor* f = o->field(j); + if (!IgnoreField(f)) { + index++; + break; // inner loop + } + } + if (o == oneof) { + break; + } + } return StrCat(index); -} - -// Decodes a codepoint in \x0000 -- \xFFFF. -uint16 DecodeUTF8Codepoint(uint8* bytes, size_t* length) { - if (*length == 0) { - return 0; - } - size_t expected = 0; - if ((*bytes & 0x80) == 0) { - expected = 1; - } else if ((*bytes & 0xe0) == 0xc0) { - expected = 2; - } else if ((*bytes & 0xf0) == 0xe0) { - expected = 3; - } else { - // Too long -- don't accept. - *length = 0; - return 0; - } - - if (*length < expected) { - // Not enough bytes -- don't accept. - *length = 0; - return 0; - } - - *length = expected; - switch (expected) { +} + +// Decodes a codepoint in \x0000 -- \xFFFF. +uint16 DecodeUTF8Codepoint(uint8* bytes, size_t* length) { + if (*length == 0) { + return 0; + } + size_t expected = 0; + if ((*bytes & 0x80) == 0) { + expected = 1; + } else if ((*bytes & 0xe0) == 0xc0) { + expected = 2; + } else if ((*bytes & 0xf0) == 0xe0) { + expected = 3; + } else { + // Too long -- don't accept. + *length = 0; + return 0; + } + + if (*length < expected) { + // Not enough bytes -- don't accept. + *length = 0; + return 0; + } + + *length = expected; + switch (expected) { case 1: return bytes[0]; case 2: @@ -613,32 +613,32 @@ uint16 DecodeUTF8Codepoint(uint8* bytes, size_t* length) { ((bytes[2] & 0x3F) << 0); default: return 0; - } -} - -// Escapes the contents of a string to be included within double-quotes ("") in -// JavaScript. The input data should be a UTF-8 encoded C++ string of chars. -// Returns false if |out| was truncated because |in| contained invalid UTF-8 or -// codepoints outside the BMP. + } +} + +// Escapes the contents of a string to be included within double-quotes ("") in +// JavaScript. The input data should be a UTF-8 encoded C++ string of chars. +// Returns false if |out| was truncated because |in| contained invalid UTF-8 or +// codepoints outside the BMP. // TODO(b/115551870): Support codepoints outside the BMP. bool EscapeJSString(const TProtoStringType& in, TProtoStringType* out) { - size_t decoded = 0; - for (size_t i = 0; i < in.size(); i += decoded) { - uint16 codepoint = 0; - // Decode the next UTF-8 codepoint. - size_t have_bytes = in.size() - i; - uint8 bytes[3] = { - static_cast<uint8>(in[i]), - static_cast<uint8>(((i + 1) < in.size()) ? in[i + 1] : 0), - static_cast<uint8>(((i + 2) < in.size()) ? in[i + 2] : 0), - }; - codepoint = DecodeUTF8Codepoint(bytes, &have_bytes); - if (have_bytes == 0) { - return false; - } - decoded = have_bytes; - - switch (codepoint) { + size_t decoded = 0; + for (size_t i = 0; i < in.size(); i += decoded) { + uint16 codepoint = 0; + // Decode the next UTF-8 codepoint. + size_t have_bytes = in.size() - i; + uint8 bytes[3] = { + static_cast<uint8>(in[i]), + static_cast<uint8>(((i + 1) < in.size()) ? in[i + 1] : 0), + static_cast<uint8>(((i + 2) < in.size()) ? in[i + 2] : 0), + }; + codepoint = DecodeUTF8Codepoint(bytes, &have_bytes); + if (have_bytes == 0) { + return false; + } + decoded = have_bytes; + + switch (codepoint) { case '\'': *out += "\\x27"; break; @@ -675,352 +675,352 @@ bool EscapeJSString(const TProtoStringType& in, TProtoStringType* out) { case '\\': *out += "\\\\"; break; - default: + default: // TODO(b/115551870): Once we're supporting codepoints outside the BMP, - // use a single Unicode codepoint escape if the output language is - // ECMAScript 2015 or above. Otherwise, use a surrogate pair. - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#String_literals - if (codepoint >= 0x20 && codepoint <= 0x7e) { - *out += static_cast<char>(codepoint); - } else if (codepoint >= 0x100) { - *out += StringPrintf("\\u%04x", codepoint); - } else { - *out += StringPrintf("\\x%02x", codepoint); - } - break; - } - } - return true; -} - + // use a single Unicode codepoint escape if the output language is + // ECMAScript 2015 or above. Otherwise, use a surrogate pair. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#String_literals + if (codepoint >= 0x20 && codepoint <= 0x7e) { + *out += static_cast<char>(codepoint); + } else if (codepoint >= 0x100) { + *out += StringPrintf("\\u%04x", codepoint); + } else { + *out += StringPrintf("\\x%02x", codepoint); + } + break; + } + } + return true; +} + TProtoStringType EscapeBase64(const TProtoStringType& in) { - static const char* kAlphabet = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + static const char* kAlphabet = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; TProtoStringType result; - - for (size_t i = 0; i < in.size(); i += 3) { + + for (size_t i = 0; i < in.size(); i += 3) { int value = (in[i] << 16) | (((i + 1) < in.size()) ? (in[i + 1] << 8) : 0) | (((i + 2) < in.size()) ? (in[i + 2] << 0) : 0); - result += kAlphabet[(value >> 18) & 0x3f]; - result += kAlphabet[(value >> 12) & 0x3f]; - if ((i + 1) < in.size()) { + result += kAlphabet[(value >> 18) & 0x3f]; + result += kAlphabet[(value >> 12) & 0x3f]; + if ((i + 1) < in.size()) { result += kAlphabet[(value >> 6) & 0x3f]; - } else { - result += '='; - } - if ((i + 2) < in.size()) { + } else { + result += '='; + } + if ((i + 2) < in.size()) { result += kAlphabet[(value >> 0) & 0x3f]; - } else { - result += '='; - } - } - - return result; -} - -// Post-process the result of SimpleFtoa/SimpleDtoa to *exactly* match the -// original codegen's formatting (which is just .toString() on java.lang.Double -// or java.lang.Float). + } else { + result += '='; + } + } + + return result; +} + +// Post-process the result of SimpleFtoa/SimpleDtoa to *exactly* match the +// original codegen's formatting (which is just .toString() on java.lang.Double +// or java.lang.Float). TProtoStringType PostProcessFloat(TProtoStringType result) { - // If inf, -inf or nan, replace with +Infinity, -Infinity or NaN. - if (result == "inf") { - return "Infinity"; - } else if (result == "-inf") { - return "-Infinity"; - } else if (result == "nan") { - return "NaN"; - } - - // If scientific notation (e.g., "1e10"), (i) capitalize the "e", (ii) - // ensure that the mantissa (portion prior to the "e") has at least one - // fractional digit (after the decimal point), and (iii) strip any unnecessary - // leading zeroes and/or '+' signs from the exponent. + // If inf, -inf or nan, replace with +Infinity, -Infinity or NaN. + if (result == "inf") { + return "Infinity"; + } else if (result == "-inf") { + return "-Infinity"; + } else if (result == "nan") { + return "NaN"; + } + + // If scientific notation (e.g., "1e10"), (i) capitalize the "e", (ii) + // ensure that the mantissa (portion prior to the "e") has at least one + // fractional digit (after the decimal point), and (iii) strip any unnecessary + // leading zeroes and/or '+' signs from the exponent. TProtoStringType::size_type exp_pos = result.find('e'); if (exp_pos != TProtoStringType::npos) { TProtoStringType mantissa = result.substr(0, exp_pos); TProtoStringType exponent = result.substr(exp_pos + 1); - - // Add ".0" to mantissa if no fractional part exists. + + // Add ".0" to mantissa if no fractional part exists. if (mantissa.find('.') == TProtoStringType::npos) { - mantissa += ".0"; - } - - // Strip the sign off the exponent and store as |exp_neg|. - bool exp_neg = false; - if (!exponent.empty() && exponent[0] == '+') { - exponent = exponent.substr(1); - } else if (!exponent.empty() && exponent[0] == '-') { - exp_neg = true; - exponent = exponent.substr(1); - } - - // Strip any leading zeroes off the exponent. - while (exponent.size() > 1 && exponent[0] == '0') { - exponent = exponent.substr(1); - } - + mantissa += ".0"; + } + + // Strip the sign off the exponent and store as |exp_neg|. + bool exp_neg = false; + if (!exponent.empty() && exponent[0] == '+') { + exponent = exponent.substr(1); + } else if (!exponent.empty() && exponent[0] == '-') { + exp_neg = true; + exponent = exponent.substr(1); + } + + // Strip any leading zeroes off the exponent. + while (exponent.size() > 1 && exponent[0] == '0') { + exponent = exponent.substr(1); + } + return mantissa + "E" + TProtoStringType(exp_neg ? "-" : "") + exponent; - } - - // Otherwise, this is an ordinary decimal number. Append ".0" if result has no - // decimal/fractional part in order to match output of original codegen. + } + + // Otherwise, this is an ordinary decimal number. Append ".0" if result has no + // decimal/fractional part in order to match output of original codegen. if (result.find('.') == TProtoStringType::npos) { - result += ".0"; - } - - return result; -} - + result += ".0"; + } + + return result; +} + TProtoStringType FloatToString(float value) { TProtoStringType result = SimpleFtoa(value); - return PostProcessFloat(result); -} - + return PostProcessFloat(result); +} + TProtoStringType DoubleToString(double value) { TProtoStringType result = SimpleDtoa(value); - return PostProcessFloat(result); -} - + return PostProcessFloat(result); +} + bool InRealOneof(const FieldDescriptor* field) { return field->containing_oneof() && !field->containing_oneof()->is_synthetic(); } -// Return true if this is an integral field that should be represented as string -// in JS. -bool IsIntegralFieldWithStringJSType(const FieldDescriptor* field) { - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_INT64: - case FieldDescriptor::CPPTYPE_UINT64: - // The default value of JSType is JS_NORMAL, which behaves the same as - // JS_NUMBER. +// Return true if this is an integral field that should be represented as string +// in JS. +bool IsIntegralFieldWithStringJSType(const FieldDescriptor* field) { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_UINT64: + // The default value of JSType is JS_NORMAL, which behaves the same as + // JS_NUMBER. return field->options().jstype() == FieldOptions::JS_STRING; - default: - return false; - } -} - + default: + return false; + } +} + TProtoStringType MaybeNumberString(const FieldDescriptor* field, const TProtoStringType& orig) { - return IsIntegralFieldWithStringJSType(field) ? ("\"" + orig + "\"") : orig; -} - + return IsIntegralFieldWithStringJSType(field) ? ("\"" + orig + "\"") : orig; +} + TProtoStringType JSFieldDefault(const FieldDescriptor* field) { - if (field->is_repeated()) { - return "[]"; - } - - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_INT32: + if (field->is_repeated()) { + return "[]"; + } + + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: return MaybeNumberString(field, StrCat(field->default_value_int32())); - case FieldDescriptor::CPPTYPE_UINT32: - // The original codegen is in Java, and Java protobufs store unsigned - // integer values as signed integer values. In order to exactly match the - // output, we need to reinterpret as base-2 signed. Ugh. - return MaybeNumberString( + case FieldDescriptor::CPPTYPE_UINT32: + // The original codegen is in Java, and Java protobufs store unsigned + // integer values as signed integer values. In order to exactly match the + // output, we need to reinterpret as base-2 signed. Ugh. + return MaybeNumberString( field, StrCat(static_cast<int32>(field->default_value_uint32()))); - case FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_INT64: return MaybeNumberString(field, StrCat(field->default_value_int64())); - case FieldDescriptor::CPPTYPE_UINT64: - // See above note for uint32 -- reinterpreting as signed. - return MaybeNumberString( + case FieldDescriptor::CPPTYPE_UINT64: + // See above note for uint32 -- reinterpreting as signed. + return MaybeNumberString( field, StrCat(static_cast<int64>(field->default_value_uint64()))); - case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_ENUM: return StrCat(field->default_value_enum()->number()); - case FieldDescriptor::CPPTYPE_BOOL: - return field->default_value_bool() ? "true" : "false"; - case FieldDescriptor::CPPTYPE_FLOAT: - return FloatToString(field->default_value_float()); - case FieldDescriptor::CPPTYPE_DOUBLE: - return DoubleToString(field->default_value_double()); - case FieldDescriptor::CPPTYPE_STRING: - if (field->type() == FieldDescriptor::TYPE_STRING) { + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool() ? "true" : "false"; + case FieldDescriptor::CPPTYPE_FLOAT: + return FloatToString(field->default_value_float()); + case FieldDescriptor::CPPTYPE_DOUBLE: + return DoubleToString(field->default_value_double()); + case FieldDescriptor::CPPTYPE_STRING: + if (field->type() == FieldDescriptor::TYPE_STRING) { TProtoStringType out; - bool is_valid = EscapeJSString(field->default_value_string(), &out); - if (!is_valid) { + bool is_valid = EscapeJSString(field->default_value_string(), &out); + if (!is_valid) { // TODO(b/115551870): Decide whether this should be a hard error. GOOGLE_LOG(WARNING) << "The default value for field " << field->full_name() << " was truncated since it contained invalid UTF-8 or" " codepoints outside the basic multilingual plane."; - } - return "\"" + out + "\""; - } else { // Bytes - return "\"" + EscapeBase64(field->default_value_string()) + "\""; - } - case FieldDescriptor::CPPTYPE_MESSAGE: - return "null"; - } - GOOGLE_LOG(FATAL) << "Shouldn't reach here."; - return ""; -} - + } + return "\"" + out + "\""; + } else { // Bytes + return "\"" + EscapeBase64(field->default_value_string()) + "\""; + } + case FieldDescriptor::CPPTYPE_MESSAGE: + return "null"; + } + GOOGLE_LOG(FATAL) << "Shouldn't reach here."; + return ""; +} + TProtoStringType ProtoTypeName(const GeneratorOptions& options, const FieldDescriptor* field) { - switch (field->type()) { - case FieldDescriptor::TYPE_BOOL: - return "bool"; - case FieldDescriptor::TYPE_INT32: - return "int32"; - case FieldDescriptor::TYPE_UINT32: - return "uint32"; - case FieldDescriptor::TYPE_SINT32: - return "sint32"; - case FieldDescriptor::TYPE_FIXED32: - return "fixed32"; - case FieldDescriptor::TYPE_SFIXED32: - return "sfixed32"; - case FieldDescriptor::TYPE_INT64: - return "int64"; - case FieldDescriptor::TYPE_UINT64: - return "uint64"; - case FieldDescriptor::TYPE_SINT64: - return "sint64"; - case FieldDescriptor::TYPE_FIXED64: - return "fixed64"; - case FieldDescriptor::TYPE_SFIXED64: - return "sfixed64"; - case FieldDescriptor::TYPE_FLOAT: - return "float"; - case FieldDescriptor::TYPE_DOUBLE: - return "double"; - case FieldDescriptor::TYPE_STRING: - return "string"; - case FieldDescriptor::TYPE_BYTES: - return "bytes"; - case FieldDescriptor::TYPE_GROUP: - return GetMessagePath(options, field->message_type()); - case FieldDescriptor::TYPE_ENUM: - return GetEnumPath(options, field->enum_type()); - case FieldDescriptor::TYPE_MESSAGE: - return GetMessagePath(options, field->message_type()); - default: - return ""; - } -} - + switch (field->type()) { + case FieldDescriptor::TYPE_BOOL: + return "bool"; + case FieldDescriptor::TYPE_INT32: + return "int32"; + case FieldDescriptor::TYPE_UINT32: + return "uint32"; + case FieldDescriptor::TYPE_SINT32: + return "sint32"; + case FieldDescriptor::TYPE_FIXED32: + return "fixed32"; + case FieldDescriptor::TYPE_SFIXED32: + return "sfixed32"; + case FieldDescriptor::TYPE_INT64: + return "int64"; + case FieldDescriptor::TYPE_UINT64: + return "uint64"; + case FieldDescriptor::TYPE_SINT64: + return "sint64"; + case FieldDescriptor::TYPE_FIXED64: + return "fixed64"; + case FieldDescriptor::TYPE_SFIXED64: + return "sfixed64"; + case FieldDescriptor::TYPE_FLOAT: + return "float"; + case FieldDescriptor::TYPE_DOUBLE: + return "double"; + case FieldDescriptor::TYPE_STRING: + return "string"; + case FieldDescriptor::TYPE_BYTES: + return "bytes"; + case FieldDescriptor::TYPE_GROUP: + return GetMessagePath(options, field->message_type()); + case FieldDescriptor::TYPE_ENUM: + return GetEnumPath(options, field->enum_type()); + case FieldDescriptor::TYPE_MESSAGE: + return GetMessagePath(options, field->message_type()); + default: + return ""; + } +} + TProtoStringType JSIntegerTypeName(const FieldDescriptor* field) { - return IsIntegralFieldWithStringJSType(field) ? "string" : "number"; -} - + return IsIntegralFieldWithStringJSType(field) ? "string" : "number"; +} + TProtoStringType JSStringTypeName(const GeneratorOptions& options, const FieldDescriptor* field, BytesMode bytes_mode) { - if (field->type() == FieldDescriptor::TYPE_BYTES) { - switch (bytes_mode) { - case BYTES_DEFAULT: - return "(string|Uint8Array)"; - case BYTES_B64: - return "string"; - case BYTES_U8: - return "Uint8Array"; - default: - assert(false); - } - } - return "string"; -} - + if (field->type() == FieldDescriptor::TYPE_BYTES) { + switch (bytes_mode) { + case BYTES_DEFAULT: + return "(string|Uint8Array)"; + case BYTES_B64: + return "string"; + case BYTES_U8: + return "Uint8Array"; + default: + assert(false); + } + } + return "string"; +} + TProtoStringType JSTypeName(const GeneratorOptions& options, const FieldDescriptor* field, BytesMode bytes_mode) { - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_BOOL: - return "boolean"; - case FieldDescriptor::CPPTYPE_INT32: - return JSIntegerTypeName(field); - case FieldDescriptor::CPPTYPE_INT64: - return JSIntegerTypeName(field); - case FieldDescriptor::CPPTYPE_UINT32: - return JSIntegerTypeName(field); - case FieldDescriptor::CPPTYPE_UINT64: - return JSIntegerTypeName(field); - case FieldDescriptor::CPPTYPE_FLOAT: - return "number"; - case FieldDescriptor::CPPTYPE_DOUBLE: - return "number"; - case FieldDescriptor::CPPTYPE_STRING: - return JSStringTypeName(options, field, bytes_mode); - case FieldDescriptor::CPPTYPE_ENUM: - return GetEnumPath(options, field->enum_type()); - case FieldDescriptor::CPPTYPE_MESSAGE: - return GetMessagePath(options, field->message_type()); - default: - return ""; - } -} - -// Used inside Google only -- do not remove. -bool UseBrokenPresenceSemantics(const GeneratorOptions& options, - const FieldDescriptor* field) { - return false; -} - -// Returns true for fields that return "null" from accessors when they are + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_BOOL: + return "boolean"; + case FieldDescriptor::CPPTYPE_INT32: + return JSIntegerTypeName(field); + case FieldDescriptor::CPPTYPE_INT64: + return JSIntegerTypeName(field); + case FieldDescriptor::CPPTYPE_UINT32: + return JSIntegerTypeName(field); + case FieldDescriptor::CPPTYPE_UINT64: + return JSIntegerTypeName(field); + case FieldDescriptor::CPPTYPE_FLOAT: + return "number"; + case FieldDescriptor::CPPTYPE_DOUBLE: + return "number"; + case FieldDescriptor::CPPTYPE_STRING: + return JSStringTypeName(options, field, bytes_mode); + case FieldDescriptor::CPPTYPE_ENUM: + return GetEnumPath(options, field->enum_type()); + case FieldDescriptor::CPPTYPE_MESSAGE: + return GetMessagePath(options, field->message_type()); + default: + return ""; + } +} + +// Used inside Google only -- do not remove. +bool UseBrokenPresenceSemantics(const GeneratorOptions& options, + const FieldDescriptor* field) { + return false; +} + +// Returns true for fields that return "null" from accessors when they are // unset. This should normally only be true for non-repeated submessages, but we // have legacy users who relied on old behavior where accessors behaved this -// way. -bool ReturnsNullWhenUnset(const GeneratorOptions& options, - const FieldDescriptor* field) { - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && - field->is_optional()) { - return true; - } - - // TODO(haberman): remove this case and unconditionally return false. - return UseBrokenPresenceSemantics(options, field) && !field->is_repeated() && - !field->has_default_value(); -} - -// In a sane world, this would be the same as ReturnsNullWhenUnset(). But in -// the status quo, some fields declare that they never return null/undefined -// even though they actually do: -// * required fields -// * optional enum fields -// * proto3 primitive fields. -bool DeclaredReturnTypeIsNullable(const GeneratorOptions& options, - const FieldDescriptor* field) { - if (field->is_required() || field->type() == FieldDescriptor::TYPE_ENUM) { - return false; - } - - if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 && - field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { - return false; - } - - return ReturnsNullWhenUnset(options, field); -} - -bool SetterAcceptsUndefined(const GeneratorOptions& options, - const FieldDescriptor* field) { - if (ReturnsNullWhenUnset(options, field)) { - return true; - } - - // Broken presence semantics always accepts undefined for setters. - return UseBrokenPresenceSemantics(options, field); -} - -bool SetterAcceptsNull(const GeneratorOptions& options, - const FieldDescriptor* field) { - if (ReturnsNullWhenUnset(options, field)) { - return true; - } - - // With broken presence semantics, fields with defaults accept "null" for - // setters, but other fields do not. This is a strange quirk of the old - // codegen. - return UseBrokenPresenceSemantics(options, field) && - field->has_default_value(); -} - -// Returns types which are known to by non-nullable by default. -// The style guide requires that we omit "!" in this case. +// way. +bool ReturnsNullWhenUnset(const GeneratorOptions& options, + const FieldDescriptor* field) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + field->is_optional()) { + return true; + } + + // TODO(haberman): remove this case and unconditionally return false. + return UseBrokenPresenceSemantics(options, field) && !field->is_repeated() && + !field->has_default_value(); +} + +// In a sane world, this would be the same as ReturnsNullWhenUnset(). But in +// the status quo, some fields declare that they never return null/undefined +// even though they actually do: +// * required fields +// * optional enum fields +// * proto3 primitive fields. +bool DeclaredReturnTypeIsNullable(const GeneratorOptions& options, + const FieldDescriptor* field) { + if (field->is_required() || field->type() == FieldDescriptor::TYPE_ENUM) { + return false; + } + + if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 && + field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + return false; + } + + return ReturnsNullWhenUnset(options, field); +} + +bool SetterAcceptsUndefined(const GeneratorOptions& options, + const FieldDescriptor* field) { + if (ReturnsNullWhenUnset(options, field)) { + return true; + } + + // Broken presence semantics always accepts undefined for setters. + return UseBrokenPresenceSemantics(options, field); +} + +bool SetterAcceptsNull(const GeneratorOptions& options, + const FieldDescriptor* field) { + if (ReturnsNullWhenUnset(options, field)) { + return true; + } + + // With broken presence semantics, fields with defaults accept "null" for + // setters, but other fields do not. This is a strange quirk of the old + // codegen. + return UseBrokenPresenceSemantics(options, field) && + field->has_default_value(); +} + +// Returns types which are known to by non-nullable by default. +// The style guide requires that we omit "!" in this case. bool IsPrimitive(const TProtoStringType& type) { - return type == "undefined" || type == "string" || type == "number" || - type == "boolean"; -} - + return type == "undefined" || type == "string" || type == "number" || + type == "boolean"; +} + TProtoStringType JSFieldTypeAnnotation(const GeneratorOptions& options, const FieldDescriptor* field, bool is_setter_argument, bool force_present, @@ -1028,83 +1028,83 @@ TProtoStringType JSFieldTypeAnnotation(const GeneratorOptions& options, BytesMode bytes_mode = BYTES_DEFAULT, bool force_singular = false) { TProtoStringType jstype = JSTypeName(options, field, bytes_mode); - + if (!force_singular && field->is_repeated() && - (field->is_packed() || !singular_if_not_packed)) { - if (field->type() == FieldDescriptor::TYPE_BYTES && - bytes_mode == BYTES_DEFAULT) { - jstype = "(Array<!Uint8Array>|Array<string>)"; - } else { - if (!IsPrimitive(jstype)) { - jstype = "!" + jstype; - } + (field->is_packed() || !singular_if_not_packed)) { + if (field->type() == FieldDescriptor::TYPE_BYTES && + bytes_mode == BYTES_DEFAULT) { + jstype = "(Array<!Uint8Array>|Array<string>)"; + } else { + if (!IsPrimitive(jstype)) { + jstype = "!" + jstype; + } jstype = "Array<" + jstype + ">"; - } - } - - bool is_null_or_undefined = false; - - if (is_setter_argument) { - if (SetterAcceptsNull(options, field)) { - jstype = "?" + jstype; - is_null_or_undefined = true; - } - - if (SetterAcceptsUndefined(options, field)) { - jstype += "|undefined"; - is_null_or_undefined = true; - } - } else if (force_present) { - // Don't add null or undefined. - } else { - if (DeclaredReturnTypeIsNullable(options, field)) { - jstype = "?" + jstype; - is_null_or_undefined = true; - } - } - - if (!is_null_or_undefined && !IsPrimitive(jstype)) { - jstype = "!" + jstype; - } - - return jstype; -} - + } + } + + bool is_null_or_undefined = false; + + if (is_setter_argument) { + if (SetterAcceptsNull(options, field)) { + jstype = "?" + jstype; + is_null_or_undefined = true; + } + + if (SetterAcceptsUndefined(options, field)) { + jstype += "|undefined"; + is_null_or_undefined = true; + } + } else if (force_present) { + // Don't add null or undefined. + } else { + if (DeclaredReturnTypeIsNullable(options, field)) { + jstype = "?" + jstype; + is_null_or_undefined = true; + } + } + + if (!is_null_or_undefined && !IsPrimitive(jstype)) { + jstype = "!" + jstype; + } + + return jstype; +} + TProtoStringType JSBinaryReaderMethodType(const FieldDescriptor* field) { TProtoStringType name = field->type_name(); - if (name[0] >= 'a' && name[0] <= 'z') { - name[0] = (name[0] - 'a') + 'A'; - } - return IsIntegralFieldWithStringJSType(field) ? (name + "String") : name; -} - + if (name[0] >= 'a' && name[0] <= 'z') { + name[0] = (name[0] - 'a') + 'A'; + } + return IsIntegralFieldWithStringJSType(field) ? (name + "String") : name; +} + TProtoStringType JSBinaryReadWriteMethodName(const FieldDescriptor* field, bool is_writer) { TProtoStringType name = JSBinaryReaderMethodType(field); - if (field->is_packed()) { - name = "Packed" + name; - } else if (is_writer && field->is_repeated()) { - name = "Repeated" + name; - } - return name; -} - + if (field->is_packed()) { + name = "Packed" + name; + } else if (is_writer && field->is_repeated()) { + name = "Repeated" + name; + } + return name; +} + TProtoStringType JSBinaryReaderMethodName(const GeneratorOptions& options, const FieldDescriptor* field) { - return "jspb.BinaryReader.prototype.read" + - JSBinaryReadWriteMethodName(field, /* is_writer = */ false); -} - + return "jspb.BinaryReader.prototype.read" + + JSBinaryReadWriteMethodName(field, /* is_writer = */ false); +} + TProtoStringType JSBinaryWriterMethodName(const GeneratorOptions& options, const FieldDescriptor* field) { if (field->containing_type() && field->containing_type()->options().message_set_wire_format()) { return "jspb.BinaryWriter.prototype.writeMessageSet"; } - return "jspb.BinaryWriter.prototype.write" + - JSBinaryReadWriteMethodName(field, /* is_writer = */ true); -} - + return "jspb.BinaryWriter.prototype.write" + + JSBinaryReadWriteMethodName(field, /* is_writer = */ true); +} + TProtoStringType JSTypeTag(const FieldDescriptor* desc) { switch (desc->type()) { case FieldDescriptor::TYPE_DOUBLE: @@ -1136,285 +1136,285 @@ TProtoStringType JSTypeTag(const FieldDescriptor* desc) { default: assert(false); } - return ""; -} - -bool HasRepeatedFields(const GeneratorOptions& options, - const Descriptor* desc) { - for (int i = 0; i < desc->field_count(); i++) { + return ""; +} + +bool HasRepeatedFields(const GeneratorOptions& options, + const Descriptor* desc) { + for (int i = 0; i < desc->field_count(); i++) { if (desc->field(i)->is_repeated() && !desc->field(i)->is_map()) { - return true; - } - } - return false; -} - -static const char* kRepeatedFieldArrayName = ".repeatedFields_"; - + return true; + } + } + return false; +} + +static const char* kRepeatedFieldArrayName = ".repeatedFields_"; + TProtoStringType RepeatedFieldsArrayName(const GeneratorOptions& options, const Descriptor* desc) { - return HasRepeatedFields(options, desc) - ? (GetMessagePath(options, desc) + kRepeatedFieldArrayName) - : "null"; -} - -bool HasOneofFields(const Descriptor* desc) { - for (int i = 0; i < desc->field_count(); i++) { + return HasRepeatedFields(options, desc) + ? (GetMessagePath(options, desc) + kRepeatedFieldArrayName) + : "null"; +} + +bool HasOneofFields(const Descriptor* desc) { + for (int i = 0; i < desc->field_count(); i++) { if (InRealOneof(desc->field(i))) { - return true; - } - } - return false; -} - -static const char* kOneofGroupArrayName = ".oneofGroups_"; - + return true; + } + } + return false; +} + +static const char* kOneofGroupArrayName = ".oneofGroups_"; + TProtoStringType OneofFieldsArrayName(const GeneratorOptions& options, const Descriptor* desc) { - return HasOneofFields(desc) - ? (GetMessagePath(options, desc) + kOneofGroupArrayName) - : "null"; -} - + return HasOneofFields(desc) + ? (GetMessagePath(options, desc) + kOneofGroupArrayName) + : "null"; +} + TProtoStringType RepeatedFieldNumberList(const GeneratorOptions& options, const Descriptor* desc) { std::vector<TProtoStringType> numbers; - for (int i = 0; i < desc->field_count(); i++) { + for (int i = 0; i < desc->field_count(); i++) { if (desc->field(i)->is_repeated() && !desc->field(i)->is_map()) { - numbers.push_back(JSFieldIndex(desc->field(i))); - } - } - return "[" + Join(numbers, ",") + "]"; -} - + numbers.push_back(JSFieldIndex(desc->field(i))); + } + } + return "[" + Join(numbers, ",") + "]"; +} + TProtoStringType OneofGroupList(const Descriptor* desc) { - // List of arrays (one per oneof), each of which is a list of field indices + // List of arrays (one per oneof), each of which is a list of field indices std::vector<TProtoStringType> oneof_entries; - for (int i = 0; i < desc->oneof_decl_count(); i++) { - const OneofDescriptor* oneof = desc->oneof_decl(i); - if (IgnoreOneof(oneof)) { - continue; - } - + for (int i = 0; i < desc->oneof_decl_count(); i++) { + const OneofDescriptor* oneof = desc->oneof_decl(i); + if (IgnoreOneof(oneof)) { + continue; + } + std::vector<TProtoStringType> oneof_fields; - for (int j = 0; j < oneof->field_count(); j++) { - if (IgnoreField(oneof->field(j))) { - continue; - } - oneof_fields.push_back(JSFieldIndex(oneof->field(j))); - } - oneof_entries.push_back("[" + Join(oneof_fields, ",") + "]"); - } - return "[" + Join(oneof_entries, ",") + "]"; -} - + for (int j = 0; j < oneof->field_count(); j++) { + if (IgnoreField(oneof->field(j))) { + continue; + } + oneof_fields.push_back(JSFieldIndex(oneof->field(j))); + } + oneof_entries.push_back("[" + Join(oneof_fields, ",") + "]"); + } + return "[" + Join(oneof_entries, ",") + "]"; +} + TProtoStringType JSOneofArray(const GeneratorOptions& options, const FieldDescriptor* field) { - return OneofFieldsArrayName(options, field->containing_type()) + "[" + + return OneofFieldsArrayName(options, field->containing_type()) + "[" + JSOneofIndex(field->containing_oneof()) + "]"; -} - +} + TProtoStringType RelativeTypeName(const FieldDescriptor* field) { - assert(field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM || - field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE); - // For a field with an enum or message type, compute a name relative to the - // path name of the message type containing this field. + assert(field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM || + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE); + // For a field with an enum or message type, compute a name relative to the + // path name of the message type containing this field. TProtoStringType package = field->file()->package(); TProtoStringType containing_type = field->containing_type()->full_name() + "."; TProtoStringType type = (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) ? field->enum_type()->full_name() : field->message_type()->full_name(); - - // |prefix| is advanced as we find separators '.' past the common package - // prefix that yield common prefixes in the containing type's name and this - // type's name. - int prefix = 0; - for (int i = 0; i < type.size() && i < containing_type.size(); i++) { - if (type[i] != containing_type[i]) { - break; - } - if (type[i] == '.' && i >= package.size()) { - prefix = i + 1; - } - } - - return type.substr(prefix); -} - + + // |prefix| is advanced as we find separators '.' past the common package + // prefix that yield common prefixes in the containing type's name and this + // type's name. + int prefix = 0; + for (int i = 0; i < type.size() && i < containing_type.size(); i++) { + if (type[i] != containing_type[i]) { + break; + } + if (type[i] == '.' && i >= package.size()) { + prefix = i + 1; + } + } + + return type.substr(prefix); +} + TProtoStringType JSExtensionsObjectName(const GeneratorOptions& options, const FileDescriptor* from_file, const Descriptor* desc) { - if (desc->full_name() == "google.protobuf.bridge.MessageSet") { - // TODO(haberman): fix this for the kImportCommonJs case. - return "jspb.Message.messageSetExtensions"; - } else { - return MaybeCrossFileRef(options, from_file, desc) + ".extensions"; - } -} - -static const int kMapKeyField = 1; -static const int kMapValueField = 2; - -const FieldDescriptor* MapFieldKey(const FieldDescriptor* field) { - assert(field->is_map()); - return field->message_type()->FindFieldByNumber(kMapKeyField); -} - -const FieldDescriptor* MapFieldValue(const FieldDescriptor* field) { - assert(field->is_map()); - return field->message_type()->FindFieldByNumber(kMapValueField); -} - + if (desc->full_name() == "google.protobuf.bridge.MessageSet") { + // TODO(haberman): fix this for the kImportCommonJs case. + return "jspb.Message.messageSetExtensions"; + } else { + return MaybeCrossFileRef(options, from_file, desc) + ".extensions"; + } +} + +static const int kMapKeyField = 1; +static const int kMapValueField = 2; + +const FieldDescriptor* MapFieldKey(const FieldDescriptor* field) { + assert(field->is_map()); + return field->message_type()->FindFieldByNumber(kMapKeyField); +} + +const FieldDescriptor* MapFieldValue(const FieldDescriptor* field) { + assert(field->is_map()); + return field->message_type()->FindFieldByNumber(kMapValueField); +} + TProtoStringType FieldDefinition(const GeneratorOptions& options, const FieldDescriptor* field) { if (field->is_map()) { - const FieldDescriptor* key_field = MapFieldKey(field); - const FieldDescriptor* value_field = MapFieldValue(field); + const FieldDescriptor* key_field = MapFieldKey(field); + const FieldDescriptor* value_field = MapFieldValue(field); TProtoStringType key_type = ProtoTypeName(options, key_field); TProtoStringType value_type; - if (value_field->type() == FieldDescriptor::TYPE_ENUM || - value_field->type() == FieldDescriptor::TYPE_MESSAGE) { - value_type = RelativeTypeName(value_field); - } else { - value_type = ProtoTypeName(options, value_field); - } + if (value_field->type() == FieldDescriptor::TYPE_ENUM || + value_field->type() == FieldDescriptor::TYPE_MESSAGE) { + value_type = RelativeTypeName(value_field); + } else { + value_type = ProtoTypeName(options, value_field); + } return StringPrintf("map<%s, %s> %s = %d;", key_type.c_str(), value_type.c_str(), field->name().c_str(), - field->number()); - } else { + field->number()); + } else { TProtoStringType qualifier = field->is_repeated() ? "repeated" : (field->is_optional() ? "optional" : "required"); TProtoStringType type, name; - if (field->type() == FieldDescriptor::TYPE_ENUM || - field->type() == FieldDescriptor::TYPE_MESSAGE) { - type = RelativeTypeName(field); - name = field->name(); - } else if (field->type() == FieldDescriptor::TYPE_GROUP) { - type = "group"; - name = field->message_type()->name(); - } else { - type = ProtoTypeName(options, field); - name = field->name(); - } + if (field->type() == FieldDescriptor::TYPE_ENUM || + field->type() == FieldDescriptor::TYPE_MESSAGE) { + type = RelativeTypeName(field); + name = field->name(); + } else if (field->type() == FieldDescriptor::TYPE_GROUP) { + type = "group"; + name = field->message_type()->name(); + } else { + type = ProtoTypeName(options, field); + name = field->name(); + } return StringPrintf("%s %s %s = %d;", qualifier.c_str(), type.c_str(), name.c_str(), field->number()); - } -} - + } +} + TProtoStringType FieldComments(const FieldDescriptor* field, BytesMode bytes_mode) { TProtoStringType comments; - if (field->type() == FieldDescriptor::TYPE_BYTES && bytes_mode == BYTES_U8) { - comments += - " * Note that Uint8Array is not supported on all browsers.\n" - " * @see http://caniuse.com/Uint8Array\n"; - } - return comments; -} - -bool ShouldGenerateExtension(const FieldDescriptor* field) { + if (field->type() == FieldDescriptor::TYPE_BYTES && bytes_mode == BYTES_U8) { + comments += + " * Note that Uint8Array is not supported on all browsers.\n" + " * @see http://caniuse.com/Uint8Array\n"; + } + return comments; +} + +bool ShouldGenerateExtension(const FieldDescriptor* field) { return field->is_extension() && !IgnoreField(field); -} - -bool HasExtensions(const Descriptor* desc) { - for (int i = 0; i < desc->extension_count(); i++) { - if (ShouldGenerateExtension(desc->extension(i))) { - return true; - } - } - for (int i = 0; i < desc->nested_type_count(); i++) { - if (HasExtensions(desc->nested_type(i))) { - return true; - } - } - return false; -} - -bool HasExtensions(const FileDescriptor* file) { - for (int i = 0; i < file->extension_count(); i++) { - if (ShouldGenerateExtension(file->extension(i))) { - return true; - } - } - for (int i = 0; i < file->message_type_count(); i++) { - if (HasExtensions(file->message_type(i))) { - return true; - } - } - return false; -} - -bool HasMap(const GeneratorOptions& options, const Descriptor* desc) { - for (int i = 0; i < desc->field_count(); i++) { +} + +bool HasExtensions(const Descriptor* desc) { + for (int i = 0; i < desc->extension_count(); i++) { + if (ShouldGenerateExtension(desc->extension(i))) { + return true; + } + } + for (int i = 0; i < desc->nested_type_count(); i++) { + if (HasExtensions(desc->nested_type(i))) { + return true; + } + } + return false; +} + +bool HasExtensions(const FileDescriptor* file) { + for (int i = 0; i < file->extension_count(); i++) { + if (ShouldGenerateExtension(file->extension(i))) { + return true; + } + } + for (int i = 0; i < file->message_type_count(); i++) { + if (HasExtensions(file->message_type(i))) { + return true; + } + } + return false; +} + +bool HasMap(const GeneratorOptions& options, const Descriptor* desc) { + for (int i = 0; i < desc->field_count(); i++) { if (desc->field(i)->is_map()) { - return true; - } - } - for (int i = 0; i < desc->nested_type_count(); i++) { - if (HasMap(options, desc->nested_type(i))) { - return true; - } - } - return false; -} - -bool FileHasMap(const GeneratorOptions& options, const FileDescriptor* desc) { - for (int i = 0; i < desc->message_type_count(); i++) { - if (HasMap(options, desc->message_type(i))) { - return true; - } - } - return false; -} - -bool IsExtendable(const Descriptor* desc) { - return desc->extension_range_count() > 0; -} - -// Returns the max index in the underlying data storage array beyond which the -// extension object is used. + return true; + } + } + for (int i = 0; i < desc->nested_type_count(); i++) { + if (HasMap(options, desc->nested_type(i))) { + return true; + } + } + return false; +} + +bool FileHasMap(const GeneratorOptions& options, const FileDescriptor* desc) { + for (int i = 0; i < desc->message_type_count(); i++) { + if (HasMap(options, desc->message_type(i))) { + return true; + } + } + return false; +} + +bool IsExtendable(const Descriptor* desc) { + return desc->extension_range_count() > 0; +} + +// Returns the max index in the underlying data storage array beyond which the +// extension object is used. TProtoStringType GetPivot(const Descriptor* desc) { - static const int kDefaultPivot = 500; - - // Find the max field number - int max_field_number = 0; - for (int i = 0; i < desc->field_count(); i++) { - if (!IgnoreField(desc->field(i)) && - desc->field(i)->number() > max_field_number) { - max_field_number = desc->field(i)->number(); - } - } - - int pivot = -1; - if (IsExtendable(desc) || (max_field_number >= kDefaultPivot)) { + static const int kDefaultPivot = 500; + + // Find the max field number + int max_field_number = 0; + for (int i = 0; i < desc->field_count(); i++) { + if (!IgnoreField(desc->field(i)) && + desc->field(i)->number() > max_field_number) { + max_field_number = desc->field(i)->number(); + } + } + + int pivot = -1; + if (IsExtendable(desc) || (max_field_number >= kDefaultPivot)) { pivot = ((max_field_number + 1) < kDefaultPivot) ? (max_field_number + 1) : kDefaultPivot; - } - + } + return StrCat(pivot); -} - -// Whether this field represents presence. For fields with presence, we -// generate extra methods (clearFoo() and hasFoo()) for this field. -bool HasFieldPresence(const GeneratorOptions& options, - const FieldDescriptor* field) { +} + +// Whether this field represents presence. For fields with presence, we +// generate extra methods (clearFoo() and hasFoo()) for this field. +bool HasFieldPresence(const GeneratorOptions& options, + const FieldDescriptor* field) { // This returns false for repeated fields and maps, but we still do // generate clearFoo() methods for these through a special case elsewhere. return field->has_presence(); -} - -// We use this to implement the semantics that same file can be generated +} + +// We use this to implement the semantics that same file can be generated // multiple times, but only the last one keep the short name. Others all use // long name with extra information to distinguish (For message and enum, the // extra information is package name, for file level extension, the extra // information is proto's filename). // We never actually write the files, but we keep a set of which descriptors // were the final one for a given filename. -class FileDeduplicator { - public: - explicit FileDeduplicator(const GeneratorOptions& options) - : error_on_conflict_(options.error_on_name_conflict) {} - +class FileDeduplicator { + public: + explicit FileDeduplicator(const GeneratorOptions& options) + : error_on_conflict_(options.error_on_name_conflict) {} + // params: // filenames: a pair of {short filename, full filename} // (short filename don't have extra information, full filename @@ -1425,95 +1425,95 @@ class FileDeduplicator { const void* desc, TProtoStringType* error) { if (descs_by_shortname_.find(filenames.first) != descs_by_shortname_.end()) { - if (error_on_conflict_) { + if (error_on_conflict_) { *error = "Name conflict: file name " + filenames.first + - " would be generated by two descriptors"; - return false; - } + " would be generated by two descriptors"; + return false; + } // Change old pointer's actual name to full name. auto short_name_desc = descs_by_shortname_[filenames.first]; allowed_descs_actual_name_[short_name_desc] = allowed_descs_full_name_[short_name_desc]; - } + } descs_by_shortname_[filenames.first] = desc; allowed_descs_actual_name_[desc] = filenames.first; allowed_descs_full_name_[desc] = filenames.second; - - return true; - } - + + return true; + } + void GetAllowedMap(std::map<const void*, TProtoStringType>* allowed_set) { *allowed_set = allowed_descs_actual_name_; - } - - private: - bool error_on_conflict_; + } + + private: + bool error_on_conflict_; // The map that restores all the descs that are using short name as filename. std::map<TProtoStringType, const void*> descs_by_shortname_; // The final actual filename map. std::map<const void*, TProtoStringType> allowed_descs_actual_name_; // The full name map. std::map<const void*, TProtoStringType> allowed_descs_full_name_; -}; - -void DepthFirstSearch(const FileDescriptor* file, - std::vector<const FileDescriptor*>* list, - std::set<const FileDescriptor*>* seen) { - if (!seen->insert(file).second) { - return; - } - - // Add all dependencies. - for (int i = 0; i < file->dependency_count(); i++) { - DepthFirstSearch(file->dependency(i), list, seen); - } - - // Add this file. - list->push_back(file); -} - -// A functor for the predicate to remove_if() below. Returns true if a given -// FileDescriptor is not in the given set. -class NotInSet { - public: - explicit NotInSet(const std::set<const FileDescriptor*>& file_set) - : file_set_(file_set) {} - - bool operator()(const FileDescriptor* file) { - return file_set_.count(file) == 0; - } - - private: - const std::set<const FileDescriptor*>& file_set_; -}; - -// This function generates an ordering of the input FileDescriptors that matches -// the logic of the old code generator. The order is significant because two -// different input files can generate the same output file, and the last one -// needs to win. -void GenerateJspbFileOrder(const std::vector<const FileDescriptor*>& input, - std::vector<const FileDescriptor*>* ordered) { - // First generate an ordering of all reachable files (including dependencies) - // with depth-first search. This mimics the behavior of --include_imports, - // which is what the old codegen used. - ordered->clear(); - std::set<const FileDescriptor*> seen; - std::set<const FileDescriptor*> input_set; - for (int i = 0; i < input.size(); i++) { - DepthFirstSearch(input[i], ordered, &seen); - input_set.insert(input[i]); - } - - // Now remove the entries that are not actually in our input list. - ordered->erase( - std::remove_if(ordered->begin(), ordered->end(), NotInSet(input_set)), - ordered->end()); -} - -// If we're generating code in file-per-type mode, avoid overwriting files -// by choosing the last descriptor that writes each filename and permitting -// only those to generate code. - +}; + +void DepthFirstSearch(const FileDescriptor* file, + std::vector<const FileDescriptor*>* list, + std::set<const FileDescriptor*>* seen) { + if (!seen->insert(file).second) { + return; + } + + // Add all dependencies. + for (int i = 0; i < file->dependency_count(); i++) { + DepthFirstSearch(file->dependency(i), list, seen); + } + + // Add this file. + list->push_back(file); +} + +// A functor for the predicate to remove_if() below. Returns true if a given +// FileDescriptor is not in the given set. +class NotInSet { + public: + explicit NotInSet(const std::set<const FileDescriptor*>& file_set) + : file_set_(file_set) {} + + bool operator()(const FileDescriptor* file) { + return file_set_.count(file) == 0; + } + + private: + const std::set<const FileDescriptor*>& file_set_; +}; + +// This function generates an ordering of the input FileDescriptors that matches +// the logic of the old code generator. The order is significant because two +// different input files can generate the same output file, and the last one +// needs to win. +void GenerateJspbFileOrder(const std::vector<const FileDescriptor*>& input, + std::vector<const FileDescriptor*>* ordered) { + // First generate an ordering of all reachable files (including dependencies) + // with depth-first search. This mimics the behavior of --include_imports, + // which is what the old codegen used. + ordered->clear(); + std::set<const FileDescriptor*> seen; + std::set<const FileDescriptor*> input_set; + for (int i = 0; i < input.size(); i++) { + DepthFirstSearch(input[i], ordered, &seen); + input_set.insert(input[i]); + } + + // Now remove the entries that are not actually in our input list. + ordered->erase( + std::remove_if(ordered->begin(), ordered->end(), NotInSet(input_set)), + ordered->end()); +} + +// If we're generating code in file-per-type mode, avoid overwriting files +// by choosing the last descriptor that writes each filename and permitting +// only those to generate code. + struct DepsGenerator { std::vector<const Descriptor*> operator()(const Descriptor* desc) const { std::vector<const Descriptor*> deps; @@ -1539,62 +1539,62 @@ struct DepsGenerator { }; bool GenerateJspbAllowedMap(const GeneratorOptions& options, - const std::vector<const FileDescriptor*>& files, + const std::vector<const FileDescriptor*>& files, std::map<const void*, TProtoStringType>* allowed_set, SCCAnalyzer<DepsGenerator>* analyzer, TProtoStringType* error) { - std::vector<const FileDescriptor*> files_ordered; - GenerateJspbFileOrder(files, &files_ordered); - - // Choose the last descriptor for each filename. - FileDeduplicator dedup(options); + std::vector<const FileDescriptor*> files_ordered; + GenerateJspbFileOrder(files, &files_ordered); + + // Choose the last descriptor for each filename. + FileDeduplicator dedup(options); std::set<const SCC*> added; - for (int i = 0; i < files_ordered.size(); i++) { - for (int j = 0; j < files_ordered[i]->message_type_count(); j++) { - const Descriptor* desc = files_ordered[i]->message_type(j); + for (int i = 0; i < files_ordered.size(); i++) { + for (int j = 0; j < files_ordered[i]->message_type_count(); j++) { + const Descriptor* desc = files_ordered[i]->message_type(j); if (added.insert(analyzer->GetSCC(desc)).second && !dedup.AddFile( std::make_pair( GetMessagesFileName(options, analyzer->GetSCC(desc), false), GetMessagesFileName(options, analyzer->GetSCC(desc), true)), analyzer->GetSCC(desc), error)) { - return false; - } - } - for (int j = 0; j < files_ordered[i]->enum_type_count(); j++) { - const EnumDescriptor* desc = files_ordered[i]->enum_type(j); + return false; + } + } + for (int j = 0; j < files_ordered[i]->enum_type_count(); j++) { + const EnumDescriptor* desc = files_ordered[i]->enum_type(j); if (!dedup.AddFile(std::make_pair(GetEnumFileName(options, desc, false), GetEnumFileName(options, desc, true)), desc, error)) { - return false; - } - } - - // Pull out all free-floating extensions and generate files for those too. - bool has_extension = false; - - for (int j = 0; j < files_ordered[i]->extension_count(); j++) { - if (ShouldGenerateExtension(files_ordered[i]->extension(j))) { - has_extension = true; - } - } - - if (has_extension) { + return false; + } + } + + // Pull out all free-floating extensions and generate files for those too. + bool has_extension = false; + + for (int j = 0; j < files_ordered[i]->extension_count(); j++) { + if (ShouldGenerateExtension(files_ordered[i]->extension(j))) { + has_extension = true; + } + } + + if (has_extension) { if (!dedup.AddFile( std::make_pair( GetExtensionFileName(options, files_ordered[i], false), GetExtensionFileName(options, files_ordered[i], true)), files_ordered[i], error)) { - return false; - } - } - } - + return false; + } + } + } + dedup.GetAllowedMap(allowed_set); - - return true; -} - + + return true; +} + // Embeds base64 encoded GeneratedCodeInfo proto in a comment at the end of // file. void EmbedCodeAnnotations(const GeneratedCodeInfo& annotations, @@ -1615,11 +1615,11 @@ bool IsWellKnownTypeFile(const FileDescriptor* file) { return HasPrefixString(file->name(), "google/protobuf/"); } -} // anonymous namespace - -void Generator::GenerateHeader(const GeneratorOptions& options, +} // anonymous namespace + +void Generator::GenerateHeader(const GeneratorOptions& options, const FileDescriptor* file, - io::Printer* printer) const { + io::Printer* printer) const { if (file != nullptr) { printer->Print("// source: $filename$\n", "filename", file->name()); } @@ -1639,31 +1639,31 @@ void Generator::GenerateHeader(const GeneratorOptions& options, "/* eslint-disable */\n" "// @ts-nocheck\n" "\n"); -} - -void Generator::FindProvidesForFile(const GeneratorOptions& options, - io::Printer* printer, - const FileDescriptor* file, +} + +void Generator::FindProvidesForFile(const GeneratorOptions& options, + io::Printer* printer, + const FileDescriptor* file, std::set<TProtoStringType>* provided) const { - for (int i = 0; i < file->message_type_count(); i++) { - FindProvidesForMessage(options, printer, file->message_type(i), provided); - } - for (int i = 0; i < file->enum_type_count(); i++) { - FindProvidesForEnum(options, printer, file->enum_type(i), provided); - } -} - -void Generator::FindProvides(const GeneratorOptions& options, - io::Printer* printer, - const std::vector<const FileDescriptor*>& files, + for (int i = 0; i < file->message_type_count(); i++) { + FindProvidesForMessage(options, printer, file->message_type(i), provided); + } + for (int i = 0; i < file->enum_type_count(); i++) { + FindProvidesForEnum(options, printer, file->enum_type(i), provided); + } +} + +void Generator::FindProvides(const GeneratorOptions& options, + io::Printer* printer, + const std::vector<const FileDescriptor*>& files, std::set<TProtoStringType>* provided) const { - for (int i = 0; i < files.size(); i++) { - FindProvidesForFile(options, printer, files[i], provided); - } - - printer->Print("\n"); -} - + for (int i = 0; i < files.size(); i++) { + FindProvidesForFile(options, printer, files[i], provided); + } + + printer->Print("\n"); +} + void FindProvidesForOneOfEnum(const GeneratorOptions& options, const OneofDescriptor* oneof, std::set<TProtoStringType>* provided) { @@ -1690,62 +1690,62 @@ void Generator::FindProvidesForMessage(const GeneratorOptions& options, const Descriptor* desc, std::set<TProtoStringType>* provided) const { if (IgnoreMessage(desc)) { - return; - } - + return; + } + TProtoStringType name = GetMessagePath(options, desc); - provided->insert(name); - - for (int i = 0; i < desc->enum_type_count(); i++) { + provided->insert(name); + + for (int i = 0; i < desc->enum_type_count(); i++) { FindProvidesForEnum(options, printer, desc->enum_type(i), provided); - } + } FindProvidesForOneOfEnums(options, printer, desc, provided); - for (int i = 0; i < desc->nested_type_count(); i++) { + for (int i = 0; i < desc->nested_type_count(); i++) { FindProvidesForMessage(options, printer, desc->nested_type(i), provided); - } -} -void Generator::FindProvidesForEnum(const GeneratorOptions& options, - io::Printer* printer, - const EnumDescriptor* enumdesc, + } +} +void Generator::FindProvidesForEnum(const GeneratorOptions& options, + io::Printer* printer, + const EnumDescriptor* enumdesc, std::set<TProtoStringType>* provided) const { TProtoStringType name = GetEnumPath(options, enumdesc); - provided->insert(name); -} - -void Generator::FindProvidesForFields( + provided->insert(name); +} + +void Generator::FindProvidesForFields( const GeneratorOptions& options, io::Printer* printer, - const std::vector<const FieldDescriptor*>& fields, + const std::vector<const FieldDescriptor*>& fields, std::set<TProtoStringType>* provided) const { - for (int i = 0; i < fields.size(); i++) { - const FieldDescriptor* field = fields[i]; - - if (IgnoreField(field)) { - continue; - } - + for (int i = 0; i < fields.size(); i++) { + const FieldDescriptor* field = fields[i]; + + if (IgnoreField(field)) { + continue; + } + TProtoStringType name = GetNamespace(options, field->file()) + "." + JSObjectFieldName(options, field); - provided->insert(name); - } -} - -void Generator::GenerateProvides(const GeneratorOptions& options, - io::Printer* printer, + provided->insert(name); + } +} + +void Generator::GenerateProvides(const GeneratorOptions& options, + io::Printer* printer, std::set<TProtoStringType>* provided) const { for (std::set<TProtoStringType>::iterator it = provided->begin(); - it != provided->end(); ++it) { - if (options.import_style == GeneratorOptions::kImportClosure) { - printer->Print("goog.provide('$name$');\n", "name", *it); - } else { - // We aren't using Closure's import system, but we use goog.exportSymbol() - // to construct the expected tree of objects, eg. - // - // goog.exportSymbol('foo.bar.Baz', null, this); - // - // // Later generated code expects foo.bar = {} to exist: - // foo.bar.Baz = function() { /* ... */ } + it != provided->end(); ++it) { + if (options.import_style == GeneratorOptions::kImportClosure) { + printer->Print("goog.provide('$name$');\n", "name", *it); + } else { + // We aren't using Closure's import system, but we use goog.exportSymbol() + // to construct the expected tree of objects, eg. + // + // goog.exportSymbol('foo.bar.Baz', null, this); + // + // // Later generated code expects foo.bar = {} to exist: + // foo.bar.Baz = function() { /* ... */ } // Do not use global scope in strict mode if (options.import_style == GeneratorOptions::kImportCommonJsStrict) { @@ -1759,16 +1759,16 @@ void Generator::GenerateProvides(const GeneratorOptions& options, printer->Print("goog.exportSymbol('$name$', null, global);\n", "name", *it); } - } - } -} - + } + } +} + void Generator::GenerateRequiresForSCC(const GeneratorOptions& options, io::Printer* printer, const SCC* scc, std::set<TProtoStringType>* provided) const { std::set<TProtoStringType> required; std::set<TProtoStringType> forwards; - bool have_message = false; + bool have_message = false; bool has_extension = false; bool has_map = false; for (auto desc : scc->descriptors) { @@ -1779,154 +1779,154 @@ void Generator::GenerateRequiresForSCC(const GeneratorOptions& options, has_map = (has_map || HasMap(options, desc)); } } - - GenerateRequiresImpl(options, printer, &required, &forwards, provided, - /* require_jspb = */ have_message, + + GenerateRequiresImpl(options, printer, &required, &forwards, provided, + /* require_jspb = */ have_message, /* require_extension = */ has_extension, /* require_map = */ has_map); -} - -void Generator::GenerateRequiresForLibrary( - const GeneratorOptions& options, io::Printer* printer, - const std::vector<const FileDescriptor*>& files, +} + +void Generator::GenerateRequiresForLibrary( + const GeneratorOptions& options, io::Printer* printer, + const std::vector<const FileDescriptor*>& files, std::set<TProtoStringType>* provided) const { - GOOGLE_CHECK_EQ(options.import_style, GeneratorOptions::kImportClosure); - // For Closure imports we need to import every message type individually. + GOOGLE_CHECK_EQ(options.import_style, GeneratorOptions::kImportClosure); + // For Closure imports we need to import every message type individually. std::set<TProtoStringType> required; std::set<TProtoStringType> forwards; - bool have_extensions = false; - bool have_map = false; - bool have_message = false; - - for (int i = 0; i < files.size(); i++) { - for (int j = 0; j < files[i]->message_type_count(); j++) { - const Descriptor* desc = files[i]->message_type(j); + bool have_extensions = false; + bool have_map = false; + bool have_message = false; + + for (int i = 0; i < files.size(); i++) { + for (int j = 0; j < files[i]->message_type_count(); j++) { + const Descriptor* desc = files[i]->message_type(j); if (!IgnoreMessage(desc)) { - FindRequiresForMessage(options, desc, &required, &forwards, - &have_message); - } - } - - if (!have_extensions && HasExtensions(files[i])) { - have_extensions = true; - } - - if (!have_map && FileHasMap(options, files[i])) { - have_map = true; - } - - for (int j = 0; j < files[i]->extension_count(); j++) { - const FieldDescriptor* extension = files[i]->extension(j); - if (IgnoreField(extension)) { - continue; - } - if (extension->containing_type()->full_name() != + FindRequiresForMessage(options, desc, &required, &forwards, + &have_message); + } + } + + if (!have_extensions && HasExtensions(files[i])) { + have_extensions = true; + } + + if (!have_map && FileHasMap(options, files[i])) { + have_map = true; + } + + for (int j = 0; j < files[i]->extension_count(); j++) { + const FieldDescriptor* extension = files[i]->extension(j); + if (IgnoreField(extension)) { + continue; + } + if (extension->containing_type()->full_name() != "google.protobuf.bridge.MessageSet") { - required.insert(GetMessagePath(options, extension->containing_type())); - } - FindRequiresForField(options, extension, &required, &forwards); - have_extensions = true; - } - } - - GenerateRequiresImpl(options, printer, &required, &forwards, provided, - /* require_jspb = */ have_message, - /* require_extension = */ have_extensions, - /* require_map = */ have_map); -} - -void Generator::GenerateRequiresForExtensions( - const GeneratorOptions& options, io::Printer* printer, - const std::vector<const FieldDescriptor*>& fields, + required.insert(GetMessagePath(options, extension->containing_type())); + } + FindRequiresForField(options, extension, &required, &forwards); + have_extensions = true; + } + } + + GenerateRequiresImpl(options, printer, &required, &forwards, provided, + /* require_jspb = */ have_message, + /* require_extension = */ have_extensions, + /* require_map = */ have_map); +} + +void Generator::GenerateRequiresForExtensions( + const GeneratorOptions& options, io::Printer* printer, + const std::vector<const FieldDescriptor*>& fields, std::set<TProtoStringType>* provided) const { std::set<TProtoStringType> required; std::set<TProtoStringType> forwards; - for (int i = 0; i < fields.size(); i++) { - const FieldDescriptor* field = fields[i]; - if (IgnoreField(field)) { - continue; - } - FindRequiresForExtension(options, field, &required, &forwards); - } - - GenerateRequiresImpl(options, printer, &required, &forwards, provided, - /* require_jspb = */ false, - /* require_extension = */ fields.size() > 0, - /* require_map = */ false); -} - -void Generator::GenerateRequiresImpl(const GeneratorOptions& options, - io::Printer* printer, + for (int i = 0; i < fields.size(); i++) { + const FieldDescriptor* field = fields[i]; + if (IgnoreField(field)) { + continue; + } + FindRequiresForExtension(options, field, &required, &forwards); + } + + GenerateRequiresImpl(options, printer, &required, &forwards, provided, + /* require_jspb = */ false, + /* require_extension = */ fields.size() > 0, + /* require_map = */ false); +} + +void Generator::GenerateRequiresImpl(const GeneratorOptions& options, + io::Printer* printer, std::set<TProtoStringType>* required, std::set<TProtoStringType>* forwards, std::set<TProtoStringType>* provided, - bool require_jspb, bool require_extension, - bool require_map) const { - if (require_jspb) { - required->insert("jspb.Message"); - required->insert("jspb.BinaryReader"); - required->insert("jspb.BinaryWriter"); - } - if (require_extension) { - required->insert("jspb.ExtensionFieldBinaryInfo"); - required->insert("jspb.ExtensionFieldInfo"); - } - if (require_map) { - required->insert("jspb.Map"); - } - + bool require_jspb, bool require_extension, + bool require_map) const { + if (require_jspb) { + required->insert("jspb.Message"); + required->insert("jspb.BinaryReader"); + required->insert("jspb.BinaryWriter"); + } + if (require_extension) { + required->insert("jspb.ExtensionFieldBinaryInfo"); + required->insert("jspb.ExtensionFieldInfo"); + } + if (require_map) { + required->insert("jspb.Map"); + } + std::set<TProtoStringType>::iterator it; - for (it = required->begin(); it != required->end(); ++it) { - if (provided->find(*it) != provided->end()) { - continue; - } + for (it = required->begin(); it != required->end(); ++it) { + if (provided->find(*it) != provided->end()) { + continue; + } printer->Print("goog.require('$name$');\n", "name", *it); - } - - printer->Print("\n"); - - for (it = forwards->begin(); it != forwards->end(); ++it) { - if (provided->find(*it) != provided->end()) { - continue; - } + } + + printer->Print("\n"); + + for (it = forwards->begin(); it != forwards->end(); ++it) { + if (provided->find(*it) != provided->end()) { + continue; + } printer->Print("goog.forwardDeclare('$name$');\n", "name", *it); - } -} - + } +} + bool NamespaceOnly(const Descriptor* desc) { return false; } - + void Generator::FindRequiresForMessage(const GeneratorOptions& options, const Descriptor* desc, std::set<TProtoStringType>* required, std::set<TProtoStringType>* forwards, bool* have_message) const { - if (!NamespaceOnly(desc)) { - *have_message = true; - for (int i = 0; i < desc->field_count(); i++) { - const FieldDescriptor* field = desc->field(i); - if (IgnoreField(field)) { - continue; - } - FindRequiresForField(options, field, required, forwards); - } - } - - for (int i = 0; i < desc->extension_count(); i++) { - const FieldDescriptor* field = desc->extension(i); - if (IgnoreField(field)) { - continue; - } - FindRequiresForExtension(options, field, required, forwards); - } - - for (int i = 0; i < desc->nested_type_count(); i++) { - FindRequiresForMessage(options, desc->nested_type(i), required, forwards, - have_message); - } -} - -void Generator::FindRequiresForField(const GeneratorOptions& options, - const FieldDescriptor* field, + if (!NamespaceOnly(desc)) { + *have_message = true; + for (int i = 0; i < desc->field_count(); i++) { + const FieldDescriptor* field = desc->field(i); + if (IgnoreField(field)) { + continue; + } + FindRequiresForField(options, field, required, forwards); + } + } + + for (int i = 0; i < desc->extension_count(); i++) { + const FieldDescriptor* field = desc->extension(i); + if (IgnoreField(field)) { + continue; + } + FindRequiresForExtension(options, field, required, forwards); + } + + for (int i = 0; i < desc->nested_type_count(); i++) { + FindRequiresForMessage(options, desc->nested_type(i), required, forwards, + have_message); + } +} + +void Generator::FindRequiresForField(const GeneratorOptions& options, + const FieldDescriptor* field, std::set<TProtoStringType>* required, std::set<TProtoStringType>* forwards) const { if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM && @@ -1937,14 +1937,14 @@ void Generator::FindRequiresForField(const GeneratorOptions& options, required->insert(GetEnumPath(options, field->enum_type())); } else { forwards->insert(GetEnumPath(options, field->enum_type())); - } + } } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (!IgnoreMessage(field->message_type())) { required->insert(GetMessagePath(options, field->message_type())); } } -} - +} + void Generator::FindRequiresForExtension( const GeneratorOptions& options, const FieldDescriptor* field, std::set<TProtoStringType>* required, std::set<TProtoStringType>* forwards) const { @@ -1953,120 +1953,120 @@ void Generator::FindRequiresForExtension( required->insert(GetMessagePath(options, field->containing_type())); } FindRequiresForField(options, field, required, forwards); -} - -void Generator::GenerateTestOnly(const GeneratorOptions& options, - io::Printer* printer) const { - if (options.testonly) { - printer->Print("goog.setTestOnly();\n\n"); - } - printer->Print("\n"); -} - -void Generator::GenerateClassesAndEnums(const GeneratorOptions& options, - io::Printer* printer, - const FileDescriptor* file) const { - for (int i = 0; i < file->message_type_count(); i++) { +} + +void Generator::GenerateTestOnly(const GeneratorOptions& options, + io::Printer* printer) const { + if (options.testonly) { + printer->Print("goog.setTestOnly();\n\n"); + } + printer->Print("\n"); +} + +void Generator::GenerateClassesAndEnums(const GeneratorOptions& options, + io::Printer* printer, + const FileDescriptor* file) const { + for (int i = 0; i < file->message_type_count(); i++) { GenerateClassConstructorAndDeclareExtensionFieldInfo(options, printer, file->message_type(i)); } for (int i = 0; i < file->message_type_count(); i++) { - GenerateClass(options, printer, file->message_type(i)); - } - for (int i = 0; i < file->enum_type_count(); i++) { - GenerateEnum(options, printer, file->enum_type(i)); - } -} - -void Generator::GenerateClass(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const { + GenerateClass(options, printer, file->message_type(i)); + } + for (int i = 0; i < file->enum_type_count(); i++) { + GenerateEnum(options, printer, file->enum_type(i)); + } +} + +void Generator::GenerateClass(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const { if (IgnoreMessage(desc)) { - return; - } - - if (!NamespaceOnly(desc)) { - printer->Print("\n"); - GenerateClassFieldInfo(options, printer, desc); - - GenerateClassToObject(options, printer, desc); - // These must come *before* the extension-field info generation in - // GenerateClassRegistration so that references to the binary - // serialization/deserialization functions may be placed in the extension - // objects. - GenerateClassDeserializeBinary(options, printer, desc); - GenerateClassSerializeBinary(options, printer, desc); - } - - // Recurse on nested types. These must come *before* the extension-field - // info generation in GenerateClassRegistration so that extensions that - // reference nested types proceed the definitions of the nested types. - for (int i = 0; i < desc->enum_type_count(); i++) { - GenerateEnum(options, printer, desc->enum_type(i)); - } - for (int i = 0; i < desc->nested_type_count(); i++) { - GenerateClass(options, printer, desc->nested_type(i)); - } - - if (!NamespaceOnly(desc)) { - GenerateClassRegistration(options, printer, desc); - GenerateClassFields(options, printer, desc); - - if (options.import_style != GeneratorOptions::kImportClosure) { - for (int i = 0; i < desc->extension_count(); i++) { - GenerateExtension(options, printer, desc->extension(i)); - } - } - } -} - -void Generator::GenerateClassConstructor(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const { - printer->Print( - "/**\n" - " * Generated by JsPbCodeGenerator.\n" - " * @param {Array=} opt_data Optional initial data array, typically " - "from a\n" - " * server response, or constructed directly in Javascript. The array " - "is used\n" - " * in place and becomes part of the constructed object. It is not " - "cloned.\n" - " * If no data is provided, the constructed object will be empty, but " - "still\n" - " * valid.\n" - " * @extends {jspb.Message}\n" - " * @constructor\n" - " */\n" + return; + } + + if (!NamespaceOnly(desc)) { + printer->Print("\n"); + GenerateClassFieldInfo(options, printer, desc); + + GenerateClassToObject(options, printer, desc); + // These must come *before* the extension-field info generation in + // GenerateClassRegistration so that references to the binary + // serialization/deserialization functions may be placed in the extension + // objects. + GenerateClassDeserializeBinary(options, printer, desc); + GenerateClassSerializeBinary(options, printer, desc); + } + + // Recurse on nested types. These must come *before* the extension-field + // info generation in GenerateClassRegistration so that extensions that + // reference nested types proceed the definitions of the nested types. + for (int i = 0; i < desc->enum_type_count(); i++) { + GenerateEnum(options, printer, desc->enum_type(i)); + } + for (int i = 0; i < desc->nested_type_count(); i++) { + GenerateClass(options, printer, desc->nested_type(i)); + } + + if (!NamespaceOnly(desc)) { + GenerateClassRegistration(options, printer, desc); + GenerateClassFields(options, printer, desc); + + if (options.import_style != GeneratorOptions::kImportClosure) { + for (int i = 0; i < desc->extension_count(); i++) { + GenerateExtension(options, printer, desc->extension(i)); + } + } + } +} + +void Generator::GenerateClassConstructor(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const { + printer->Print( + "/**\n" + " * Generated by JsPbCodeGenerator.\n" + " * @param {Array=} opt_data Optional initial data array, typically " + "from a\n" + " * server response, or constructed directly in Javascript. The array " + "is used\n" + " * in place and becomes part of the constructed object. It is not " + "cloned.\n" + " * If no data is provided, the constructed object will be empty, but " + "still\n" + " * valid.\n" + " * @extends {jspb.Message}\n" + " * @constructor\n" + " */\n" "$classprefix$$classname$ = function(opt_data) {\n", "classprefix", GetMessagePathPrefix(options, desc), "classname", desc->name()); printer->Annotate("classname", desc); TProtoStringType message_id = GetMessageId(desc); - printer->Print( - " jspb.Message.initialize(this, opt_data, $messageId$, $pivot$, " - "$rptfields$, $oneoffields$);\n", + printer->Print( + " jspb.Message.initialize(this, opt_data, $messageId$, $pivot$, " + "$rptfields$, $oneoffields$);\n", "messageId", !message_id.empty() ? ("'" + message_id + "'") : (IsResponse(desc) ? "''" : "0"), "pivot", GetPivot(desc), "rptfields", RepeatedFieldsArrayName(options, desc), "oneoffields", OneofFieldsArrayName(options, desc)); - printer->Print( - "};\n" - "goog.inherits($classname$, jspb.Message);\n" - "if (goog.DEBUG && !COMPILED) {\n" + printer->Print( + "};\n" + "goog.inherits($classname$, jspb.Message);\n" + "if (goog.DEBUG && !COMPILED) {\n" // displayName overrides Function.prototype.displayName // http://google3/javascript/externs/es3.js?l=511 " /**\n" " * @public\n" " * @override\n" " */\n" - " $classname$.displayName = '$classname$';\n" - "}\n", - "classname", GetMessagePath(options, desc)); -} - + " $classname$.displayName = '$classname$';\n" + "}\n", + "classname", GetMessagePath(options, desc)); +} + void Generator::GenerateClassConstructorAndDeclareExtensionFieldInfo( const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc) const { @@ -2085,196 +2085,196 @@ void Generator::GenerateClassConstructorAndDeclareExtensionFieldInfo( } } -void Generator::GenerateClassFieldInfo(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const { - if (HasRepeatedFields(options, desc)) { - printer->Print( - "/**\n" - " * List of repeated fields within this message type.\n" - " * @private {!Array<number>}\n" - " * @const\n" - " */\n" - "$classname$$rptfieldarray$ = $rptfields$;\n" - "\n", +void Generator::GenerateClassFieldInfo(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const { + if (HasRepeatedFields(options, desc)) { + printer->Print( + "/**\n" + " * List of repeated fields within this message type.\n" + " * @private {!Array<number>}\n" + " * @const\n" + " */\n" + "$classname$$rptfieldarray$ = $rptfields$;\n" + "\n", "classname", GetMessagePath(options, desc), "rptfieldarray", kRepeatedFieldArrayName, "rptfields", RepeatedFieldNumberList(options, desc)); - } - - if (HasOneofFields(desc)) { - printer->Print( - "/**\n" - " * Oneof group definitions for this message. Each group defines the " - "field\n" - " * numbers belonging to that group. When of these fields' value is " - "set, all\n" - " * other fields in the group are cleared. During deserialization, if " - "multiple\n" - " * fields are encountered for a group, only the last value seen will " - "be kept.\n" - " * @private {!Array<!Array<number>>}\n" - " * @const\n" - " */\n" - "$classname$$oneofgrouparray$ = $oneofgroups$;\n" - "\n", + } + + if (HasOneofFields(desc)) { + printer->Print( + "/**\n" + " * Oneof group definitions for this message. Each group defines the " + "field\n" + " * numbers belonging to that group. When of these fields' value is " + "set, all\n" + " * other fields in the group are cleared. During deserialization, if " + "multiple\n" + " * fields are encountered for a group, only the last value seen will " + "be kept.\n" + " * @private {!Array<!Array<number>>}\n" + " * @const\n" + " */\n" + "$classname$$oneofgrouparray$ = $oneofgroups$;\n" + "\n", "classname", GetMessagePath(options, desc), "oneofgrouparray", kOneofGroupArrayName, "oneofgroups", OneofGroupList(desc)); - - for (int i = 0; i < desc->oneof_decl_count(); i++) { - if (IgnoreOneof(desc->oneof_decl(i))) { - continue; - } - GenerateOneofCaseDefinition(options, printer, desc->oneof_decl(i)); - } - } -} - -void Generator::GenerateClassXid(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const { - printer->Print( - "\n" - "\n" - "$class$.prototype.messageXid = xid('$class$');\n", - "class", GetMessagePath(options, desc)); -} - -void Generator::GenerateOneofCaseDefinition( + + for (int i = 0; i < desc->oneof_decl_count(); i++) { + if (IgnoreOneof(desc->oneof_decl(i))) { + continue; + } + GenerateOneofCaseDefinition(options, printer, desc->oneof_decl(i)); + } + } +} + +void Generator::GenerateClassXid(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const { + printer->Print( + "\n" + "\n" + "$class$.prototype.messageXid = xid('$class$');\n", + "class", GetMessagePath(options, desc)); +} + +void Generator::GenerateOneofCaseDefinition( const GeneratorOptions& options, io::Printer* printer, - const OneofDescriptor* oneof) const { - printer->Print( - "/**\n" - " * @enum {number}\n" - " */\n" - "$classname$.$oneof$Case = {\n" - " $upcase$_NOT_SET: 0", + const OneofDescriptor* oneof) const { + printer->Print( + "/**\n" + " * @enum {number}\n" + " */\n" + "$classname$.$oneof$Case = {\n" + " $upcase$_NOT_SET: 0", "classname", GetMessagePath(options, oneof->containing_type()), "oneof", JSOneofName(oneof), "upcase", ToEnumCase(oneof->name())); - - for (int i = 0; i < oneof->field_count(); i++) { - if (IgnoreField(oneof->field(i))) { - continue; - } - - printer->Print( - ",\n" - " $upcase$: $number$", + + for (int i = 0; i < oneof->field_count(); i++) { + if (IgnoreField(oneof->field(i))) { + continue; + } + + printer->Print( + ",\n" + " $upcase$: $number$", "upcase", ToEnumCase(oneof->field(i)->name()), "number", JSFieldIndex(oneof->field(i))); printer->Annotate("upcase", oneof->field(i)); - } - - printer->Print( - "\n" - "};\n" - "\n" - "/**\n" - " * @return {$class$.$oneof$Case}\n" - " */\n" - "$class$.prototype.get$oneof$Case = function() {\n" - " return /** @type {$class$.$oneof$Case} */(jspb.Message." - "computeOneofCase(this, $class$.oneofGroups_[$oneofindex$]));\n" - "};\n" - "\n", + } + + printer->Print( + "\n" + "};\n" + "\n" + "/**\n" + " * @return {$class$.$oneof$Case}\n" + " */\n" + "$class$.prototype.get$oneof$Case = function() {\n" + " return /** @type {$class$.$oneof$Case} */(jspb.Message." + "computeOneofCase(this, $class$.oneofGroups_[$oneofindex$]));\n" + "};\n" + "\n", "class", GetMessagePath(options, oneof->containing_type()), "oneof", JSOneofName(oneof), "oneofindex", JSOneofIndex(oneof)); -} - -void Generator::GenerateClassToObject(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const { - printer->Print( - "\n" - "\n" - "if (jspb.Message.GENERATE_TO_OBJECT) {\n" - "/**\n" +} + +void Generator::GenerateClassToObject(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const { + printer->Print( + "\n" + "\n" + "if (jspb.Message.GENERATE_TO_OBJECT) {\n" + "/**\n" " * Creates an object representation of this proto.\n" - " * Field names that are reserved in JavaScript and will be renamed to " - "pb_name.\n" + " * Field names that are reserved in JavaScript and will be renamed to " + "pb_name.\n" " * Optional fields that are not set will be set to undefined.\n" - " * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.\n" - " * For the list of reserved names please see:\n" + " * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.\n" + " * For the list of reserved names please see:\n" " * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n" " * @param {boolean=} opt_includeInstance Deprecated. whether to include " "the\n" " * JSPB instance for transitional soy proto support:\n" " * http://goto/soy-param-migration\n" - " * @return {!Object}\n" - " */\n" - "$classname$.prototype.toObject = function(opt_includeInstance) {\n" - " return $classname$.toObject(opt_includeInstance, this);\n" - "};\n" - "\n" - "\n" - "/**\n" - " * Static version of the {@see toObject} method.\n" + " * @return {!Object}\n" + " */\n" + "$classname$.prototype.toObject = function(opt_includeInstance) {\n" + " return $classname$.toObject(opt_includeInstance, this);\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Static version of the {@see toObject} method.\n" " * @param {boolean|undefined} includeInstance Deprecated. Whether to " "include\n" " * the JSPB instance for transitional soy proto support:\n" - " * http://goto/soy-param-migration\n" - " * @param {!$classname$} msg The msg instance to transform.\n" - " * @return {!Object}\n" - " * @suppress {unusedLocalVariables} f is only used for nested messages\n" - " */\n" - "$classname$.toObject = function(includeInstance, msg) {\n" - " var f, obj = {", - "classname", GetMessagePath(options, desc)); - - bool first = true; - for (int i = 0; i < desc->field_count(); i++) { - const FieldDescriptor* field = desc->field(i); - if (IgnoreField(field)) { - continue; - } - - if (!first) { - printer->Print(",\n "); - } else { - printer->Print("\n "); - first = false; - } - - GenerateClassFieldToObject(options, printer, field); - } - - if (!first) { - printer->Print("\n };\n\n"); - } else { - printer->Print("\n\n };\n\n"); - } - - if (IsExtendable(desc)) { - printer->Print( - " jspb.Message.toObjectExtension(/** @type {!jspb.Message} */ (msg), " - "obj,\n" - " $extObject$, $class$.prototype.getExtension,\n" - " includeInstance);\n", - "extObject", JSExtensionsObjectName(options, desc->file(), desc), - "class", GetMessagePath(options, desc)); - } - - printer->Print( - " if (includeInstance) {\n" - " obj.$$jspbMessageInstance = msg;\n" - " }\n" - " return obj;\n" - "};\n" - "}\n" - "\n" - "\n", - "classname", GetMessagePath(options, desc)); -} - -void Generator::GenerateFieldValueExpression(io::Printer* printer, + " * http://goto/soy-param-migration\n" + " * @param {!$classname$} msg The msg instance to transform.\n" + " * @return {!Object}\n" + " * @suppress {unusedLocalVariables} f is only used for nested messages\n" + " */\n" + "$classname$.toObject = function(includeInstance, msg) {\n" + " var f, obj = {", + "classname", GetMessagePath(options, desc)); + + bool first = true; + for (int i = 0; i < desc->field_count(); i++) { + const FieldDescriptor* field = desc->field(i); + if (IgnoreField(field)) { + continue; + } + + if (!first) { + printer->Print(",\n "); + } else { + printer->Print("\n "); + first = false; + } + + GenerateClassFieldToObject(options, printer, field); + } + + if (!first) { + printer->Print("\n };\n\n"); + } else { + printer->Print("\n\n };\n\n"); + } + + if (IsExtendable(desc)) { + printer->Print( + " jspb.Message.toObjectExtension(/** @type {!jspb.Message} */ (msg), " + "obj,\n" + " $extObject$, $class$.prototype.getExtension,\n" + " includeInstance);\n", + "extObject", JSExtensionsObjectName(options, desc->file(), desc), + "class", GetMessagePath(options, desc)); + } + + printer->Print( + " if (includeInstance) {\n" + " obj.$$jspbMessageInstance = msg;\n" + " }\n" + " return obj;\n" + "};\n" + "}\n" + "\n" + "\n", + "classname", GetMessagePath(options, desc)); +} + +void Generator::GenerateFieldValueExpression(io::Printer* printer, const char* obj_reference, - const FieldDescriptor* field, - bool use_default) const { + const FieldDescriptor* field, + bool use_default) const { const bool is_float_or_double = - field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT || - field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE; + field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT || + field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE; const bool is_boolean = field->cpp_type() == FieldDescriptor::CPPTYPE_BOOL; - + const TProtoStringType with_default = use_default ? "WithDefault" : ""; const TProtoStringType default_arg = use_default ? StrCat(", ", JSFieldDefault(field)) : ""; @@ -2299,93 +2299,93 @@ void Generator::GenerateFieldValueExpression(io::Printer* printer, // - getRepeatedBooleanField // - getRepeatedFloatingPointField if (is_float_or_double && !field->is_repeated() && !use_default) { - printer->Print( + printer->Print( "jspb.Message.getOptionalFloatingPointField($obj$, " "$index$$default$)", "obj", obj_reference, "index", JSFieldIndex(field), "default", default_arg); - } else { + } else { printer->Print( "jspb.Message.get$cardinality$$type$Field$with_default$($obj$, " "$index$$default$)", "cardinality", cardinality, "type", type, "with_default", with_default, "obj", obj_reference, "index", JSFieldIndex(field), "default", default_arg); - } -} - -void Generator::GenerateClassFieldToObject(const GeneratorOptions& options, - io::Printer* printer, - const FieldDescriptor* field) const { + } +} + +void Generator::GenerateClassFieldToObject(const GeneratorOptions& options, + io::Printer* printer, + const FieldDescriptor* field) const { printer->Print("$fieldname$: ", "fieldname", JSObjectFieldName(options, field)); - + if (field->is_map()) { - const FieldDescriptor* value_field = MapFieldValue(field); - // If the map values are of a message type, we must provide their static - // toObject() method; otherwise we pass undefined for that argument. + const FieldDescriptor* value_field = MapFieldValue(field); + // If the map values are of a message type, we must provide their static + // toObject() method; otherwise we pass undefined for that argument. TProtoStringType value_to_object; - if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - value_to_object = - GetMessagePath(options, value_field->message_type()) + ".toObject"; - } else { - value_to_object = "undefined"; - } - printer->Print( - "(f = msg.get$name$()) ? f.toObject(includeInstance, $valuetoobject$) " - ": []", - "name", JSGetterName(options, field), "valuetoobject", value_to_object); - } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - // Message field. - if (field->is_repeated()) { - { + if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + value_to_object = + GetMessagePath(options, value_field->message_type()) + ".toObject"; + } else { + value_to_object = "undefined"; + } + printer->Print( + "(f = msg.get$name$()) ? f.toObject(includeInstance, $valuetoobject$) " + ": []", + "name", JSGetterName(options, field), "valuetoobject", value_to_object); + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + // Message field. + if (field->is_repeated()) { + { printer->Print( "jspb.Message.toObjectList(msg.get$getter$(),\n" " $type$.toObject, includeInstance)", "getter", JSGetterName(options, field), "type", SubmessageTypeRef(options, field)); - } - } else { + } + } else { printer->Print( "(f = msg.get$getter$()) && " "$type$.toObject(includeInstance, f)", "getter", JSGetterName(options, field), "type", SubmessageTypeRef(options, field)); - } - } else if (field->type() == FieldDescriptor::TYPE_BYTES) { - // For bytes fields we want to always return the B64 data. + } + } else if (field->type() == FieldDescriptor::TYPE_BYTES) { + // For bytes fields we want to always return the B64 data. printer->Print("msg.get$getter$()", "getter", JSGetterName(options, field, BYTES_B64)); - } else { - bool use_default = field->has_default_value(); - - if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 && - // Repeated fields get initialized to their default in the constructor - // (why?), so we emit a plain getField() call for them. + } else { + bool use_default = field->has_default_value(); + + if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 && + // Repeated fields get initialized to their default in the constructor + // (why?), so we emit a plain getField() call for them. !field->is_repeated()) { - // Proto3 puts all defaults (including implicit defaults) in toObject(). - // But for proto2 we leave the existing semantics unchanged: unset fields - // without default are unset. - use_default = true; - } - - // We don't implement this by calling the accessors, because the semantics - // of the accessors are changing independently of the toObject() semantics. - // We are migrating the accessors to return defaults instead of null, but - // it may take longer to migrate toObject (or we might not want to do it at - // all). So we want to generate independent code. + // Proto3 puts all defaults (including implicit defaults) in toObject(). + // But for proto2 we leave the existing semantics unchanged: unset fields + // without default are unset. + use_default = true; + } + + // We don't implement this by calling the accessors, because the semantics + // of the accessors are changing independently of the toObject() semantics. + // We are migrating the accessors to return defaults instead of null, but + // it may take longer to migrate toObject (or we might not want to do it at + // all). So we want to generate independent code. // The accessor for unset optional values without default should return // null. Those are converted to undefined in the generated object. if (!use_default) { printer->Print("(f = "); } - GenerateFieldValueExpression(printer, "msg", field, use_default); + GenerateFieldValueExpression(printer, "msg", field, use_default); if (!use_default) { printer->Print(") == null ? undefined : f"); } - } -} - + } +} + void Generator::GenerateObjectTypedef(const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc) const { @@ -2417,114 +2417,114 @@ void Generator::GenerateObjectTypedef(const GeneratorOptions& options, printer->Print("};\n\n"); } -void Generator::GenerateClassFromObject(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const { +void Generator::GenerateClassFromObject(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const { printer->Print("if (jspb.Message.GENERATE_FROM_OBJECT) {\n\n"); GenerateObjectTypedef(options, printer, desc); - printer->Print( - "/**\n" - " * Loads data from an object into a new instance of this proto.\n" + printer->Print( + "/**\n" + " * Loads data from an object into a new instance of this proto.\n" " * @param {!$classname$.ObjectFormat} obj\n" " * The object representation of this proto to load the data from.\n" - " * @return {!$classname$}\n" - " */\n" - "$classname$.fromObject = function(obj) {\n" + " * @return {!$classname$}\n" + " */\n" + "$classname$.fromObject = function(obj) {\n" " var msg = new $classname$();\n", - "classname", GetMessagePath(options, desc)); - - for (int i = 0; i < desc->field_count(); i++) { - const FieldDescriptor* field = desc->field(i); + "classname", GetMessagePath(options, desc)); + + for (int i = 0; i < desc->field_count(); i++) { + const FieldDescriptor* field = desc->field(i); if (!IgnoreField(field)) { GenerateClassFieldFromObject(options, printer, field); } - } - - printer->Print( - " return msg;\n" - "};\n" + } + + printer->Print( + " return msg;\n" + "};\n" "}\n\n"); -} - -void Generator::GenerateClassFieldFromObject( +} + +void Generator::GenerateClassFieldFromObject( const GeneratorOptions& options, io::Printer* printer, - const FieldDescriptor* field) const { + const FieldDescriptor* field) const { if (field->is_map()) { - const FieldDescriptor* value_field = MapFieldValue(field); - if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { - // Since the map values are of message type, we have to do some extra work - // to recursively call fromObject() on them before setting the map field. - printer->Print( + const FieldDescriptor* value_field = MapFieldValue(field); + if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { + // Since the map values are of message type, we have to do some extra work + // to recursively call fromObject() on them before setting the map field. + printer->Print( " obj.$name$ && jspb.Message.setWrapperField(\n" - " msg, $index$, jspb.Map.fromObject(obj.$name$, $fieldclass$, " - "$fieldclass$.fromObject));\n", + " msg, $index$, jspb.Map.fromObject(obj.$name$, $fieldclass$, " + "$fieldclass$.fromObject));\n", "name", JSObjectFieldName(options, field), "index", JSFieldIndex(field), "fieldclass", GetMessagePath(options, value_field->message_type())); - } else { - // `msg` is a newly-constructed message object that has not yet built any - // map containers wrapping underlying arrays, so we can simply directly - // set the array here without fear of a stale wrapper. - printer->Print( + } else { + // `msg` is a newly-constructed message object that has not yet built any + // map containers wrapping underlying arrays, so we can simply directly + // set the array here without fear of a stale wrapper. + printer->Print( " obj.$name$ && " - "jspb.Message.setField(msg, $index$, obj.$name$);\n", + "jspb.Message.setField(msg, $index$, obj.$name$);\n", "name", JSObjectFieldName(options, field), "index", JSFieldIndex(field)); - } - } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - // Message field (singular or repeated) - if (field->is_repeated()) { - { - printer->Print( + } + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + // Message field (singular or repeated) + if (field->is_repeated()) { + { + printer->Print( " obj.$name$ && " - "jspb.Message.setRepeatedWrapperField(\n" + "jspb.Message.setRepeatedWrapperField(\n" " msg, $index$, obj.$name$.map(\n" " $fieldclass$.fromObject));\n", "name", JSObjectFieldName(options, field), "index", JSFieldIndex(field), "fieldclass", SubmessageTypeRef(options, field)); - } - } else { - printer->Print( + } + } else { + printer->Print( " obj.$name$ && jspb.Message.setWrapperField(\n" - " msg, $index$, $fieldclass$.fromObject(obj.$name$));\n", + " msg, $index$, $fieldclass$.fromObject(obj.$name$));\n", "name", JSObjectFieldName(options, field), "index", JSFieldIndex(field), "fieldclass", SubmessageTypeRef(options, field)); - } - } else { - // Simple (primitive) field. - printer->Print( + } + } else { + // Simple (primitive) field. + printer->Print( " obj.$name$ != null && jspb.Message.setField(msg, $index$, " - "obj.$name$);\n", + "obj.$name$);\n", "name", JSObjectFieldName(options, field), "index", JSFieldIndex(field)); - } -} - -void Generator::GenerateClassRegistration(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const { - // Register any extensions defined inside this message type. - for (int i = 0; i < desc->extension_count(); i++) { - const FieldDescriptor* extension = desc->extension(i); - if (ShouldGenerateExtension(extension)) { - GenerateExtension(options, printer, extension); - } - } -} - -void Generator::GenerateClassFields(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const { - for (int i = 0; i < desc->field_count(); i++) { - if (!IgnoreField(desc->field(i))) { - GenerateClassField(options, printer, desc->field(i)); - } - } -} - + } +} + +void Generator::GenerateClassRegistration(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const { + // Register any extensions defined inside this message type. + for (int i = 0; i < desc->extension_count(); i++) { + const FieldDescriptor* extension = desc->extension(i); + if (ShouldGenerateExtension(extension)) { + GenerateExtension(options, printer, extension); + } + } +} + +void Generator::GenerateClassFields(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const { + for (int i = 0; i < desc->field_count(); i++) { + if (!IgnoreField(desc->field(i))) { + GenerateClassField(options, printer, desc->field(i)); + } + } +} + void GenerateBytesWrapper(const GeneratorOptions& options, io::Printer* printer, const FieldDescriptor* field, BytesMode bytes_mode) { TProtoStringType type = @@ -2532,19 +2532,19 @@ void GenerateBytesWrapper(const GeneratorOptions& options, io::Printer* printer, /* is_setter_argument = */ false, /* force_present = */ false, /* singular_if_not_packed = */ false, bytes_mode); - printer->Print( - "/**\n" - " * $fielddef$\n" - "$comment$" - " * This is a type-conversion wrapper around `get$defname$()`\n" - " * @return {$type$}\n" - " */\n" - "$class$.prototype.get$name$ = function() {\n" - " return /** @type {$type$} */ (jspb.Message.bytes$list$As$suffix$(\n" - " this.get$defname$()));\n" - "};\n" - "\n" - "\n", + printer->Print( + "/**\n" + " * $fielddef$\n" + "$comment$" + " * This is a type-conversion wrapper around `get$defname$()`\n" + " * @return {$type$}\n" + " */\n" + "$class$.prototype.get$name$ = function() {\n" + " return /** @type {$type$} */ (jspb.Message.bytes$list$As$suffix$(\n" + " this.get$defname$()));\n" + "};\n" + "\n" + "\n", "fielddef", FieldDefinition(options, field), "comment", FieldComments(field, bytes_mode), "type", type, "class", GetMessagePath(options, field->containing_type()), "name", @@ -2552,15 +2552,15 @@ void GenerateBytesWrapper(const GeneratorOptions& options, io::Printer* printer, field->is_repeated() ? "List" : "", "suffix", JSByteGetterSuffix(bytes_mode), "defname", JSGetterName(options, field, BYTES_DEFAULT)); -} - -void Generator::GenerateClassField(const GeneratorOptions& options, - io::Printer* printer, - const FieldDescriptor* field) const { +} + +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. + const FieldDescriptor* key_field = MapFieldKey(field); + const FieldDescriptor* value_field = MapFieldValue(field); + // Map field: special handling to instantiate the map object on demand. TProtoStringType key_type = JSFieldTypeAnnotation(options, key_field, /* is_setter_argument = */ false, @@ -2571,69 +2571,69 @@ void Generator::GenerateClassField(const GeneratorOptions& options, /* 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", + + 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( + "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()), + " return /** @type {!jspb.Map<$keytype$,$valuetype$>} */ (\n", + "class", GetMessagePath(options, field->containing_type()), "gettername", "get" + JSGetterName(options, field), "keytype", key_type, - "valuetype", value_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( + " 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"); - } - + " 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", + + 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( + 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()), + " 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, @@ -2644,45 +2644,45 @@ void Generator::GenerateClassField(const GeneratorOptions& options, "required", (field->label() == FieldDescriptor::LABEL_REQUIRED ? ", 1" : "")); printer->Annotate("gettername", field); - printer->Print( + 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()), + "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( + + printer->Print( "this, $index$$oneofgroup$, value);\n" - "};\n" - "\n" - "\n", + "};\n" + "\n" + "\n", "index", JSFieldIndex(field), "oneofgroup", (InRealOneof(field) ? (", " + JSOneofArray(options, field)) : "")); - - if (field->is_repeated()) { - GenerateRepeatedMessageHelperMethods(options, printer, field); - } - - } else { + + 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 = + + // 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; @@ -2692,68 +2692,68 @@ void Generator::GenerateClassField(const GeneratorOptions& options, /* 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", + 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) { + + if (untyped) { printer->Print(" return "); - } else { + } 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); - } - + } + + 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" @@ -2772,7 +2772,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options, !HasFieldPresence(options, field)) { // Proto3 non-repeated and non-map fields without presence use the // setProto3*Field function. - printer->Print( + printer->Print( "$class$.prototype.$settername$ = function(value) {\n" " return jspb.Message.setProto3$typetag$Field(this, $index$, " "value);" @@ -2784,9 +2784,9 @@ void Generator::GenerateClassField(const GeneratorOptions& options, "settername", "set" + JSGetterName(options, field), "typetag", JSTypeTag(field), "index", JSFieldIndex(field)); printer->Annotate("settername", field); - } else { + } else { // Otherwise, use the regular setField function. - printer->Print( + printer->Print( "$class$.prototype.$settername$ = function(value) {\n" " return jspb.Message.set$oneoftag$Field(this, $index$", "class", GetMessagePath(options, field->containing_type()), @@ -2803,27 +2803,27 @@ void Generator::GenerateClassField(const GeneratorOptions& options, "typeclose", untyped ? ")" : "", "oneofgroup", (InRealOneof(field) ? (", " + JSOneofArray(options, field)) : ""), "rptvalueinit", (field->is_repeated() ? " || []" : "")); - } - - if (untyped) { - printer->Print( - "/**\n" + } + + if (untyped) { + printer->Print( + "/**\n" " * Clears the value.\n" " * @return {!$class$} returns this\n" - " */\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_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( + printer->Print( "/**\n" " * Clears values from the map. The map will be non-null.\n" " * @return {!$class$} returns this\n" @@ -2831,43 +2831,43 @@ void Generator::GenerateClassField(const GeneratorOptions& options, "$class$.prototype.$clearername$ = function() {\n" " this.$gettername$().clear();\n" " return this;" - "};\n" - "\n" - "\n", - "class", GetMessagePath(options, field->containing_type()), + "};\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. + } 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( + printer->Print( "/**\n" " * $jsdoc$\n" " * @return {!$class$} returns this\n" " */\n" "$class$.prototype.$clearername$ = function() {\n" " return this.$settername$($clearedvalue$);\n" - "};\n" - "\n" - "\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()), + "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. + } 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( + printer->Print( "/**\n" " * Clears the field making it undefined.\n" " * @return {!$class$} returns this\n" @@ -2875,50 +2875,50 @@ void Generator::GenerateClassField(const GeneratorOptions& options, "$class$.prototype.$clearername$ = function() {\n" " return jspb.Message.set$maybeoneof$Field(this, " "$index$$maybeoneofgroup$, ", - "class", GetMessagePath(options, field->containing_type()), + "class", GetMessagePath(options, field->containing_type()), "clearername", "clear" + JSGetterName(options, field), "maybeoneof", (InRealOneof(field) ? "Oneof" : ""), "maybeoneofgroup", (InRealOneof(field) ? (", " + JSOneofArray(options, field)) : ""), - "index", JSFieldIndex(field)); + "index", JSFieldIndex(field)); // clang-format on printer->Annotate("clearername", field); - printer->Print( + printer->Print( "$clearedvalue$);\n" - "};\n" - "\n" - "\n", + "};\n" + "\n" + "\n", "clearedvalue", (field->is_repeated() ? "[]" : "undefined")); - } - - if (HasFieldPresence(options, field)) { - printer->Print( - "/**\n" - " * Returns whether this field is set.\n" + } + + if (HasFieldPresence(options, field)) { + printer->Print( + "/**\n" + " * Returns whether this field is set.\n" " * @return {boolean}\n" - " */\n" + " */\n" "$class$.prototype.$hasername$ = function() {\n" - " return jspb.Message.getField(this, $index$) != null;\n" - "};\n" - "\n" - "\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); - } -} - -void Generator::GenerateRepeatedPrimitiveHelperMethods( - const GeneratorOptions& options, io::Printer* printer, - const FieldDescriptor* field, bool untyped) const { + } +} + +void Generator::GenerateRepeatedPrimitiveHelperMethods( + const GeneratorOptions& options, io::Printer* printer, + const FieldDescriptor* field, bool untyped) const { // clang-format off - printer->Print( - "/**\n" + printer->Print( + "/**\n" " * @param {$optionaltype$} value\n" - " * @param {number=} opt_index\n" + " * @param {number=} opt_index\n" " * @return {!$class$} returns this\n" - " */\n" + " */\n" "$class$.prototype.$addername$ = function(value, opt_index) {\n" " return jspb.Message.addToRepeatedField(this, " "$index$", @@ -2935,189 +2935,189 @@ void Generator::GenerateRepeatedPrimitiveHelperMethods( /* force_singular = */ true), "index", JSFieldIndex(field)); printer->Annotate("addername", field); - printer->Print( + printer->Print( "$oneofgroup$, $type$value$rptvalueinit$$typeclose$, " "opt_index);\n" - "};\n" - "\n" - "\n", - "type", untyped ? "/** @type{string|number|boolean|!Uint8Array} */(" : "", - "typeclose", untyped ? ")" : "", "oneofgroup", + "};\n" + "\n" + "\n", + "type", untyped ? "/** @type{string|number|boolean|!Uint8Array} */(" : "", + "typeclose", untyped ? ")" : "", "oneofgroup", (InRealOneof(field) ? (", " + JSOneofArray(options, field)) : ""), - "rptvalueinit", ""); + "rptvalueinit", ""); // clang-format on -} - -void Generator::GenerateRepeatedMessageHelperMethods( - const GeneratorOptions& options, io::Printer* printer, - const FieldDescriptor* field) const { - printer->Print( - "/**\n" - " * @param {!$optionaltype$=} opt_value\n" - " * @param {number=} opt_index\n" - " * @return {!$optionaltype$}\n" - " */\n" +} + +void Generator::GenerateRepeatedMessageHelperMethods( + const GeneratorOptions& options, io::Printer* printer, + const FieldDescriptor* field) const { + printer->Print( + "/**\n" + " * @param {!$optionaltype$=} opt_value\n" + " * @param {number=} opt_index\n" + " * @return {!$optionaltype$}\n" + " */\n" "$class$.prototype.$addername$ = function(opt_value, opt_index) {\n" - " return jspb.Message.addTo$repeatedtag$WrapperField(", + " return jspb.Message.addTo$repeatedtag$WrapperField(", "optionaltype", JSTypeName(options, field, BYTES_DEFAULT), "class", GetMessagePath(options, field->containing_type()), "addername", "add" + JSGetterName(options, field, BYTES_DEFAULT, /* drop_list = */ true), - "repeatedtag", (field->is_repeated() ? "Repeated" : "")); - + "repeatedtag", (field->is_repeated() ? "Repeated" : "")); + printer->Annotate("addername", field); - printer->Print( - "this, $index$$oneofgroup$, opt_value, $ctor$, opt_index);\n" - "};\n" - "\n" - "\n", - "index", JSFieldIndex(field), "oneofgroup", + printer->Print( + "this, $index$$oneofgroup$, opt_value, $ctor$, opt_index);\n" + "};\n" + "\n" + "\n", + "index", JSFieldIndex(field), "oneofgroup", (InRealOneof(field) ? (", " + JSOneofArray(options, field)) : ""), "ctor", GetMessagePath(options, field->message_type())); -} - -void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const { - if (IsExtendable(desc)) { - printer->Print( - "\n" - "/**\n" - " * The extensions registered with this message class. This is a " - "map of\n" - " * extension field number to fieldInfo object.\n" - " *\n" - " * For example:\n" - " * { 123: {fieldIndex: 123, fieldName: {my_field_name: 0}, " - "ctor: proto.example.MyMessage} }\n" - " *\n" - " * fieldName contains the JsCompiler renamed field name property " - "so that it\n" - " * works in OPTIMIZED mode.\n" - " *\n" +} + +void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const { + if (IsExtendable(desc)) { + printer->Print( + "\n" + "/**\n" + " * The extensions registered with this message class. This is a " + "map of\n" + " * extension field number to fieldInfo object.\n" + " *\n" + " * For example:\n" + " * { 123: {fieldIndex: 123, fieldName: {my_field_name: 0}, " + "ctor: proto.example.MyMessage} }\n" + " *\n" + " * fieldName contains the JsCompiler renamed field name property " + "so that it\n" + " * works in OPTIMIZED mode.\n" + " *\n" " * @type {!Object<number, jspb.ExtensionFieldInfo>}\n" - " */\n" - "$class$.extensions = {};\n" - "\n", - "class", GetMessagePath(options, desc)); - - printer->Print( - "\n" - "/**\n" - " * The extensions registered with this message class. This is a " - "map of\n" - " * extension field number to fieldInfo object.\n" - " *\n" - " * For example:\n" - " * { 123: {fieldIndex: 123, fieldName: {my_field_name: 0}, " - "ctor: proto.example.MyMessage} }\n" - " *\n" - " * fieldName contains the JsCompiler renamed field name property " - "so that it\n" - " * works in OPTIMIZED mode.\n" - " *\n" + " */\n" + "$class$.extensions = {};\n" + "\n", + "class", GetMessagePath(options, desc)); + + printer->Print( + "\n" + "/**\n" + " * The extensions registered with this message class. This is a " + "map of\n" + " * extension field number to fieldInfo object.\n" + " *\n" + " * For example:\n" + " * { 123: {fieldIndex: 123, fieldName: {my_field_name: 0}, " + "ctor: proto.example.MyMessage} }\n" + " *\n" + " * fieldName contains the JsCompiler renamed field name property " + "so that it\n" + " * works in OPTIMIZED mode.\n" + " *\n" " * @type {!Object<number, jspb.ExtensionFieldBinaryInfo>}\n" - " */\n" - "$class$.extensionsBinary = {};\n" - "\n", - "class", GetMessagePath(options, desc)); - } -} - -void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const { - // TODO(cfallin): Handle lazy decoding when requested by field option and/or - // by default for 'bytes' fields and packed repeated fields. - - printer->Print( - "/**\n" - " * Deserializes binary data (in protobuf wire format).\n" - " * @param {jspb.ByteSource} bytes The bytes to deserialize.\n" - " * @return {!$class$}\n" - " */\n" - "$class$.deserializeBinary = function(bytes) {\n" - " var reader = new jspb.BinaryReader(bytes);\n" - " var msg = new $class$;\n" - " return $class$.deserializeBinaryFromReader(msg, reader);\n" - "};\n" - "\n" - "\n" - "/**\n" - " * Deserializes binary data (in protobuf wire format) from the\n" - " * given reader into the given message object.\n" - " * @param {!$class$} msg The message object to deserialize into.\n" - " * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n" - " * @return {!$class$}\n" - " */\n" - "$class$.deserializeBinaryFromReader = function(msg, reader) {\n" + " */\n" + "$class$.extensionsBinary = {};\n" + "\n", + "class", GetMessagePath(options, desc)); + } +} + +void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const { + // TODO(cfallin): Handle lazy decoding when requested by field option and/or + // by default for 'bytes' fields and packed repeated fields. + + printer->Print( + "/**\n" + " * Deserializes binary data (in protobuf wire format).\n" + " * @param {jspb.ByteSource} bytes The bytes to deserialize.\n" + " * @return {!$class$}\n" + " */\n" + "$class$.deserializeBinary = function(bytes) {\n" + " var reader = new jspb.BinaryReader(bytes);\n" + " var msg = new $class$;\n" + " return $class$.deserializeBinaryFromReader(msg, reader);\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Deserializes binary data (in protobuf wire format) from the\n" + " * given reader into the given message object.\n" + " * @param {!$class$} msg The message object to deserialize into.\n" + " * @param {!jspb.BinaryReader} reader The BinaryReader to use.\n" + " * @return {!$class$}\n" + " */\n" + "$class$.deserializeBinaryFromReader = function(msg, reader) {\n" " while (reader.nextField()) {\n", "class", GetMessagePath(options, desc)); printer->Print( - " if (reader.isEndGroup()) {\n" - " break;\n" - " }\n" - " var field = reader.getFieldNumber();\n" + " if (reader.isEndGroup()) {\n" + " break;\n" + " }\n" + " var field = reader.getFieldNumber();\n" " switch (field) {\n"); - - for (int i = 0; i < desc->field_count(); i++) { - if (!IgnoreField(desc->field(i))) { - GenerateClassDeserializeBinaryField(options, printer, desc->field(i)); - } - } - + + for (int i = 0; i < desc->field_count(); i++) { + if (!IgnoreField(desc->field(i))) { + GenerateClassDeserializeBinaryField(options, printer, desc->field(i)); + } + } + printer->Print(" default:\n"); - if (IsExtendable(desc)) { - printer->Print( + if (IsExtendable(desc)) { + printer->Print( " jspb.Message.readBinaryExtension(msg, reader,\n" " $extobj$Binary,\n" - " $class$.prototype.getExtension,\n" - " $class$.prototype.setExtension);\n" + " $class$.prototype.getExtension,\n" + " $class$.prototype.setExtension);\n" " break;\n" " }\n", "extobj", JSExtensionsObjectName(options, desc->file(), desc), "class", GetMessagePath(options, desc)); - } else { - printer->Print( - " reader.skipField();\n" + } else { + printer->Print( + " reader.skipField();\n" " break;\n" " }\n"); - } - - printer->Print( - " }\n" - " return msg;\n" - "};\n" - "\n" - "\n"); -} - -void Generator::GenerateClassDeserializeBinaryField( + } + + printer->Print( + " }\n" + " return msg;\n" + "};\n" + "\n" + "\n"); +} + +void Generator::GenerateClassDeserializeBinaryField( const GeneratorOptions& options, io::Printer* printer, - const FieldDescriptor* field) const { + const FieldDescriptor* field) const { printer->Print(" case $num$:\n", "num", StrCat(field->number())); - + if (field->is_map()) { - const FieldDescriptor* key_field = MapFieldKey(field); - const FieldDescriptor* value_field = MapFieldValue(field); - printer->Print( - " var value = msg.get$name$();\n" - " reader.readMessage(value, function(message, reader) {\n", - "name", JSGetterName(options, field)); - + const FieldDescriptor* key_field = MapFieldKey(field); + const FieldDescriptor* value_field = MapFieldValue(field); + printer->Print( + " var value = msg.get$name$();\n" + " reader.readMessage(value, function(message, reader) {\n", + "name", JSGetterName(options, field)); + printer->Print( " jspb.Map.deserializeBinary(message, reader, " "$keyReaderFn$, $valueReaderFn$", "keyReaderFn", JSBinaryReaderMethodName(options, key_field), "valueReaderFn", JSBinaryReaderMethodName(options, value_field)); - - if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { - printer->Print(", $messageType$.deserializeBinaryFromReader", + + if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { + printer->Print(", $messageType$.deserializeBinaryFromReader", "messageType", GetMessagePath(options, value_field->message_type())); } else { printer->Print(", null"); - } + } printer->Print(", $defaultKey$", "defaultKey", JSFieldDefault(key_field)); if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { printer->Print(", new $messageType$()", "messageType", @@ -3126,14 +3126,14 @@ void Generator::GenerateClassDeserializeBinaryField( printer->Print(", $defaultValue$", "defaultValue", JSFieldDefault(value_field)); } - printer->Print(");\n"); - printer->Print(" });\n"); - } else { - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - printer->Print( - " var value = new $fieldclass$;\n" - " reader.read$msgOrGroup$($grpfield$value," - "$fieldclass$.deserializeBinaryFromReader);\n", + printer->Print(");\n"); + printer->Print(" });\n"); + } else { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + printer->Print( + " var value = new $fieldclass$;\n" + " reader.read$msgOrGroup$($grpfield$value," + "$fieldclass$.deserializeBinaryFromReader);\n", "fieldclass", SubmessageTypeRef(options, field), "msgOrGroup", (field->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message", "grpfield", @@ -3149,19 +3149,19 @@ void Generator::GenerateClassDeserializeBinaryField( JSFieldTypeAnnotation(options, field, false, true, /* singular_if_not_packed */ false, BYTES_U8), "reader", JSBinaryReaderMethodType(field)); - } else { - printer->Print( - " var value = /** @type {$fieldtype$} */ " - "(reader.read$reader$());\n", + } else { + printer->Print( + " var value = /** @type {$fieldtype$} */ " + "(reader.read$reader$());\n", "fieldtype", JSFieldTypeAnnotation(options, field, false, true, /* singular_if_not_packed */ true, BYTES_U8), - "reader", - JSBinaryReadWriteMethodName(field, /* is_writer = */ false)); - } - + "reader", + JSBinaryReadWriteMethodName(field, /* is_writer = */ false)); + } + if (field->is_packable()) { - printer->Print( + printer->Print( " for (var i = 0; i < values.length; i++) {\n" " msg.add$name$(values[i]);\n" " }\n", @@ -3169,195 +3169,195 @@ void Generator::GenerateClassDeserializeBinaryField( JSGetterName(options, field, BYTES_DEFAULT, /* drop_list = */ true)); } else if (field->is_repeated()) { printer->Print( - " msg.add$name$(value);\n", "name", - JSGetterName(options, field, BYTES_DEFAULT, /* drop_list = */ true)); - } else { - // Singular fields, and packed repeated fields, receive a |value| either - // as the field's value or as the array of all the field's values; set - // this as the field's value directly. + " msg.add$name$(value);\n", "name", + JSGetterName(options, field, BYTES_DEFAULT, /* drop_list = */ true)); + } else { + // Singular fields, and packed repeated fields, receive a |value| either + // as the field's value or as the array of all the field's values; set + // this as the field's value directly. printer->Print(" msg.set$name$(value);\n", "name", JSGetterName(options, field)); - } - } - - printer->Print(" break;\n"); -} - -void Generator::GenerateClassSerializeBinary(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const { - printer->Print( - "/**\n" - " * Serializes the message to binary data (in protobuf wire format).\n" - " * @return {!Uint8Array}\n" - " */\n" - "$class$.prototype.serializeBinary = function() {\n" - " var writer = new jspb.BinaryWriter();\n" - " $class$.serializeBinaryToWriter(this, writer);\n" - " return writer.getResultBuffer();\n" - "};\n" - "\n" - "\n" - "/**\n" - " * Serializes the given message to binary data (in protobuf wire\n" - " * format), writing to the given BinaryWriter.\n" - " * @param {!$class$} message\n" - " * @param {!jspb.BinaryWriter} writer\n" - " * @suppress {unusedLocalVariables} f is only used for nested messages\n" - " */\n" - "$class$.serializeBinaryToWriter = function(message, " - "writer) {\n" - " var f = undefined;\n", - "class", GetMessagePath(options, desc)); - - for (int i = 0; i < desc->field_count(); i++) { - if (!IgnoreField(desc->field(i))) { - GenerateClassSerializeBinaryField(options, printer, desc->field(i)); - } - } - - if (IsExtendable(desc)) { - printer->Print( - " jspb.Message.serializeBinaryExtensions(message, writer,\n" - " $extobj$Binary, $class$.prototype.getExtension);\n", + } + } + + printer->Print(" break;\n"); +} + +void Generator::GenerateClassSerializeBinary(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const { + printer->Print( + "/**\n" + " * Serializes the message to binary data (in protobuf wire format).\n" + " * @return {!Uint8Array}\n" + " */\n" + "$class$.prototype.serializeBinary = function() {\n" + " var writer = new jspb.BinaryWriter();\n" + " $class$.serializeBinaryToWriter(this, writer);\n" + " return writer.getResultBuffer();\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Serializes the given message to binary data (in protobuf wire\n" + " * format), writing to the given BinaryWriter.\n" + " * @param {!$class$} message\n" + " * @param {!jspb.BinaryWriter} writer\n" + " * @suppress {unusedLocalVariables} f is only used for nested messages\n" + " */\n" + "$class$.serializeBinaryToWriter = function(message, " + "writer) {\n" + " var f = undefined;\n", + "class", GetMessagePath(options, desc)); + + for (int i = 0; i < desc->field_count(); i++) { + if (!IgnoreField(desc->field(i))) { + GenerateClassSerializeBinaryField(options, printer, desc->field(i)); + } + } + + if (IsExtendable(desc)) { + printer->Print( + " jspb.Message.serializeBinaryExtensions(message, writer,\n" + " $extobj$Binary, $class$.prototype.getExtension);\n", "extobj", JSExtensionsObjectName(options, desc->file(), desc), "class", GetMessagePath(options, desc)); - } - - printer->Print( - "};\n" - "\n" - "\n"); -} - -void Generator::GenerateClassSerializeBinaryField( + } + + printer->Print( + "};\n" + "\n" + "\n"); +} + +void Generator::GenerateClassSerializeBinaryField( const GeneratorOptions& options, io::Printer* printer, - const FieldDescriptor* field) const { - if (HasFieldPresence(options, field) && - field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + const FieldDescriptor* field) const { + if (HasFieldPresence(options, field) && + field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { TProtoStringType typed_annotation = JSFieldTypeAnnotation(options, field, /* is_setter_argument = */ false, /* force_present = */ false, /* singular_if_not_packed = */ false, /* bytes_mode = */ BYTES_DEFAULT); - printer->Print( - " f = /** @type {$type$} */ " - "(jspb.Message.getField(message, $index$));\n", + printer->Print( + " f = /** @type {$type$} */ " + "(jspb.Message.getField(message, $index$));\n", "index", JSFieldIndex(field), "type", typed_annotation); - } else { - printer->Print( + } else { + printer->Print( " f = message.get$name$($nolazy$);\n", "name", JSGetterName(options, field, BYTES_U8), - // No lazy creation for maps containers -- fastpath the empty case. + // No lazy creation for maps containers -- fastpath the empty case. "nolazy", field->is_map() ? "true" : ""); - } - - // Print an `if (condition)` statement that evaluates to true if the field - // goes on the wire. + } + + // Print an `if (condition)` statement that evaluates to true if the field + // goes on the wire. if (field->is_map()) { printer->Print(" if (f && f.getLength() > 0) {\n"); - } else if (field->is_repeated()) { + } else if (field->is_repeated()) { printer->Print(" if (f.length > 0) {\n"); - } else { - if (HasFieldPresence(options, field)) { + } else { + if (HasFieldPresence(options, field)) { printer->Print(" if (f != null) {\n"); - } else { - // No field presence: serialize onto the wire only if value is - // non-default. Defaults are documented here: - // https://goto.google.com/lhdfm - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_INT32: - case FieldDescriptor::CPPTYPE_INT64: - case FieldDescriptor::CPPTYPE_UINT32: - case FieldDescriptor::CPPTYPE_UINT64: { - if (IsIntegralFieldWithStringJSType(field)) { - // We can use `parseInt` here even though it will not be precise for - // 64-bit quantities because we are only testing for zero/nonzero, - // and JS numbers (64-bit floating point values, i.e., doubles) are - // integer-precise in the range that includes zero. - printer->Print(" if (parseInt(f, 10) !== 0) {\n"); - } else { - printer->Print(" if (f !== 0) {\n"); - } - break; - } - - case FieldDescriptor::CPPTYPE_ENUM: - case FieldDescriptor::CPPTYPE_FLOAT: - case FieldDescriptor::CPPTYPE_DOUBLE: + } else { + // No field presence: serialize onto the wire only if value is + // non-default. Defaults are documented here: + // https://goto.google.com/lhdfm + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_UINT64: { + if (IsIntegralFieldWithStringJSType(field)) { + // We can use `parseInt` here even though it will not be precise for + // 64-bit quantities because we are only testing for zero/nonzero, + // and JS numbers (64-bit floating point values, i.e., doubles) are + // integer-precise in the range that includes zero. + printer->Print(" if (parseInt(f, 10) !== 0) {\n"); + } else { + printer->Print(" if (f !== 0) {\n"); + } + break; + } + + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_DOUBLE: printer->Print(" if (f !== 0.0) {\n"); - break; - case FieldDescriptor::CPPTYPE_BOOL: + break; + case FieldDescriptor::CPPTYPE_BOOL: printer->Print(" if (f) {\n"); - break; - case FieldDescriptor::CPPTYPE_STRING: + break; + case FieldDescriptor::CPPTYPE_STRING: printer->Print(" if (f.length > 0) {\n"); - break; - default: - assert(false); - break; - } - } - } - - // Write the field on the wire. + break; + default: + assert(false); + break; + } + } + } + + // Write the field on the wire. if (field->is_map()) { - const FieldDescriptor* key_field = MapFieldKey(field); - const FieldDescriptor* value_field = MapFieldValue(field); - printer->Print( - " f.serializeBinary($index$, writer, " + const FieldDescriptor* key_field = MapFieldKey(field); + const FieldDescriptor* value_field = MapFieldValue(field); + printer->Print( + " f.serializeBinary($index$, writer, " "$keyWriterFn$, $valueWriterFn$", "index", StrCat(field->number()), "keyWriterFn", JSBinaryWriterMethodName(options, key_field), "valueWriterFn", JSBinaryWriterMethodName(options, value_field)); - - if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { + + if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { printer->Print(", $messageType$.serializeBinaryToWriter", "messageType", GetMessagePath(options, value_field->message_type())); - } - - printer->Print(");\n"); - } else { - printer->Print( - " writer.write$method$(\n" - " $index$,\n" - " f", - "method", JSBinaryReadWriteMethodName(field, /* is_writer = */ true), + } + + printer->Print(");\n"); + } else { + printer->Print( + " writer.write$method$(\n" + " $index$,\n" + " f", + "method", JSBinaryReadWriteMethodName(field, /* is_writer = */ true), "index", StrCat(field->number())); - - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && !field->is_map()) { - printer->Print( - ",\n" - " $submsg$.serializeBinaryToWriter\n", + printer->Print( + ",\n" + " $submsg$.serializeBinaryToWriter\n", "submsg", SubmessageTypeRef(options, field)); - } else { - printer->Print("\n"); - } - + } else { + printer->Print("\n"); + } + printer->Print(" );\n"); - } - - // Close the `if`. + } + + // Close the `if`. printer->Print(" }\n"); -} - -void Generator::GenerateEnum(const GeneratorOptions& options, - io::Printer* printer, - const EnumDescriptor* enumdesc) const { - printer->Print( - "/**\n" - " * @enum {number}\n" - " */\n" +} + +void Generator::GenerateEnum(const GeneratorOptions& options, + io::Printer* printer, + const EnumDescriptor* enumdesc) const { + printer->Print( + "/**\n" + " * @enum {number}\n" + " */\n" "$enumprefix$$name$ = {\n", "enumprefix", GetEnumPathPrefix(options, enumdesc), "name", enumdesc->name()); printer->Annotate("name", enumdesc); - + std::set<TProtoStringType> used_name; std::vector<int> valid_index; - for (int i = 0; i < enumdesc->value_count(); i++) { + for (int i = 0; i < enumdesc->value_count(); i++) { if (enumdesc->options().allow_alias() && !used_name.insert(ToEnumCase(enumdesc->value(i)->name())).second) { continue; @@ -3365,35 +3365,35 @@ void Generator::GenerateEnum(const GeneratorOptions& options, valid_index.push_back(i); } for (auto i : valid_index) { - const EnumValueDescriptor* value = enumdesc->value(i); + const EnumValueDescriptor* value = enumdesc->value(i); printer->Print(" $name$: $value$$comma$\n", "name", ToEnumCase(value->name()), "value", StrCat(value->number()), "comma", (i == valid_index.back()) ? "" : ","); printer->Annotate("name", value); - } - - printer->Print( - "};\n" - "\n"); -} - -void Generator::GenerateExtension(const GeneratorOptions& options, - io::Printer* printer, - const FieldDescriptor* field) const { + } + + printer->Print( + "};\n" + "\n"); +} + +void Generator::GenerateExtension(const GeneratorOptions& options, + io::Printer* printer, + const FieldDescriptor* field) const { TProtoStringType extension_scope = - (field->extension_scope() - ? GetMessagePath(options, field->extension_scope()) + (field->extension_scope() + ? GetMessagePath(options, field->extension_scope()) : GetNamespace(options, field->file())); - + const TProtoStringType extension_object_name = JSObjectFieldName(options, field); - printer->Print( - "\n" - "/**\n" - " * A tuple of {field number, class constructor} for the extension\n" + printer->Print( + "\n" + "/**\n" + " * A tuple of {field number, class constructor} for the extension\n" " * field named `$nameInComment$`.\n" " * @type {!jspb.ExtensionFieldInfo<$extensionType$>}\n" - " */\n" - "$class$.$name$ = new jspb.ExtensionFieldInfo(\n", + " */\n" + "$class$.$name$ = new jspb.ExtensionFieldInfo(\n", "nameInComment", extension_object_name, "name", extension_object_name, "class", extension_scope, "extensionType", JSFieldTypeAnnotation(options, field, @@ -3401,14 +3401,14 @@ void Generator::GenerateExtension(const GeneratorOptions& options, /* force_present = */ true, /* singular_if_not_packed = */ false)); printer->Annotate("name", field); - printer->Print( - " $index$,\n" - " {$name$: 0},\n" - " $ctor$,\n" - " /** @type {?function((boolean|undefined),!jspb.Message=): " - "!Object} */ (\n" - " $toObject$),\n" - " $repeated$);\n", + printer->Print( + " $index$,\n" + " {$name$: 0},\n" + " $ctor$,\n" + " /** @type {?function((boolean|undefined),!jspb.Message=): " + "!Object} */ (\n" + " $toObject$),\n" + " $repeated$);\n", "index", StrCat(field->number()), "name", extension_object_name, "ctor", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ? SubmessageTypeRef(options, field) @@ -3417,185 +3417,185 @@ void Generator::GenerateExtension(const GeneratorOptions& options, (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ? (SubmessageTypeRef(options, field) + ".toObject") : TProtoStringType("null")), - "repeated", (field->is_repeated() ? "1" : "0")); - - printer->Print( - "\n" - "$extendName$Binary[$index$] = new jspb.ExtensionFieldBinaryInfo(\n" - " $class$.$name$,\n" - " $binaryReaderFn$,\n" - " $binaryWriterFn$,\n" - " $binaryMessageSerializeFn$,\n" - " $binaryMessageDeserializeFn$,\n", - "extendName", - JSExtensionsObjectName(options, field->file(), field->containing_type()), + "repeated", (field->is_repeated() ? "1" : "0")); + + printer->Print( + "\n" + "$extendName$Binary[$index$] = new jspb.ExtensionFieldBinaryInfo(\n" + " $class$.$name$,\n" + " $binaryReaderFn$,\n" + " $binaryWriterFn$,\n" + " $binaryMessageSerializeFn$,\n" + " $binaryMessageDeserializeFn$,\n", + "extendName", + JSExtensionsObjectName(options, field->file(), field->containing_type()), "index", StrCat(field->number()), "class", extension_scope, "name", extension_object_name, "binaryReaderFn", - JSBinaryReaderMethodName(options, field), "binaryWriterFn", - JSBinaryWriterMethodName(options, field), "binaryMessageSerializeFn", - (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) - ? (SubmessageTypeRef(options, field) + ".serializeBinaryToWriter") - : "undefined", - "binaryMessageDeserializeFn", - (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) - ? (SubmessageTypeRef(options, field) + ".deserializeBinaryFromReader") - : "undefined"); - - printer->Print(" $isPacked$);\n", "isPacked", - (field->is_packed() ? "true" : "false")); - - printer->Print( - "// This registers the extension field with the extended class, so that\n" - "// toObject() will function correctly.\n" - "$extendName$[$index$] = $class$.$name$;\n" - "\n", + JSBinaryReaderMethodName(options, field), "binaryWriterFn", + JSBinaryWriterMethodName(options, field), "binaryMessageSerializeFn", + (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) + ? (SubmessageTypeRef(options, field) + ".serializeBinaryToWriter") + : "undefined", + "binaryMessageDeserializeFn", + (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) + ? (SubmessageTypeRef(options, field) + ".deserializeBinaryFromReader") + : "undefined"); + + printer->Print(" $isPacked$);\n", "isPacked", + (field->is_packed() ? "true" : "false")); + + printer->Print( + "// This registers the extension field with the extended class, so that\n" + "// toObject() will function correctly.\n" + "$extendName$[$index$] = $class$.$name$;\n" + "\n", "extendName", JSExtensionsObjectName(options, field->file(), field->containing_type()), "index", StrCat(field->number()), "class", extension_scope, "name", extension_object_name); -} - -bool GeneratorOptions::ParseFromOptions( +} + +bool GeneratorOptions::ParseFromOptions( const std::vector<std::pair<TProtoStringType, TProtoStringType> >& options, TProtoStringType* error) { - for (int i = 0; i < options.size(); i++) { - if (options[i].first == "add_require_for_enums") { - if (options[i].second != "") { - *error = "Unexpected option value for add_require_for_enums"; - return false; - } - add_require_for_enums = true; - } else if (options[i].first == "binary") { - if (options[i].second != "") { - *error = "Unexpected option value for binary"; - return false; - } - binary = true; - } else if (options[i].first == "testonly") { - if (options[i].second != "") { - *error = "Unexpected option value for testonly"; - return false; - } - testonly = true; - } else if (options[i].first == "error_on_name_conflict") { - if (options[i].second != "") { - *error = "Unexpected option value for error_on_name_conflict"; - return false; - } - error_on_name_conflict = true; - } else if (options[i].first == "output_dir") { - output_dir = options[i].second; - } else if (options[i].first == "namespace_prefix") { - namespace_prefix = options[i].second; - } else if (options[i].first == "library") { - library = options[i].second; - } else if (options[i].first == "import_style") { - if (options[i].second == "closure") { - import_style = kImportClosure; - } else if (options[i].second == "commonjs") { - import_style = kImportCommonJs; + for (int i = 0; i < options.size(); i++) { + if (options[i].first == "add_require_for_enums") { + if (options[i].second != "") { + *error = "Unexpected option value for add_require_for_enums"; + return false; + } + add_require_for_enums = true; + } else if (options[i].first == "binary") { + if (options[i].second != "") { + *error = "Unexpected option value for binary"; + return false; + } + binary = true; + } else if (options[i].first == "testonly") { + if (options[i].second != "") { + *error = "Unexpected option value for testonly"; + return false; + } + testonly = true; + } else if (options[i].first == "error_on_name_conflict") { + if (options[i].second != "") { + *error = "Unexpected option value for error_on_name_conflict"; + return false; + } + error_on_name_conflict = true; + } else if (options[i].first == "output_dir") { + output_dir = options[i].second; + } else if (options[i].first == "namespace_prefix") { + namespace_prefix = options[i].second; + } else if (options[i].first == "library") { + library = options[i].second; + } else if (options[i].first == "import_style") { + if (options[i].second == "closure") { + import_style = kImportClosure; + } else if (options[i].second == "commonjs") { + import_style = kImportCommonJs; } else if (options[i].second == "commonjs_strict") { import_style = kImportCommonJsStrict; - } else if (options[i].second == "browser") { - import_style = kImportBrowser; - } else if (options[i].second == "es6") { - import_style = kImportEs6; - } else { - *error = "Unknown import style " + options[i].second + ", expected " + - "one of: closure, commonjs, browser, es6."; - } - } else if (options[i].first == "extension") { - extension = options[i].second; - } else if (options[i].first == "one_output_file_per_input_file") { - if (!options[i].second.empty()) { - *error = "Unexpected option value for one_output_file_per_input_file"; - return false; - } - one_output_file_per_input_file = true; + } else if (options[i].second == "browser") { + import_style = kImportBrowser; + } else if (options[i].second == "es6") { + import_style = kImportEs6; + } else { + *error = "Unknown import style " + options[i].second + ", expected " + + "one of: closure, commonjs, browser, es6."; + } + } else if (options[i].first == "extension") { + extension = options[i].second; + } else if (options[i].first == "one_output_file_per_input_file") { + if (!options[i].second.empty()) { + *error = "Unexpected option value for one_output_file_per_input_file"; + return false; + } + one_output_file_per_input_file = true; } else if (options[i].first == "annotate_code") { if (!options[i].second.empty()) { *error = "Unexpected option value for annotate_code"; return false; } annotate_code = true; - } else { - // Assume any other option is an output directory, as long as it is a bare - // `key` rather than a `key=value` option. - if (options[i].second != "") { - *error = "Unknown option: " + options[i].first; - return false; - } - output_dir = options[i].first; - } - } - - if (import_style != kImportClosure && - (add_require_for_enums || testonly || !library.empty() || - error_on_name_conflict || extension != ".js" || - one_output_file_per_input_file)) { - *error = - "The add_require_for_enums, testonly, library, error_on_name_conflict, " - "extension, and one_output_file_per_input_file options should only be " - "used for import_style=closure"; - return false; - } - - return true; -} - -GeneratorOptions::OutputMode GeneratorOptions::output_mode() const { - // We use one output file per input file if we are not using Closure or if - // this is explicitly requested. - if (import_style != kImportClosure || one_output_file_per_input_file) { - return kOneOutputFilePerInputFile; - } - - // If a library name is provided, we put everything in that one file. - if (!library.empty()) { - return kEverythingInOneFile; - } - + } else { + // Assume any other option is an output directory, as long as it is a bare + // `key` rather than a `key=value` option. + if (options[i].second != "") { + *error = "Unknown option: " + options[i].first; + return false; + } + output_dir = options[i].first; + } + } + + if (import_style != kImportClosure && + (add_require_for_enums || testonly || !library.empty() || + error_on_name_conflict || extension != ".js" || + one_output_file_per_input_file)) { + *error = + "The add_require_for_enums, testonly, library, error_on_name_conflict, " + "extension, and one_output_file_per_input_file options should only be " + "used for import_style=closure"; + return false; + } + + return true; +} + +GeneratorOptions::OutputMode GeneratorOptions::output_mode() const { + // We use one output file per input file if we are not using Closure or if + // this is explicitly requested. + if (import_style != kImportClosure || one_output_file_per_input_file) { + return kOneOutputFilePerInputFile; + } + + // If a library name is provided, we put everything in that one file. + if (!library.empty()) { + return kEverythingInOneFile; + } + // Otherwise, we create one output file per SCC. return kOneOutputFilePerSCC; -} - -void Generator::GenerateFilesInDepOrder( +} + +void Generator::GenerateFilesInDepOrder( const GeneratorOptions& options, io::Printer* printer, - const std::vector<const FileDescriptor*>& files) const { - // Build a std::set over all files so that the DFS can detect when it recurses - // into a dep not specified in the user's command line. - std::set<const FileDescriptor*> all_files(files.begin(), files.end()); - // Track the in-progress set of files that have been generated already. - std::set<const FileDescriptor*> generated; - for (int i = 0; i < files.size(); i++) { - GenerateFileAndDeps(options, printer, files[i], &all_files, &generated); - } -} - -void Generator::GenerateFileAndDeps( + const std::vector<const FileDescriptor*>& files) const { + // Build a std::set over all files so that the DFS can detect when it recurses + // into a dep not specified in the user's command line. + std::set<const FileDescriptor*> all_files(files.begin(), files.end()); + // Track the in-progress set of files that have been generated already. + std::set<const FileDescriptor*> generated; + for (int i = 0; i < files.size(); i++) { + GenerateFileAndDeps(options, printer, files[i], &all_files, &generated); + } +} + +void Generator::GenerateFileAndDeps( const GeneratorOptions& options, io::Printer* printer, const FileDescriptor* root, std::set<const FileDescriptor*>* all_files, - std::set<const FileDescriptor*>* generated) const { - // Skip if already generated. - if (generated->find(root) != generated->end()) { - return; - } - generated->insert(root); - - // Generate all dependencies before this file's content. - for (int i = 0; i < root->dependency_count(); i++) { - const FileDescriptor* dep = root->dependency(i); - GenerateFileAndDeps(options, printer, dep, all_files, generated); - } - - // Generate this file's content. Only generate if the file is part of the - // original set requested to be generated; i.e., don't take all transitive - // deps down to the roots. - if (all_files->find(root) != all_files->end()) { - GenerateClassesAndEnums(options, printer, root); - } -} - + std::set<const FileDescriptor*>* generated) const { + // Skip if already generated. + if (generated->find(root) != generated->end()) { + return; + } + generated->insert(root); + + // Generate all dependencies before this file's content. + for (int i = 0; i < root->dependency_count(); i++) { + const FileDescriptor* dep = root->dependency(i); + GenerateFileAndDeps(options, printer, dep, all_files, generated); + } + + // Generate this file's content. Only generate if the file is part of the + // original set requested to be generated; i.e., don't take all transitive + // deps down to the roots. + if (all_files->find(root) != all_files->end()) { + GenerateClassesAndEnums(options, printer, root); + } +} + bool Generator::GenerateFile(const FileDescriptor* file, const GeneratorOptions& options, GeneratorContext* context, @@ -3626,17 +3626,17 @@ bool Generator::GenerateFile(const FileDescriptor* file, return true; } -void Generator::GenerateFile(const GeneratorOptions& options, - io::Printer* printer, - const FileDescriptor* file) const { +void Generator::GenerateFile(const GeneratorOptions& options, + io::Printer* printer, + const FileDescriptor* file) const { GenerateHeader(options, file, printer); - - // Generate "require" statements. + + // Generate "require" statements. if ((options.import_style == GeneratorOptions::kImportCommonJs || options.import_style == GeneratorOptions::kImportCommonJsStrict)) { - printer->Print("var jspb = require('google-protobuf');\n"); - printer->Print("var goog = jspb;\n"); - + printer->Print("var jspb = require('google-protobuf');\n"); + printer->Print("var goog = jspb;\n"); + // Do not use global scope in strict mode if (options.import_style == GeneratorOptions::kImportCommonJsStrict) { printer->Print("var proto = {};\n\n"); @@ -3644,48 +3644,48 @@ void Generator::GenerateFile(const GeneratorOptions& options, printer->Print("var global = Function('return this')();\n\n"); } - for (int i = 0; i < file->dependency_count(); i++) { + for (int i = 0; i < file->dependency_count(); i++) { const TProtoStringType& name = file->dependency(i)->name(); - printer->Print( + printer->Print( "var $alias$ = require('$file$');\n" "goog.object.extend(proto, $alias$);\n", "alias", ModuleAlias(name), "file", - GetRootPath(file->name(), name) + GetJSFilename(options, name)); - } - } - + GetRootPath(file->name(), name) + GetJSFilename(options, name)); + } + } + std::set<TProtoStringType> provided; - std::set<const FieldDescriptor*> extensions; - for (int i = 0; i < file->extension_count(); i++) { - // We honor the jspb::ignore option here only when working with - // Closure-style imports. Use of this option is discouraged and so we want - // to avoid adding new support for it. - if (options.import_style == GeneratorOptions::kImportClosure && - IgnoreField(file->extension(i))) { - continue; - } + std::set<const FieldDescriptor*> extensions; + for (int i = 0; i < file->extension_count(); i++) { + // We honor the jspb::ignore option here only when working with + // Closure-style imports. Use of this option is discouraged and so we want + // to avoid adding new support for it. + if (options.import_style == GeneratorOptions::kImportClosure && + IgnoreField(file->extension(i))) { + continue; + } provided.insert(GetNamespace(options, file) + "." + - JSObjectFieldName(options, file->extension(i))); - extensions.insert(file->extension(i)); - } - - FindProvidesForFile(options, printer, file, &provided); - GenerateProvides(options, printer, &provided); - std::vector<const FileDescriptor*> files; - files.push_back(file); - if (options.import_style == GeneratorOptions::kImportClosure) { - GenerateRequiresForLibrary(options, printer, files, &provided); - } - - GenerateClassesAndEnums(options, printer, file); - - // Generate code for top-level extensions. Extensions nested inside messages - // are emitted inside GenerateClassesAndEnums(). - for (std::set<const FieldDescriptor*>::const_iterator it = extensions.begin(); - it != extensions.end(); ++it) { - GenerateExtension(options, printer, *it); - } - + JSObjectFieldName(options, file->extension(i))); + extensions.insert(file->extension(i)); + } + + FindProvidesForFile(options, printer, file, &provided); + GenerateProvides(options, printer, &provided); + std::vector<const FileDescriptor*> files; + files.push_back(file); + if (options.import_style == GeneratorOptions::kImportClosure) { + GenerateRequiresForLibrary(options, printer, files, &provided); + } + + GenerateClassesAndEnums(options, printer, file); + + // Generate code for top-level extensions. Extensions nested inside messages + // are emitted inside GenerateClassesAndEnums(). + for (std::set<const FieldDescriptor*>::const_iterator it = extensions.begin(); + it != extensions.end(); ++it) { + GenerateExtension(options, printer, *it); + } + // if provided is empty, do not export anything if (options.import_style == GeneratorOptions::kImportCommonJs && !provided.empty()) { @@ -3694,75 +3694,75 @@ void Generator::GenerateFile(const GeneratorOptions& options, } else if (options.import_style == GeneratorOptions::kImportCommonJsStrict) { printer->Print("goog.object.extend(exports, proto);\n", "package", GetNamespace(options, file)); - } - - // Emit well-known type methods. - for (FileToc* toc = well_known_types_js; toc->name != NULL; toc++) { + } + + // Emit well-known type methods. + for (FileToc* toc = well_known_types_js; toc->name != NULL; toc++) { TProtoStringType name = TProtoStringType("google/protobuf/") + toc->name; - if (name == StripProto(file->name()) + ".js") { - printer->Print(toc->data); - } - } -} - -bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files, + if (name == StripProto(file->name()) + ".js") { + printer->Print(toc->data); + } + } +} + +bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files, const TProtoStringType& parameter, - GeneratorContext* context, + GeneratorContext* context, TProtoStringType* error) const { std::vector<std::pair<TProtoStringType, TProtoStringType> > option_pairs; - ParseGeneratorParameter(parameter, &option_pairs); - GeneratorOptions options; - if (!options.ParseFromOptions(option_pairs, error)) { - return false; - } - - if (options.output_mode() == GeneratorOptions::kEverythingInOneFile) { - // All output should go in a single file. + ParseGeneratorParameter(parameter, &option_pairs); + GeneratorOptions options; + if (!options.ParseFromOptions(option_pairs, error)) { + return false; + } + + if (options.output_mode() == GeneratorOptions::kEverythingInOneFile) { + // All output should go in a single file. TProtoStringType filename = options.output_dir + "/" + options.library + options.GetFileNameExtension(); std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename)); - GOOGLE_CHECK(output.get()); + GOOGLE_CHECK(output.get()); GeneratedCodeInfo annotations; io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector( &annotations); io::Printer printer( output.get(), '$', options.annotate_code ? &annotation_collector : nullptr); - - // Pull out all extensions -- we need these to generate all - // provides/requires. - std::vector<const FieldDescriptor*> extensions; - for (int i = 0; i < files.size(); i++) { - for (int j = 0; j < files[i]->extension_count(); j++) { - const FieldDescriptor* extension = files[i]->extension(j); - extensions.push_back(extension); - } - } - + + // Pull out all extensions -- we need these to generate all + // provides/requires. + std::vector<const FieldDescriptor*> extensions; + for (int i = 0; i < files.size(); i++) { + for (int j = 0; j < files[i]->extension_count(); j++) { + const FieldDescriptor* extension = files[i]->extension(j); + extensions.push_back(extension); + } + } + if (files.size() == 1) { GenerateHeader(options, files[0], &printer); } else { GenerateHeader(options, nullptr, &printer); } - + std::set<TProtoStringType> provided; - FindProvides(options, &printer, files, &provided); - FindProvidesForFields(options, &printer, extensions, &provided); - GenerateProvides(options, &printer, &provided); - GenerateTestOnly(options, &printer); - GenerateRequiresForLibrary(options, &printer, files, &provided); - - GenerateFilesInDepOrder(options, &printer, files); - - for (int i = 0; i < extensions.size(); i++) { - if (ShouldGenerateExtension(extensions[i])) { - GenerateExtension(options, &printer, extensions[i]); - } - } - - if (printer.failed()) { - return false; - } + FindProvides(options, &printer, files, &provided); + FindProvidesForFields(options, &printer, extensions, &provided); + GenerateProvides(options, &printer, &provided); + GenerateTestOnly(options, &printer); + GenerateRequiresForLibrary(options, &printer, files, &provided); + + GenerateFilesInDepOrder(options, &printer, files); + + for (int i = 0; i < extensions.size(); i++) { + if (ShouldGenerateExtension(extensions[i])) { + GenerateExtension(options, &printer, extensions[i]); + } + } + + if (printer.failed()) { + return false; + } if (options.annotate_code) { EmbedCodeAnnotations(annotations, &printer); } @@ -3772,12 +3772,12 @@ bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files, std::map<const void*, TProtoStringType> allowed_map; if (!GenerateJspbAllowedMap(options, files, &allowed_map, &analyzer, error)) { - return false; - } - + return false; + } + bool generated = false; - for (int i = 0; i < files.size(); i++) { - const FileDescriptor* file = files[i]; + for (int i = 0; i < files.size(); i++) { + const FileDescriptor* file = files[i]; // Force well known type to generate in a whole file. if (IsWellKnownTypeFile(file)) { if (!GenerateFile(file, options, context, true)) { @@ -3786,38 +3786,38 @@ bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files, generated = true; continue; } - for (int j = 0; j < file->message_type_count(); j++) { - const Descriptor* desc = file->message_type(j); + for (int j = 0; j < file->message_type_count(); j++) { + const Descriptor* desc = file->message_type(j); if (have_printed.count(desc) || allowed_map.count(analyzer.GetSCC(desc)) == 0) { - continue; - } - + continue; + } + generated = true; const SCC* scc = analyzer.GetSCC(desc); const TProtoStringType& filename = allowed_map[scc]; std::unique_ptr<io::ZeroCopyOutputStream> output( - context->Open(filename)); - GOOGLE_CHECK(output.get()); + context->Open(filename)); + GOOGLE_CHECK(output.get()); GeneratedCodeInfo annotations; io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector( &annotations); io::Printer printer( output.get(), '$', options.annotate_code ? &annotation_collector : nullptr); - + GenerateHeader(options, file, &printer); - + std::set<TProtoStringType> provided; for (auto one_desc : scc->descriptors) { if (one_desc->containing_type() == nullptr) { FindProvidesForMessage(options, &printer, one_desc, &provided); } } - GenerateProvides(options, &printer, &provided); - GenerateTestOnly(options, &printer); + GenerateProvides(options, &printer, &provided); + GenerateTestOnly(options, &printer); GenerateRequiresForSCC(options, &printer, scc, &provided); - + for (auto one_desc : scc->descriptors) { if (one_desc->containing_type() == nullptr) { GenerateClassConstructorAndDeclareExtensionFieldInfo( @@ -3829,114 +3829,114 @@ bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files, GenerateClass(options, &printer, one_desc); } } - + for (auto one_desc : scc->descriptors) { have_printed.insert(one_desc); } - if (printer.failed()) { - return false; - } + if (printer.failed()) { + return false; + } if (options.annotate_code) { EmbedCodeAnnotations(annotations, &printer); } - } - for (int j = 0; j < file->enum_type_count(); j++) { - const EnumDescriptor* enumdesc = file->enum_type(j); + } + for (int j = 0; j < file->enum_type_count(); j++) { + const EnumDescriptor* enumdesc = file->enum_type(j); if (allowed_map.count(enumdesc) == 0) { - continue; - } - + continue; + } + generated = true; const TProtoStringType& filename = allowed_map[enumdesc]; std::unique_ptr<io::ZeroCopyOutputStream> output( - context->Open(filename)); - GOOGLE_CHECK(output.get()); + context->Open(filename)); + GOOGLE_CHECK(output.get()); GeneratedCodeInfo annotations; io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector( &annotations); io::Printer printer( output.get(), '$', options.annotate_code ? &annotation_collector : nullptr); - + GenerateHeader(options, file, &printer); - + std::set<TProtoStringType> provided; - FindProvidesForEnum(options, &printer, enumdesc, &provided); - GenerateProvides(options, &printer, &provided); - GenerateTestOnly(options, &printer); - - GenerateEnum(options, &printer, enumdesc); - - if (printer.failed()) { - return false; - } + FindProvidesForEnum(options, &printer, enumdesc, &provided); + GenerateProvides(options, &printer, &provided); + GenerateTestOnly(options, &printer); + + GenerateEnum(options, &printer, enumdesc); + + if (printer.failed()) { + return false; + } if (options.annotate_code) { EmbedCodeAnnotations(annotations, &printer); } - } - // File-level extensions (message-level extensions are generated under - // the enclosing message). + } + // File-level extensions (message-level extensions are generated under + // the enclosing message). if (allowed_map.count(file) == 1) { generated = true; const TProtoStringType& filename = allowed_map[file]; - + std::unique_ptr<io::ZeroCopyOutputStream> output( - context->Open(filename)); - GOOGLE_CHECK(output.get()); + context->Open(filename)); + GOOGLE_CHECK(output.get()); GeneratedCodeInfo annotations; io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector( &annotations); io::Printer printer( output.get(), '$', options.annotate_code ? &annotation_collector : nullptr); - + GenerateHeader(options, file, &printer); - + std::set<TProtoStringType> provided; - std::vector<const FieldDescriptor*> fields; - - for (int j = 0; j < files[i]->extension_count(); j++) { - if (ShouldGenerateExtension(files[i]->extension(j))) { - fields.push_back(files[i]->extension(j)); - } - } - - FindProvidesForFields(options, &printer, fields, &provided); - GenerateProvides(options, &printer, &provided); - GenerateTestOnly(options, &printer); - GenerateRequiresForExtensions(options, &printer, fields, &provided); - - for (int j = 0; j < files[i]->extension_count(); j++) { - if (ShouldGenerateExtension(files[i]->extension(j))) { - GenerateExtension(options, &printer, files[i]->extension(j)); - } - } + std::vector<const FieldDescriptor*> fields; + + for (int j = 0; j < files[i]->extension_count(); j++) { + if (ShouldGenerateExtension(files[i]->extension(j))) { + fields.push_back(files[i]->extension(j)); + } + } + + FindProvidesForFields(options, &printer, fields, &provided); + GenerateProvides(options, &printer, &provided); + GenerateTestOnly(options, &printer); + GenerateRequiresForExtensions(options, &printer, fields, &provided); + + for (int j = 0; j < files[i]->extension_count(); j++) { + if (ShouldGenerateExtension(files[i]->extension(j))) { + GenerateExtension(options, &printer, files[i]->extension(j)); + } + } if (options.annotate_code) { EmbedCodeAnnotations(annotations, &printer); } - } - } + } + } if (!generated) { TProtoStringType filename = options.output_dir + "/" + "empty_no_content_void_file" + options.GetFileNameExtension(); std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename)); } - } else /* options.output_mode() == kOneOutputFilePerInputFile */ { - // Generate one output file per input (.proto) file. - - for (int i = 0; i < files.size(); i++) { + } else /* options.output_mode() == kOneOutputFilePerInputFile */ { + // Generate one output file per input (.proto) file. + + for (int i = 0; i < files.size(); i++) { const FileDescriptor* file = files[i]; if (!GenerateFile(file, options, context, false)) { - return false; - } - } - } - return true; -} - -} // namespace js -} // namespace compiler -} // namespace protobuf -} // namespace google + return false; + } + } + } + return true; +} + +} // namespace js +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/js/js_generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/js/js_generator.h index 4e6c89b019..f8d6be4eef 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/js/js_generator.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/js/js_generator.h @@ -1,223 +1,223 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Generates JavaScript code for a given .proto file. -// -#ifndef GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__ -#define GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__ - +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Generates JavaScript code for a given .proto file. +// +#ifndef GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__ +#define GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__ + #include <set> -#include <string> - +#include <string> + #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/common.h> #include <google/protobuf/compiler/scc.h> #include <google/protobuf/compiler/code_generator.h> - + #include <google/protobuf/port_def.inc> -namespace google { -namespace protobuf { - -class Descriptor; -class EnumDescriptor; -class FieldDescriptor; -class OneofDescriptor; -class FileDescriptor; - +namespace google { +namespace protobuf { + +class Descriptor; +class EnumDescriptor; +class FieldDescriptor; +class OneofDescriptor; +class FileDescriptor; + namespace io { class Printer; } - -namespace compiler { -namespace js { - -struct GeneratorOptions { - // Output path. + +namespace compiler { +namespace js { + +struct GeneratorOptions { + // Output path. TProtoStringType output_dir; - // Namespace prefix. + // Namespace prefix. TProtoStringType namespace_prefix; - // Enable binary-format support? - bool binary; - // What style of imports should be used. - enum ImportStyle { + // Enable binary-format support? + bool binary; + // What style of imports should be used. + enum ImportStyle { kImportClosure, // goog.require() kImportCommonJs, // require() kImportCommonJsStrict, // require() with no global export kImportBrowser, // no import statements kImportEs6, // import { member } from '' - } import_style; - - GeneratorOptions() - : output_dir("."), - namespace_prefix(""), - binary(false), - import_style(kImportClosure), - add_require_for_enums(false), - testonly(false), - library(""), - error_on_name_conflict(false), - extension(".js"), + } import_style; + + GeneratorOptions() + : output_dir("."), + namespace_prefix(""), + binary(false), + import_style(kImportClosure), + add_require_for_enums(false), + testonly(false), + library(""), + error_on_name_conflict(false), + extension(".js"), one_output_file_per_input_file(false), annotate_code(false) {} - - bool ParseFromOptions( + + bool ParseFromOptions( const std::vector<std::pair<TProtoStringType, TProtoStringType> >& options, TProtoStringType* error); - - // Returns the file name extension to use for generated code. + + // Returns the file name extension to use for generated code. TProtoStringType GetFileNameExtension() const { - return import_style == kImportClosure ? extension : "_pb.js"; - } - - enum OutputMode { - // Create an output file for each input .proto file. - kOneOutputFilePerInputFile, - // Create an output file for each type. + return import_style == kImportClosure ? extension : "_pb.js"; + } + + enum OutputMode { + // Create an output file for each input .proto file. + kOneOutputFilePerInputFile, + // Create an output file for each type. kOneOutputFilePerSCC, - // Put everything in a single file named by the library option. - kEverythingInOneFile, - }; - - // Indicates how to output the generated code based on the provided options. - OutputMode output_mode() const; - - // The remaining options are only relevant when we are using kImportClosure. - - // Add a `goog.requires()` call for each enum type used. If not set, a - // forward declaration with `goog.forwardDeclare` is produced instead. - bool add_require_for_enums; - // Set this as a test-only module via `goog.setTestOnly();`. - bool testonly; - // Create a library with name <name>_lib.js rather than a separate .js file - // per type? + // Put everything in a single file named by the library option. + kEverythingInOneFile, + }; + + // Indicates how to output the generated code based on the provided options. + OutputMode output_mode() const; + + // The remaining options are only relevant when we are using kImportClosure. + + // Add a `goog.requires()` call for each enum type used. If not set, a + // forward declaration with `goog.forwardDeclare` is produced instead. + bool add_require_for_enums; + // Set this as a test-only module via `goog.setTestOnly();`. + bool testonly; + // Create a library with name <name>_lib.js rather than a separate .js file + // per type? TProtoStringType library; - // Error if there are two types that would generate the same output file? - bool error_on_name_conflict; - // The extension to use for output file names. + // Error if there are two types that would generate the same output file? + bool error_on_name_conflict; + // The extension to use for output file names. TProtoStringType extension; - // Create a separate output file for each input file? - bool one_output_file_per_input_file; + // Create a separate output file for each input file? + bool one_output_file_per_input_file; // If true, we should append annotations as comments on the last line for // generated .js file. Annotations used by tools like https://kythe.io // to provide cross-references between .js and .proto files. Annotations // are encoded as base64 proto of GeneratedCodeInfo message (see // descriptor.proto). bool annotate_code; -}; - -// CodeGenerator implementation which generates a JavaScript source file and -// header. If you create your own protocol compiler binary and you want it to -// support JavaScript output, you can do so by registering an instance of this -// CodeGenerator with the CommandLineInterface in your main() function. +}; + +// CodeGenerator implementation which generates a JavaScript source file and +// header. If you create your own protocol compiler binary and you want it to +// support JavaScript output, you can do so by registering an instance of this +// CodeGenerator with the CommandLineInterface in your main() function. class PROTOC_EXPORT Generator : public CodeGenerator { - public: - Generator() {} - virtual ~Generator() {} - + public: + Generator() {} + virtual ~Generator() {} + bool Generate(const FileDescriptor* file, const TProtoStringType& parameter, GeneratorContext* context, TProtoStringType* error) const override { - *error = "Unimplemented Generate() method. Call GenerateAll() instead."; - return false; - } - + *error = "Unimplemented Generate() method. Call GenerateAll() instead."; + return false; + } + bool HasGenerateAll() const override { return true; } - + bool GenerateAll(const std::vector<const FileDescriptor*>& files, const TProtoStringType& parameter, GeneratorContext* context, TProtoStringType* error) const override; - + uint64_t GetSupportedFeatures() const override { return FEATURE_PROTO3_OPTIONAL; } - private: - void GenerateHeader(const GeneratorOptions& options, + private: + void GenerateHeader(const GeneratorOptions& options, const FileDescriptor* file, io::Printer* printer) const; - - // Generate goog.provides() calls. + + // Generate goog.provides() calls. void FindProvides(const GeneratorOptions& options, io::Printer* printer, - const std::vector<const FileDescriptor*>& file, + const std::vector<const FileDescriptor*>& file, std::set<TProtoStringType>* provided) const; - void FindProvidesForFile(const GeneratorOptions& options, + void FindProvidesForFile(const GeneratorOptions& options, io::Printer* printer, const FileDescriptor* file, std::set<TProtoStringType>* provided) const; - void FindProvidesForMessage(const GeneratorOptions& options, + void FindProvidesForMessage(const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc, std::set<TProtoStringType>* provided) const; - void FindProvidesForEnum(const GeneratorOptions& options, + void FindProvidesForEnum(const GeneratorOptions& options, io::Printer* printer, const EnumDescriptor* enumdesc, std::set<TProtoStringType>* provided) const; - // For extension fields at file scope. - void FindProvidesForFields(const GeneratorOptions& options, - io::Printer* printer, - const std::vector<const FieldDescriptor*>& fields, + // For extension fields at file scope. + void FindProvidesForFields(const GeneratorOptions& options, + io::Printer* printer, + const std::vector<const FieldDescriptor*>& fields, std::set<TProtoStringType>* provided) const; - // Print the goog.provides() found by the methods above. + // Print the goog.provides() found by the methods above. void GenerateProvides(const GeneratorOptions& options, io::Printer* printer, std::set<TProtoStringType>* provided) const; - - // Generate goog.setTestOnly() if indicated. - void GenerateTestOnly(const GeneratorOptions& options, - io::Printer* printer) const; - - // Generate goog.requires() calls. - void GenerateRequiresForLibrary( - const GeneratorOptions& options, io::Printer* printer, - const std::vector<const FileDescriptor*>& files, + + // Generate goog.setTestOnly() if indicated. + void GenerateTestOnly(const GeneratorOptions& options, + io::Printer* printer) const; + + // Generate goog.requires() calls. + void GenerateRequiresForLibrary( + const GeneratorOptions& options, io::Printer* printer, + const std::vector<const FileDescriptor*>& files, std::set<TProtoStringType>* provided) const; void GenerateRequiresForSCC(const GeneratorOptions& options, io::Printer* printer, const SCC* scc, std::set<TProtoStringType>* provided) const; - // For extension fields at file scope. - void GenerateRequiresForExtensions( - const GeneratorOptions& options, io::Printer* printer, - const std::vector<const FieldDescriptor*>& fields, + // For extension fields at file scope. + void GenerateRequiresForExtensions( + const GeneratorOptions& options, io::Printer* printer, + const std::vector<const FieldDescriptor*>& fields, std::set<TProtoStringType>* provided) const; - void GenerateRequiresImpl(const GeneratorOptions& options, + void GenerateRequiresImpl(const GeneratorOptions& options, io::Printer* printer, std::set<TProtoStringType>* required, std::set<TProtoStringType>* forwards, std::set<TProtoStringType>* provided, bool require_jspb, - bool require_extension, bool require_map) const; - void FindRequiresForMessage(const GeneratorOptions& options, - const Descriptor* desc, + bool require_extension, bool require_map) const; + void FindRequiresForMessage(const GeneratorOptions& options, + const Descriptor* desc, std::set<TProtoStringType>* required, std::set<TProtoStringType>* forwards, - bool* have_message) const; - void FindRequiresForField(const GeneratorOptions& options, - const FieldDescriptor* field, + bool* have_message) const; + void FindRequiresForField(const GeneratorOptions& options, + const FieldDescriptor* field, std::set<TProtoStringType>* required, std::set<TProtoStringType>* forwards) const; - void FindRequiresForExtension(const GeneratorOptions& options, - const FieldDescriptor* field, + void FindRequiresForExtension(const GeneratorOptions& options, + const FieldDescriptor* field, std::set<TProtoStringType>* required, std::set<TProtoStringType>* forwards) const; // Generate all things in a proto file into one file. @@ -226,114 +226,114 @@ class PROTOC_EXPORT Generator : public CodeGenerator { bool GenerateFile(const FileDescriptor* file, const GeneratorOptions& options, GeneratorContext* context, bool use_short_name) const; void GenerateFile(const GeneratorOptions& options, io::Printer* printer, - const FileDescriptor* file) const; - - // Generate definitions for all message classes and enums in all files, - // processing the files in dependence order. - void GenerateFilesInDepOrder( - const GeneratorOptions& options, io::Printer* printer, - const std::vector<const FileDescriptor*>& file) const; - // Helper for above. - void GenerateFileAndDeps(const GeneratorOptions& options, + const FileDescriptor* file) const; + + // Generate definitions for all message classes and enums in all files, + // processing the files in dependence order. + void GenerateFilesInDepOrder( + const GeneratorOptions& options, io::Printer* printer, + const std::vector<const FileDescriptor*>& file) const; + // Helper for above. + void GenerateFileAndDeps(const GeneratorOptions& options, io::Printer* printer, const FileDescriptor* root, - std::set<const FileDescriptor*>* all_files, - std::set<const FileDescriptor*>* generated) const; - - // Generate definitions for all message classes and enums. - void GenerateClassesAndEnums(const GeneratorOptions& options, - io::Printer* printer, - const FileDescriptor* file) const; - - void GenerateFieldValueExpression(io::Printer* printer, - const char* obj_reference, - const FieldDescriptor* field, - bool use_default) const; - - // Generate definition for one class. + std::set<const FileDescriptor*>* all_files, + std::set<const FileDescriptor*>* generated) const; + + // Generate definitions for all message classes and enums. + void GenerateClassesAndEnums(const GeneratorOptions& options, + io::Printer* printer, + const FileDescriptor* file) const; + + void GenerateFieldValueExpression(io::Printer* printer, + const char* obj_reference, + const FieldDescriptor* field, + bool use_default) const; + + // Generate definition for one class. void GenerateClass(const GeneratorOptions& options, io::Printer* printer, - const Descriptor* desc) const; - void GenerateClassConstructor(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const; - void GenerateClassFieldInfo(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const; + const Descriptor* desc) const; + void GenerateClassConstructor(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const; + void GenerateClassFieldInfo(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const; void GenerateClassConstructorAndDeclareExtensionFieldInfo( const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc) const; void GenerateClassXid(const GeneratorOptions& options, io::Printer* printer, - const Descriptor* desc) const; - void GenerateOneofCaseDefinition(const GeneratorOptions& options, - io::Printer* printer, - const OneofDescriptor* oneof) const; + const Descriptor* desc) const; + void GenerateOneofCaseDefinition(const GeneratorOptions& options, + io::Printer* printer, + const OneofDescriptor* oneof) const; void GenerateObjectTypedef(const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc) const; - void GenerateClassToObject(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const; - void GenerateClassFieldToObject(const GeneratorOptions& options, - io::Printer* printer, - const FieldDescriptor* field) const; - void GenerateClassFromObject(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const; - void GenerateClassFieldFromObject(const GeneratorOptions& options, - io::Printer* printer, - const FieldDescriptor* field) const; - void GenerateClassRegistration(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const; - void GenerateClassFields(const GeneratorOptions& options, + void GenerateClassToObject(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const; + void GenerateClassFieldToObject(const GeneratorOptions& options, + io::Printer* printer, + const FieldDescriptor* field) const; + void GenerateClassFromObject(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const; + void GenerateClassFieldFromObject(const GeneratorOptions& options, + io::Printer* printer, + const FieldDescriptor* field) const; + void GenerateClassRegistration(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const; + void GenerateClassFields(const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc) const; void GenerateClassField(const GeneratorOptions& options, io::Printer* printer, - const FieldDescriptor* desc) const; - void GenerateClassExtensionFieldInfo(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const; - void GenerateClassDeserialize(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const; - void GenerateClassDeserializeBinary(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const; - void GenerateClassDeserializeBinaryField(const GeneratorOptions& options, - io::Printer* printer, - const FieldDescriptor* field) const; - void GenerateClassSerializeBinary(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const; - void GenerateClassSerializeBinaryField(const GeneratorOptions& options, - io::Printer* printer, - const FieldDescriptor* field) const; - - // Generate definition for one enum. + const FieldDescriptor* desc) const; + void GenerateClassExtensionFieldInfo(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const; + void GenerateClassDeserialize(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const; + void GenerateClassDeserializeBinary(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const; + void GenerateClassDeserializeBinaryField(const GeneratorOptions& options, + io::Printer* printer, + const FieldDescriptor* field) const; + void GenerateClassSerializeBinary(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const; + void GenerateClassSerializeBinaryField(const GeneratorOptions& options, + io::Printer* printer, + const FieldDescriptor* field) const; + + // Generate definition for one enum. void GenerateEnum(const GeneratorOptions& options, io::Printer* printer, - const EnumDescriptor* enumdesc) const; - - // Generate an extension definition. + const EnumDescriptor* enumdesc) const; + + // Generate an extension definition. void GenerateExtension(const GeneratorOptions& options, io::Printer* printer, - const FieldDescriptor* field) const; - - // Generate addFoo() method for repeated primitive fields. - void GenerateRepeatedPrimitiveHelperMethods(const GeneratorOptions& options, - io::Printer* printer, - const FieldDescriptor* field, - bool untyped) const; - - // Generate addFoo() method for repeated message fields. - void GenerateRepeatedMessageHelperMethods(const GeneratorOptions& options, - io::Printer* printer, - const FieldDescriptor* field) const; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator); -}; - -} // namespace js -} // namespace compiler -} // namespace protobuf + const FieldDescriptor* field) const; + + // Generate addFoo() method for repeated primitive fields. + void GenerateRepeatedPrimitiveHelperMethods(const GeneratorOptions& options, + io::Printer* printer, + const FieldDescriptor* field, + bool untyped) const; + + // Generate addFoo() method for repeated message fields. + void GenerateRepeatedMessageHelperMethods(const GeneratorOptions& options, + io::Printer* printer, + const FieldDescriptor* field) const; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator); +}; + +} // namespace js +} // namespace compiler +} // namespace protobuf } // namespace google - + #include <google/protobuf/port_undef.inc> -#endif // GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__ +#endif // GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/js/well_known_types_embed.cc b/contrib/libs/protoc/src/google/protobuf/compiler/js/well_known_types_embed.cc index 5cb73657e7..a8aebb349d 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/js/well_known_types_embed.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/js/well_known_types_embed.cc @@ -30,7 +30,7 @@ #include <google/protobuf/compiler/js/well_known_types_embed.h> -struct FileToc well_known_types_js[] = { +struct FileToc well_known_types_js[] = { {"any.js", "/* This code will be inserted into generated code for\n" " * google/protobuf/any.proto. */\n" @@ -267,4 +267,4 @@ struct FileToc well_known_types_js[] = { " return ret;\n" "};\n"}, {NULL, NULL} // Terminate the list. -}; +}; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/js/well_known_types_embed.h b/contrib/libs/protoc/src/google/protobuf/compiler/js/well_known_types_embed.h index 174c665e45..c6bc6f17ae 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/js/well_known_types_embed.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/js/well_known_types_embed.h @@ -1,43 +1,43 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JS_WELL_KNOWN_TYPES_EMBED_H__ -#define GOOGLE_PROTOBUF_COMPILER_JS_WELL_KNOWN_TYPES_EMBED_H__ - -#include <stddef.h> - -struct FileToc { - const char* name; - const char* data; -}; - -extern struct FileToc well_known_types_js[]; - -#endif // GOOGLE_PROTOBUF_COMPILER_JS_WELL_KNOWN_TYPES_EMBED_H__ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JS_WELL_KNOWN_TYPES_EMBED_H__ +#define GOOGLE_PROTOBUF_COMPILER_JS_WELL_KNOWN_TYPES_EMBED_H__ + +#include <stddef.h> + +struct FileToc { + const char* name; + const char* data; +}; + +extern struct FileToc well_known_types_js[]; + +#endif // GOOGLE_PROTOBUF_COMPILER_JS_WELL_KNOWN_TYPES_EMBED_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/main.cc b/contrib/libs/protoc/src/google/protobuf/compiler/main.cc index 10de997f0c..30b0c0ceaa 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/main.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/main.cc @@ -101,11 +101,11 @@ int ProtobufMain(int argc, char* argv[]) { perlxs::PerlXSGenerator perlxs_generator; cli.RegisterGenerator("--perlxs_out", &perlxs_generator, "Generate Perl/XS source files."); - - // JavaScript + + // JavaScript js::Generator js_generator; cli.RegisterGenerator("--js_out", "--js_opt", &js_generator, - "Generate JavaScript source."); + "Generate JavaScript source."); return cli.Run(argc, argv); } |