Skip to content

Commit

Permalink
New: Preserve comments when serializing/deserializing with toJSON and…
Browse files Browse the repository at this point in the history
… fromJSON. (#983)
  • Loading branch information
gideongoodwin authored and dcodeIO committed Feb 12, 2018
1 parent 635fef0 commit 462132f
Show file tree
Hide file tree
Showing 13 changed files with 249 additions and 50 deletions.
65 changes: 51 additions & 14 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,15 +156,20 @@ export class Enum extends ReflectionObject {
* @param name Unique name within its namespace
* @param [values] Enum values as an object, by name
* @param [options] Declared options
* @param [comment] The comment for this enum
* @param [comments] The value comments for this enum
*/
constructor(name: string, values?: { [k: string]: number }, options?: { [k: string]: any });
constructor(name: string, values?: { [k: string]: number }, options?: { [k: string]: any }, comment?: string, comments?: { [k: string]: string });

/** Enum values by id. */
public valuesById: { [k: number]: string };

/** Enum values by name. */
public values: { [k: string]: number };

/** Enum comment text. */
public comment: (string|null);

/** Value comment texts, if any. */
public comments: { [k: string]: string };

Expand All @@ -182,9 +187,10 @@ export class Enum extends ReflectionObject {

/**
* Converts this enum to an enum descriptor.
* @param [toJSONOptions] JSON conversion options
* @returns Enum descriptor
*/
public toJSON(): IEnum;
public toJSON(toJSONOptions?: IToJSONOptions): IEnum;

/**
* Adds a value to this enum.
Expand Down Expand Up @@ -288,8 +294,9 @@ export class FieldBase extends ReflectionObject {
* @param [rule="optional"] Field rule
* @param [extend] Extended type if different from parent
* @param [options] Declared options
* @param [comment] Comment associated with this field
*/
constructor(name: string, id: number, type: string, rule?: (string|{ [k: string]: any }), extend?: (string|{ [k: string]: any }), options?: { [k: string]: any });
constructor(name: string, id: number, type: string, rule?: (string|{ [k: string]: any }), extend?: (string|{ [k: string]: any }), options?: { [k: string]: any }, comment?: string);

/** Field rule, if any. */
public rule?: string;
Expand Down Expand Up @@ -342,11 +349,15 @@ export class FieldBase extends ReflectionObject {
/** Sister-field within the declaring namespace if an extended field. */
public declaringField: (Field|null);

/** Comment for this field. */
public comment: (string|null);

/**
* Converts this field to a field descriptor.
* @param [toJSONOptions] JSON conversion options
* @returns Field descriptor
*/
public toJSON(): IField;
public toJSON(toJSONOptions?: IToJSONOptions): IField;

/**
* Resolves this field's type references.
Expand Down Expand Up @@ -445,8 +456,9 @@ export class MapField extends FieldBase {
* @param keyType Key type
* @param type Value type
* @param [options] Declared options
* @param [comment] Comment associated with this field
*/
constructor(name: string, id: number, keyType: string, type: string, options?: { [k: string]: any });
constructor(name: string, id: number, keyType: string, type: string, options?: { [k: string]: any }, comment?: string);

/** Key type. */
public keyType: string;
Expand All @@ -465,9 +477,10 @@ export class MapField extends FieldBase {

/**
* Converts this map field to a map field descriptor.
* @param [toJSONOptions] JSON conversion options
* @returns Map field descriptor
*/
public toJSON(): IMapField;
public toJSON(toJSONOptions?: IToJSONOptions): IMapField;

/**
* Map field decorator (TypeScript).
Expand Down Expand Up @@ -586,8 +599,9 @@ export class Method extends ReflectionObject {
* @param [requestStream] Whether the request is streamed
* @param [responseStream] Whether the response is streamed
* @param [options] Declared options
* @param [comment] The comment for this method
*/
constructor(name: string, type: (string|undefined), requestType: string, responseType: string, requestStream?: (boolean|{ [k: string]: any }), responseStream?: (boolean|{ [k: string]: any }), options?: { [k: string]: any });
constructor(name: string, type: (string|undefined), requestType: string, responseType: string, requestStream?: (boolean|{ [k: string]: any }), responseStream?: (boolean|{ [k: string]: any }), options?: { [k: string]: any }, comment?: string);

/** Method type. */
public type: string;
Expand All @@ -610,6 +624,9 @@ export class Method extends ReflectionObject {
/** Resolved response type. */
public resolvedResponseType: (Type|null);

/** Comment for this method */
public comment: (string|null);

/**
* Constructs a method from a method descriptor.
* @param name Method name
Expand All @@ -621,9 +638,10 @@ export class Method extends ReflectionObject {

/**
* Converts this method to a method descriptor.
* @param [toJSONOptions] JSON conversion options
* @returns Method descriptor
*/
public toJSON(): IMethod;
public toJSON(toJSONOptions?: IToJSONOptions): IMethod;
}

/** Method descriptor. */
Expand Down Expand Up @@ -670,9 +688,10 @@ export class Namespace extends NamespaceBase {
/**
* Converts an array of reflection objects to JSON.
* @param array Object array
* @param [toJSONOptions] JSON conversion options
* @returns JSON object or `undefined` when array is empty
*/
public static arrayToJSON(array: ReflectionObject[]): ({ [k: string]: any }|undefined);
public static arrayToJSON(array: ReflectionObject[], toJSONOptions?: IToJSONOptions): ({ [k: string]: any }|undefined);

/**
* Tests if the specified id is reserved.
Expand Down Expand Up @@ -702,9 +721,10 @@ export abstract class NamespaceBase extends ReflectionObject {

/**
* Converts this namespace to a namespace descriptor.
* @param [toJSONOptions] JSON conversion options
* @returns Namespace descriptor
*/
public toJSON(): INamespace;
public toJSON(toJSONOptions?: IToJSONOptions): INamespace;

/**
* Adds nested objects to this namespace from nested object descriptors.
Expand Down Expand Up @@ -921,15 +941,19 @@ export class OneOf extends ReflectionObject {
* @param name Oneof name
* @param [fieldNames] Field names
* @param [options] Declared options
* @param [comment] Comment associated with this field
*/
constructor(name: string, fieldNames?: (string[]|{ [k: string]: any }), options?: { [k: string]: any });
constructor(name: string, fieldNames?: (string[]|{ [k: string]: any }), options?: { [k: string]: any }, comment?: string);

/** Field names that belong to this oneof. */
public oneof: string[];

/** Fields that belong to this oneof as an array for iteration. */
public readonly fieldsArray: Field[];

/** Comment for this field. */
public comment: (string|null);

/**
* Constructs a oneof from a oneof descriptor.
* @param name Oneof name
Expand All @@ -941,9 +965,10 @@ export class OneOf extends ReflectionObject {

/**
* Converts this oneof to a oneof descriptor.
* @param [toJSONOptions] JSON conversion options
* @returns Oneof descriptor
*/
public toJSON(): IOneOf;
public toJSON(toJSONOptions?: IToJSONOptions): IOneOf;

/**
* Adds a field to this oneof and removes it from its current parent, if any.
Expand Down Expand Up @@ -1016,6 +1041,16 @@ export interface IParseOptions {

/** Keeps field casing instead of converting to camel case */
keepCase?: boolean;

/** Recognize double-slash comments in addition to doc-block comments. */
alternateCommentMode?: boolean;
}

/** Options modifying the behavior of JSON serialization. */
export interface IToJSONOptions {

/** Serializes comments. */
keepComments?: boolean;
}

/**
Expand Down Expand Up @@ -1345,9 +1380,10 @@ export class Service extends NamespaceBase {

/**
* Converts this service to a service descriptor.
* @param [toJSONOptions] JSON conversion options
* @returns Service descriptor
*/
public toJSON(): IService;
public toJSON(toJSONOptions?: IToJSONOptions): IService;

/** Methods of this service as an array for iteration. */
public readonly methodsArray: Method[];
Expand Down Expand Up @@ -1497,9 +1533,10 @@ export class Type extends NamespaceBase {

/**
* Converts this message type to a message type descriptor.
* @param [toJSONOptions] JSON conversion options
* @returns Message type descriptor
*/
public toJSON(): IType;
public toJSON(toJSONOptions?: IToJSONOptions): IType;

/**
* Adds a nested object to this type.
Expand Down
22 changes: 17 additions & 5 deletions src/enum.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ var Namespace = require("./namespace"),
* @param {string} name Unique name within its namespace
* @param {Object.<string,number>} [values] Enum values as an object, by name
* @param {Object.<string,*>} [options] Declared options
* @param {string} [comment] The comment for this enum
* @param {Object.<string,string>} [comments] The value comments for this enum
*/
function Enum(name, values, options) {
function Enum(name, values, options, comment, comments) {
ReflectionObject.call(this, name, options);

if (values && typeof values !== "object")
Expand All @@ -35,11 +37,17 @@ function Enum(name, values, options) {
*/
this.values = Object.create(this.valuesById); // toJSON, marker

/**
* Enum comment text.
* @type {string|null}
*/
this.comment = comment;

/**
* Value comment texts, if any.
* @type {Object.<string,string>}
*/
this.comments = {};
this.comments = comments || {};

/**
* Reserved ranges, if any.
Expand Down Expand Up @@ -72,20 +80,24 @@ function Enum(name, values, options) {
* @throws {TypeError} If arguments are invalid
*/
Enum.fromJSON = function fromJSON(name, json) {
var enm = new Enum(name, json.values, json.options);
var enm = new Enum(name, json.values, json.options, json.comment, json.comments);
enm.reserved = json.reserved;
return enm;
};

/**
* Converts this enum to an enum descriptor.
* @param {IToJSONOptions} [toJSONOptions] JSON conversion options
* @returns {IEnum} Enum descriptor
*/
Enum.prototype.toJSON = function toJSON() {
Enum.prototype.toJSON = function toJSON(toJSONOptions) {
var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
return util.toObject([
"options" , this.options,
"values" , this.values,
"reserved" , this.reserved && this.reserved.length ? this.reserved : undefined
"reserved" , this.reserved && this.reserved.length ? this.reserved : undefined,
"comment" , keepComments ? this.comment : undefined,
"comments" , keepComments ? this.comments : undefined
]);
};

Expand Down
20 changes: 16 additions & 4 deletions src/field.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ var ruleRe = /^required|optional|repeated$/;
* @throws {TypeError} If arguments are invalid
*/
Field.fromJSON = function fromJSON(name, json) {
return new Field(name, json.id, json.type, json.rule, json.extend, json.options);
return new Field(name, json.id, json.type, json.rule, json.extend, json.options, json.comment);
};

/**
Expand All @@ -50,13 +50,16 @@ Field.fromJSON = function fromJSON(name, json) {
* @param {string|Object.<string,*>} [rule="optional"] Field rule
* @param {string|Object.<string,*>} [extend] Extended type if different from parent
* @param {Object.<string,*>} [options] Declared options
* @param {string} [comment] Comment associated with this field
*/
function Field(name, id, type, rule, extend, options) {
function Field(name, id, type, rule, extend, options, comment) {

if (util.isObject(rule)) {
comment = extend;
options = rule;
rule = extend = undefined;
} else if (util.isObject(extend)) {
comment = options;
options = extend;
extend = undefined;
}
Expand Down Expand Up @@ -183,6 +186,12 @@ function Field(name, id, type, rule, extend, options) {
* @private
*/
this._packed = null;

/**
* Comment for this field.
* @type {string|null}
*/
this.comment = comment;
}

/**
Expand Down Expand Up @@ -227,15 +236,18 @@ Field.prototype.setOption = function setOption(name, value, ifNotSet) {

/**
* Converts this field to a field descriptor.
* @param {IToJSONOptions} [toJSONOptions] JSON conversion options
* @returns {IField} Field descriptor
*/
Field.prototype.toJSON = function toJSON() {
Field.prototype.toJSON = function toJSON(toJSONOptions) {
var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
return util.toObject([
"rule" , this.rule !== "optional" && this.rule || undefined,
"type" , this.type,
"id" , this.id,
"extend" , this.extend,
"options" , this.options
"options" , this.options,
"comment" , keepComments ? this.comment : undefined
]);
};

Expand Down
14 changes: 9 additions & 5 deletions src/mapfield.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ var types = require("./types"),
* @param {string} keyType Key type
* @param {string} type Value type
* @param {Object.<string,*>} [options] Declared options
* @param {string} [comment] Comment associated with this field
*/
function MapField(name, id, keyType, type, options) {
Field.call(this, name, id, type, options);
function MapField(name, id, keyType, type, options, comment) {
Field.call(this, name, id, type, undefined, undefined, options, comment);

/* istanbul ignore if */
if (!util.isString(keyType))
Expand Down Expand Up @@ -64,20 +65,23 @@ function MapField(name, id, keyType, type, options) {
* @throws {TypeError} If arguments are invalid
*/
MapField.fromJSON = function fromJSON(name, json) {
return new MapField(name, json.id, json.keyType, json.type, json.options);
return new MapField(name, json.id, json.keyType, json.type, json.options, json.comment);
};

/**
* Converts this map field to a map field descriptor.
* @param {IToJSONOptions} [toJSONOptions] JSON conversion options
* @returns {IMapField} Map field descriptor
*/
MapField.prototype.toJSON = function toJSON() {
MapField.prototype.toJSON = function toJSON(toJSONOptions) {
var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
return util.toObject([
"keyType" , this.keyType,
"type" , this.type,
"id" , this.id,
"extend" , this.extend,
"options" , this.options
"options" , this.options,
"comment" , keepComments ? this.comment : undefined
]);
};

Expand Down
Loading

0 comments on commit 462132f

Please sign in to comment.