diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.where.test.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.where.test.ts index 1fdc6fa2ae769..4105a6a097e5a 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.where.test.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.where.test.ts @@ -411,7 +411,7 @@ describe('WHERE ', () => { detail: 'Click to create', command: { id: 'esql.control.values.create', title: 'Click to create' }, sortText: '11', - rangeToReplace: { start: 31, end: 31 }, + rangeToReplace: { start: 30, end: 30 }, }); }); @@ -439,7 +439,7 @@ describe('WHERE ', () => { detail: 'Named parameter', command: undefined, sortText: '11A', - rangeToReplace: { start: 31, end: 31 }, + rangeToReplace: { start: 30, end: 30 }, }); }); }); diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/helper.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/helper.ts index 8fc421bda3751..a7be67ca460bf 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/helper.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/helper.ts @@ -608,7 +608,7 @@ export async function getSuggestionsToRightOfOperatorExpression({ ) { suggestions.push(listCompleteItem); } else { - const finalType = leftArgType || leftArgType || 'any'; + const finalType = leftArgType || 'any'; const supportedTypes = getSupportedTypesForBinaryOperators(fnDef, finalType as string); // this is a special case with AND/OR @@ -671,12 +671,11 @@ export async function getSuggestionsToRightOfOperatorExpression({ } return suggestions.map((s) => { const overlap = getOverlapRange(queryText, s.text); - const offset = overlap.start === overlap.end ? 1 : 0; return { ...s, rangeToReplace: { - start: overlap.start + offset, - end: overlap.end + offset, + start: overlap.start, + end: overlap.end, }, }; }); diff --git a/src/platform/packages/shared/kbn-monaco/src/esql/lib/shared/utils.test.ts b/src/platform/packages/shared/kbn-monaco/src/esql/lib/shared/utils.test.ts new file mode 100644 index 0000000000000..0a703771d4dd6 --- /dev/null +++ b/src/platform/packages/shared/kbn-monaco/src/esql/lib/shared/utils.test.ts @@ -0,0 +1,63 @@ +/* + * 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 { offsetRangeToMonacoRange } from './utils'; + +describe('offsetRangeToMonacoRange', () => { + test('should convert offset range to monaco range when the cursor is not at the end', () => { + const expression = 'FROM test | WHERE test == | LIMIT 1'; + const range = { start: 26, end: 26 }; + const monacoRange = offsetRangeToMonacoRange(expression, range); + + expect(monacoRange).toEqual({ + startColumn: 26, + endColumn: 26, + startLineNumber: 1, + endLineNumber: 1, + }); + }); + + test('should convert offset range to monaco range when the cursor is at the end', () => { + const expression = 'FROM test | WHERE test == 1 | LIMIT 1'; + const range = { start: 37, end: 37 }; + const monacoRange = offsetRangeToMonacoRange(expression, range); + + expect(monacoRange).toEqual({ + startColumn: 37, + endColumn: 37, + startLineNumber: 1, + endLineNumber: 1, + }); + }); + + test('should convert offset range to monaco range for multiple lines query when the cursor is not at the end', () => { + const expression = 'FROM test \n| WHERE test == \n| LIMIT 1'; + const range = { start: 27, end: 27 }; + const monacoRange = offsetRangeToMonacoRange(expression, range); + + expect(monacoRange).toEqual({ + startColumn: 16, + endColumn: 16, + startLineNumber: 2, + endLineNumber: 2, + }); + }); + + test('should convert offset range to monaco range for multiple lines query when the cursor is at the end', () => { + const expression = 'FROM test \n| WHERE test == \n| LIMIT 1'; + const range = { start: 35, end: 35 }; + const monacoRange = offsetRangeToMonacoRange(expression, range); + + expect(monacoRange).toEqual({ + startColumn: 7, + endColumn: 7, + startLineNumber: 3, + endLineNumber: 3, + }); + }); +}); diff --git a/src/platform/packages/shared/kbn-monaco/src/esql/lib/shared/utils.ts b/src/platform/packages/shared/kbn-monaco/src/esql/lib/shared/utils.ts index 17f9dce029d25..81fa80bf654a4 100644 --- a/src/platform/packages/shared/kbn-monaco/src/esql/lib/shared/utils.ts +++ b/src/platform/packages/shared/kbn-monaco/src/esql/lib/shared/utils.ts @@ -47,22 +47,25 @@ export const offsetRangeToMonacoRange = ( let endLineNumber = 1; let currentLine = 1; - for (let i = 0; i < expression.length; i++) { - if (expression[i] === '\n') { - currentLine++; - currentOffset = i + 1; - } + const hasMultipleLines = expression.includes('\n'); + const offset = hasMultipleLines ? 1 : 0; - if (i === range.start) { + for (let i = 0; i < expression.length; i++) { + if (i === range.start - offset) { startLineNumber = currentLine; startColumn = i - currentOffset; } - if (i === range.end) { + if (i === range.end - offset) { endLineNumber = currentLine; endColumn = i - currentOffset; break; // No need to continue once we find the end position } + + if (expression[i] === '\n') { + currentLine++; + currentOffset = i; + } } // Handle the case where the start offset is past the end of the string