mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[ES|QL] Support argument precedence in BasicPrettyPrinter
(#191727)
## Summary Inserts brackets where necessary, if binary expressions have different precedence. For example: ``` FROM a | WHERE (1 + 2) * (3 - 4) ``` ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios ### For maintainers - [x] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
This commit is contained in:
parent
3de8133a5a
commit
a156e6726f
3 changed files with 60 additions and 2 deletions
|
@ -211,7 +211,7 @@ describe('single line query', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('binary expression expression', () => {
|
||||
describe('binary expression', () => {
|
||||
test('arithmetic expression', () => {
|
||||
const { text } = reprint('ROW 1 + 2');
|
||||
|
||||
|
@ -235,6 +235,36 @@ describe('single line query', () => {
|
|||
|
||||
expect(text).toBe('FROM a | WHERE a LIKE "b"');
|
||||
});
|
||||
|
||||
test('inserts brackets where necessary due precedence', () => {
|
||||
const { text } = reprint('FROM a | WHERE (1 + 2) * 3');
|
||||
|
||||
expect(text).toBe('FROM a | WHERE (1 + 2) * 3');
|
||||
});
|
||||
|
||||
test('inserts brackets where necessary due precedence - 2', () => {
|
||||
const { text } = reprint('FROM a | WHERE (1 + 2) * (3 - 4)');
|
||||
|
||||
expect(text).toBe('FROM a | WHERE (1 + 2) * (3 - 4)');
|
||||
});
|
||||
|
||||
test('inserts brackets where necessary due precedence - 3', () => {
|
||||
const { text } = reprint('FROM a | WHERE (1 + 2) * (3 - 4) / (5 + 6 + 7)');
|
||||
|
||||
expect(text).toBe('FROM a | WHERE (1 + 2) * (3 - 4) / (5 + 6 + 7)');
|
||||
});
|
||||
|
||||
test('inserts brackets where necessary due precedence - 4', () => {
|
||||
const { text } = reprint('FROM a | WHERE (1 + (1 + 2)) * ((3 - 4) / (5 + 6 + 7))');
|
||||
|
||||
expect(text).toBe('FROM a | WHERE (1 + 1 + 2) * (3 - 4) / (5 + 6 + 7)');
|
||||
});
|
||||
|
||||
test('inserts brackets where necessary due precedence - 5', () => {
|
||||
const { text } = reprint('FROM a | WHERE (1 + (1 + 2)) * (((3 - 4) / (5 + 6 + 7)) + 1)');
|
||||
|
||||
expect(text).toBe('FROM a | WHERE (1 + 1 + 2) * ((3 - 4) / (5 + 6 + 7) + 1)');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { binaryExpressionGroup } from '../ast/helpers';
|
||||
import { ESQLAstCommand } from '../types';
|
||||
import { ESQLAstExpressionNode, ESQLAstQueryNode, Visitor } from '../visitor';
|
||||
import { LeafPrinter } from './leaf_printer';
|
||||
|
@ -135,10 +136,12 @@ export class BasicPrettyPrinter {
|
|||
.on('visitExpression', (ctx) => {
|
||||
return '<EXPRESSION>';
|
||||
})
|
||||
|
||||
.on('visitSourceExpression', (ctx) => LeafPrinter.source(ctx.node))
|
||||
.on('visitColumnExpression', (ctx) => LeafPrinter.column(ctx.node))
|
||||
.on('visitLiteralExpression', (ctx) => LeafPrinter.literal(ctx.node))
|
||||
.on('visitTimeIntervalLiteralExpression', (ctx) => LeafPrinter.timeInterval(ctx.node))
|
||||
|
||||
.on('visitInlineCastExpression', (ctx) => {
|
||||
const value = ctx.value();
|
||||
const wrapInBrackets =
|
||||
|
@ -154,6 +157,7 @@ export class BasicPrettyPrinter {
|
|||
|
||||
return `${valueFormatted}::${ctx.node.castType}`;
|
||||
})
|
||||
|
||||
.on('visitListLiteralExpression', (ctx) => {
|
||||
let elements = '';
|
||||
|
||||
|
@ -163,6 +167,7 @@ export class BasicPrettyPrinter {
|
|||
|
||||
return `[${elements}]`;
|
||||
})
|
||||
|
||||
.on('visitFunctionCallExpression', (ctx) => {
|
||||
const opts = this.opts;
|
||||
const node = ctx.node;
|
||||
|
@ -183,7 +188,25 @@ export class BasicPrettyPrinter {
|
|||
case 'binary-expression': {
|
||||
operator = this.keyword(operator);
|
||||
|
||||
return `${ctx.visitArgument(0)} ${operator} ${ctx.visitArgument(1)}`;
|
||||
const group = binaryExpressionGroup(ctx.node);
|
||||
const [left, right] = ctx.arguments();
|
||||
const groupLeft = binaryExpressionGroup(left);
|
||||
const groupRight = binaryExpressionGroup(right);
|
||||
|
||||
let leftFormatted = ctx.visitArgument(0);
|
||||
let rightFormatted = ctx.visitArgument(1);
|
||||
|
||||
if (groupLeft && groupLeft < group) {
|
||||
leftFormatted = `(${leftFormatted})`;
|
||||
}
|
||||
|
||||
if (groupRight && groupRight < group) {
|
||||
rightFormatted = `(${rightFormatted})`;
|
||||
}
|
||||
|
||||
const formatted = `${leftFormatted} ${operator} ${rightFormatted}`;
|
||||
|
||||
return formatted;
|
||||
}
|
||||
default: {
|
||||
if (opts.lowercaseFunctions) {
|
||||
|
@ -200,9 +223,11 @@ export class BasicPrettyPrinter {
|
|||
}
|
||||
}
|
||||
})
|
||||
|
||||
.on('visitRenameExpression', (ctx) => {
|
||||
return `${ctx.visitArgument(0)} ${this.keyword('AS')} ${ctx.visitArgument(1)}`;
|
||||
})
|
||||
|
||||
.on('visitCommandOption', (ctx) => {
|
||||
const opts = this.opts;
|
||||
const option = opts.lowercaseOptions ? ctx.node.name : ctx.node.name.toUpperCase();
|
||||
|
@ -218,6 +243,7 @@ export class BasicPrettyPrinter {
|
|||
|
||||
return optionFormatted;
|
||||
})
|
||||
|
||||
.on('visitCommand', (ctx) => {
|
||||
const opts = this.opts;
|
||||
const cmd = opts.lowercaseCommands ? ctx.node.name : ctx.node.name.toUpperCase();
|
||||
|
@ -239,6 +265,7 @@ export class BasicPrettyPrinter {
|
|||
|
||||
return cmdFormatted;
|
||||
})
|
||||
|
||||
.on('visitQuery', (ctx) => {
|
||||
const opts = this.opts;
|
||||
const cmdSeparator = opts.multiline ? `\n${opts.pipeTab ?? ' '}| ` : ' | ';
|
||||
|
|
|
@ -332,6 +332,7 @@ export class WrappingPrettyPrinter {
|
|||
|
||||
.on('visitRenameExpression', (ctx, inp: Input): Output => {
|
||||
const operator = this.keyword('AS');
|
||||
|
||||
return this.visitBinaryExpression(ctx, operator, inp);
|
||||
})
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue