From 1223926450736fba5f67d17279ccf650d8b3ff2a Mon Sep 17 00:00:00 2001 From: Drew Tate Date: Fri, 14 Feb 2025 07:44:46 -0700 Subject: [PATCH] [ES|QL] Separate `GROK` and `DISSECT` autocomplete routines (#211101) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Part of https://github.com/elastic/kibana/issues/195418 Gives `GROK` and `DISSECT` autocomplete logic its own home 🏡 ### 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 ### Identify risks - [ ] As with any refactor, there's a possibility this will introduce a regression in the behavior of commands. However, all automated tests are passing and I have tested the behavior manually and can detect no regression. --- .../autocomplete.command.dissect.test.ts | 71 ++++++++++++++++ .../autocomplete.command.grok.test.ts | 42 ++++++++++ .../src/autocomplete/autocomplete.test.ts | 82 ------------------- .../src/autocomplete/autocomplete.ts | 19 +---- .../autocomplete/commands/dissect/index.ts | 77 +++++++++++++++++ .../src/autocomplete/commands/grok/index.ts | 47 +++++++++++ .../src/autocomplete/commands/show/index.ts | 2 +- .../src/autocomplete/complete_items.ts | 15 +++- .../src/autocomplete/factories.ts | 20 ----- .../src/autocomplete/types.ts | 2 +- .../src/definitions/commands.ts | 8 +- .../src/shared/resources_helpers.ts | 2 +- 12 files changed, 261 insertions(+), 126 deletions(-) create mode 100644 src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.dissect.test.ts create mode 100644 src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.grok.test.ts create mode 100644 src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/dissect/index.ts create mode 100644 src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/grok/index.ts diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.dissect.test.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.dissect.test.ts new file mode 100644 index 0000000000000..b7bdd9de4a361 --- /dev/null +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.dissect.test.ts @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { ESQL_STRING_TYPES } from '../../shared/esql_types'; +import { attachTriggerCommand, getFieldNamesByType, setup } from './helpers'; + +describe('autocomplete.suggest', () => { + describe('DISSECT', () => { + it('suggests fields after DISSECT', async () => { + const { assertSuggestions } = await setup(); + await assertSuggestions( + 'from a | DISSECT /', + getFieldNamesByType(ESQL_STRING_TYPES).map((name) => `${name} `) + ); + await assertSuggestions( + 'from a | DISSECT /', + getFieldNamesByType(ESQL_STRING_TYPES).map((name) => `${name} `), + { triggerCharacter: ' ' } + ); + await assertSuggestions( + 'from a | DISSECT key/', + getFieldNamesByType(ESQL_STRING_TYPES).map((name) => `${name} `) + ); + await assertSuggestions( + 'from a | DISSECT keywordField/', + ['keywordField ', 'textField '].map(attachTriggerCommand) + ); + }); + + const constantPattern = '"%{firstWord}" '; + it('suggests a pattern after a field name', async () => { + const { assertSuggestions } = await setup(); + await assertSuggestions('from a | DISSECT keywordField /', [constantPattern]); + }); + + it('suggests an append separator or pipe after a pattern', async () => { + const { assertSuggestions } = await setup(); + assertSuggestions( + `from a | DISSECT keywordField ${constantPattern} /`, + ['APPEND_SEPARATOR = ', '| '].map(attachTriggerCommand), + { triggerCharacter: ' ' } + ); + assertSuggestions( + `from a | DISSECT keywordField ${constantPattern} /`, + ['APPEND_SEPARATOR = ', '| '].map(attachTriggerCommand) + ); + }); + + it('suggests append separators', async () => { + const { assertSuggestions } = await setup(); + await assertSuggestions( + `from a | DISSECT keywordField ${constantPattern} append_separator = /`, + ['":" ', '";" '].map(attachTriggerCommand) + ); + }); + + it('suggests a pipe after an append separator', async () => { + const { assertSuggestions } = await setup(); + await assertSuggestions( + `from a | DISSECT keywordField ${constantPattern} append_separator = ":" /`, + ['| '] + ); + }); + }); +}); diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.grok.test.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.grok.test.ts new file mode 100644 index 0000000000000..343674180f4dd --- /dev/null +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.grok.test.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { ESQL_STRING_TYPES } from '../../shared/esql_types'; +import { attachTriggerCommand, getFieldNamesByType, setup } from './helpers'; + +describe('autocomplete.suggest', () => { + describe('GROK', () => { + it('suggests fields after GROK', async () => { + const { assertSuggestions } = await setup(); + await assertSuggestions( + 'from a | grok /', + getFieldNamesByType(ESQL_STRING_TYPES).map((name) => `${name} `) + ); + await assertSuggestions( + 'from a | grok key/', + getFieldNamesByType(ESQL_STRING_TYPES).map((name) => `${name} `) + ); + await assertSuggestions( + 'from a | grok keywordField/', + ['keywordField ', 'textField '].map(attachTriggerCommand) + ); + }); + + const constantPattern = '"%{WORD:firstWord}"'; + it('suggests a pattern after a field name', async () => { + const { assertSuggestions } = await setup(); + await assertSuggestions('from a | grok keywordField /', [constantPattern + ' ']); + }); + + it('suggests a pipe after a pattern', async () => { + const { assertSuggestions } = await setup(); + await assertSuggestions(`from a | grok keywordField ${constantPattern} /`, ['| ']); + }); + }); +}); diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts index c6ffd39ce237a..fce7aa8ae9e44 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts @@ -113,88 +113,6 @@ describe('autocomplete', () => { testSuggestions('from a metadata _id | eval var0 = a | /', commands); }); - describe('show', () => { - testSuggestions('show /', ['INFO']); - for (const fn of ['info']) { - testSuggestions(`show ${fn} /`, ['| ']); - } - }); - - describe('grok', () => { - const constantPattern = '"%{WORD:firstWord}"'; - const subExpressions = [ - '', - `grok keywordField |`, - `grok keywordField ${constantPattern} |`, - `dissect keywordField ${constantPattern} append_separator = ":" |`, - `dissect keywordField ${constantPattern} |`, - ]; - for (const subExpression of subExpressions) { - testSuggestions( - `from a | ${subExpression} grok /`, - getFieldNamesByType(ESQL_STRING_TYPES).map((name) => `${name} `) - ); - testSuggestions(`from a | ${subExpression} grok keywordField /`, [constantPattern], ' '); - testSuggestions(`from a | ${subExpression} grok keywordField ${constantPattern} /`, ['| ']); - } - - testSuggestions( - 'from a | grok /', - getFieldNamesByType(ESQL_STRING_TYPES).map((name) => `${name} `) - ); - testSuggestions( - 'from a | grok key/', - getFieldNamesByType(ESQL_STRING_TYPES).map((name) => `${name} `) - ); - testSuggestions( - 'from a | grok keywordField/', - ['keywordField ', 'textField '].map(attachTriggerCommand) - ); - }); - - describe('dissect', () => { - const constantPattern = '"%{firstWord}"'; - const subExpressions = [ - '', - `dissect keywordField |`, - `dissect keywordField ${constantPattern} |`, - `dissect keywordField ${constantPattern} append_separator = ":" |`, - ]; - for (const subExpression of subExpressions) { - testSuggestions( - `from a | ${subExpression} dissect /`, - getFieldNamesByType(ESQL_STRING_TYPES).map((name) => `${name} `) - ); - testSuggestions(`from a | ${subExpression} dissect keywordField /`, [constantPattern], ' '); - testSuggestions( - `from a | ${subExpression} dissect keywordField ${constantPattern} /`, - ['APPEND_SEPARATOR = $0', '| '], - ' ' - ); - testSuggestions( - `from a | ${subExpression} dissect keywordField ${constantPattern} append_separator = /`, - ['":"', '";"'] - ); - testSuggestions( - `from a | ${subExpression} dissect keywordField ${constantPattern} append_separator = ":" /`, - ['| '] - ); - } - - testSuggestions( - 'from a | dissect /', - getFieldNamesByType(ESQL_STRING_TYPES).map((name) => `${name} `) - ); - testSuggestions( - 'from a | dissect key/', - getFieldNamesByType(ESQL_STRING_TYPES).map((name) => `${name} `) - ); - testSuggestions( - 'from a | dissect keywordField/', - ['keywordField ', 'textField '].map(attachTriggerCommand) - ); - }); - describe('limit', () => { testSuggestions('from a | limit /', ['10 ', '100 ', '1000 ']); testSuggestions('from a | limit 4 /', ['| ']); diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts index ddb74b2a27487..ba23575931c8b 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts @@ -52,12 +52,10 @@ import { collectVariables, excludeVariablesFromCurrentCommand } from '../shared/ import type { ESQLPolicy, ESQLRealField, ESQLVariable, ReferenceMaps } from '../validation/types'; import { allStarConstant, - colonCompleteItem, commaCompleteItem, getAssignmentDefinitionCompletitionItem, getCommandAutocompleteDefinitions, pipeCompleteItem, - semiColonCompleteItem, } from './complete_items'; import { buildFieldsDefinitions, @@ -210,6 +208,7 @@ export async function suggest( if ( astContext.type === 'expression' || (astContext.type === 'option' && astContext.command?.name === 'join') || + (astContext.type === 'option' && astContext.command?.name === 'dissect') || (astContext.type === 'option' && astContext.command?.name === 'from') ) { return getSuggestionsWithinCommandExpression( @@ -285,7 +284,7 @@ export function getFieldsByTypeRetriever( const supportsControls = resourceRetriever?.canSuggestVariables?.() ?? false; return { getFieldsByType: async ( - expectedType: string | string[] = 'any', + expectedType: Readonly | Readonly = 'any', ignored: string[] = [], options ) => { @@ -791,7 +790,7 @@ async function getExpressionSuggestionsByType( // it can be just literal values (i.e. "string") if (argDef.constantOnly) { // ... | ... - suggestions.push(...getCompatibleLiterals(command.name, [argDef.type], [argDef.name])); + suggestions.push(...getCompatibleLiterals(command.name, [argDef.type])); } else { // or it can be anything else as long as it is of the right type and the end (i.e. column or function) if (!nodeArg) { @@ -1078,7 +1077,6 @@ async function getFunctionArgsSuggestions( ...getCompatibleLiterals( command.name, getTypesFromParamDefs(constantOnlyParamDefs) as string[], - undefined, { addComma: shouldAddComma, advanceCursorAndOpenSuggestions: hasMoreMandatoryArgs, @@ -1151,7 +1149,7 @@ async function getFunctionArgsSuggestions( if (isLiteralItem(arg) && isNumericType(arg.literalType)) { // ... | EVAL fn(2 ) suggestions.push( - ...getCompatibleLiterals(command.name, ['time_literal_unit'], undefined, { + ...getCompatibleLiterals(command.name, ['time_literal_unit'], { addComma: shouldAddComma, advanceCursorAndOpenSuggestions: hasMoreMandatoryArgs, }) @@ -1403,15 +1401,6 @@ async function getOptionArgsSuggestions( } } - if (command.name === 'dissect') { - if ( - option.args.filter((arg) => !(isSingleItem(arg) && arg.type === 'unknown')).length < 1 && - optionDef - ) { - suggestions.push(colonCompleteItem, semiColonCompleteItem); - } - } - if (optionDef) { if (!suggestions.length) { const argDefIndex = optionDef.signature.multipleParams diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/dissect/index.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/dissect/index.ts new file mode 100644 index 0000000000000..150ca6cd858b3 --- /dev/null +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/dissect/index.ts @@ -0,0 +1,77 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { EDITOR_MARKER } from '../../../shared/constants'; +import { isSingleItem } from '../../../..'; +import { ESQL_STRING_TYPES } from '../../../shared/esql_types'; +import { CommandSuggestParams } from '../../../definitions/types'; + +import type { SuggestionRawDefinition } from '../../types'; +import { TRIGGER_SUGGESTION_COMMAND, buildConstantsDefinitions } from '../../factories'; +import { colonCompleteItem, pipeCompleteItem, semiColonCompleteItem } from '../../complete_items'; + +export async function suggest({ + command, + innerText, + getColumnsByType, +}: CommandSuggestParams<'dissect'>): Promise { + const commandArgs = command.args.filter( + (arg) => isSingleItem(arg) && arg.text !== EDITOR_MARKER && arg.text !== '' + ); + + // DISSECT field / + if (commandArgs.length === 1) { + return buildConstantsDefinitions( + ['"%{firstWord}"'], + i18n.translate('kbn-esql-validation-autocomplete.esql.autocomplete.aPatternString', { + defaultMessage: 'A pattern string', + }), + undefined, + { + advanceCursorAndOpenSuggestions: true, + } + ); + } + // DISSECT field pattern / + else if (commandArgs.length === 2) { + return [ + { ...pipeCompleteItem, command: TRIGGER_SUGGESTION_COMMAND }, + appendSeparatorCompletionItem, + ]; + } + // DISSECT field APPEND_SEPARATOR = / + else if (/append_separator\s*=\s*$/i.test(innerText)) { + return [colonCompleteItem, semiColonCompleteItem]; + } + // DISSECT field APPEND_SEPARATOR = ":" / + else if (commandArgs.some((arg) => isSingleItem(arg) && arg.type === 'option')) { + return [{ ...pipeCompleteItem, command: TRIGGER_SUGGESTION_COMMAND }]; + } + + // DISSECT / + const fieldSuggestions = await getColumnsByType(ESQL_STRING_TYPES); + return fieldSuggestions.map((sug) => ({ + ...sug, + text: `${sug.text} `, + command: TRIGGER_SUGGESTION_COMMAND, + })); +} + +const appendSeparatorCompletionItem: SuggestionRawDefinition = { + command: TRIGGER_SUGGESTION_COMMAND, + detail: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.appendSeparatorDoc', { + defaultMessage: + 'The character(s) that separate the appended fields. Default to empty string ("").', + }), + kind: 'Reference', + label: 'APPEND_SEPARATOR', + sortText: '1', + text: 'APPEND_SEPARATOR = ', +}; diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/grok/index.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/grok/index.ts new file mode 100644 index 0000000000000..c50bb8d1b5fdf --- /dev/null +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/grok/index.ts @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { CommandSuggestParams } from '../../../definitions/types'; + +import type { SuggestionRawDefinition } from '../../types'; +import { ESQL_STRING_TYPES } from '../../../shared/esql_types'; +import { TRIGGER_SUGGESTION_COMMAND, buildConstantsDefinitions } from '../../factories'; +import { pipeCompleteItem } from '../../complete_items'; + +export async function suggest({ + command, + getColumnsByType, +}: CommandSuggestParams<'grok'>): Promise { + // GROK field / + if (command.args.length === 1) { + return buildConstantsDefinitions( + ['"%{WORD:firstWord}"'], + i18n.translate('kbn-esql-validation-autocomplete.esql.autocomplete.aPatternString', { + defaultMessage: 'A pattern string', + }), + undefined, + { + advanceCursorAndOpenSuggestions: true, + } + ); + } + // GROK field pattern / + else if (command.args.length === 2) { + return [{ ...pipeCompleteItem, command: TRIGGER_SUGGESTION_COMMAND }]; + } + + // GROK / + const fieldSuggestions = await getColumnsByType(ESQL_STRING_TYPES); + return fieldSuggestions.map((sug) => ({ + ...sug, + text: `${sug.text} `, + command: TRIGGER_SUGGESTION_COMMAND, + })); +} diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/show/index.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/show/index.ts index caa45b7ca5efb..43a4e244cb4d1 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/show/index.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/show/index.ts @@ -20,7 +20,7 @@ export async function suggest({ if (/INFO\s+$/i.test(innerText)) { return [{ ...pipeCompleteItem, command: TRIGGER_SUGGESTION_COMMAND }]; } - // SHOW INSOF / + // SHOW LOLZ / else if (/SHOW\s+\S+\s+$/i.test(innerText)) { return []; } diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/complete_items.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/complete_items.ts index 83f4324ef05f1..eef398ae4db0f 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/complete_items.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/complete_items.ts @@ -79,14 +79,21 @@ export const getCommandAutocompleteDefinitions = ( function buildCharCompleteItem( label: string, detail: string, - { sortText, quoted }: { sortText?: string; quoted: boolean } = { quoted: false } + { + sortText, + quoted, + advanceCursorAndOpenSuggestions, + }: { sortText?: string; quoted: boolean; advanceCursorAndOpenSuggestions?: boolean } = { + quoted: false, + } ): SuggestionRawDefinition { return { label, - text: quoted ? `"${label}"` : label, + text: (quoted ? `"${label}"` : label) + (advanceCursorAndOpenSuggestions ? ' ' : ''), kind: 'Keyword', detail, sortText, + command: advanceCursorAndOpenSuggestions ? TRIGGER_SUGGESTION_COMMAND : undefined, }; } export const pipeCompleteItem: SuggestionRawDefinition = { @@ -113,14 +120,14 @@ export const colonCompleteItem = buildCharCompleteItem( i18n.translate('kbn-esql-validation-autocomplete.esql.autocomplete.colonDoc', { defaultMessage: 'Colon (:)', }), - { sortText: 'A', quoted: true } + { sortText: 'A', quoted: true, advanceCursorAndOpenSuggestions: true } ); export const semiColonCompleteItem = buildCharCompleteItem( ';', i18n.translate('kbn-esql-validation-autocomplete.esql.autocomplete.semiColonDoc', { defaultMessage: 'Semi colon (;)', }), - { sortText: 'A', quoted: true } + { sortText: 'A', quoted: true, advanceCursorAndOpenSuggestions: true } ); export const listCompleteItem: SuggestionRawDefinition = { diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/factories.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/factories.ts index 2ba04ccb9c1e6..b4ef8a84cb341 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/factories.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/factories.ts @@ -459,7 +459,6 @@ export function getUnitDuration(unit: number = 1) { export function getCompatibleLiterals( commandName: string, types: string[], - names?: string[], options?: { advanceCursorAndOpenSuggestions?: boolean; addComma?: boolean; @@ -505,25 +504,6 @@ export function getCompatibleLiterals( ) ); // i.e. year, month, ... } - if (types.includes('string')) { - if (names) { - const index = types.indexOf('string'); - if (/pattern/.test(names[index])) { - suggestions.push( - ...buildConstantsDefinitions( - [commandName === 'grok' ? '"%{WORD:firstWord}"' : '"%{firstWord}"'], - i18n.translate('kbn-esql-validation-autocomplete.esql.autocomplete.aPatternString', { - defaultMessage: 'A pattern string', - }), - undefined, - options - ) - ); - } else { - suggestions.push(...buildConstantsDefinitions(['string'], '', undefined, options)); - } - } - } return suggestions; } diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/types.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/types.ts index c7b8396beaf6e..7b686cbb56134 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/types.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/types.ts @@ -83,7 +83,7 @@ export interface EditorContext { } export type GetColumnsByTypeFn = ( - type: string | string[], + type: Readonly | Readonly, ignored?: string[], options?: { advanceCursor?: boolean; diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/definitions/commands.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/definitions/commands.ts index 8b0f722604bfa..2c421c90fb53d 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/definitions/commands.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/definitions/commands.ts @@ -46,6 +46,8 @@ import { suggest as suggestForJoin } from '../autocomplete/commands/join'; import { suggest as suggestForFrom } from '../autocomplete/commands/from'; import { suggest as suggestForRow } from '../autocomplete/commands/row'; import { suggest as suggestForShow } from '../autocomplete/commands/show'; +import { suggest as suggestForGrok } from '../autocomplete/commands/grok'; +import { suggest as suggestForDissect } from '../autocomplete/commands/dissect'; const statsValidator = (command: ESQLCommand) => { const messages: ESQLMessage[] = []; @@ -454,7 +456,7 @@ export const commandDefinitions: Array> = [ defaultMessage: 'Extracts multiple string values from a single string input, based on a pattern', }), - examples: ['… | dissect a "%{b} %{c}"'], + examples: ['… | DISSECT a "%{b} %{c}" APPEND_SEPARATOR = ":"'], options: [appendSeparatorOption], modes: [], signature: { @@ -464,6 +466,7 @@ export const commandDefinitions: Array> = [ { name: 'pattern', type: 'string', constantOnly: true }, ], }, + suggest: suggestForDissect, }, { name: 'grok', @@ -471,7 +474,7 @@ export const commandDefinitions: Array> = [ defaultMessage: 'Extracts multiple string values from a single string input, based on a pattern', }), - examples: ['… | grok a "%{IP:b} %{NUMBER:c}"'], + examples: ['… | GROK a "%{IP:b} %{NUMBER:c}"'], options: [], modes: [], signature: { @@ -481,6 +484,7 @@ export const commandDefinitions: Array> = [ { name: 'pattern', type: 'string', constantOnly: true }, ], }, + suggest: suggestForGrok, }, { name: 'mv_expand', diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/shared/resources_helpers.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/shared/resources_helpers.ts index 5659a585ed758..d7265320e73f3 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/shared/resources_helpers.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/shared/resources_helpers.ts @@ -48,7 +48,7 @@ export function getFieldsByTypeHelper(queryText: string, resourceRetriever?: ESQ return { getFieldsByType: async ( - expectedType: string | string[] = 'any', + expectedType: Readonly | Readonly = 'any', ignored: string[] = [] ): Promise => { const types = Array.isArray(expectedType) ? expectedType : [expectedType];