UNPKG

flink-sql-language-server

Version:

A LSP-based language server for Apache Flink SQL

742 lines (741 loc) 28.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AssembleTokensVisitor = void 0; const tree_1 = require("antlr4ts/tree"); const TerminalNode_1 = require("antlr4ts/tree/TerminalNode"); class AssembleTokensVisitor extends tree_1.AbstractParseTreeVisitor { constructor(tokens, config) { super(); this.tokens = tokens; this.config = config; this.indentNumber = 0; this.indentString = ''; this.visitedCommentTokens = new WeakSet(); this.indentString = ' '.repeat(config.tabSize); this.maxLineLength = 60; this.newline = '\n'; } defaultResult() { return ''; } aggregateResult(aggregate, nextResult) { if (!aggregate) { return nextResult; } if (/(-{2,}.*|\/\*[^+].*?\*\/)$/.test(aggregate.trim()) || /^(-{2,}.*|\/\*[^+].*?\*\/)/.test(nextResult.trim())) { return aggregate.trimEnd() + this.newlineIndent + nextResult; } if (/[.;({\[]$/.test(aggregate.trim()) || /^[.,;()}\[\]]/.test(nextResult.trim())) { return aggregate + nextResult; } return `${aggregate} ${nextResult}`; } get indent() { return this.indentString.repeat(this.indentNumber); } get newlineIndent() { return this.newline + this.indent; } addIndent() { this.indentNumber++; } minusIndent() { if (this.indentNumber === 0) { return; } this.indentNumber--; } handleInlineClause(ctx) { if (ctx.children) { const shouldInline = !this.containComment(ctx) && ctx.text.length < this.maxLineLength - this.indent.length; if (!shouldInline) { let formatted = ''; for (const token of ctx.children) { if (token instanceof TerminalNode_1.TerminalNode && token.text === ',') { formatted = this.handleComma(token, formatted); } else { formatted += super.visit(token); } } return formatted; } } return super.visitChildren(ctx); } handleInlineParenthesis(ctx) { if (ctx.children) { const shouldInline = !this.containComment(ctx) && ctx.text.length < this.maxLineLength - this.indent.length; if (!shouldInline) { let formatted = ``; for (const token of ctx.children) { if (token.text === '(') { this.addIndent(); formatted += `${super.visit(token)}${this.newlineIndent}`; } else if (token.text === ')') { this.minusIndent(); formatted = `${formatted.trimEnd() + this.newlineIndent}${super.visit(token)}`; } else if (token instanceof TerminalNode_1.TerminalNode && token.text === ',') { formatted = this.handleComma(token, formatted); } else { formatted += `${super.visit(token)} `; } } return formatted; } } return super.visitChildren(ctx); } handleInvocation(ctx) { if (ctx.children) { const shouldInline = !this.containComment(ctx) && ctx.text.length < this.maxLineLength - this.indent.length; if (!shouldInline) { let formatted = ''; for (const token of ctx.children) { if (token instanceof TerminalNode_1.TerminalNode && token.text === ',') { formatted = this.handleComma(token, formatted); } else if (token.text === '(') { this.addIndent(); formatted = `${formatted.trimEnd()}${super.visit(token)}${this.newlineIndent}`; } else if (token.text === ')') { this.minusIndent(); formatted = `${formatted.trimEnd() + this.newlineIndent}${super.visit(token)}`; } else { formatted += `${super.visit(token)} `; } } return formatted; } } return super.visitChildren(ctx); } addNewlineVisit(formatted, ctx) { this.addIndent(); formatted = formatted.trimEnd() + this.newlineIndent + super.visit(ctx).trim(); this.minusIndent(); return formatted; } addNewlineIndent(ctx) { this.addIndent(); const formatted = this.getNewlineIfNotAfterComment(ctx, 1) + super.visitChildren(ctx); this.minusIndent(); return formatted; } isBeforeComment(node) { const tokenIndex = node.symbol.tokenIndex; const nextToken = this.tokens.get(tokenIndex + 1); return nextToken.channel === 2; } isAfterComment(token) { const tokenIndex = token.tokenIndex; const nextToken = this.tokens.get(tokenIndex - 1); return nextToken.channel === 2; } getNewlineIfNotAfterComment(ctx, indent = 0) { if (this.isAfterComment(ctx._start)) { return indent > 0 ? this.indentString.repeat(indent) : ''; } return this.newlineIndent; } handleComma(node, formatted) { if (this.isAfterComment(node.symbol)) { formatted = `${formatted.trimEnd() + this.newlineIndent}, `; } else if (this.isBeforeComment(node)) { formatted = `${formatted.trimEnd()}, `; } else { formatted = `${formatted.trimEnd()},${this.newlineIndent}`; } return formatted; } containComment(ctx) { if (!ctx._stop) { return false; } const startIndex = ctx._start.tokenIndex; const stopIndex = ctx._stop.tokenIndex; for (let i = startIndex; i <= stopIndex; i++) { const token = this.tokens.get(i); if (token.channel === 2) { return true; } } return false; } visitTerminal(node) { if (node.symbol.type === -1) { return ''; } let text = ''; const tokenIndex = node.symbol.tokenIndex; const cur = this.tokens.get(tokenIndex); const preComments = []; let pre; let preIndex = tokenIndex - 1; while (preIndex >= 0) { pre = this.tokens.get(preIndex); if (pre.channel !== 2) { break; } if (!this.visitedCommentTokens.has(pre) && pre.channel === 2 && pre.line < cur.line) { this.visitedCommentTokens.add(pre); preComments.push(pre); } preIndex--; } for (const preComment of preComments.reverse()) { text += preComment.text + this.newlineIndent; } text += node.text; if (tokenIndex + 1 < this.tokens.size) { const next = this.tokens.get(tokenIndex + 1); if (!this.visitedCommentTokens.has(next) && next.channel === 2 && next.line === cur.line) { this.visitedCommentTokens.add(next); text += ` ${next.text}${this.newlineIndent}`; } } return text; } visitErrorNode(node) { return node.text; } visitProgram(ctx) { return super.visitChildren(ctx); } visitStatementEnd(ctx) { this.indentNumber = 0; return super.visitChildren(ctx) + this.newline.repeat(2); } visitTemporalFunction(ctx) { const child = ctx.getChild(0); if (child instanceof TerminalNode_1.TerminalNode) { return super.visit(child); } return this.handleInvocation(child); } visitJsonFunction(ctx) { const child = ctx.getChild(0); return this.handleInvocation(child); } visitWhenExpr(ctx) { return this.addNewlineIndent(ctx); } visitThenExpr(ctx) { return this.getNewlineIfNotAfterComment(ctx) + super.visitChildren(ctx); } visitElseExpr(ctx) { return this.addNewlineIndent(ctx); } visitCaseEnd(ctx) { return this.getNewlineIfNotAfterComment(ctx) + super.visitChildren(ctx); } visitColumns(ctx) { return this.handleInlineParenthesis(ctx); } visitValueAssignments(ctx) { return this.handleInlineParenthesis(ctx); } visitParenthesisQuery(ctx) { let formatted = ' '; this.addIndent(); formatted += `${super.visit(ctx.L_PARENTHESIS())}${this.newlineIndent}`; formatted += super.visitChildren(ctx.query()); this.minusIndent(); formatted = `${formatted.trimEnd() + this.newlineIndent}${super.visit(ctx.R_PARENTHESIS())}`; return formatted; } visitLogicalBind(ctx) { this.addIndent(); const formatted = this.newlineIndent + super.visitChildren(ctx); this.minusIndent(); return formatted; } visitParenthesisExpressions(ctx) { if (ctx.children) { const shouldInline = !this.containComment(ctx) && ctx.text.length < this.maxLineLength - this.indent.length; if (!shouldInline) { let formatted = ' '; for (const token of ctx.children) { if (token === ctx.L_PARENTHESIS()) { this.addIndent(); formatted += `${super.visit(token)}${this.newlineIndent}`; } else if (token === ctx.R_PARENTHESIS()) { this.minusIndent(); formatted = `${formatted.trimEnd() + this.newlineIndent}${super.visit(token)}`; } else if (token instanceof TerminalNode_1.TerminalNode && token.text === ',') { formatted = this.handleComma(token, formatted); } else { formatted += super.visit(token); } } return formatted; } } return ` ${super.visitChildren(ctx)}`; } visitExpressions(ctx) { if (ctx.children) { const shouldInline = !this.containComment(ctx) && ctx.text.length < this.maxLineLength - this.indent.length; if (!shouldInline) { let formatted = this.getNewlineIfNotAfterComment(ctx); for (const token of ctx.children) { if (token instanceof TerminalNode_1.TerminalNode && token.text === ',') { formatted = this.handleComma(token, formatted); } else { formatted += super.visit(token); } } return formatted; } } return super.visitChildren(ctx); } visitAggregateFilter(ctx) { return this.addNewlineIndent(ctx); } visitAggregateWithin(ctx) { return this.addNewlineIndent(ctx); } visitOverWindow(ctx) { this.addIndent(); const formatted = `${this.getNewlineIfNotAfterComment(ctx, 1) + super.visit(ctx.OVER())} ${super.visit(ctx.window())}`; this.minusIndent(); return formatted; } visitExplain(ctx) { if (ctx.children) { let formatted = ''; for (const token of ctx.children) { if (token === ctx.query() || token === ctx.insert()) { this.addIndent(); formatted = formatted.trimEnd() + this.newlineIndent + super.visit(token); this.minusIndent(); } else { formatted += `${super.visit(token)} `; } } return formatted; } return super.visitChildren(ctx); } visitInsert(ctx) { if (ctx.children) { let formatted = super.visit(ctx.getChild(0)); this.addIndent(); for (let i = 1; i < ctx.children.length; i++) { const token = ctx.children[i]; if (token === ctx.query() || token === ctx.columns()) { formatted = formatted.trimEnd() + this.newlineIndent + super.visit(token); } else { formatted += ` ${super.visit(token)}`; } } this.minusIndent(); return formatted; } return super.visitChildren(ctx); } visitPartition(ctx) { return `${super.visit(ctx.PARTITION())} ${super.visit(ctx.columnAssignments())}`; } visitCreateView(ctx) { if (ctx.children) { this.addIndent(); let formatted = ''; for (const token of ctx.children) { if (token === ctx.AS()) { formatted += `${super.visit(token)}${this.newlineIndent}`; } else { formatted += `${super.visit(token)} `; } } this.minusIndent(); return formatted.trim(); } return super.visitChildren(ctx); } visitDefineValues(ctx) { return ` ${this.handleInlineParenthesis(ctx)}`; } visitLikeConfig(ctx) { this.addIndent(); let formatted = ` ${super.visit(ctx.L_PARENTHESIS())}${this.newlineIndent}`; formatted += super.visit(ctx.likeOptions()); this.minusIndent(); formatted = `${formatted.trimEnd() + this.newlineIndent}${super.visit(ctx.R_PARENTHESIS())}`; return formatted; } visitLikeOptions(ctx) { if (ctx.children) { return ctx.children.map(token => super.visit(token)).join(this.newlineIndent); } return super.visitChildren(ctx); } visitComment(ctx) { return this.getNewlineIfNotAfterComment(ctx) + super.visitChildren(ctx); } visitPartitionedBy(ctx) { return `${this.getNewlineIfNotAfterComment(ctx)}${super.visit(ctx.PARTITIONED())} ${super.visit(ctx.BY())} ${super.visit(ctx.columns())}`; } visitWithValues(ctx) { return `${this.getNewlineIfNotAfterComment(ctx) + super.visit(ctx.WITH())} ${super.visit(ctx.valueAssignments())}`; } visitLikeTable(ctx) { return this.getNewlineIfNotAfterComment(ctx) + super.visitChildren(ctx); } visitAsTable(ctx) { return this.getNewlineIfNotAfterComment(ctx) + super.visitChildren(ctx); } visitAsDatabase(ctx) { return this.getNewlineIfNotAfterComment(ctx) + super.visitChildren(ctx); } visitIncludingTable(ctx) { return this.getNewlineIfNotAfterComment(ctx) + super.visitChildren(ctx); } visitExcludingTable(ctx) { return this.getNewlineIfNotAfterComment(ctx) + super.visitChildren(ctx); } visitMapQuery(ctx) { let operator = super.visit(ctx.getChild(0)); if (ctx.setQuantifier()) { operator += ` ${super.visit(ctx.setQuantifier())}`; } this.minusIndent(); let formatted = this.getNewlineIfNotAfterComment(ctx) + operator; this.addIndent(); formatted += this.newlineIndent + super.visit(ctx.queryTerm()); return formatted; } visitMapTable(ctx) { let formatted = `${this.getNewlineIfNotAfterComment(ctx) + super.visit(ctx.getChild(0))} `; for (let i = 1; i < ctx.childCount; i++) { if (ctx.getChild(i) instanceof TerminalNode_1.TerminalNode) { formatted += `${super.visit(ctx.getChild(i))} `; } else if (ctx.getChild(i) === ctx.joinCondition()) { this.addIndent(); formatted = formatted.trimEnd() + this.newlineIndent + super.visit(ctx.getChild(i)); this.minusIndent(); } else { formatted += super.visit(ctx.getChild(i)); } } return formatted; } visitValuesRows(ctx) { if (ctx.children) { const shouldInline = !this.containComment(ctx) && ctx.text.length < this.maxLineLength - this.indent.length; if (!shouldInline) { this.addIndent(); let formatted = ''; for (const token of ctx.children) { if (token === ctx.VALUES()) { formatted = `${super.visit(token)}${this.newlineIndent}`; } else if (token instanceof TerminalNode_1.TerminalNode && token.text === ',') { formatted = this.handleComma(token, formatted); } else { formatted += super.visit(token).trim(); } } this.minusIndent(); return formatted; } } return super.visitChildren(ctx); } visitValuesRowsParenthesis(ctx) { if (ctx.children) { const shouldInline = !this.containComment(ctx) && ctx.text.length < this.maxLineLength - this.indent.length; if (!shouldInline) { let formatted = ''; for (const token of ctx.children) { if (token === ctx.L_PARENTHESIS()) { this.addIndent(); formatted += super.visit(token) + this.newlineIndent; } else if (token === ctx.R_PARENTHESIS()) { this.minusIndent(); formatted = formatted.trimEnd() + this.newlineIndent + super.visit(token); } else if (token === ctx.VALUES()) { formatted += `${super.visit(token)} `; } else if (token instanceof TerminalNode_1.TerminalNode && token.text === ',') { formatted = this.handleComma(token, formatted); } else { formatted += super.visit(token); } } return formatted; } } return super.visitChildren(ctx); } visitQueryOrderBy(ctx) { const formatted = `${this.getNewlineIfNotAfterComment(ctx) + super.visit(ctx.ORDER())} ${super.visit(ctx.BY())}`; return this.addNewlineVisit(formatted, ctx.orderItems()); } visitQueryLimit(ctx) { return this.getNewlineIfNotAfterComment(ctx) + super.visitChildren(ctx); } visitQueryOffset(ctx) { return this.getNewlineIfNotAfterComment(ctx) + super.visitChildren(ctx); } visitQueryFetch(ctx) { return this.getNewlineIfNotAfterComment(ctx) + super.visitChildren(ctx); } visitTableQuery(ctx) { let formatted = ctx.LATERAL() ? `${super.visit(ctx.getChild(0))} ` : ''; formatted += super.visit(ctx.parenthesisQuery()); return formatted; } visitProjectItems(ctx) { this.addIndent(); let formatted = this.getNewlineIfNotAfterComment(ctx, 1); if (ctx.children) { const shouldInline = !this.containComment(ctx) && ctx.text.length < this.maxLineLength - this.indent.length; if (!shouldInline) { for (const token of ctx.children) { if (token instanceof TerminalNode_1.TerminalNode && token.text === ',') { formatted = this.handleComma(token, formatted); } else { formatted += super.visit(token); } } this.minusIndent(); return formatted; } } formatted += super.visitChildren(ctx); this.minusIndent(); return formatted; } visitTableExpression(ctx) { return this.handleInlineClause(ctx); } visitTableReference(ctx) { if (ctx.children) { let formatted = ''; for (const token of ctx.children) { if (token === ctx.matchRecognize()) { this.addIndent(); formatted = `${formatted.trimEnd() + this.newlineIndent + super.visit(token)} `; this.minusIndent(); } else { formatted += `${super.visit(token)} `; } } return formatted.trim(); } return super.visitChildren(ctx); } visitTableLateral(ctx) { return this.handleInvocation(ctx); } visitOrderItems(ctx) { return this.handleInlineClause(ctx); } visitGroupItem(ctx) { if (ctx.L_PARENTHESIS()) { return ' ()'; } return super.visitChildren(ctx); } visitGroupItems(ctx) { return this.handleInlineClause(ctx).trimStart(); } visitParenthesisGroupItems(ctx) { return this.handleInlineParenthesis(ctx); } visitGroupingSets(ctx) { return `${super.visit(ctx.GROUPING())} ${super.visit(ctx.SETS())} ${super.visit(ctx.parenthesisGroupItems())}`; } visitPartitionBy(ctx) { const formatted = `${super.visit(ctx.PARTITION())} ${super.visit(ctx.BY())}`; return this.addNewlineVisit(formatted, ctx.expressions()); } visitOrderBy(ctx) { const formatted = `${super.visit(ctx.ORDER())} ${super.visit(ctx.BY())}`; return this.addNewlineVisit(formatted, ctx.orderItems()); } visitWindowSpec(ctx) { if (ctx.children) { let formatted = ''; for (const token of ctx.children) { if (token === ctx.L_PARENTHESIS()) { this.addIndent(); formatted += `${super.visit(token)}${this.newlineIndent}`; } else if (token === ctx.R_PARENTHESIS()) { this.minusIndent(); formatted = `${formatted.trim() + this.newlineIndent}${super.visit(token)}`; } else if (token === ctx.name()) { formatted = `${token.text} `; } else { formatted += super.visit(token) + this.newlineIndent; } } return formatted; } return super.visitChildren(ctx); } visitSelect(ctx) { return super.visitChildren(ctx); } visitFromTable(ctx) { const formatted = this.getNewlineIfNotAfterComment(ctx) + super.visit(ctx.FROM()); return this.addNewlineVisit(formatted, ctx.tableExpression()); } visitWhere(ctx) { const formatted = this.getNewlineIfNotAfterComment(ctx) + super.visit(ctx.WHERE()); return this.addNewlineVisit(formatted, ctx.booleanExpr()); } visitGroupBy(ctx) { const formatted = `${this.getNewlineIfNotAfterComment(ctx) + super.visit(ctx.GROUP())} ${super.visit(ctx.BY())}`; return this.addNewlineVisit(formatted, ctx.groupItems()); } visitHaving(ctx) { const formatted = this.getNewlineIfNotAfterComment(ctx) + super.visit(ctx.HAVING()); return this.addNewlineVisit(formatted, ctx.booleanExpr()); } visitWindowSelect(ctx) { return this.getNewlineIfNotAfterComment(ctx) + super.visitChildren(ctx); } visitHints(ctx) { if (ctx.children) { const shouldInline = !this.containComment(ctx) && ctx.text.length < this.maxLineLength - this.indent.length; if (!shouldInline) { let formatted = this.getNewlineIfNotAfterComment(ctx); this.addIndent(); formatted += super.visit(ctx.L_HINT()) + this.newlineIndent; for (let i = 1; i < ctx.children.length - 1; i++) { const token = ctx.children[i]; if (token instanceof TerminalNode_1.TerminalNode && token.text === ',') { formatted = this.handleComma(token, formatted); } else { formatted += super.visit(token); } } this.minusIndent(); formatted = formatted.trimEnd() + this.newlineIndent + super.visit(ctx.R_HINT()); return formatted; } } return this.getNewlineIfNotAfterComment(ctx) + super.visitChildren(ctx); } visitPivot(ctx) { if (ctx.children) { let formatted = ''; for (const token of ctx.children) { if (token === ctx.L_PARENTHESIS()) { this.addIndent(); formatted = `${formatted.trimEnd()} ${super.visit(token)}${this.newlineIndent}`; } else if (token === ctx.R_PARENTHESIS()) { this.minusIndent(); formatted = `${formatted.trimEnd() + this.newlineIndent}${super.visit(token)}`; } else if (token === ctx.PIVOT()) { formatted = `${super.visit(token)} `; } else { formatted += super.visit(token) + this.newlineIndent; } } return formatted; } return super.visitChildren(ctx); } visitForPivotList(ctx) { return `${super.visit(ctx.FOR())} ${super.visit(ctx.pivotList())}`; } visitInPivotExprs(ctx) { return `${super.visit(ctx.IN())} ${super.visit(ctx.pivotExprs())}`; } visitMatchRecognize(ctx) { if (ctx.children) { let formatted = ''; for (const token of ctx.children) { if (token === ctx.L_PARENTHESIS()) { this.addIndent(); formatted = `${formatted.trimEnd()} ${super.visit(token)}${this.newlineIndent}`; } else if (token === ctx.R_PARENTHESIS()) { this.minusIndent(); formatted = `${formatted.trimEnd() + this.newlineIndent}${super.visit(token)}`; } else if (token === ctx.MATCH_RECOGNIZE()) { formatted = `${super.visit(token)} `; } else { formatted += super.visit(token) + this.newlineIndent; } } return formatted; } return super.visitChildren(ctx); } visitMeasures(ctx) { const formatted = super.visit(ctx.getChild(0)); return this.addNewlineVisit(formatted, ctx.measureColumns()); } visitSubsetMatch(ctx) { const formatted = super.visit(ctx.getChild(0)); return this.addNewlineVisit(formatted, ctx.subsetItems()); } visitPatternMatch(ctx) { return `${super.visit(ctx.PATTERN())} ${super.visit(ctx.pattern())}`; } visitDefineMatch(ctx) { const formatted = super.visit(ctx.getChild(0)); return this.addNewlineVisit(formatted, ctx.defineItems()); } visitMeasureColumns(ctx) { return this.handleInlineClause(ctx); } visitSubsetItems(ctx) { return this.handleInlineClause(ctx); } visitDefineItems(ctx) { return this.handleInlineClause(ctx); } visitRenameTo(ctx) { return `${this.getNewlineIfNotAfterComment(ctx) + super.visit(ctx.RENAME())} ${super.visit(ctx.TO())} ${super.visit(ctx.alias())}`; } visitSetValues(ctx) { return `${this.getNewlineIfNotAfterComment(ctx) + super.visit(ctx.SET())} ${super.visit(ctx.valueAssignments())}`; } visitCharsetIntroducer(ctx) { return ctx .IDENTIFIER() .map(node => super.visit(node)) .join(' '); } visitCharsetLiteral(ctx) { return `${super.visit(ctx.charsetIntroducer())}${super.visit(ctx.string())}`; } } exports.AssembleTokensVisitor = AssembleTokensVisitor;