From af90873ccbd909939f963bb0be5cc1e82cb323d7 Mon Sep 17 00:00:00 2001 From: "Quynh Nguyen (Quinn)" <43350163+qn895@users.noreply.github.com> Date: Mon, 21 Oct 2024 11:29:48 -0500 Subject: [PATCH] [8.16] [ES|QL] Fix duplicate autocomplete suggestions for where clause, and suggestions with no space in between (#195771) (#196716) # Backport This will backport the following commits from `main` to `8.16`: - [[ES|QL] Fix duplicate autocomplete suggestions for where clause, and suggestions with no space in between (#195771)](https://github.com/elastic/kibana/pull/195771) ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) \n\n### Questions ?\nPlease refer to the [Backport tool\ndocumentation](https://github.com/sqren/backport)\n\n\n\nCo-authored-by: Quynh Nguyen (Quinn) <43350163+qn895@users.noreply.github.com>"}}]}] BACKPORT--> Co-authored-by: Stratoula Kalafateli --- .../src/autocomplete/autocomplete.test.ts | 30 +++++++------------ .../src/autocomplete/autocomplete.ts | 18 ++++++++--- .../src/autocomplete/complete_items.ts | 3 +- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts b/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts index 8524cd4950955..e463902554074 100644 --- a/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts +++ b/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts @@ -1262,41 +1262,33 @@ describe('autocomplete', () => { describe('Replacement ranges are attached when needed', () => { testSuggestions('FROM a | WHERE doubleField IS NOT N/', [ { text: 'IS NOT NULL', rangeToReplace: { start: 28, end: 35 } }, - { text: 'IS NULL', rangeToReplace: { start: 35, end: 35 } }, + { text: 'IS NULL', rangeToReplace: { start: 36, end: 36 } }, '!= $0', - '< $0', - '<= $0', '== $0', - '> $0', - '>= $0', 'IN $0', + 'AND $0', + 'NOT', + 'OR $0', ]); testSuggestions('FROM a | WHERE doubleField IS N/', [ { text: 'IS NOT NULL', rangeToReplace: { start: 28, end: 31 } }, { text: 'IS NULL', rangeToReplace: { start: 28, end: 31 } }, - { text: '!= $0', rangeToReplace: { start: 31, end: 31 } }, - '< $0', - '<= $0', + { text: '!= $0', rangeToReplace: { start: 32, end: 32 } }, '== $0', - '> $0', - '>= $0', 'IN $0', + 'AND $0', + 'NOT', + 'OR $0', ]); testSuggestions('FROM a | EVAL doubleField IS NOT N/', [ { text: 'IS NOT NULL', rangeToReplace: { start: 27, end: 34 } }, 'IS NULL', - '% $0', - '* $0', - '+ $0', - '- $0', - '/ $0', '!= $0', - '< $0', - '<= $0', '== $0', - '> $0', - '>= $0', 'IN $0', + 'AND $0', + 'NOT', + 'OR $0', ]); describe('dot-separated field names', () => { testSuggestions( diff --git a/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts b/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts index 4b732d25151da..cbc84232b8eb6 100644 --- a/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts +++ b/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts @@ -324,10 +324,16 @@ function findNewVariable(variables: Map) { function workoutBuiltinOptions( nodeArg: ESQLAstItem, references: Pick -): { skipAssign: boolean } { +): { skipAssign: boolean; commandsToInclude?: string[] } { + const commandsToInclude = + (isSingleItem(nodeArg) && nodeArg.text?.toLowerCase().trim().endsWith('null')) ?? false + ? ['and', 'or'] + : undefined; + // skip assign operator if it's a function or an existing field to avoid promoting shadowing return { skipAssign: Boolean(!isColumnItem(nodeArg) || getColumnForASTNode(nodeArg, references)), + commandsToInclude, }; } @@ -447,7 +453,10 @@ function isFunctionArgComplete( } const hasCorrectTypes = fnDefinition.signatures.some((def) => { return arg.args.every((a, index) => { - return def.params[index].type === extractTypeFromASTArg(a, references); + return ( + (fnDefinition.name.endsWith('null') && def.params[index].type === 'any') || + def.params[index].type === extractTypeFromASTArg(a, references) + ); }); }); if (!hasCorrectTypes) { @@ -1140,11 +1149,12 @@ async function getBuiltinFunctionNextArgument( } return suggestions.map((s) => { const overlap = getOverlapRange(queryText, s.text); + const offset = overlap.start === overlap.end ? 1 : 0; return { ...s, rangeToReplace: { - start: overlap.start, - end: overlap.end, + start: overlap.start + offset, + end: overlap.end + offset, }, }; }); diff --git a/packages/kbn-esql-validation-autocomplete/src/autocomplete/complete_items.ts b/packages/kbn-esql-validation-autocomplete/src/autocomplete/complete_items.ts index 662b84c4a788f..000c196b49e5e 100644 --- a/packages/kbn-esql-validation-autocomplete/src/autocomplete/complete_items.ts +++ b/packages/kbn-esql-validation-autocomplete/src/autocomplete/complete_items.ts @@ -59,10 +59,11 @@ export const getBuiltinCompatibleFunctionDefinition = ( option: string | undefined, argType: FunctionParameterType, returnTypes?: FunctionReturnType[], - { skipAssign }: { skipAssign?: boolean } = {} + { skipAssign, commandsToInclude }: { skipAssign?: boolean; commandsToInclude?: string[] } = {} ): SuggestionRawDefinition[] => { const compatibleFunctions = [...builtinFunctions, ...getTestFunctions()].filter( ({ name, supportedCommands, supportedOptions, signatures, ignoreAsSuggestion }) => + (command === 'where' && commandsToInclude ? commandsToInclude.indexOf(name) > -1 : true) && !ignoreAsSuggestion && (!skipAssign || name !== '=') && (option ? supportedOptions?.includes(option) : supportedCommands.includes(command)) &&