From db2dd49f6aab6ecd606eee334b95cc0969e483c2 Mon Sep 17 00:00:00 2001 From: dcodeIO Date: Mon, 27 Nov 2017 17:45:05 +0100 Subject: [PATCH] Fixed: Prevent invalid JSDoc names when generating service methods, see #870 --- cli/targets/static.js | 2 +- scripts/gentests.js | 2 + tests/data/rpc-es6.js | 2 +- tests/data/rpc-reserved.d.ts | 49 ++++ tests/data/rpc-reserved.js | 454 ++++++++++++++++++++++++++++++++++ tests/data/rpc-reserved.proto | 13 + tests/data/rpc.js | 2 +- 7 files changed, 521 insertions(+), 3 deletions(-) create mode 100644 tests/data/rpc-reserved.d.ts create mode 100644 tests/data/rpc-reserved.js create mode 100644 tests/data/rpc-reserved.proto diff --git a/cli/targets/static.js b/cli/targets/static.js index 021152ba6..d44be23c1 100644 --- a/cli/targets/static.js +++ b/cli/targets/static.js @@ -645,7 +645,7 @@ function buildService(ref, service) { push(""); pushComment([ method.comment || "Calls " + method.name + ".", - "@function " + util.safeProp(lcName), + "@function " + lcName, "@memberof " + exportName(service), "@instance", "@param {" + exportName(method.resolvedRequestType, !config.forceMessage) + "} request " + method.resolvedRequestType.name + " message or plain object", diff --git a/scripts/gentests.js b/scripts/gentests.js index 67345ef8c..a635a8923 100644 --- a/scripts/gentests.js +++ b/scripts/gentests.js @@ -11,6 +11,7 @@ var fs = require("fs"), { file: "tests/data/package.proto", flags: [] }, { file: "tests/data/rpc.proto", flags: [ "es6" ] }, { file: "tests/data/rpc.proto", flags: [] }, + { file: "tests/data/rpc-reserved.proto", flags: [] }, { file: "tests/data/test.proto", flags: [] }, { file: "bench/data/bench.proto", flags: ["no-create", "no-verify", "no-delimited", "no-convert", "no-comments"], out: "bench/data/static_pbjs.js" } ] @@ -50,6 +51,7 @@ process.stdout.write("\n"); { file: "tests/data/package.js" }, { file: "tests/data/rpc.js" }, { file: "tests/data/rpc-es6.js" }, + { file: "tests/data/rpc-reserved.js" }, { file: "tests/data/test.js" }, { file: "ext/descriptor/index.js", ext: true } ] diff --git a/tests/data/rpc-es6.js b/tests/data/rpc-es6.js index 650abeeb4..4103a287b 100644 --- a/tests/data/rpc-es6.js +++ b/tests/data/rpc-es6.js @@ -50,7 +50,7 @@ export const MyService = $root.MyService = (() => { /** * Calls MyMethod. - * @function .myMethod + * @function myMethod * @memberof MyService * @instance * @param {IMyRequest} request MyRequest message or plain object diff --git a/tests/data/rpc-reserved.d.ts b/tests/data/rpc-reserved.d.ts new file mode 100644 index 000000000..d08439125 --- /dev/null +++ b/tests/data/rpc-reserved.d.ts @@ -0,0 +1,49 @@ +import * as $protobuf from "../.."; + +export class MyService extends $protobuf.rpc.Service { + constructor(rpcImpl: $protobuf.RPCImpl, requestDelimited?: boolean, responseDelimited?: boolean); + public static create(rpcImpl: $protobuf.RPCImpl, requestDelimited?: boolean, responseDelimited?: boolean): MyService; + public delete(request: IMyRequest, callback: MyService.DeleteCallback): void; + public delete(request: IMyRequest): Promise; +} + +export namespace MyService { + + type DeleteCallback = (error: (Error|null), response?: MyResponse) => void; +} + +export interface IMyRequest { + path?: (string|null); +} + +export class MyRequest implements IMyRequest { + constructor(properties?: IMyRequest); + public path: string; + public static create(properties?: IMyRequest): MyRequest; + public static encode(message: IMyRequest, writer?: $protobuf.Writer): $protobuf.Writer; + public static encodeDelimited(message: IMyRequest, writer?: $protobuf.Writer): $protobuf.Writer; + public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): MyRequest; + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): MyRequest; + public static verify(message: { [k: string]: any }): (string|null); + public static fromObject(object: { [k: string]: any }): MyRequest; + public static toObject(message: MyRequest, options?: $protobuf.IConversionOptions): { [k: string]: any }; + public toJSON(): { [k: string]: any }; +} + +export interface IMyResponse { + status?: (number|null); +} + +export class MyResponse implements IMyResponse { + constructor(properties?: IMyResponse); + public status: number; + public static create(properties?: IMyResponse): MyResponse; + public static encode(message: IMyResponse, writer?: $protobuf.Writer): $protobuf.Writer; + public static encodeDelimited(message: IMyResponse, writer?: $protobuf.Writer): $protobuf.Writer; + public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): MyResponse; + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): MyResponse; + public static verify(message: { [k: string]: any }): (string|null); + public static fromObject(object: { [k: string]: any }): MyResponse; + public static toObject(message: MyResponse, options?: $protobuf.IConversionOptions): { [k: string]: any }; + public toJSON(): { [k: string]: any }; +} diff --git a/tests/data/rpc-reserved.js b/tests/data/rpc-reserved.js new file mode 100644 index 000000000..efee206b7 --- /dev/null +++ b/tests/data/rpc-reserved.js @@ -0,0 +1,454 @@ +/*eslint-disable block-scoped-var, no-redeclare, no-control-regex, no-prototype-builtins*/ +"use strict"; + +var $protobuf = require("../../minimal"); + +// Common aliases +var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util; + +// Exported root namespace +var $root = $protobuf.roots["test_rpc-reserved"] || ($protobuf.roots["test_rpc-reserved"] = {}); + +$root.MyService = (function() { + + /** + * Constructs a new MyService service. + * @exports MyService + * @classdesc Represents a MyService + * @extends $protobuf.rpc.Service + * @constructor + * @param {$protobuf.RPCImpl} rpcImpl RPC implementation + * @param {boolean} [requestDelimited=false] Whether requests are length-delimited + * @param {boolean} [responseDelimited=false] Whether responses are length-delimited + */ + function MyService(rpcImpl, requestDelimited, responseDelimited) { + $protobuf.rpc.Service.call(this, rpcImpl, requestDelimited, responseDelimited); + } + + (MyService.prototype = Object.create($protobuf.rpc.Service.prototype)).constructor = MyService; + + /** + * Creates new MyService service using the specified rpc implementation. + * @function create + * @memberof MyService + * @static + * @param {$protobuf.RPCImpl} rpcImpl RPC implementation + * @param {boolean} [requestDelimited=false] Whether requests are length-delimited + * @param {boolean} [responseDelimited=false] Whether responses are length-delimited + * @returns {MyService} RPC service. Useful where requests and/or responses are streamed. + */ + MyService.create = function create(rpcImpl, requestDelimited, responseDelimited) { + return new this(rpcImpl, requestDelimited, responseDelimited); + }; + + /** + * Callback as used by {@link MyService#delete_}. + * @memberof MyService + * @typedef DeleteCallback + * @type {function} + * @param {Error|null} error Error, if any + * @param {MyResponse} [response] MyResponse + */ + + /** + * Calls Delete. + * @function delete + * @memberof MyService + * @instance + * @param {IMyRequest} request MyRequest message or plain object + * @param {MyService.DeleteCallback} callback Node-style callback called with the error, if any, and MyResponse + * @returns {undefined} + * @variation 1 + */ + MyService.prototype["delete"] = function delete_(request, callback) { + return this.rpcCall(delete_, $root.MyRequest, $root.MyResponse, request, callback); + }; + + /** + * Calls Delete. + * @function delete + * @memberof MyService + * @instance + * @param {IMyRequest} request MyRequest message or plain object + * @returns {Promise} Promise + * @variation 2 + */ + + return MyService; +})(); + +$root.MyRequest = (function() { + + /** + * Properties of a MyRequest. + * @exports IMyRequest + * @interface IMyRequest + * @property {string|null} [path] MyRequest path + */ + + /** + * Constructs a new MyRequest. + * @exports MyRequest + * @classdesc Represents a MyRequest. + * @implements IMyRequest + * @constructor + * @param {IMyRequest=} [properties] Properties to set + */ + function MyRequest(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * MyRequest path. + * @member {string} path + * @memberof MyRequest + * @instance + */ + MyRequest.prototype.path = ""; + + /** + * Creates a new MyRequest instance using the specified properties. + * @function create + * @memberof MyRequest + * @static + * @param {IMyRequest=} [properties] Properties to set + * @returns {MyRequest} MyRequest instance + */ + MyRequest.create = function create(properties) { + return new MyRequest(properties); + }; + + /** + * Encodes the specified MyRequest message. Does not implicitly {@link MyRequest.verify|verify} messages. + * @function encode + * @memberof MyRequest + * @static + * @param {IMyRequest} message MyRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MyRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.path != null && message.hasOwnProperty("path")) + writer.uint32(/* id 1, wireType 2 =*/10).string(message.path); + return writer; + }; + + /** + * Encodes the specified MyRequest message, length delimited. Does not implicitly {@link MyRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof MyRequest + * @static + * @param {IMyRequest} message MyRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MyRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a MyRequest message from the specified reader or buffer. + * @function decode + * @memberof MyRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {MyRequest} MyRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MyRequest.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.MyRequest(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.path = reader.string(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a MyRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof MyRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {MyRequest} MyRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MyRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a MyRequest message. + * @function verify + * @memberof MyRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + MyRequest.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.path != null && message.hasOwnProperty("path")) + if (!$util.isString(message.path)) + return "path: string expected"; + return null; + }; + + /** + * Creates a MyRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof MyRequest + * @static + * @param {Object.} object Plain object + * @returns {MyRequest} MyRequest + */ + MyRequest.fromObject = function fromObject(object) { + if (object instanceof $root.MyRequest) + return object; + var message = new $root.MyRequest(); + if (object.path != null) + message.path = String(object.path); + return message; + }; + + /** + * Creates a plain object from a MyRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof MyRequest + * @static + * @param {MyRequest} message MyRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + MyRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) + object.path = ""; + if (message.path != null && message.hasOwnProperty("path")) + object.path = message.path; + return object; + }; + + /** + * Converts this MyRequest to JSON. + * @function toJSON + * @memberof MyRequest + * @instance + * @returns {Object.} JSON object + */ + MyRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return MyRequest; +})(); + +$root.MyResponse = (function() { + + /** + * Properties of a MyResponse. + * @exports IMyResponse + * @interface IMyResponse + * @property {number|null} [status] MyResponse status + */ + + /** + * Constructs a new MyResponse. + * @exports MyResponse + * @classdesc Represents a MyResponse. + * @implements IMyResponse + * @constructor + * @param {IMyResponse=} [properties] Properties to set + */ + function MyResponse(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * MyResponse status. + * @member {number} status + * @memberof MyResponse + * @instance + */ + MyResponse.prototype.status = 0; + + /** + * Creates a new MyResponse instance using the specified properties. + * @function create + * @memberof MyResponse + * @static + * @param {IMyResponse=} [properties] Properties to set + * @returns {MyResponse} MyResponse instance + */ + MyResponse.create = function create(properties) { + return new MyResponse(properties); + }; + + /** + * Encodes the specified MyResponse message. Does not implicitly {@link MyResponse.verify|verify} messages. + * @function encode + * @memberof MyResponse + * @static + * @param {IMyResponse} message MyResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MyResponse.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.status != null && message.hasOwnProperty("status")) + writer.uint32(/* id 2, wireType 0 =*/16).int32(message.status); + return writer; + }; + + /** + * Encodes the specified MyResponse message, length delimited. Does not implicitly {@link MyResponse.verify|verify} messages. + * @function encodeDelimited + * @memberof MyResponse + * @static + * @param {IMyResponse} message MyResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MyResponse.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a MyResponse message from the specified reader or buffer. + * @function decode + * @memberof MyResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {MyResponse} MyResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MyResponse.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.MyResponse(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 2: + message.status = reader.int32(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a MyResponse message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof MyResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {MyResponse} MyResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MyResponse.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a MyResponse message. + * @function verify + * @memberof MyResponse + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + MyResponse.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.status != null && message.hasOwnProperty("status")) + if (!$util.isInteger(message.status)) + return "status: integer expected"; + return null; + }; + + /** + * Creates a MyResponse message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof MyResponse + * @static + * @param {Object.} object Plain object + * @returns {MyResponse} MyResponse + */ + MyResponse.fromObject = function fromObject(object) { + if (object instanceof $root.MyResponse) + return object; + var message = new $root.MyResponse(); + if (object.status != null) + message.status = object.status | 0; + return message; + }; + + /** + * Creates a plain object from a MyResponse message. Also converts values to other types if specified. + * @function toObject + * @memberof MyResponse + * @static + * @param {MyResponse} message MyResponse + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + MyResponse.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) + object.status = 0; + if (message.status != null && message.hasOwnProperty("status")) + object.status = message.status; + return object; + }; + + /** + * Converts this MyResponse to JSON. + * @function toJSON + * @memberof MyResponse + * @instance + * @returns {Object.} JSON object + */ + MyResponse.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return MyResponse; +})(); + +module.exports = $root; diff --git a/tests/data/rpc-reserved.proto b/tests/data/rpc-reserved.proto new file mode 100644 index 000000000..17193f9d2 --- /dev/null +++ b/tests/data/rpc-reserved.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +service MyService { + rpc Delete (MyRequest) returns (MyResponse); +} + +message MyRequest { + string path = 1; +} + +message MyResponse { + int32 status = 2; +} diff --git a/tests/data/rpc.js b/tests/data/rpc.js index 391fcfcf1..14235e958 100644 --- a/tests/data/rpc.js +++ b/tests/data/rpc.js @@ -52,7 +52,7 @@ $root.MyService = (function() { /** * Calls MyMethod. - * @function .myMethod + * @function myMethod * @memberof MyService * @instance * @param {IMyRequest} request MyRequest message or plain object