diff --git a/packages/kbn-text-based-editor/src/helpers.test.ts b/packages/kbn-text-based-editor/src/helpers.test.ts index f7b100419b2c7..f0a4268f857bc 100644 --- a/packages/kbn-text-based-editor/src/helpers.test.ts +++ b/packages/kbn-text-based-editor/src/helpers.test.ts @@ -114,6 +114,73 @@ describe('helpers', function () { }, ]); }); + + it('should return the correct array of warnings if multiple warnins are detected without line indicators', function () { + const warning = + '299 Elasticsearch-8.10.0-SNAPSHOT-adb9fce96079b421c2575f0d2d445f492eb5f075 "Field [geo.coordinates] cannot be retrieved, it is unsupported or not indexed; returning null.", 299 Elasticsearch-8.10.0-SNAPSHOT-adb9fce96079b421c2575f0d2d445f492eb5f075 "Field [ip_range] cannot be retrieved, it is unsupported or not indexed; returning null.", 299 Elasticsearch-8.10.0-SNAPSHOT-adb9fce96079b421c2575f0d2d445f492eb5f075 "Field [timestamp_range] cannot be retrieved, it is unsupported or not indexed; returning null."'; + expect(parseWarning(warning)).toEqual([ + { + endColumn: 10, + endLineNumber: 1, + message: + 'Field [geo.coordinates] cannot be retrieved, it is unsupported or not indexed; returning null.', + severity: 8, + startColumn: 1, + startLineNumber: 1, + }, + { + endColumn: 10, + endLineNumber: 1, + message: + 'Field [ip_range] cannot be retrieved, it is unsupported or not indexed; returning null.', + severity: 8, + startColumn: 1, + startLineNumber: 1, + }, + { + endColumn: 10, + endLineNumber: 1, + message: + 'Field [timestamp_range] cannot be retrieved, it is unsupported or not indexed; returning null.', + severity: 8, + startColumn: 1, + startLineNumber: 1, + }, + ]); + }); + it('should return the correct array of warnings if multiple warnins of different types', function () { + const warning = + '299 Elasticsearch-8.10.0-SNAPSHOT-adb9fce96079b421c2575f0d2d445f492eb5f075 "Field [geo.coordinates] cannot be retrieved, it is unsupported or not indexed; returning null.", 299 Elasticsearch-8.10.0-SNAPSHOT-adb9fce96079b421c2575f0d2d445f492eb5f075 "Field [ip_range] cannot be retrieved, it is unsupported or not indexed; returning null.", 299 Elasticsearch-8.10.0-SNAPSHOT-adb9fce96079b421c2575f0d2d445f492eb5f075 "Line 1:52: evaluation of [date_parse(geo.dest)] failed, treating result as null. Only first 20 failures recorded."'; + expect(parseWarning(warning)).toEqual([ + { + endColumn: 10, + endLineNumber: 1, + message: + 'Field [geo.coordinates] cannot be retrieved, it is unsupported or not indexed; returning null.', + severity: 8, + startColumn: 1, + startLineNumber: 1, + }, + { + endColumn: 10, + endLineNumber: 1, + message: + 'Field [ip_range] cannot be retrieved, it is unsupported or not indexed; returning null.', + severity: 8, + startColumn: 1, + startLineNumber: 1, + }, + { + endColumn: 138, + endLineNumber: 1, + message: + 'evaluation of [date_parse(geo.dest)] failed, treating result as null. Only first 20 failures recorded.', + severity: 8, + startColumn: 52, + startLineNumber: 1, + }, + ]); + }); }); describe('getInlineEditorText', function () { diff --git a/packages/kbn-text-based-editor/src/helpers.ts b/packages/kbn-text-based-editor/src/helpers.ts index 8932276695117..234a5ae0089ab 100644 --- a/packages/kbn-text-based-editor/src/helpers.ts +++ b/packages/kbn-text-based-editor/src/helpers.ts @@ -43,41 +43,60 @@ export const useDebounceWithOptions = ( ); }; +const quotedWarningMessageRegexp = /"(.*?)"/g; + export const parseWarning = (warning: string): MonacoError[] => { - if (warning.includes('Line')) { - const splitByLine = warning.split('Line'); - splitByLine.shift(); - return splitByLine.map((item) => { - const [lineNumber, startPosition, warningMessage] = item.split(':'); - const [trimmedMessage] = warningMessage.split('"'); - // initialize the length to 10 in case no error word found - let errorLength = 10; - const [_, wordWithError] = trimmedMessage.split('['); - if (wordWithError) { - errorLength = wordWithError.length - 1; - } - return { - message: trimmedMessage.trimStart(), - startColumn: Number(startPosition), - startLineNumber: Number(lineNumber), - endColumn: Number(startPosition) + errorLength, - endLineNumber: Number(lineNumber), - severity: monaco.MarkerSeverity.Error, - }; - }); - } else { - // unknown warning message - return [ - { - message: warning, - startColumn: 1, - startLineNumber: 1, - endColumn: 10, - endLineNumber: 1, - severity: monaco.MarkerSeverity.Error, - }, - ]; + if (quotedWarningMessageRegexp.test(warning)) { + const matches = warning.match(quotedWarningMessageRegexp); + if (matches) { + return matches.map((message) => { + // start extracting the quoted message and with few default positioning + let warningMessage = message.replace(/"/g, ''); + let startColumn = 1; + let startLineNumber = 1; + // initialize the length to 10 in case no error word found + let errorLength = 10; + // if there's line number encoded in the message use it as new positioning + // and replace the actual message without it + if (/Line (\d+):(\d+):/.test(warningMessage)) { + const [encodedLine, encodedColumn, innerMessage] = warningMessage.split(':'); + warningMessage = innerMessage; + if (!Number.isNaN(Number(encodedColumn))) { + startColumn = Number(encodedColumn); + startLineNumber = Number(encodedLine.replace('Line ', '')); + } + // extract the length of the "expression" within the message + // and try to guess the correct size for the editor marker to highlight + if (/\[.*\]/.test(warningMessage)) { + const [_, wordWithError] = warningMessage.split('['); + if (wordWithError) { + errorLength = wordWithError.length; + } + } + } + + return { + message: warningMessage.trimStart(), + startColumn, + startLineNumber, + endColumn: startColumn + errorLength - 1, + endLineNumber: startLineNumber, + severity: monaco.MarkerSeverity.Error, + }; + }); + } } + // unknown warning message + return [ + { + message: warning, + startColumn: 1, + startLineNumber: 1, + endColumn: 10, + endLineNumber: 1, + severity: monaco.MarkerSeverity.Error, + }, + ]; }; export const parseErrors = (errors: Error[], code: string): MonacoError[] => {