UNPKG

@protobuf-ts/plugin

Version:

The protocol buffer compiler plugin "protobuf-ts" generates TypeScript, gRPC-web, Twirp, and more.

157 lines (156 loc) 6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CommentGenerator = void 0; const ts = require("typescript"); const protoplugin_1 = require("@bufbuild/protoplugin"); const typescript_comments_1 = require("../framework/typescript-comments"); class CommentGenerator { constructor() { } /** * Adds comments from the .proto as a JSDoc block. * * Looks up comments for the given descriptor in * the source code info. * * Adds `@deprecated` tag if the element is * marked deprecated. Also adds @deprecated if * the descriptor is a type (enum, message) and * the entire .proto file is marked deprecated. * * Adds `@generated` tag with source code * information. * * Leading detached comments are added as line * comments in front of the JSDoc block. * * Trailing comments are a bit weird. For .proto * enums and messages, they sit between open * bracket and first member. A message seems to * only ever have a trailing comment if it is * empty. For a simple solution, trailing * comments on enums and messages should simply * be appended to the leading block so that the * information is not discarded. */ addCommentsForDescriptor(node, descriptor, trailingCommentsMode) { if (descriptor.kind == "file") { return; } const source = this.getComments(descriptor); // add leading detached comments as line comments typescript_comments_1.addCommentBlocksAsLeadingDetachedLines(node, ...source.leadingDetached); // start with leading block let leading = this.getCommentBlock(descriptor, trailingCommentsMode === "appendToLeadingBlock"); // add leading block as jsdoc comment block typescript_comments_1.addCommentBlockAsJsDoc(node, leading); // add trailing comments as trailing line comments if (source.trailing && trailingCommentsMode === 'trailingLines') { let lines = source.trailing.split('\n').map(l => l[0] !== ' ' ? ` ${l}` : l); for (let line of lines) { ts.addSyntheticTrailingComment(node, ts.SyntaxKind.SingleLineCommentTrivia, line, true); } } } getComments(desc) { if (desc.kind == "file") { return { leadingDetached: [], }; } const comments = protoplugin_1.getComments(desc); return { leading: comments.leading !== undefined ? this.stripTrailingNewlines(comments.leading) : comments.leading, trailing: comments.trailing !== undefined ? this.stripTrailingNewlines(comments.trailing) : comments.trailing, leadingDetached: comments.leadingDetached.map(t => this.stripTrailingNewlines(t)), }; } stripTrailingNewlines(block) { return block.endsWith('\n') ? block.slice(0, -1) : block; } /** * Returns a block of source comments (no leading detached!), * with @generated tags and @deprecated tag (if applicable). */ getCommentBlock(descriptor, appendTrailingComments = false) { var _a; if (descriptor.kind == "file") { return ""; } const source = this.getComments(descriptor); // start with leading block let commentBlock = (_a = source.leading) !== null && _a !== void 0 ? _a : ''; // add trailing comments to the leading block if (source.trailing && appendTrailingComments) { if (commentBlock.length > 0) { commentBlock += '\n\n'; } commentBlock += source.trailing; } // if there were any leading comments, we need some space if (commentBlock.length > 0) { commentBlock += '\n\n'; } // add deprecated information to the leading block commentBlock += this.makeDeprecatedTag(descriptor); // add source info to the leading block commentBlock += this.makeGeneratedTag(descriptor); return commentBlock; } /** * Creates string like "@generated from protobuf field: string foo = 1;" */ makeGeneratedTag(desc) { switch (desc.kind) { case "oneof": return `@generated from protobuf oneof: ${desc.name}`; case "enum_value": return `@generated from protobuf enum value: ${protoplugin_1.getDeclarationString(desc)};`; case "field": return `@generated from protobuf field: ${protoplugin_1.getDeclarationString(desc)}`; case "extension": return `@generated from protobuf extension: ${protoplugin_1.getDeclarationString(desc)}`; case "rpc": return `@generated from protobuf rpc: ${desc.name}`; case "message": case "enum": case "service": case "file": return `@generated from protobuf ${desc.toString()}`; } } /** * Returns "@deprecated\n" if explicitly deprecated. * For top level types, also returns "@deprecated\n" if entire file is deprecated. * Otherwise, returns "". */ makeDeprecatedTag(desc) { if (CommentGenerator.isDeprecated(desc)) { return '@deprecated\n'; } return ''; } static isDeprecated(desc) { if (desc.kind == "file") { return false; } if (desc.deprecated) { return true; } switch (desc.kind) { case "enum": case "service": case "message": case "extension": return desc.file.deprecated; case "field": case "rpc": case "enum_value": case "oneof": return desc.parent.file.deprecated; } } } exports.CommentGenerator = CommentGenerator;