[Canvas] Feat: make an empty pipeline expression legal (#28796)
This commit is contained in:
parent
9036aa49f4
commit
2e37f0d62f
|
@ -22,17 +22,21 @@ import { getType } from './get_type';
|
|||
|
||||
describe('ast fromExpression', () => {
|
||||
describe('invalid expression', () => {
|
||||
it('throws when empty', () => {
|
||||
const check = () => fromExpression('');
|
||||
expect(check).toThrowError(/Unable to parse expression/i);
|
||||
});
|
||||
|
||||
it('throws with invalid expression', () => {
|
||||
const check = () => fromExpression('wat!');
|
||||
expect(check).toThrowError(/Unable to parse expression/i);
|
||||
});
|
||||
});
|
||||
|
||||
describe('zero-item expression', () => {
|
||||
it('yields a zero-length chain when empty', () => {
|
||||
const expression = '';
|
||||
const astObject = fromExpression(expression);
|
||||
expect(astObject).toHaveProperty('chain');
|
||||
expect(astObject.chain).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('single item expression', () => {
|
||||
it('is a chain', () => {
|
||||
const expression = 'whatever';
|
||||
|
|
|
@ -147,7 +147,7 @@ function peg$parse(input, options) {
|
|||
peg$c3 = function(first, rest) {
|
||||
return addMeta({
|
||||
type: 'expression',
|
||||
chain: [first].concat(rest)
|
||||
chain: first ? [first].concat(rest) : []
|
||||
}, text(), location());
|
||||
},
|
||||
peg$c4 = peg$otherExpectation("function"),
|
||||
|
@ -364,6 +364,9 @@ function peg$parse(input, options) {
|
|||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsefunction();
|
||||
if (s2 === peg$FAILED) {
|
||||
s2 = null;
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = [];
|
||||
s4 = peg$currPos;
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
* Yes, technically you can load this and build the parser in real time, but this makes it annoying
|
||||
* to share the grammar between the front end and back, so, you know, just generate the parser.
|
||||
* You shouldn't be futzing around in the grammar very often anyway.
|
||||
*
|
||||
* Instructions for generating `grammar.json`: https://github.com/elastic/kibana/issues/28776#issue-399489673
|
||||
*
|
||||
*/
|
||||
|
||||
{
|
||||
|
@ -20,10 +23,10 @@ start
|
|||
= expression
|
||||
|
||||
expression
|
||||
= space? first:function rest:('|' space? fn:function { return fn; })* {
|
||||
= space? first:function? rest:('|' space? fn:function { return fn; })* {
|
||||
return addMeta({
|
||||
type: 'expression',
|
||||
chain: [first].concat(rest)
|
||||
chain: first ? [first].concat(rest) : []
|
||||
}, text(), location());
|
||||
}
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ export function interpreterProvider(config) {
|
|||
const argAstsWithDefaults = reduce(
|
||||
argDefs,
|
||||
(argAsts, argDef, argName) => {
|
||||
if (typeof argAsts[argName] === 'undefined' && typeof argDef.default !== 'undefined') {
|
||||
if (typeof argAsts[argName] === 'undefined' && typeof argDef.default !== 'undefined') {
|
||||
argAsts[argName] = [fromExpression(argDef.default, 'argument')];
|
||||
}
|
||||
|
||||
|
|
|
@ -16,16 +16,18 @@ export const timeFilter = () => ({
|
|||
help: 'Set a time window',
|
||||
reuseDomNode: true, // must be true, otherwise filters get reset when re-rendered
|
||||
render(domNode, config, handlers) {
|
||||
const ast = fromExpression(handlers.getFilter());
|
||||
|
||||
// Check if the current column is what we expect it to be. If the user changes column this will be called again,
|
||||
// but we don't want to run setFilter() unless we have to because it will cause a data refresh
|
||||
const column = get(ast, 'chain[0].arguments.column[0]');
|
||||
if (column !== config.column) {
|
||||
set(ast, 'chain[0].arguments.column[0]', config.column);
|
||||
handlers.setFilter(toExpression(ast));
|
||||
const filterExpression = handlers.getFilter();
|
||||
const filterExists = filterExpression !== '';
|
||||
const ast = fromExpression(filterExpression);
|
||||
if (filterExists) {
|
||||
// Check if the current column is what we expect it to be. If the user changes column this will be called again,
|
||||
// but we don't want to run setFilter() unless we have to because it will cause a data refresh
|
||||
const column = get(ast, 'chain[0].arguments.column[0]');
|
||||
if (column !== config.column) {
|
||||
set(ast, 'chain[0].arguments.column[0]', config.column);
|
||||
handlers.setFilter(toExpression(ast));
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<TimeFilter
|
||||
compact={config.compact}
|
||||
|
|
|
@ -14,5 +14,5 @@ export const Debug = ({ payload }) => (
|
|||
);
|
||||
|
||||
Debug.propTypes = {
|
||||
payload: PropTypes.object.isRequired,
|
||||
payload: PropTypes.object,
|
||||
};
|
||||
|
|
|
@ -25,7 +25,7 @@ export class RenderWithFn extends React.Component {
|
|||
destroy: PropTypes.func.isRequired,
|
||||
onDestroy: PropTypes.func.isRequired,
|
||||
}),
|
||||
config: PropTypes.object.isRequired,
|
||||
config: PropTypes.object,
|
||||
size: PropTypes.object.isRequired,
|
||||
onError: PropTypes.func.isRequired,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue