diff --git a/packages/kbn-monaco/src/es_ql/constants.ts b/packages/kbn-monaco/src/es_ql/constants.ts deleted file mode 100644 index ab986d5a84135..0000000000000 --- a/packages/kbn-monaco/src/es_ql/constants.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * 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 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 or the Server - * Side Public License, v 1. - */ - -export const ID = 'es_ql'; diff --git a/packages/kbn-monaco/src/es_ql/index.ts b/packages/kbn-monaco/src/es_ql/index.ts deleted file mode 100644 index 910041bab4038..0000000000000 --- a/packages/kbn-monaco/src/es_ql/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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 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 or the Server - * Side Public License, v 1. - */ - -import { LangModuleType } from '../types'; -import { ID } from './constants'; -import { lexerRules } from './lexer_rules'; - -// eslint-disable-next-line @typescript-eslint/naming-convention -export const ES_QLLang: LangModuleType = { ID, lexerRules }; diff --git a/packages/kbn-monaco/src/es_ql/lexer_rules/es_ql.ts b/packages/kbn-monaco/src/es_ql/lexer_rules/es_ql.ts deleted file mode 100644 index 8d29609100a2e..0000000000000 --- a/packages/kbn-monaco/src/es_ql/lexer_rules/es_ql.ts +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 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 or the Server - * Side Public License, v 1. - */ - -import { monaco } from '../../monaco_imports'; - -const brackets = [ - { open: '[', close: ']', token: 'delimiter.square' }, - { open: '(', close: ')', token: 'delimiter.parenthesis' }, -]; - -const keywords = ['from', 'limit', 'project']; -const builtinFunctions: string[] = [ - // TODO fill once endpoint supports them -]; - -export const lexerRules = { - defaultToken: 'invalid', - ignoreCase: true, - tokenPostfix: '', - keywords, - builtinFunctions, - brackets, - tokenizer: { - root: [ - [ - /[a-zA-Z_$][a-zA-Z0-9_$]*\b/, - { - cases: { - '@keywords': 'keyword', - '@builtinFunctions': 'identifier', - '@default': 'identifier', - }, - }, - ], - [/[()]/, '@brackets'], - [/--.*$/, 'comment'], - [/\/\*/, 'comment', '@comment'], - [/\/.*$/, 'comment'], - - [/".*?"/, 'string'], - - [/'.*?'/, 'constant'], - [/`.*?`/, 'string'], - // whitespace - [/[ \t\r\n]+/, { token: '@whitespace' }], - [/[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b/, 'entity.name.function'], - [/⇐|<⇒|\*|\.|\:\:|\+|\-|\/|\/\/|%|&|\^|~|<|>|<=|=>|==|!=|<>|=/, 'keyword.operator'], - [/[\(]/, 'paren.lparen'], - [/[\)]/, 'paren.rparen'], - [/\s+/, 'text'], - ], - numbers: [ - [/0[xX][0-9a-fA-F]*/, 'number'], - [/[$][+-]*\d*(\.\d*)?/, 'number'], - [/((\d+(\.\d*)?)|(\.\d+))([eE][\-+]?\d+)?/, 'number'], - ], - strings: [ - [/N'/, { token: 'string', next: '@string' }], - [/'/, { token: 'string', next: '@string' }], - ], - string: [ - [/[^']+/, 'string'], - [/''/, 'string'], - [/'/, { token: 'string', next: '@pop' }], - ], - comment: [ - [/[^\/*]+/, 'comment'], - [/\*\//, 'comment', '@pop'], - [/[\/*]/, 'comment'], - ], - }, -} as monaco.languages.IMonarchLanguage; diff --git a/packages/kbn-monaco/src/es_ql/lexer_rules/index.ts b/packages/kbn-monaco/src/es_ql/lexer_rules/index.ts deleted file mode 100644 index 016132377dde2..0000000000000 --- a/packages/kbn-monaco/src/es_ql/lexer_rules/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * 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 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 or the Server - * Side Public License, v 1. - */ - -export { lexerRules } from './es_ql'; diff --git a/src/plugins/unified_search/public/query_string_input/text_based_languages_editor/index.tsx b/src/plugins/unified_search/public/query_string_input/text_based_languages_editor/index.tsx index 0ef1b856c8fc3..4afd677885d79 100644 --- a/src/plugins/unified_search/public/query_string_input/text_based_languages_editor/index.tsx +++ b/src/plugins/unified_search/public/query_string_input/text_based_languages_editor/index.tsx @@ -6,9 +6,16 @@ * Side Public License, v 1. */ -import React, { useRef, memo, useEffect, useState, useCallback } from 'react'; +import React, { useRef, memo, useEffect, useState, useCallback, useMemo } from 'react'; import classNames from 'classnames'; -import { SQLLang, monaco, ESQL_LANG_ID, ESQL_THEME_ID } from '@kbn/monaco'; +import { + SQLLang, + monaco, + ESQL_LANG_ID, + ESQL_THEME_ID, + ESQLLang, + ESQLCustomAutocompleteCallbacks, +} from '@kbn/monaco'; import type { AggregateQuery } from '@kbn/es-query'; import { getAggregateQueryMode } from '@kbn/es-query'; import { @@ -111,7 +118,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ const [documentationSections, setDocumentationSections] = useState(); const kibana = useKibana(); - const { uiSettings } = kibana.services; + const { uiSettings, dataViews } = kibana.services; const styles = textBasedLanguagedEditorStyles( euiTheme, @@ -331,6 +338,42 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ getDocumentation(); }, [language]); + const getSourceIdentifiers: ESQLCustomAutocompleteCallbacks['getSourceIdentifiers'] = + useCallback(() => { + return dataViews.getTitles(); + }, [dataViews]); + + const getFieldsIdentifiers: ESQLCustomAutocompleteCallbacks['getFieldsIdentifiers'] = + useMemo(() => { + let source: string; + let cachedSuggestions: string[] = []; + + return async (ctx) => { + let data: string[] = []; + const sourceKey = ctx.userDefinedVariables.sourceIdentifiers.join(','); + if (sourceKey === source) { + return cachedSuggestions; + } + for (const s of ctx.userDefinedVariables.sourceIdentifiers) { + if (s) { + try { + const [dataView] = await dataViews.find(s, 1); + if (dataView) { + data = [...data, ...dataView.fields.map((f) => f.name)]; + } + } catch (e) { + // nothing to be here + } + } + } + + cachedSuggestions = data; + source = sourceKey; + + return cachedSuggestions; + }; + }, [dataViews]); + const codeEditorOptions: CodeEditorProps['options'] = { automaticLayout: false, accessibilitySupport: 'off', @@ -520,6 +563,14 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ value={codeOneLiner || code} options={codeEditorOptions} width="100%" + suggestionProvider={ + language === 'esql' + ? ESQLLang.getSuggestionProvider?.({ + getSourceIdentifiers, + getFieldsIdentifiers, + }) + : undefined + } onChange={onQueryUpdate} editorDidMount={(editor) => { editor1.current = editor;