flink-sql-language-server
Version:
A LSP-based language server for Apache Flink SQL
742 lines (741 loc) • 28.4 kB
JavaScript
"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;