thrift-fmt-ts
Version:
A formatter of Thrift, re-implement of python thrift-fmt
835 lines (834 loc) • 30.3 kB
JavaScript
"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;