From 88ff11414a09f3191216cb04391224a5aa9bfba5 Mon Sep 17 00:00:00 2001 From: David Fox Date: Mon, 3 Apr 2017 17:19:28 -0500 Subject: [PATCH 1/2] Update TypeScript default values for proto3 syntax --- cli/targets/static.js | 38 ++++++++++++++++++++++++++++++++------ src/parse.js | 10 ++++++++++ src/root.js | 6 ++++++ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/cli/targets/static.js b/cli/targets/static.js index 2316b7a4e..6a32e1a65 100644 --- a/cli/targets/static.js +++ b/cli/targets/static.js @@ -44,7 +44,7 @@ function static_target(root, options, callback) { } var rootProp = cliUtil.safeProp(config.root || "default"); push((config.es6 ? "const" : "var") + " $root = $protobuf.roots" + rootProp + " || ($protobuf.roots" + rootProp + " = {});"); - buildNamespace(null, root); + buildNamespace(null, root, root); return callback(null, out.join("\n")); } catch (err) { return callback(err); @@ -92,7 +92,7 @@ function aOrAn(name) { : "a ") + name; } -function buildNamespace(ref, ns) { +function buildNamespace(ref, ns, root) { if (!ns) return; if (ns.name !== "") { @@ -105,7 +105,7 @@ function buildNamespace(ref, ns) { } if (ns instanceof Type) { - buildType(undefined, ns); + buildType(undefined, ns, root); } else if (ns instanceof Service) buildService(undefined, ns); else if (ns.name !== "") { @@ -122,7 +122,7 @@ function buildNamespace(ref, ns) { if (nested instanceof Enum) buildEnum(ns.name, nested); else if (nested instanceof Namespace) - buildNamespace(ns.name, nested); + buildNamespace(ns.name, nested, root); }); if (ns.name !== "") { push(""); @@ -338,7 +338,26 @@ function toJsType(field) { : type; } -function buildType(ref, type) { +/** + * If the given field will have a default value assigned to it by a Proto3 lib + * @param {Field} field + */ +function willFieldHaveDefaultValue(field) { + if (field.repeated || field.map) { + // Default value being an empty array or map + return true; + } + + field.resolve(); + if (!field.resolvedType || field.resolvedType instanceof Enum) { + // Enums default to 0 + return true; + } + + return false; +} + +function buildType(ref, type, root) { var fullName = type.fullName.substring(1); if (config.comments) { @@ -372,11 +391,18 @@ function buildType(ref, type) { type.fieldsArray.forEach(function(field) { field.resolve(); var prop = util.safeProp(field.name); + var canFieldBeUndefined = field.optional; + if (root.containsProto3) { + // Only fields not given defaults can be undefined since proto3 has + // no "optional" or "required" fields + canFieldBeUndefined = !willFieldHaveDefaultValue(field); + } + if (config.comments) { push(""); pushComment([ field.comment || type.name + " " + field.name + ".", - "@type {" + toJsType(field) + (field.optional ? "|undefined" : "") + "}" + "@type {" + toJsType(field) + (canFieldBeUndefined ? "|null" : "") + "}" ]); } else if (firstField) { push(""); diff --git a/src/parse.js b/src/parse.js index c22a38b77..81330998e 100644 --- a/src/parse.js +++ b/src/parse.js @@ -86,6 +86,11 @@ function parse(source, root, options) { syntax, isProto3 = false; + /** + * If proto3 syntax was used at any point in the source + */ + var sourceContainsProto3 = false; + var ptr = root; var applyCase = options.keepCase ? function(name) { return name; } : camelCase; @@ -244,6 +249,10 @@ function parse(source, root, options) { syntax = readString(); isProto3 = syntax === "proto3"; + if (!sourceContainsProto3) { + sourceContainsProto3 = isProto3; + } + /* istanbul ignore if */ if (!isProto3 && syntax !== "proto2") throw illegal(syntax, "syntax"); @@ -729,6 +738,7 @@ function parse(source, root, options) { } parse.filename = null; + root.containsProto3 = sourceContainsProto3; return { "package" : pkg, "imports" : imports, diff --git a/src/root.js b/src/root.js index f7d0af149..a5d62053f 100644 --- a/src/root.js +++ b/src/root.js @@ -34,6 +34,12 @@ function Root(options) { * @type {string[]} */ this.files = []; + + /** + * If any sources which built this Root used protobuf 3 syntax + * @type {boolean} + */ + this.containsProto3 = false; } /** From 68e5a99c51b2c4347319749cd66ff9d62f1779ad Mon Sep 17 00:00:00 2001 From: David Fox Date: Mon, 3 Apr 2017 17:31:50 -0500 Subject: [PATCH 2/2] Added missing @returns --- cli/targets/static.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cli/targets/static.js b/cli/targets/static.js index 6a32e1a65..688a3cc2b 100644 --- a/cli/targets/static.js +++ b/cli/targets/static.js @@ -341,6 +341,7 @@ function toJsType(field) { /** * If the given field will have a default value assigned to it by a Proto3 lib * @param {Field} field + * @returns {boolean} */ function willFieldHaveDefaultValue(field) { if (field.repeated || field.map) {