UNPKG

thrift-fmt-ts

Version:

A formatter of Thrift, re-implement of python thrift-fmt

835 lines (834 loc) 30.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ThriftFormatter = exports.calcFieldAlignByAssignPadding = exports.PureThriftFormatter = exports.splitRepeatNodes = exports.walkNode = exports.getNodeChildren = exports.splitFieldByAssign = exports.isEOF = exports.isToken = exports.newOption = void 0; const antlr4ts_1 = require("antlr4ts"); const tree_1 = require("antlr4ts/tree"); const thrift_parser_ts_1 = require("thrift-parser-ts"); const ThriftParserNS = __importStar(require("thrift-parser-ts/lib/ThriftParser")); const newOption = (opt) => { const defaultOption = { indent: 4, patchRequired: true, patchSeparator: true, keepComment: true, alignByAssign: false, alignByField: false, }; return { ...defaultOption, ...opt, }; }; exports.newOption = newOption; const isToken = (node, text) => { return node instanceof tree_1.TerminalNode && node.symbol.text === text; }; exports.isToken = isToken; const isEOF = (node) => { return node instanceof tree_1.TerminalNode && node.symbol.type === thrift_parser_ts_1.ThriftParser.EOF; }; exports.isEOF = isEOF; const fakeNodeLineNo = -1; const isFakeNode = (node) => { return node.symbol.line === fakeNodeLineNo; }; const notSameClass = (a, b) => { return a.constructor.name !== b.constructor.name; }; const isNeedNewLineNode = (node) => { return (node instanceof ThriftParserNS.Enum_ruleContext || node instanceof ThriftParserNS.Struct_Context || node instanceof ThriftParserNS.Union_Context || node instanceof ThriftParserNS.Exception_Context || node instanceof ThriftParserNS.ServiceContext); }; const isFunctionOrThrowsListNode = (node) => { return (node instanceof ThriftParserNS.Function_Context || node instanceof ThriftParserNS.Throws_listContext); }; const isFieldOrEnumField = (node) => { return (node instanceof ThriftParserNS.FieldContext || node instanceof ThriftParserNS.Enum_fieldContext); }; const splitFieldChildrenByAssign = (node) => { const children = node.children || []; let i = 0; let curLeft = true; for (; i < node.childCount; i++) { const child = node.getChild(i); if ((0, exports.isToken)(child, '=') || (child instanceof ThriftParserNS.List_separatorContext)) { curLeft = false; break; } } // current child is belong to left. if (curLeft) { i++; } const left = children.slice(0, i); const right = children.slice(i); return [left, right]; }; const splitFieldByAssign = (node) => { /* split field's children to [left, right] field: '1: required i32 number_a = 0,' left: '1: required i32 number_a' right: '= 0,' */ let left = undefined; let right = undefined; if (node instanceof ThriftParserNS.FieldContext) { left = new ThriftParserNS.FieldContext(node.parent, 0); right = new ThriftParserNS.FieldContext(node.parent, 0); } else { left = new ThriftParserNS.Enum_fieldContext(node.parent, 0); right = new ThriftParserNS.Enum_fieldContext(node.parent, 0); } const [leftChildren, rightChildren] = splitFieldChildrenByAssign(node); for (const child of leftChildren) { left.addAnyChild(child); } for (const child of rightChildren) { right.addAnyChild(child); } return [left, right]; }; exports.splitFieldByAssign = splitFieldByAssign; const getSplitFieldsLeftRightSize = (fields) => { let leftMaxSize = 0; let rightMaxSize = 0; for (const field of fields) { const node = field; const [left, right] = (0, exports.splitFieldByAssign)(node); const leftSize = new PureThriftFormatter().formatNode(left).length; const rightSize = new PureThriftFormatter().formatNode(right).length; leftMaxSize = leftMaxSize > leftSize ? leftMaxSize : leftSize; rightMaxSize = rightMaxSize > rightSize ? rightMaxSize : rightSize; } return [leftMaxSize, rightMaxSize]; }; const getNodeChildren = (node) => { const children = []; for (let i = 0; i < node.childCount; i++) { children.push(node.getChild(i)); } return children; }; exports.getNodeChildren = getNodeChildren; const walkNode = (root, callback) => { const stack = [root]; while (stack.length > 0) { const node = stack.shift(); if (node === undefined) { break; } callback(node); const children = (0, exports.getNodeChildren)(node); children.forEach(value => stack.push(value)); } }; exports.walkNode = walkNode; const splitRepeatNodes = (nodes, kindFn) => { const children = []; for (const [index, node] of nodes.entries()) { if (!kindFn(node)) { return [children, nodes.slice(index)]; } children.push(node); } return [children, []]; }; exports.splitRepeatNodes = splitRepeatNodes; const genInlineContext = (join = ' ', tightFn) => { return function (node) { for (let i = 0; i < node.childCount; i++) { const child = node.getChild(i); if (i > 0 && join.length > 0) { if (!tightFn || !tightFn(i, child)) { this.append(join); } } this.processNode(child); } }; }; const genSubblocksContext = (start, kindFn) => { return function (node) { const children = (0, exports.getNodeChildren)(node); this.processInlineNodes(children.slice(0, start)); this.newline(); const leftChildren = children.slice(start); const [subblocks, leftNodes] = (0, exports.splitRepeatNodes)(leftChildren, kindFn); this.beforeSubblocks(subblocks); this.processBlockNodes(subblocks, ' '.repeat(this._option.indent)); this.afterSubblocks(subblocks); this.newline(); this.processInlineNodes(leftNodes); }; }; const tupleTightInline = genInlineContext(' ', (i, n) => (0, exports.isToken)(n, '(') || (0, exports.isToken)(n, ')') || (0, exports.isToken)(n.parent?.getChild(i - 1), '(') || n instanceof ThriftParserNS.List_separatorContext); const listSeparatorInline = genInlineContext(' ', (_, node) => node instanceof ThriftParserNS.List_separatorContext); const fieldSubblocks = genSubblocksContext(3, (n) => n instanceof ThriftParserNS.FieldContext); class PureThriftFormatter { _option = (0, exports.newOption)(); currentIndent = ''; newlineCounter = 0; _out = ''; formatNode(node) { this._out = ''; this.newlineCounter = 0; this.currentIndent = ''; this.processNode(node); return this._out; } option(opt) { this._option = opt; } get out() { return this._out; } push(text) { this._out += text; } // if this.newlineCounter was set. `append` will first write newlines and then append append(text) { if (this.newlineCounter > 0) { this.push('\n'.repeat(this.newlineCounter)); this.newlineCounter = 0; } this.push(text); } // appendCurrentLine append to current line, and ignore this.newlineCounter. appendCurrentLine(text) { this.push(text); } newline(repeat = 1) { const diff = repeat - this.newlineCounter; if (diff > 0) { this.newlineCounter += diff; } } setCurrentIndent(indent = '') { this.currentIndent = indent; } pushCurrentIndent() { if (this.currentIndent.length > 0) { this.append(this.currentIndent); } } beforeBlockNode(_) { } // eslint-disable-line afterBlockNode(_) { } // eslint-disable-line beforeSubblocks(_) { } // eslint-disable-line afterSubblocks(_) { } // eslint-disable-line beforeProcessNode(_) { } // eslint-disable-line afterProcessNode(_) { } // eslint-disable-line processBlockNodes(nodes, indent = '') { let lastNode = undefined; // eslint-disable-next-line for (let [index, node] of nodes.entries()) { if (node instanceof ThriftParserNS.HeaderContext || node instanceof ThriftParserNS.DefinitionContext) { node = node.getChild(0); } this.beforeBlockNode(node); if (index > 0 && lastNode !== undefined) { if (notSameClass(lastNode, node) || isNeedNewLineNode(node)) { this.newline(2); } else { this.newline(); } } this.setCurrentIndent(indent); this.processNode(node); this.afterBlockNode(node); lastNode = node; } } processInlineNodes(nodes, join = ' ') { // eslint-disable-next-line for (const [index, node] of nodes.entries()) { if (index > 0) { this.append(join); } this.processNode(node); } } processNode(node) { this.beforeProcessNode(node); this._processNode(node); this.afterProcessNode(node); } _processNode(node) { if (node instanceof tree_1.TerminalNode) { this.TerminalNode(node); } else if (node instanceof ThriftParserNS.DocumentContext) { this.DocumentContext(node); } else if (node instanceof ThriftParserNS.HeaderContext) { this.HeaderContext(node); } else if (node instanceof ThriftParserNS.DefinitionContext) { this.DefinitionContext(node); } else if (node instanceof ThriftParserNS.Include_Context) { this.Include_Context(node); } else if (node instanceof ThriftParserNS.Namespace_Context) { this.Namespace_Context(node); } else if (node instanceof ThriftParserNS.Typedef_Context) { this.Typedef_Context(node); } else if (node instanceof ThriftParserNS.Base_typeContext) { this.Base_typeContext(node); } else if (node instanceof ThriftParserNS.Real_base_typeContext) { this.Real_base_typeContext(node); } else if (node instanceof ThriftParserNS.Const_ruleContext) { this.Const_ruleContext(node); } else if (node instanceof ThriftParserNS.Const_valueContext) { this.Const_valueContext(node); } else if (node instanceof ThriftParserNS.IntegerContext) { this.IntegerContext(node); } else if (node instanceof ThriftParserNS.Container_typeContext) { this.Container_typeContext(node); } else if (node instanceof ThriftParserNS.Set_typeContext) { this.Set_typeContext(node); } else if (node instanceof ThriftParserNS.List_typeContext) { this.List_typeContext(node); } else if (node instanceof ThriftParserNS.Cpp_typeContext) { this.Cpp_typeContext(node); } else if (node instanceof ThriftParserNS.Const_mapContext) { this.Const_mapContext(node); } else if (node instanceof ThriftParserNS.Const_map_entryContext) { this.Const_map_entryContext(node); } else if (node instanceof ThriftParserNS.List_separatorContext) { this.List_separatorContext(node); } else if (node instanceof ThriftParserNS.Field_idContext) { this.Field_idContext(node); } else if (node instanceof ThriftParserNS.Field_reqContext) { this.Field_reqContext(node); } else if (node instanceof ThriftParserNS.Field_typeContext) { this.Field_typeContext(node); } else if (node instanceof ThriftParserNS.Map_typeContext) { this.Map_typeContext(node); } else if (node instanceof ThriftParserNS.Const_listContext) { this.Const_listContext(node); } else if (node instanceof ThriftParserNS.Enum_ruleContext) { this.Enum_ruleContext(node); } else if (node instanceof ThriftParserNS.Struct_Context) { this.Struct_Context(node); } else if (node instanceof ThriftParserNS.Union_Context) { this.Union_Context(node); } else if (node instanceof ThriftParserNS.Exception_Context) { this.Exception_Context(node); } else if (node instanceof ThriftParserNS.Enum_fieldContext) { this.Enum_fieldContext(node); } else if (node instanceof ThriftParserNS.FieldContext) { this.FieldContext(node); } else if (node instanceof ThriftParserNS.Function_Context) { this.Function_Context(node); } else if (node instanceof ThriftParserNS.OnewayContext) { this.OnewayContext(node); } else if (node instanceof ThriftParserNS.Function_typeContext) { this.Function_typeContext(node); } else if (node instanceof ThriftParserNS.Throws_listContext) { this.Throws_listContext(node); } else if (node instanceof ThriftParserNS.Type_annotationsContext) { this.Type_annotationsContext(node); } else if (node instanceof ThriftParserNS.Type_annotationContext) { this.Type_annotationContext(node); } else if (node instanceof ThriftParserNS.Annotation_valueContext) { this.Annotation_valueContext(node); } else if (node instanceof ThriftParserNS.ServiceContext) { this.ServiceContext(node); } else if (node instanceof ThriftParserNS.SenumContext) { this.SenumContext(node); } else { // unsupport node } } TerminalNode(node) { if ((0, exports.isEOF)(node)) { return; } this.pushCurrentIndent(); this.setCurrentIndent(''); this.append(node.symbol.text || ''); } DocumentContext = function (node) { const children = (0, exports.getNodeChildren)(node); this.processBlockNodes(children); }; HeaderContext = function (node) { this.processNode(node.getChild(0)); }; DefinitionContext = function (node) { this.processNode(node.getChild(0)); }; // TODO: clean this? Include_Context = genInlineContext(); Namespace_Context = genInlineContext(); Typedef_Context = genInlineContext(); Base_typeContext = genInlineContext(); Field_typeContext = genInlineContext(); Real_base_typeContext = genInlineContext(); Const_ruleContext = genInlineContext(); Const_valueContext = genInlineContext(); IntegerContext = genInlineContext(); Container_typeContext = genInlineContext(''); Set_typeContext = genInlineContext(''); List_typeContext = genInlineContext(''); Cpp_typeContext = genInlineContext(); Const_mapContext = genInlineContext(); Const_map_entryContext = genInlineContext(); List_separatorContext = genInlineContext(); Field_idContext = genInlineContext(''); Field_reqContext = genInlineContext(); Map_typeContext = genInlineContext(' ', (i, n) => !(0, exports.isToken)(n.parent?.getChild(i - 1), ',')); Const_listContext = listSeparatorInline; Enum_ruleContext = genSubblocksContext(3, (n) => n instanceof ThriftParserNS.Enum_fieldContext); Enum_fieldContext = listSeparatorInline; Struct_Context = fieldSubblocks; Union_Context = fieldSubblocks; Exception_Context = fieldSubblocks; FieldContext = listSeparatorInline; Function_Context = tupleTightInline; OnewayContext = genInlineContext(); Function_typeContext = genInlineContext(); Throws_listContext = tupleTightInline; Type_annotationsContext = tupleTightInline; Type_annotationContext = tupleTightInline; Annotation_valueContext = genInlineContext(); ServiceContext_Default = genSubblocksContext(3, (n) => n instanceof ThriftParserNS.Function_Context); ServiceContext_Extends = genSubblocksContext(5, (n) => n instanceof ThriftParserNS.Function_Context); ServiceContext = function (n) { const node = n; if ((0, exports.isToken)(node.getChild(2), 'extends')) { this.ServiceContext_Extends(node); } else { this.ServiceContext_Default(node); } }; SenumContext = function (_) { }; // eslint-disable-line } exports.PureThriftFormatter = PureThriftFormatter; const patchFieldRequired = (n) => { if (!(n instanceof ThriftParserNS.FieldContext)) { return; } if (n.parent === undefined || isFunctionOrThrowsListNode(n.parent)) { return; } let i = 0; for (; i < n.childCount; i++) { const child = n.getChild(i); if (child instanceof ThriftParserNS.Field_reqContext) { return; } if (child instanceof ThriftParserNS.Field_typeContext) { break; } } const fakeToken = new antlr4ts_1.CommonToken(thrift_parser_ts_1.ThriftParser.T__20, 'required'); fakeToken.line = fakeNodeLineNo; fakeToken.charPositionInLine = fakeNodeLineNo; fakeToken.tokenIndex = -1; const fakeNode = new tree_1.TerminalNode(fakeToken); const fakeReq = new ThriftParserNS.Field_reqContext(n, 0); fakeNode.setParent(fakeReq); fakeReq.addChild(fakeNode); fakeReq.setParent(n); n.children?.splice(i, 0, fakeReq); // addChild }; const patchFieldListSeparator = (n) => { if (!(n instanceof ThriftParserNS.Enum_fieldContext || n instanceof ThriftParserNS.FieldContext || n instanceof ThriftParserNS.Function_Context)) { return; } const child = n.getChild(n.childCount - 1); if (child instanceof ThriftParserNS.List_separatorContext) { const comma = child.getChild(0); const token = comma.symbol; token.text = ','; return; } const fakeToken = new antlr4ts_1.CommonToken(thrift_parser_ts_1.ThriftParser.COMMA, ','); fakeToken.line = fakeNodeLineNo; fakeToken.charPositionInLine = fakeNodeLineNo; fakeToken.tokenIndex = -1; const fakeNode = new tree_1.TerminalNode(fakeToken); const fakeCtx = new ThriftParserNS.List_separatorContext(n, 0); fakeNode.setParent(fakeCtx); fakeCtx.addChild(fakeNode); fakeCtx.setParent(n); n.addChild(fakeCtx); }; const patchRemoveLastListSeparator = (n) => { const isInlineField = n instanceof ThriftParserNS.FieldContext && n.parent !== undefined && isFunctionOrThrowsListNode(n.parent); const isInlineNode = n instanceof ThriftParserNS.Type_annotationContext; if (!(isInlineField || isInlineNode)) { return; } if (n.parent === undefined) { return; } let last = false; const brothers = n.parent.children || []; const bortherCount = n.parent.childCount; for (let i = 0; i < bortherCount; i++) { if (brothers[i] === n) { if (i === bortherCount - 1 || notSameClass(n, brothers[i + 1])) { last = true; break; } } } if (last) { const child = n.getChild(n.childCount - 1); if (child instanceof ThriftParserNS.List_separatorContext) { n.removeLastChild(); } } }; const calcSubBlocksCommentPadding = (subblocks) => { let padding = 0; for (const subblock of subblocks) { const nodeLength = (new PureThriftFormatter().formatNode(subblock)).length; padding = padding >= nodeLength ? padding : nodeLength; } if (padding > 0) { padding = padding + 1; } return padding; }; const calcFieldAlignByAssignPadding = (fields) => { if (fields.length === 0 || !isFieldOrEnumField(fields[0])) { return [0, 0]; } const [leftMaxSize, rightMaxSize] = getSplitFieldsLeftRightSize(fields); // add extra space "xxx = yyy" -> "xxx" + " " + "= yyy" const assignPadding = leftMaxSize + 1; let commentPadding = assignPadding + rightMaxSize + 1; // add an extra space for next comment /* if it is not list sep, need add extra space case 1 --> "1: bool a = true," ---> "1: bool a" + " " + "= true," case 2 --> "2: bool b," ---> "2: bool b" + "" + "," */ if (rightMaxSize <= 1) { // case 1 commentPadding = commentPadding - 1; } return [assignPadding, commentPadding]; }; exports.calcFieldAlignByAssignPadding = calcFieldAlignByAssignPadding; const getFieldChildName = (n) => { if ((0, exports.isToken)(n, '=')) { return '='; } return n.constructor.name; }; const calcFieldAlignByFieldPaddingMap = (fields) => { const paddingMap = new Map(); if (fields.length == 0 || !isFieldOrEnumField(fields[0])) { return [paddingMap, 0]; } const nameLevels = new Map(); for (const field of fields) { let i = 0; for (; i < field.childCount - 1; i++) { const nameA = getFieldChildName(field.getChild(i)); const nameB = getFieldChildName(field.getChild(i + 1)); if (!nameLevels.has(nameA)) { nameLevels.set(nameA, 0); } if (!nameLevels.has(nameB)) { nameLevels.set(nameB, 0); } const levelB = Math.max(nameLevels.get(nameB), nameLevels.get(nameA) + 1); // eslint-disable-line nameLevels.set(nameB, levelB); } } // 检查 levles 连续 if (Math.max(...nameLevels.values()) != (nameLevels.size - 1)) { return [paddingMap, 0]; } const levelLength = new Map(); for (const field of fields) { let i = 0; for (; i < field.childCount; i++) { const child = field.getChild(i); const level = nameLevels.get(getFieldChildName(child)); // eslint-disable-line const length = new PureThriftFormatter().formatNode(child).length; levelLength.set(level, Math.max(levelLength.get(level) || 0, length)); } } const sep = new ThriftParserNS.List_separatorContext(undefined, 0); const levelPadding = new Map(); for (const [level,] of levelLength) { let padding = level; if (level === nameLevels.get(getFieldChildName(sep))) { padding -= 1; } let i = 0; for (; i < level; i++) { padding += levelLength.get(i) || 0; } levelPadding.set(level, padding); } for (const [name, level] of nameLevels) { paddingMap.set(name, levelPadding.get(level)); // eslint-disable-line } let commentPadding = levelLength.size; for (const [, length] of levelLength) { commentPadding += length; } if (paddingMap.has(getFieldChildName(sep))) { commentPadding -= 1; } return [paddingMap, commentPadding]; }; class ThriftFormatter extends PureThriftFormatter { data; document; fieldCommentPadding = 0; fieldAlignByAssignPadding = 0; fieldAlignByFieldPaddingMap = new Map(); lastTokenIndex = -1; constructor(data) { super(); this.data = data; this.document = data.document; } format() { this.patch(); return this.formatNode(this.document); } patch() { if (this._option.patchRequired) { (0, exports.walkNode)(this.document, patchFieldRequired); } if (this._option.patchSeparator) { (0, exports.walkNode)(this.document, patchFieldListSeparator); (0, exports.walkNode)(this.document, patchRemoveLastListSeparator); } } beforeSubblocks(subblocks) { if (this._option.alignByField) { const [paddingMap, commentPadding] = calcFieldAlignByFieldPaddingMap(subblocks); paddingMap.forEach((value, key, m) => { m.set(key, this.calcAddIndentPadding(value)); }); this.fieldAlignByFieldPaddingMap = paddingMap; this.fieldCommentPadding = this.calcAddIndentPadding(commentPadding); } else if (this._option.alignByAssign) { const [alignPadding, commentPadding] = (0, exports.calcFieldAlignByAssignPadding)(subblocks); this.fieldAlignByAssignPadding = this.calcAddIndentPadding(alignPadding); this.fieldCommentPadding = this.calcAddIndentPadding(commentPadding); } if (this._option.keepComment && this.fieldCommentPadding === 0) { const commentPadding = calcSubBlocksCommentPadding(subblocks); this.fieldCommentPadding = this.calcAddIndentPadding(commentPadding); } } afterSubblocks(_) { this.fieldAlignByAssignPadding = 0; this.fieldAlignByFieldPaddingMap = new Map(); this.fieldCommentPadding = 0; } afterBlockNode(_) { this.addTailComment(); } beforeProcessNode(n) { this.addAlignPadding(n); } get currentLine() { if (this.newlineCounter > 0) { return ''; } const parts = this.out.split('\n'); const cur = parts[parts.length - 1]; return cur; } calcAddIndentPadding(padding) { if (padding > 0) { padding += this._option.indent; } return padding; } addAlignPadding(n) { if (!isFieldOrEnumField(n.parent)) { return; } if (this._option.alignByField && this.fieldAlignByFieldPaddingMap.size > 0) { const name = getFieldChildName(n); const padding = this.fieldAlignByFieldPaddingMap.get(name); if (padding && padding > 0) { this.padding(padding); } return; } if (this._option.alignByAssign && (0, exports.isToken)(n, '=')) { this.padding(this.fieldAlignByAssignPadding); return; } return; } padding(padding, pad = ' ') { if (padding > 0) { padding = padding - this.currentLine.length; if (padding > 0) { this.appendCurrentLine(pad.repeat(padding)); } } } addInlineComments(node) { if (!this._option.keepComment) { return; } if (isFakeNode(node)) { return; } const tokenIndex = node.symbol.tokenIndex; const comments = []; const tokens = this.data.tokens.getTokens(); for (const token of tokens.slice(this.lastTokenIndex + 1)) { if (token.channel != thrift_parser_ts_1.CommentChannel) { continue; } if (token.tokenIndex < tokenIndex) { comments.push(token); } } for (const token of comments) { if (token.tokenIndex > 0 && token.type == thrift_parser_ts_1.ThriftParser.ML_COMMENT) { this.newline(2); } if (token.text === undefined) { return; } // TODO: 确认是否需要 clean indent; this.pushCurrentIndent(); const text = token.text; this.append(text.trim()); const lastLine = token.line + text.split('\n').length - 1; const lineDiff = node.symbol.line - lastLine; const isTight = token.type == thrift_parser_ts_1.ThriftParser.SL_COMMENT || (0, exports.isEOF)(node) || (0 < lineDiff && lineDiff <= 1); if (isTight) { this.newline(); } else { this.newline(2); } } this.lastTokenIndex = tokenIndex; } addTailComment() { if (!this._option.keepComment) { return; } if (this.lastTokenIndex === -1) { return; } const tokens = this.data.tokens.getTokens(); const lastToken = tokens[this.lastTokenIndex]; const comments = []; for (const token of tokens.slice(this.lastTokenIndex + 1)) { if (token.line != lastToken.line) { break; } if (token.channel != thrift_parser_ts_1.CommentChannel) { continue; } comments.push(token); } if (comments.length > 0) { const comment = comments[0]; if (comment.text === undefined) { return; } // align comment if (this.fieldCommentPadding > 0) { this.padding(this.fieldCommentPadding, ' '); } else { this.appendCurrentLine(' '); } this.appendCurrentLine(comment.text.trim()); this.append(''); this.lastTokenIndex = comment.tokenIndex; } } TerminalNode(n) { if (this.newlineCounter > 0) { this.addTailComment(); } this.addInlineComments(n); super.TerminalNode(n); } } exports.ThriftFormatter = ThriftFormatter;