aboutsummaryrefslogtreecommitdiff
path: root/src/google/protobuf/compiler/js/js_generator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/compiler/js/js_generator.cc')
-rwxr-xr-xsrc/google/protobuf/compiler/js/js_generator.cc510
1 files changed, 313 insertions, 197 deletions
diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc
index 727ed090..d8282e40 100755
--- a/src/google/protobuf/compiler/js/js_generator.cc
+++ b/src/google/protobuf/compiler/js/js_generator.cc
@@ -35,9 +35,6 @@
#include <limits>
#include <map>
#include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
#include <string>
#include <utility>
#include <vector>
@@ -52,6 +49,7 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/stubs/strutil.h>
+
namespace google {
namespace protobuf {
namespace compiler {
@@ -143,12 +141,16 @@ bool IsReserved(const string& ident) {
return false;
}
+bool StrEndsWith(StringPiece sp, StringPiece x) {
+ return sp.size() >= x.size() && sp.substr(sp.size() - x.size()) == x;
+}
+
// Returns a copy of |filename| with any trailing ".protodevel" or ".proto
// suffix stripped.
// TODO(haberman): Unify with copy in compiler/cpp/internal/helpers.cc.
string StripProto(const string& filename) {
- const char* suffix = HasSuffixString(filename, ".protodevel")
- ? ".protodevel" : ".proto";
+ const char* suffix =
+ StrEndsWith(filename, ".protodevel") ? ".protodevel" : ".proto";
return StripSuffixString(filename, suffix);
}
@@ -191,15 +193,16 @@ string ModuleAlias(const string& filename) {
// 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.
string basename = StripProto(filename);
- StripString(&basename, "-", '$');
- StripString(&basename, "/", '_');
+ ReplaceCharacters(&basename, "-", '$');
+ ReplaceCharacters(&basename, "/", '_');
+ ReplaceCharacters(&basename, ".", '_');
return basename + "_pb";
}
// Returns the fully normalized JavaScript path for the given
// file descriptor's package.
-string GetPath(const GeneratorOptions& options,
- const FileDescriptor* file) {
+string GetFilePath(const GeneratorOptions& options,
+ const FileDescriptor* file) {
if (!options.namespace_prefix.empty()) {
return options.namespace_prefix;
} else if (!file->package().empty()) {
@@ -231,49 +234,43 @@ string GetNestedMessageName(const Descriptor* descriptor) {
string GetPrefix(const GeneratorOptions& options,
const FileDescriptor* file_descriptor,
const Descriptor* containing_type) {
- string prefix =
- GetPath(options, file_descriptor) + GetNestedMessageName(containing_type);
+ string prefix = GetFilePath(options, file_descriptor) +
+ GetNestedMessageName(containing_type);
if (!prefix.empty()) {
prefix += ".";
}
return prefix;
}
-
-// Returns the fully normalized JavaScript path for the given
+// Returns the fully normalized JavaScript path prefix for the given
// message descriptor.
-string GetPath(const GeneratorOptions& options,
- const Descriptor* descriptor) {
+string GetMessagePathPrefix(const GeneratorOptions& options,
+ const Descriptor* descriptor) {
return GetPrefix(
options, descriptor->file(),
- descriptor->containing_type()) + descriptor->name();
+ descriptor->containing_type());
}
-
// Returns the fully normalized JavaScript path for the given
-// field's containing message descriptor.
-string GetPath(const GeneratorOptions& options,
- const FieldDescriptor* descriptor) {
- return GetPath(options, descriptor->containing_type());
+// message descriptor.
+string GetMessagePath(const GeneratorOptions& options,
+ const Descriptor* descriptor) {
+ return GetMessagePathPrefix(options, descriptor) + descriptor->name();
}
-// Returns the fully normalized JavaScript path for the given
+// Returns the fully normalized JavaScript path prefix for the given
// enumeration descriptor.
-string GetPath(const GeneratorOptions& options,
- const EnumDescriptor* enum_descriptor) {
- return GetPrefix(
- options, enum_descriptor->file(),
- enum_descriptor->containing_type()) + enum_descriptor->name();
+string GetEnumPathPrefix(const GeneratorOptions& options,
+ const EnumDescriptor* enum_descriptor) {
+ return GetPrefix(options, enum_descriptor->file(),
+ enum_descriptor->containing_type());
}
-
// Returns the fully normalized JavaScript path for the given
-// enumeration value descriptor.
-string GetPath(const GeneratorOptions& options,
- const EnumValueDescriptor* value_descriptor) {
- return GetPath(
- options,
- value_descriptor->type()) + "." + value_descriptor->name();
+// enumeration descriptor.
+string GetEnumPath(const GeneratorOptions& options,
+ const EnumDescriptor* enum_descriptor) {
+ return GetEnumPathPrefix(options, enum_descriptor) + enum_descriptor->name();
}
string MaybeCrossFileRef(const GeneratorOptions& options,
@@ -288,7 +285,7 @@ string MaybeCrossFileRef(const GeneratorOptions& options,
to_message->name();
} else {
// Within a single file we use a full name.
- return GetPath(options, to_message);
+ return GetMessagePath(options, to_message);
}
}
@@ -413,7 +410,7 @@ string ToFileName(const string& input) {
// that top-level extensions should go in.
string GetExtensionFileName(const GeneratorOptions& options,
const FileDescriptor* file) {
- return options.output_dir + "/" + ToFileName(GetPath(options, file)) +
+ return options.output_dir + "/" + ToFileName(GetFilePath(options, file)) +
options.GetFileNameExtension();
}
@@ -550,14 +547,6 @@ string JSGetterName(const GeneratorOptions& options,
return name;
}
-string JSMapGetterName(const GeneratorOptions& options,
- const FieldDescriptor* field) {
- return JSIdent(options, field,
- /* is_upper_camel = */ true,
- /* is_map = */ true,
- /* drop_list = */ false);
-}
-
string JSOneofName(const OneofDescriptor* oneof) {
@@ -783,8 +772,22 @@ string DoubleToString(double value) {
return PostProcessFloat(result);
}
+// 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() == google::protobuf::FieldOptions::JS_STRING;
+ default:
+ return false;
+ }
+}
+
string MaybeNumberString(const FieldDescriptor* field, const string& orig) {
- return orig;
+ return IsIntegralFieldWithStringJSType(field) ? ("\"" + orig + "\"") : orig;
}
string JSFieldDefault(const FieldDescriptor* field) {
@@ -872,18 +875,18 @@ string ProtoTypeName(const GeneratorOptions& options,
case FieldDescriptor::TYPE_BYTES:
return "bytes";
case FieldDescriptor::TYPE_GROUP:
- return GetPath(options, field->message_type());
+ return GetMessagePath(options, field->message_type());
case FieldDescriptor::TYPE_ENUM:
- return GetPath(options, field->enum_type());
+ return GetEnumPath(options, field->enum_type());
case FieldDescriptor::TYPE_MESSAGE:
- return GetPath(options, field->message_type());
+ return GetMessagePath(options, field->message_type());
default:
return "";
}
}
string JSIntegerTypeName(const FieldDescriptor* field) {
- return "number";
+ return IsIntegralFieldWithStringJSType(field) ? "string" : "number";
}
string JSStringTypeName(const GeneratorOptions& options,
@@ -925,9 +928,9 @@ string JSTypeName(const GeneratorOptions& options,
case FieldDescriptor::CPPTYPE_STRING:
return JSStringTypeName(options, field, bytes_mode);
case FieldDescriptor::CPPTYPE_ENUM:
- return GetPath(options, field->enum_type());
+ return GetEnumPath(options, field->enum_type());
case FieldDescriptor::CPPTYPE_MESSAGE:
- return GetPath(options, field->message_type());
+ return GetMessagePath(options, field->message_type());
default:
return "";
}
@@ -1023,7 +1026,7 @@ string JSFieldTypeAnnotation(const GeneratorOptions& options,
if (!IsPrimitive(jstype)) {
jstype = "!" + jstype;
}
- jstype = "Array.<" + jstype + ">";
+ jstype = "Array<" + jstype + ">";
}
}
@@ -1060,8 +1063,7 @@ string JSBinaryReaderMethodType(const FieldDescriptor* field) {
if (name[0] >= 'a' && name[0] <= 'z') {
name[0] = (name[0] - 'a') + 'A';
}
-
- return name;
+ return IsIntegralFieldWithStringJSType(field) ? (name + "String") : name;
}
string JSBinaryReadWriteMethodName(const FieldDescriptor* field,
@@ -1091,6 +1093,40 @@ string JSReturnClause(const FieldDescriptor* desc) {
return "";
}
+string JSTypeTag(const FieldDescriptor* desc) {
+ switch (desc->type()) {
+ case FieldDescriptor::TYPE_DOUBLE:
+ case FieldDescriptor::TYPE_FLOAT:
+ return "Float";
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_FIXED64:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_SFIXED32:
+ case FieldDescriptor::TYPE_SFIXED64:
+ if (IsIntegralFieldWithStringJSType(desc)) {
+ return "StringInt";
+ } else {
+ return "Int";
+ }
+ case FieldDescriptor::TYPE_BOOL:
+ return "Boolean";
+ case FieldDescriptor::TYPE_STRING:
+ return "String";
+ case FieldDescriptor::TYPE_BYTES:
+ return "Bytes";
+ case FieldDescriptor::TYPE_ENUM:
+ return "Enum";
+ default:
+ assert(false);
+ }
+ return "";
+}
+
string JSReturnDoc(const GeneratorOptions& options,
const FieldDescriptor* desc) {
return "";
@@ -1111,7 +1147,7 @@ static const char* kRepeatedFieldArrayName = ".repeatedFields_";
string RepeatedFieldsArrayName(const GeneratorOptions& options,
const Descriptor* desc) {
return HasRepeatedFields(options, desc)
- ? (GetPath(options, desc) + kRepeatedFieldArrayName)
+ ? (GetMessagePath(options, desc) + kRepeatedFieldArrayName)
: "null";
}
@@ -1128,8 +1164,9 @@ static const char* kOneofGroupArrayName = ".oneofGroups_";
string OneofFieldsArrayName(const GeneratorOptions& options,
const Descriptor* desc) {
- return HasOneofFields(desc) ?
- (GetPath(options, desc) + kOneofGroupArrayName) : "null";
+ return HasOneofFields(desc)
+ ? (GetMessagePath(options, desc) + kOneofGroupArrayName)
+ : "null";
}
string RepeatedFieldNumberList(const GeneratorOptions& options,
@@ -1270,13 +1307,6 @@ string FieldComments(const FieldDescriptor* field, BytesMode bytes_mode) {
" * You should avoid comparisons like {@code val === true/false} in "
"those cases.\n";
}
- if (field->is_repeated()) {
- comments +=
- " * If you change this array by adding, removing or replacing "
- "elements, or if you\n"
- " * replace the array itself, then you must call the setter to "
- "update it.\n";
- }
if (field->type() == FieldDescriptor::TYPE_BYTES && bytes_mode == BYTES_U8) {
comments +=
" * Note that Uint8Array is not supported on all browsers.\n"
@@ -1349,7 +1379,7 @@ bool IsExtendable(const Descriptor* desc) {
// Returns the max index in the underlying data storage array beyond which the
// extension object is used.
string GetPivot(const Descriptor* desc) {
- static const int kDefaultPivot = (1 << 29); // max field number (29 bits)
+ static const int kDefaultPivot = 500;
// Find the max field number
int max_field_number = 0;
@@ -1361,7 +1391,7 @@ string GetPivot(const Descriptor* desc) {
}
int pivot = -1;
- if (IsExtendable(desc)) {
+ if (IsExtendable(desc) || (max_field_number >= kDefaultPivot)) {
pivot = ((max_field_number + 1) < kDefaultPivot) ?
(max_field_number + 1) : kDefaultPivot;
}
@@ -1526,6 +1556,22 @@ bool GenerateJspbAllowedSet(const GeneratorOptions& options,
return true;
}
+// Embeds base64 encoded GeneratedCodeInfo proto in a comment at the end of
+// file.
+void EmbedCodeAnnotations(const GeneratedCodeInfo& annotations,
+ io::Printer* printer) {
+ // Serialize annotations proto into base64 string.
+ string meta_content;
+ annotations.SerializeToString(&meta_content);
+ string meta_64;
+ Base64Escape(meta_content, &meta_64);
+
+ // Print base64 encoded annotations at the end of output file in
+ // a comment.
+ printer->Print("\n// Below is base64 encoded GeneratedCodeInfo proto");
+ printer->Print("\n// $encoded_proto$\n", "encoded_proto", meta_64);
+}
+
} // anonymous namespace
void Generator::GenerateHeader(const GeneratorOptions& options,
@@ -1533,6 +1579,10 @@ void Generator::GenerateHeader(const GeneratorOptions& options,
printer->Print("/**\n"
" * @fileoverview\n"
" * @enhanceable\n"
+ " * @suppress {messageConventions} JS Compiler reports an "
+ "error if a variable or\n"
+ " * field starts with 'MSG_' and isn't a translatable "
+ "message.\n"
" * @public\n"
" */\n"
"// GENERATED CODE -- DO NOT EDIT!\n"
@@ -1571,7 +1621,7 @@ void Generator::FindProvidesForMessage(
return;
}
- string name = GetPath(options, desc);
+ string name = GetMessagePath(options, desc);
provided->insert(name);
for (int i = 0; i < desc->enum_type_count(); i++) {
@@ -1588,7 +1638,7 @@ void Generator::FindProvidesForEnum(const GeneratorOptions& options,
io::Printer* printer,
const EnumDescriptor* enumdesc,
std::set<string>* provided) const {
- string name = GetPath(options, enumdesc);
+ string name = GetEnumPath(options, enumdesc);
provided->insert(name);
}
@@ -1604,9 +1654,8 @@ void Generator::FindProvidesForFields(
continue;
}
- string name =
- GetPath(options, field->file()) + "." +
- JSObjectFieldName(options, field);
+ string name = GetFilePath(options, field->file()) + "." +
+ JSObjectFieldName(options, field);
provided->insert(name);
}
}
@@ -1684,7 +1733,7 @@ void Generator::GenerateRequiresForLibrary(
}
if (extension->containing_type()->full_name() !=
"google.protobuf.bridge.MessageSet") {
- required.insert(GetPath(options, extension->containing_type()));
+ required.insert(GetMessagePath(options, extension->containing_type()));
}
FindRequiresForField(options, extension, &required, &forwards);
have_extensions = true;
@@ -1725,18 +1774,16 @@ void Generator::GenerateRequiresImpl(const GeneratorOptions& options,
bool require_jspb, bool require_extension,
bool require_map) const {
if (require_jspb) {
- printer->Print(
- "goog.require('jspb.Message');\n"
- "goog.require('jspb.BinaryReader');\n"
- "goog.require('jspb.BinaryWriter');\n");
+ required->insert("jspb.Message");
+ required->insert("jspb.BinaryReader");
+ required->insert("jspb.BinaryWriter");
}
if (require_extension) {
- printer->Print("goog.require('jspb.ExtensionFieldBinaryInfo');\n");
- printer->Print(
- "goog.require('jspb.ExtensionFieldInfo');\n");
+ required->insert("jspb.ExtensionFieldBinaryInfo");
+ required->insert("jspb.ExtensionFieldInfo");
}
if (require_map) {
- printer->Print("goog.require('jspb.Map');\n");
+ required->insert("jspb.Map");
}
std::set<string>::iterator it;
@@ -1805,13 +1852,13 @@ void Generator::FindRequiresForField(const GeneratorOptions& options,
// dependencies, as per original codegen.
!(field->is_extension() && field->extension_scope() == NULL)) {
if (options.add_require_for_enums) {
- required->insert(GetPath(options, field->enum_type()));
+ required->insert(GetEnumPath(options, field->enum_type()));
} else {
- forwards->insert(GetPath(options, field->enum_type()));
+ forwards->insert(GetEnumPath(options, field->enum_type()));
}
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
if (!IgnoreMessage(options, field->message_type())) {
- required->insert(GetPath(options, field->message_type()));
+ required->insert(GetMessagePath(options, field->message_type()));
}
}
}
@@ -1821,7 +1868,7 @@ void Generator::FindRequiresForExtension(const GeneratorOptions& options,
std::set<string>* required,
std::set<string>* forwards) const {
if (field->containing_type()->full_name() != "google.protobuf.bridge.MessageSet") {
- required->insert(GetPath(options, field->containing_type()));
+ required->insert(GetMessagePath(options, field->containing_type()));
}
FindRequiresForField(options, field, required, forwards);
}
@@ -1868,7 +1915,7 @@ void Generator::GenerateClass(const GeneratorOptions& options,
}
// Recurse on nested types. These must come *before* the extension-field
- // info generation in GenerateClassRegistration so that extensions that
+ // 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));
@@ -1890,7 +1937,6 @@ void Generator::GenerateClass(const GeneratorOptions& options,
}
}
}
-
}
void Generator::GenerateClassConstructor(const GeneratorOptions& options,
@@ -1911,8 +1957,10 @@ void Generator::GenerateClassConstructor(const GeneratorOptions& options,
" * @extends {jspb.Message}\n"
" * @constructor\n"
" */\n"
- "$classname$ = function(opt_data) {\n",
- "classname", GetPath(options, desc));
+ "$classprefix$$classname$ = function(opt_data) {\n",
+ "classprefix", GetMessagePathPrefix(options, desc),
+ "classname", desc->name());
+ printer->Annotate("classname", desc);
string message_id = GetMessageId(desc);
printer->Print(
" jspb.Message.initialize(this, opt_data, $messageId$, $pivot$, "
@@ -1929,7 +1977,7 @@ void Generator::GenerateClassConstructor(const GeneratorOptions& options,
"if (goog.DEBUG && !COMPILED) {\n"
" $classname$.displayName = '$classname$';\n"
"}\n",
- "classname", GetPath(options, desc));
+ "classname", GetMessagePath(options, desc));
}
void Generator::GenerateClassFieldInfo(const GeneratorOptions& options,
@@ -1944,7 +1992,7 @@ void Generator::GenerateClassFieldInfo(const GeneratorOptions& options,
" */\n"
"$classname$$rptfieldarray$ = $rptfields$;\n"
"\n",
- "classname", GetPath(options, desc),
+ "classname", GetMessagePath(options, desc),
"rptfieldarray", kRepeatedFieldArrayName,
"rptfields", RepeatedFieldNumberList(options, desc));
}
@@ -1965,7 +2013,7 @@ void Generator::GenerateClassFieldInfo(const GeneratorOptions& options,
" */\n"
"$classname$$oneofgrouparray$ = $oneofgroups$;\n"
"\n",
- "classname", GetPath(options, desc),
+ "classname", GetMessagePath(options, desc),
"oneofgrouparray", kOneofGroupArrayName,
"oneofgroups", OneofGroupList(desc));
@@ -1985,7 +2033,7 @@ void Generator::GenerateClassXid(const GeneratorOptions& options,
"\n"
"\n"
"$class$.prototype.messageXid = xid('$class$');\n",
- "class", GetPath(options, desc));
+ "class", GetMessagePath(options, desc));
}
void Generator::GenerateOneofCaseDefinition(
@@ -1998,7 +2046,7 @@ void Generator::GenerateOneofCaseDefinition(
" */\n"
"$classname$.$oneof$Case = {\n"
" $upcase$_NOT_SET: 0",
- "classname", GetPath(options, oneof->containing_type()),
+ "classname", GetMessagePath(options, oneof->containing_type()),
"oneof", JSOneofName(oneof),
"upcase", ToEnumCase(oneof->name()));
@@ -2012,6 +2060,7 @@ void Generator::GenerateOneofCaseDefinition(
" $upcase$: $number$",
"upcase", ToEnumCase(oneof->field(i)->name()),
"number", JSFieldIndex(oneof->field(i)));
+ printer->Annotate("upcase", oneof->field(i));
}
printer->Print(
@@ -2026,7 +2075,7 @@ void Generator::GenerateOneofCaseDefinition(
"computeOneofCase(this, $class$.oneofGroups_[$oneofindex$]));\n"
"};\n"
"\n",
- "class", GetPath(options, oneof->containing_type()),
+ "class", GetMessagePath(options, oneof->containing_type()),
"oneof", JSOneofName(oneof),
"oneofindex", JSOneofIndex(oneof));
}
@@ -2065,10 +2114,11 @@ void Generator::GenerateClassToObject(const GeneratorOptions& options,
" * 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", GetPath(options, desc));
+ "classname", GetMessagePath(options, desc));
bool first = true;
for (int i = 0; i < desc->field_count(); i++) {
@@ -2100,7 +2150,7 @@ void Generator::GenerateClassToObject(const GeneratorOptions& options,
" $extObject$, $class$.prototype.getExtension,\n"
" includeInstance);\n",
"extObject", JSExtensionsObjectName(options, desc->file(), desc),
- "class", GetPath(options, desc));
+ "class", GetMessagePath(options, desc));
}
printer->Print(
@@ -2112,7 +2162,7 @@ void Generator::GenerateClassToObject(const GeneratorOptions& options,
"}\n"
"\n"
"\n",
- "classname", GetPath(options, desc));
+ "classname", GetMessagePath(options, desc));
}
void Generator::GenerateFieldValueExpression(io::Printer* printer,
@@ -2153,7 +2203,8 @@ void Generator::GenerateFieldValueExpression(io::Printer* printer,
"obj", obj_reference);
}
} else {
- printer->Print("jspb.Message.getField($obj$, $index$)",
+ printer->Print("jspb.Message.get$cardinality$Field($obj$, $index$)",
+ "cardinality", field->is_repeated() ? "Repeated" : "",
"index", JSFieldIndex(field),
"obj", obj_reference);
}
@@ -2173,7 +2224,7 @@ void Generator::GenerateClassFieldToObject(const GeneratorOptions& options,
string value_to_object;
if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
value_to_object =
- GetPath(options, value_field->message_type()) + ".toObject";
+ GetMessagePath(options, value_field->message_type()) + ".toObject";
} else {
value_to_object = "undefined";
}
@@ -2235,7 +2286,7 @@ void Generator::GenerateClassFromObject(const GeneratorOptions& options,
" */\n"
"$classname$.fromObject = function(obj) {\n"
" var f, msg = new $classname$();\n",
- "classname", GetPath(options, desc));
+ "classname", GetMessagePath(options, desc));
for (int i = 0; i < desc->field_count(); i++) {
const FieldDescriptor* field = desc->field(i);
@@ -2263,7 +2314,7 @@ void Generator::GenerateClassFieldFromObject(
"$fieldclass$.fromObject));\n",
"name", JSObjectFieldName(options, field),
"index", JSFieldIndex(field),
- "fieldclass", GetPath(options, value_field->message_type()));
+ "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
@@ -2354,14 +2405,13 @@ void GenerateBytesWrapper(const GeneratorOptions& options,
"fielddef", FieldDefinition(options, field),
"comment", FieldComments(field, bytes_mode),
"type", type,
- "class", GetPath(options, field->containing_type()),
+ "class", GetMessagePath(options, field->containing_type()),
"name", JSGetterName(options, field, bytes_mode),
"list", 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 {
@@ -2393,20 +2443,22 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
"keytype", key_type,
"valuetype", value_type);
printer->Print(
- "$class$.prototype.get$name$ = function(opt_noLazyCreate) {\n"
+ "$class$.prototype.$gettername$ = function(opt_noLazyCreate) {\n"
" return /** @type {!jspb.Map<$keytype$,$valuetype$>} */ (\n",
- "class", GetPath(options, field->containing_type()),
- "name", JSGetterName(options, field),
+ "class", GetMessagePath(options, field->containing_type()),
+ "gettername", "get" + JSGetterName(options, field),
"keytype", key_type,
"valuetype", value_type);
+ printer->Annotate("gettername", field);
printer->Print(
" jspb.Message.getMapField(this, $index$, opt_noLazyCreate",
"index", JSFieldIndex(field));
if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
- printer->Print(",\n"
+ printer->Print(
+ ",\n"
" $messageType$",
- "messageType", GetPath(options, value_field->message_type()));
+ "messageType", GetMessagePath(options, value_field->message_type()));
} else {
printer->Print(",\n"
" null");
@@ -2436,15 +2488,15 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
/* force_present = */ false,
/* singular_if_not_packed = */ false));
printer->Print(
- "$class$.prototype.get$name$ = function() {\n"
+ "$class$.prototype.$gettername$ = function() {\n"
" return /** @type{$type$} */ (\n"
" jspb.Message.get$rpt$WrapperField(this, $wrapperclass$, "
"$index$$required$));\n"
"};\n"
"\n"
"\n",
- "class", GetPath(options, field->containing_type()),
- "name", JSGetterName(options, field),
+ "class", GetMessagePath(options, field->containing_type()),
+ "gettername", "get" + JSGetterName(options, field),
"type", JSFieldTypeAnnotation(options, field,
/* is_setter_argument = */ false,
/* force_present = */ false,
@@ -2454,9 +2506,10 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
"wrapperclass", SubmessageTypeRef(options, field),
"required", (field->label() == FieldDescriptor::LABEL_REQUIRED ?
", 1" : ""));
+ printer->Annotate("gettername", field);
printer->Print(
"/** @param {$optionaltype$} value$returndoc$ */\n"
- "$class$.prototype.set$name$ = function(value) {\n"
+ "$class$.prototype.$settername$ = function(value) {\n"
" jspb.Message.set$oneoftag$$repeatedtag$WrapperField(",
"optionaltype",
JSFieldTypeAnnotation(options, field,
@@ -2464,10 +2517,11 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
/* force_present = */ false,
/* singular_if_not_packed = */ false),
"returndoc", JSReturnDoc(options, field),
- "class", GetPath(options, field->containing_type()),
- "name", JSGetterName(options, field),
+ "class", GetMessagePath(options, field->containing_type()),
+ "settername", "set" + JSGetterName(options, field),
"oneoftag", (field->containing_oneof() ? "Oneof" : ""),
"repeatedtag", (field->is_repeated() ? "Repeated" : ""));
+ printer->Annotate("settername", field);
printer->Print(
"this, $index$$oneofgroup$, value);$returnvalue$\n"
@@ -2490,7 +2544,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
// 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 the return
+ // 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 ?
@@ -2519,9 +2573,10 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
}
printer->Print(
- "$class$.prototype.get$name$ = function() {\n",
- "class", GetPath(options, field->containing_type()),
- "name", JSGetterName(options, field));
+ "$class$.prototype.$gettername$ = function() {\n",
+ "class", GetMessagePath(options, field->containing_type()),
+ "gettername", "get" + JSGetterName(options, field));
+ printer->Annotate("gettername", field);
if (untyped) {
printer->Print(
@@ -2582,26 +2637,47 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
/* singular_if_not_packed = */ false),
"returndoc", JSReturnDoc(options, field));
}
- printer->Print(
- "$class$.prototype.set$name$ = function(value) {\n"
- " jspb.Message.set$oneoftag$Field(this, $index$",
- "class", GetPath(options, field->containing_type()),
- "name", JSGetterName(options, field),
- "oneoftag", (field->containing_oneof() ? "Oneof" : ""),
- "index", JSFieldIndex(field));
- printer->Print(
- "$oneofgroup$, $type$value$rptvalueinit$$typeclose$);$returnvalue$\n"
- "};\n"
- "\n"
- "\n",
- "type",
- untyped ? "/** @type{string|number|boolean|Array|undefined} */(" : "",
- "typeclose", untyped ? ")" : "",
- "oneofgroup",
- (field->containing_oneof() ? (", " + JSOneofArray(options, field))
- : ""),
- "returnvalue", JSReturnClause(field), "rptvalueinit",
- (field->is_repeated() ? " || []" : ""));
+
+ if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
+ !field->is_repeated() && !field->is_map() &&
+ !HasFieldPresence(options, field)) {
+ // Proto3 non-repeated and non-map fields without presence use the
+ // setProto3*Field function.
+ printer->Print(
+ "$class$.prototype.$settername$ = function(value) {\n"
+ " jspb.Message.setProto3$typetag$Field(this, $index$, "
+ "value);$returnvalue$\n"
+ "};\n"
+ "\n"
+ "\n",
+ "class", GetMessagePath(options, field->containing_type()),
+ "settername", "set" + JSGetterName(options, field), "typetag",
+ JSTypeTag(field), "index", JSFieldIndex(field), "returnvalue",
+ JSReturnClause(field));
+ printer->Annotate("settername", field);
+ } else {
+ // Otherwise, use the regular setField function.
+ printer->Print(
+ "$class$.prototype.$settername$ = function(value) {\n"
+ " jspb.Message.set$oneoftag$Field(this, $index$",
+ "class", GetMessagePath(options, field->containing_type()),
+ "settername", "set" + JSGetterName(options, field), "oneoftag",
+ (field->containing_oneof() ? "Oneof" : ""), "index",
+ JSFieldIndex(field));
+ printer->Annotate("settername", field);
+ printer->Print(
+ "$oneofgroup$, $type$value$rptvalueinit$$typeclose$);$returnvalue$\n"
+ "};\n"
+ "\n"
+ "\n",
+ "type",
+ untyped ? "/** @type{string|number|boolean|Array|undefined} */(" : "",
+ "typeclose", untyped ? ")" : "", "oneofgroup",
+ (field->containing_oneof() ? (", " + JSOneofArray(options, field))
+ : ""),
+ "returnvalue", JSReturnClause(field), "rptvalueinit",
+ (field->is_repeated() ? " || []" : ""));
+ }
if (untyped) {
printer->Print(
@@ -2621,41 +2697,46 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
// fields with presence.
if (IsMap(options, field)) {
printer->Print(
- "$class$.prototype.clear$name$ = function() {\n"
- " this.get$name$().clear();$returnvalue$\n"
+ "$class$.prototype.$clearername$ = function() {\n"
+ " this.$gettername$().clear();$returnvalue$\n"
"};\n"
"\n"
"\n",
- "class", GetPath(options, field->containing_type()),
- "name", JSGetterName(options, field),
+ "class", GetMessagePath(options, field->containing_type()),
+ "clearername", "clear" + JSGetterName(options, field),
+ "gettername", "get" + JSGetterName(options, field),
"returnvalue", JSReturnClause(field));
+ 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.
printer->Print(
- "$class$.prototype.clear$name$ = function() {\n"
- " this.set$name$($clearedvalue$);$returnvalue$\n"
+ "$class$.prototype.$clearername$ = function() {\n"
+ " this.$settername$($clearedvalue$);$returnvalue$\n"
"};\n"
"\n"
"\n",
- "class", GetPath(options, field->containing_type()),
- "name", JSGetterName(options, field),
+ "class", GetMessagePath(options, field->containing_type()),
+ "clearername", "clear" + JSGetterName(options, field),
+ "settername", "set" + JSGetterName(options, field),
"clearedvalue", (field->is_repeated() ? "[]" : "undefined"),
"returnvalue", JSReturnClause(field));
+ 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.
printer->Print(
- "$class$.prototype.clear$name$ = function() {\n"
+ "$class$.prototype.$clearername$ = function() {\n"
" jspb.Message.set$maybeoneof$Field(this, "
"$index$$maybeoneofgroup$, ",
- "class", GetPath(options, field->containing_type()),
- "name", JSGetterName(options, field),
+ "class", GetMessagePath(options, field->containing_type()),
+ "clearername", "clear" + JSGetterName(options, field),
"maybeoneof", (field->containing_oneof() ? "Oneof" : ""),
"maybeoneofgroup", (field->containing_oneof() ?
(", " + JSOneofArray(options, field)) : ""),
"index", JSFieldIndex(field));
+ printer->Annotate("clearername", field);
printer->Print(
"$clearedvalue$);$returnvalue$\n"
"};\n"
@@ -2671,41 +2752,48 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
" * Returns whether this field is set.\n"
" * @return {!boolean}\n"
" */\n"
- "$class$.prototype.has$name$ = function() {\n"
+ "$class$.prototype.$hasername$ = function() {\n"
" return jspb.Message.getField(this, $index$) != null;\n"
"};\n"
"\n"
"\n",
- "class", GetPath(options, field->containing_type()),
- "name", JSGetterName(options, field),
+ "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 {
+ // clang-format off
printer->Print(
"/**\n"
" * @param {!$optionaltype$} value\n"
- " * @param {number=} opt_index\n"
+ " * @param {number=} opt_index$returndoc$\n"
" */\n"
- "$class$.prototype.add$name$ = function(value, opt_index) {\n"
+ "$class$.prototype.$addername$ = function(value, opt_index) {\n"
" jspb.Message.addToRepeatedField(this, $index$",
- "class", GetPath(options, field->containing_type()), "name",
- JSGetterName(options, field, BYTES_DEFAULT,
- /* drop_list = */ true),
- "optionaltype", JSTypeName(options, field, BYTES_DEFAULT), "index",
- JSFieldIndex(field));
+ "class", GetMessagePath(options, field->containing_type()), "addername",
+ "add" + JSGetterName(options, field, BYTES_DEFAULT,
+ /* drop_list = */ true),
+ "optionaltype", JSTypeName(options, field, BYTES_DEFAULT),
+ "index", JSFieldIndex(field),
+ "returndoc", JSReturnDoc(options, field));
+ printer->Annotate("addername", field);
printer->Print(
- "$oneofgroup$, $type$value$rptvalueinit$$typeclose$, opt_index);\n"
+ "$oneofgroup$, $type$value$rptvalueinit$$typeclose$, "
+ "opt_index);$returnvalue$\n"
"};\n"
"\n"
"\n",
"type", untyped ? "/** @type{string|number|boolean|!Uint8Array} */(" : "",
"typeclose", untyped ? ")" : "", "oneofgroup",
(field->containing_oneof() ? (", " + JSOneofArray(options, field)) : ""),
- "rptvalueinit", "");
+ "rptvalueinit", "",
+ "returnvalue", JSReturnClause(field));
+ // clang-format on
}
void Generator::GenerateRepeatedMessageHelperMethods(
@@ -2719,9 +2807,9 @@ void Generator::GenerateRepeatedMessageHelperMethods(
" */\n"
"$class$.prototype.add$name$ = function(opt_value, opt_index) {\n"
" return jspb.Message.addTo$repeatedtag$WrapperField(",
- "optionaltype", JSTypeName(options, field, BYTES_DEFAULT), "class",
- GetPath(options, field->containing_type()), "name",
- JSGetterName(options, field, BYTES_DEFAULT,
+ "optionaltype", JSTypeName(options, field, BYTES_DEFAULT),
+ "class", GetMessagePath(options, field->containing_type()),
+ "name", JSGetterName(options, field, BYTES_DEFAULT,
/* drop_list = */ true),
"repeatedtag", (field->is_repeated() ? "Repeated" : ""));
@@ -2732,7 +2820,7 @@ void Generator::GenerateRepeatedMessageHelperMethods(
"\n",
"index", JSFieldIndex(field), "oneofgroup",
(field->containing_oneof() ? (", " + JSOneofArray(options, field)) : ""),
- "ctor", GetPath(options, field->message_type()));
+ "ctor", GetMessagePath(options, field->message_type()));
}
void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
@@ -2754,11 +2842,11 @@ void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
"so that it\n"
" * works in OPTIMIZED mode.\n"
" *\n"
- " * @type {!Object.<number, jspb.ExtensionFieldInfo>}\n"
+ " * @type {!Object<number, jspb.ExtensionFieldInfo>}\n"
" */\n"
"$class$.extensions = {};\n"
"\n",
- "class", GetPath(options, desc));
+ "class", GetMessagePath(options, desc));
printer->Print(
"\n"
@@ -2775,11 +2863,11 @@ void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
"so that it\n"
" * works in OPTIMIZED mode.\n"
" *\n"
- " * @type {!Object.<number, jspb.ExtensionFieldBinaryInfo>}\n"
+ " * @type {!Object<number, jspb.ExtensionFieldBinaryInfo>}\n"
" */\n"
"$class$.extensionsBinary = {};\n"
"\n",
- "class", GetPath(options, desc));
+ "class", GetMessagePath(options, desc));
}
}
@@ -2817,7 +2905,7 @@ void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options,
" }\n"
" var field = reader.getFieldNumber();\n"
" switch (field) {\n",
- "class", GetPath(options, desc));
+ "class", GetMessagePath(options, desc));
for (int i = 0; i < desc->field_count(); i++) {
if (!IgnoreField(desc->field(i))) {
@@ -2834,7 +2922,7 @@ void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options,
" $class$.prototype.setExtension);\n"
" break;\n",
"extobj", JSExtensionsObjectName(options, desc->file(), desc),
- "class", GetPath(options, desc));
+ "class", GetMessagePath(options, desc));
} else {
printer->Print(
" reader.skipField();\n"
@@ -2873,7 +2961,7 @@ void Generator::GenerateClassDeserializeBinaryField(
if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
printer->Print(", $messageType$.deserializeBinaryFromReader",
- "messageType", GetPath(options, value_field->message_type()));
+ "messageType", GetMessagePath(options, value_field->message_type()));
}
printer->Print(");\n");
@@ -2937,11 +3025,12 @@ void Generator::GenerateClassSerializeBinary(const GeneratorOptions& options,
" * 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", GetPath(options, desc));
+ "class", GetMessagePath(options, desc));
for (int i = 0; i < desc->field_count(); i++) {
if (!IgnoreField(desc->field(i))) {
@@ -2954,7 +3043,7 @@ void Generator::GenerateClassSerializeBinary(const GeneratorOptions& options,
" jspb.Message.serializeBinaryExtensions(message, writer,\n"
" $extobj$Binary, $class$.prototype.getExtension);\n",
"extobj", JSExtensionsObjectName(options, desc->file(), desc),
- "class", GetPath(options, desc));
+ "class", GetMessagePath(options, desc));
}
printer->Print(
@@ -3009,7 +3098,13 @@ void Generator::GenerateClassSerializeBinaryField(
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;
@@ -3049,7 +3144,7 @@ void Generator::GenerateClassSerializeBinaryField(
if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
printer->Print(", $messageType$.serializeBinaryToWriter",
- "messageType", GetPath(options, value_field->message_type()));
+ "messageType", GetMessagePath(options, value_field->message_type()));
}
printer->Print(");\n");
@@ -3087,8 +3182,10 @@ void Generator::GenerateEnum(const GeneratorOptions& options,
"/**\n"
" * @enum {number}\n"
" */\n"
- "$name$ = {\n",
- "name", GetPath(options, enumdesc));
+ "$enumprefix$$name$ = {\n",
+ "enumprefix", GetEnumPathPrefix(options, enumdesc),
+ "name", enumdesc->name());
+ printer->Annotate("name", enumdesc);
for (int i = 0; i < enumdesc->value_count(); i++) {
const EnumValueDescriptor* value = enumdesc->value(i);
@@ -3097,6 +3194,7 @@ void Generator::GenerateEnum(const GeneratorOptions& options,
"name", ToEnumCase(value->name()),
"value", SimpleItoa(value->number()),
"comma", (i == enumdesc->value_count() - 1) ? "" : ",");
+ printer->Annotate("name", value);
}
printer->Print(
@@ -3108,25 +3206,28 @@ void Generator::GenerateExtension(const GeneratorOptions& options,
io::Printer* printer,
const FieldDescriptor* field) const {
string extension_scope =
- (field->extension_scope() ?
- GetPath(options, field->extension_scope()) :
- GetPath(options, field->file()));
+ (field->extension_scope()
+ ? GetMessagePath(options, field->extension_scope())
+ : GetFilePath(options, field->file()));
+ const string extension_object_name = JSObjectFieldName(options, field);
printer->Print(
"\n"
"/**\n"
" * A tuple of {field number, class constructor} for the extension\n"
- " * field named `$name$`.\n"
- " * @type {!jspb.ExtensionFieldInfo.<$extensionType$>}\n"
+ " * field named `$nameInComment$`.\n"
+ " * @type {!jspb.ExtensionFieldInfo<$extensionType$>}\n"
" */\n"
"$class$.$name$ = new jspb.ExtensionFieldInfo(\n",
- "name", JSObjectFieldName(options, field),
+ "nameInComment", extension_object_name,
+ "name", extension_object_name,
"class", extension_scope,
"extensionType", JSFieldTypeAnnotation(
options, field,
/* is_setter_argument = */ false,
/* force_present = */ true,
/* singular_if_not_packed = */ false));
+ printer->Annotate("name", field);
printer->Print(
" $index$,\n"
" {$name$: 0},\n"
@@ -3136,7 +3237,7 @@ void Generator::GenerateExtension(const GeneratorOptions& options,
" $toObject$),\n"
" $repeated$);\n",
"index", SimpleItoa(field->number()),
- "name", JSObjectFieldName(options, field),
+ "name", extension_object_name,
"ctor", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ?
SubmessageTypeRef(options, field) : string("null")),
"toObject", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ?
@@ -3155,7 +3256,7 @@ void Generator::GenerateExtension(const GeneratorOptions& options,
"extendName",
JSExtensionsObjectName(options, field->file(), field->containing_type()),
"index", SimpleItoa(field->number()), "class", extension_scope, "name",
- JSObjectFieldName(options, field), "binaryReaderFn",
+ extension_object_name, "binaryReaderFn",
JSBinaryReaderMethodName(options, field), "binaryWriterFn",
JSBinaryWriterMethodName(options, field), "binaryMessageSerializeFn",
(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE)
@@ -3178,7 +3279,7 @@ void Generator::GenerateExtension(const GeneratorOptions& options,
field->containing_type()),
"index", SimpleItoa(field->number()),
"class", extension_scope,
- "name", JSObjectFieldName(options, field));
+ "name", extension_object_name);
}
bool GeneratorOptions::ParseFromOptions(
@@ -3236,6 +3337,12 @@ bool GeneratorOptions::ParseFromOptions(
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.
@@ -3333,7 +3440,8 @@ void Generator::GenerateFile(const GeneratorOptions& options,
printer->Print(
"var $alias$ = require('$file$');\n",
"alias", ModuleAlias(name),
- "file", GetRootPath(file->name(), name) + GetJSFilename(options, name));
+ "file",
+ GetRootPath(file->name(), name) + GetJSFilename(options, name));
}
}
@@ -3347,7 +3455,7 @@ void Generator::GenerateFile(const GeneratorOptions& options,
IgnoreField(file->extension(i))) {
continue;
}
- provided.insert(GetPath(options, file) + "." +
+ provided.insert(GetFilePath(options, file) + "." +
JSObjectFieldName(options, file->extension(i)));
extensions.insert(file->extension(i));
}
@@ -3371,7 +3479,7 @@ void Generator::GenerateFile(const GeneratorOptions& options,
if (options.import_style == GeneratorOptions::kImportCommonJs) {
printer->Print("goog.object.extend(exports, $package$);\n",
- "package", GetPath(options, file));
+ "package", GetFilePath(options, file));
}
// Emit well-known type methods.
@@ -3399,7 +3507,7 @@ bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files,
// All output should go in a single file.
string filename = options.output_dir + "/" + options.library +
options.GetFileNameExtension();
- google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+ std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
GOOGLE_CHECK(output.get());
io::Printer printer(output.get(), '$');
@@ -3448,7 +3556,7 @@ bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files,
}
string filename = GetMessageFileName(options, desc);
- google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
context->Open(filename));
GOOGLE_CHECK(output.get());
io::Printer printer(output.get(), '$');
@@ -3474,7 +3582,7 @@ bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files,
}
string filename = GetEnumFileName(options, enumdesc);
- google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
context->Open(filename));
GOOGLE_CHECK(output.get());
io::Printer printer(output.get(), '$');
@@ -3497,7 +3605,7 @@ bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files,
if (allowed_set.count(file) == 1) {
string filename = GetExtensionFileName(options, file);
- google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
context->Open(filename));
GOOGLE_CHECK(output.get());
io::Printer printer(output.get(), '$');
@@ -3533,18 +3641,26 @@ bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files,
string filename =
options.output_dir + "/" + GetJSFilename(options, file->name());
- google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+ std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
GOOGLE_CHECK(output.get());
- io::Printer printer(output.get(), '$');
+ GeneratedCodeInfo annotations;
+ io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+ &annotations);
+ io::Printer printer(output.get(), '$',
+ options.annotate_code ? &annotation_collector : NULL);
+
GenerateFile(options, &printer, file);
if (printer.failed()) {
return false;
}
+
+ if (options.annotate_code) {
+ EmbedCodeAnnotations(annotations, &printer);
+ }
}
}
-
return true;
}