[ES|QL] simplify signature definition (removes infiniteParams) (#177628)

## Summary

Close https://github.com/elastic/kibana/issues/177117


### Checklist

Delete any items that are not applicable to this PR.


- [ ] [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

---------

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Drew Tate 2024-03-07 16:30:52 +01:00 committed by GitHub
parent bfee4d79e8
commit bf2ebe9da4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 42 additions and 64 deletions

View file

@ -425,9 +425,6 @@ function isFunctionArgComplete(
}
const cleanedArgs = removeMarkerArgFromArgsList(arg)!.args;
const argLengthCheck = fnDefinition.signatures.some((def) => {
if (def.infiniteParams && cleanedArgs.length > 0) {
return true;
}
if (def.minParams && cleanedArgs.length >= def.minParams) {
return true;
}
@ -444,9 +441,6 @@ function isFunctionArgComplete(
}
const hasCorrectTypes = fnDefinition.signatures.some((def) => {
return arg.args.every((a, index) => {
if (def.infiniteParams) {
return true;
}
return def.params[index].type === extractFinalTypeFromArg(a, references);
});
});
@ -1087,7 +1081,7 @@ async function getFunctionArgsSuggestions(
if (signature.params.length > argIndex) {
return signature.params[argIndex].type;
}
if (signature.infiniteParams || signature.minParams) {
if (signature.minParams) {
return signature.params[signature.params.length - 1].type;
}
return [];

View file

@ -677,7 +677,7 @@ export const evalFunctionsDefinitions: FunctionDefinition[] = [
signatures: [
{
params: [{ name: 'field', type: 'any' }],
infiniteParams: true,
minParams: 1,
returnType: 'any',
examples: [`ROW a=null, b="b" | EVAL COALESCE(a, b)`],
},
@ -730,7 +730,7 @@ export const evalFunctionsDefinitions: FunctionDefinition[] = [
signatures: [
{
params: [{ name: 'field', type: 'any' }],
infiniteParams: true,
minParams: 1,
returnType: 'any',
examples: [`ROW a = 10, b = 20 | EVAL g = GREATEST(a, b)`],
},
@ -744,7 +744,7 @@ export const evalFunctionsDefinitions: FunctionDefinition[] = [
signatures: [
{
params: [{ name: 'first', type: 'any' }],
infiniteParams: true,
minParams: 1,
returnType: 'any',
examples: ['from index | eval l = least(a, b)'],
},

View file

@ -8,25 +8,26 @@
import { CommandDefinition, FunctionDefinition } from './types';
/**
* Given a function definition, this function will return a list of function signatures
*
* If withTypes is true, the function will return a formal function definition with all arguments typed.
* This is used when generating the function signature for the monaco editor. If withTypes is false, you get
* an "injectable" version of the signature to be used to generate test cases.
*/
export function getFunctionSignatures(
{ name, signatures }: FunctionDefinition,
{ withTypes }: { withTypes: boolean } = { withTypes: true }
) {
return signatures.map(({ params, returnType, infiniteParams, minParams, examples }) => {
return signatures.map(({ params, returnType, minParams, examples }) => {
// for functions with a minimum number of args, repeat the last arg multiple times
// just make sure to compute the right number of args to add
const minParamsToAdd = Math.max((minParams || 0) - params.length, 0);
const hasMoreOptionalArgs = !!infiniteParams || !!minParams;
const extraArg = Array(minParamsToAdd || 1).fill(params[Math.max(params.length - 1, 0)]);
return {
declaration: `${name}(${params
.map((arg) => printArguments(arg, withTypes))
.join(', ')}${handleAdditionalArgs(
minParamsToAdd > 0,
extraArg,
withTypes,
false
)}${handleAdditionalArgs(hasMoreOptionalArgs, extraArg, withTypes)})${
.join(', ')}${handleAdditionalArgs(minParamsToAdd > 0, extraArg, withTypes)})${
withTypes ? `: ${returnType}` : ''
}`,
examples,
@ -42,13 +43,12 @@ function handleAdditionalArgs(
optional?: boolean;
reference?: string;
}>,
withTypes: boolean,
optionalArg: boolean = true
withTypes: boolean
) {
return criteria
? `${withTypes && optionalArg ? ' ,[... ' : ', '}${additionalArgs
? `${withTypes ? ' ,[... ' : ', '}${additionalArgs
.map((arg) => printArguments(arg, withTypes))
.join(', ')}${withTypes && optionalArg ? ']' : ''}`
.join(', ')}${withTypes ? ']' : ''}`
: '';
}

View file

@ -25,7 +25,6 @@ export interface FunctionDefinition {
supportsWildcard?: boolean;
literalOnly?: boolean;
}>;
infiniteParams?: boolean;
minParams?: number;
returnType: string;
examples?: string[];

View file

@ -519,11 +519,11 @@
"error": false
},
{
"query": "row var = case(true, \"a\", \"a\", \"a\")",
"query": "row var = case(true, \"a\", \"a\")",
"error": false
},
{
"query": "row case(true, \"a\", \"a\", \"a\")",
"query": "row case(true, \"a\", \"a\")",
"error": false
},
{
@ -543,19 +543,19 @@
"error": true
},
{
"query": "row var = cidr_match(to_ip(\"127.0.0.1\"), \"a\", \"a\")",
"query": "row var = cidr_match(to_ip(\"127.0.0.1\"), \"a\")",
"error": false
},
{
"query": "row cidr_match(to_ip(\"127.0.0.1\"), \"a\", \"a\")",
"query": "row cidr_match(to_ip(\"127.0.0.1\"), \"a\")",
"error": false
},
{
"query": "row var = cidr_match(to_ip(\"a\"), to_string(\"a\"), to_string(\"a\"))",
"query": "row var = cidr_match(to_ip(\"a\"), to_string(\"a\"))",
"error": false
},
{
"query": "row var = cidr_match(\"a\", 5, 5)",
"query": "row var = cidr_match(\"a\", 5)",
"error": true
},
{
@ -567,19 +567,19 @@
"error": false
},
{
"query": "row var = concat(\"a\", \"a\", \"a\")",
"query": "row var = concat(\"a\", \"a\")",
"error": false
},
{
"query": "row concat(\"a\", \"a\", \"a\")",
"query": "row concat(\"a\", \"a\")",
"error": false
},
{
"query": "row var = concat(to_string(\"a\"), to_string(\"a\"), to_string(\"a\"))",
"query": "row var = concat(to_string(\"a\"), to_string(\"a\"))",
"error": false
},
{
"query": "row var = concat(5, 5, 5)",
"query": "row var = concat(5, 5)",
"error": true
},
{
@ -3607,11 +3607,11 @@
"error": true
},
{
"query": "from a_index | where length(concat(stringField, stringField, stringField)) > 0",
"query": "from a_index | where length(concat(stringField, stringField)) > 0",
"error": false
},
{
"query": "from a_index | where length(concat(numberField, numberField, numberField)) > 0",
"query": "from a_index | where length(concat(numberField, numberField)) > 0",
"error": true
},
{
@ -4815,11 +4815,11 @@
"error": true
},
{
"query": "from a_index | eval var = case(booleanField, stringField, stringField, stringField)",
"query": "from a_index | eval var = case(booleanField, stringField, stringField)",
"error": false
},
{
"query": "from a_index | eval case(booleanField, stringField, stringField, stringField)",
"query": "from a_index | eval case(booleanField, stringField, stringField)",
"error": false
},
{
@ -4847,19 +4847,19 @@
"error": true
},
{
"query": "from a_index | eval var = cidr_match(ipField, stringField, stringField)",
"query": "from a_index | eval var = cidr_match(ipField, stringField)",
"error": false
},
{
"query": "from a_index | eval cidr_match(ipField, stringField, stringField)",
"query": "from a_index | eval cidr_match(ipField, stringField)",
"error": false
},
{
"query": "from a_index | eval var = cidr_match(to_ip(stringField), to_string(stringField), to_string(stringField))",
"query": "from a_index | eval var = cidr_match(to_ip(stringField), to_string(stringField))",
"error": false
},
{
"query": "from a_index | eval cidr_match(stringField, numberField, numberField)",
"query": "from a_index | eval cidr_match(stringField, numberField)",
"error": true
},
{
@ -4871,23 +4871,19 @@
"error": false
},
{
"query": "from a_index | eval var = coalesce(*)",
"error": true
},
{
"query": "from a_index | eval var = concat(stringField, stringField, stringField)",
"query": "from a_index | eval var = concat(stringField, stringField)",
"error": false
},
{
"query": "from a_index | eval concat(stringField, stringField, stringField)",
"query": "from a_index | eval concat(stringField, stringField)",
"error": false
},
{
"query": "from a_index | eval var = concat(to_string(stringField), to_string(stringField), to_string(stringField))",
"query": "from a_index | eval var = concat(to_string(stringField), to_string(stringField))",
"error": false
},
{
"query": "from a_index | eval concat(numberField, numberField, numberField)",
"query": "from a_index | eval concat(numberField, numberField)",
"error": true
},
{
@ -5090,10 +5086,6 @@
"query": "from a_index | eval greatest(stringField)",
"error": false
},
{
"query": "from a_index | eval var = greatest(*)",
"error": true
},
{
"query": "from a_index | eval var = least(stringField)",
"error": false
@ -5102,10 +5094,6 @@
"query": "from a_index | eval least(stringField)",
"error": false
},
{
"query": "from a_index | eval var = least(*)",
"error": true
},
{
"query": "from a_index | eval var = left(stringField, numberField)",
"error": false

View file

@ -514,7 +514,7 @@ describe('validation logic', () => {
}
for (const { name, alias, signatures, ...defRest } of evalFunctionsDefinitions) {
for (const { params, infiniteParams, ...signRest } of signatures) {
for (const { params, ...signRest } of signatures) {
const fieldMapping = getFieldMapping(params);
const signatureStringCorrect = tweakSignatureForRowCommand(
getFunctionSignatures(
@ -1307,7 +1307,7 @@ describe('validation logic', () => {
}
for (const { name, alias, signatures, ...defRest } of evalFunctionsDefinitions) {
for (const { params, infiniteParams, ...signRest } of signatures) {
for (const { params, ...signRest } of signatures) {
const fieldMapping = getFieldMapping(params);
testErrorsAndWarnings(
`from a_index | eval var = ${
@ -1414,7 +1414,7 @@ describe('validation logic', () => {
expectedErrors
);
if (!infiniteParams && !signRest.minParams) {
if (!signRest.minParams) {
// test that additional args are spotted
const fieldMappingWithOneExtraArg = getFieldMapping(params).concat({
name: 'extraArg',
@ -1835,7 +1835,7 @@ describe('validation logic', () => {
]);
for (const { name, alias, signatures, ...defRest } of statsAggregationFunctionDefinitions) {
for (const { params, infiniteParams, ...signRest } of signatures) {
for (const { params, ...signRest } of signatures) {
const fieldMapping = getFieldMapping(params);
const correctSignature = getFunctionSignatures(

View file

@ -255,9 +255,6 @@ function extractCompatibleSignaturesForFunction(
astFunction: ESQLFunction
) {
return fnDef.signatures.filter((def) => {
if (def.infiniteParams) {
return astFunction.args.length > 0;
}
if (def.minParams) {
return astFunction.args.length >= def.minParams;
}