From ae1d2fb505cb843bac311752e73962a8b001f1d1 Mon Sep 17 00:00:00 2001 From: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> Date: Fri, 8 Jan 2021 18:31:21 +0100 Subject: [PATCH] Prometheus: Fix autocomplete does not work on incomplete input (#29854) * WIP, works but need to do more testing * Update solution * Fix autocomplete with metrics * Update public/app/plugins/datasource/prometheus/language_provider.ts * Update public/app/plugins/datasource/prometheus/language_provider.ts * Change test for new functionality --- .../app/plugins/datasource/prometheus/language_provider.ts | 6 +++--- .../plugins/datasource/prometheus/language_utils.test.ts | 5 +++-- public/app/plugins/datasource/prometheus/language_utils.ts | 2 +- public/app/plugins/datasource/prometheus/promql.ts | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/public/app/plugins/datasource/prometheus/language_provider.ts b/public/app/plugins/datasource/prometheus/language_provider.ts index 629c842cd0a..685517fe0df 100644 --- a/public/app/plugins/datasource/prometheus/language_provider.ts +++ b/public/app/plugins/datasource/prometheus/language_provider.ts @@ -329,11 +329,11 @@ export default class PromQlLanguageProvider extends LanguageProvider { const suffix = line.substr(cursorOffset); const prefix = line.substr(0, cursorOffset); const isValueStart = text.match(/^(=|=~|!=|!~)/); - const isValueEnd = suffix.match(/^"?[,}]/); - // detect cursor in front of value, e.g., {key=|"} + const isValueEnd = suffix.match(/^"?[,}]|$/); + // Detect cursor in front of value, e.g., {key=|"} const isPreValue = prefix.match(/(=|=~|!=|!~)$/) && suffix.match(/^"/); - // Don't suggestq anything at the beginning or inside a value + // Don't suggest anything at the beginning or inside a value const isValueEmpty = isValueStart && isValueEnd; const hasValuePrefix = isValueEnd && !isValueStart; if ((!isValueEmpty && !hasValuePrefix) || isPreValue) { diff --git a/public/app/plugins/datasource/prometheus/language_utils.test.ts b/public/app/plugins/datasource/prometheus/language_utils.test.ts index 6cadc67c32b..c0933f5a3cf 100644 --- a/public/app/plugins/datasource/prometheus/language_utils.test.ts +++ b/public/app/plugins/datasource/prometheus/language_utils.test.ts @@ -9,8 +9,9 @@ describe('parseSelector()', () => { expect(parsed.labelKeys).toEqual([]); }); - it('throws if selector is broken', () => { - expect(() => parseSelector('{foo')).toThrow(); + it('returns a clean selector from an unclosed selector', () => { + const parsed = parseSelector('{foo'); + expect(parsed.selector).toBe('{}'); }); it('returns the selector sorted by label key', () => { diff --git a/public/app/plugins/datasource/prometheus/language_utils.ts b/public/app/plugins/datasource/prometheus/language_utils.ts index c0ea9e1c51b..716172a131f 100644 --- a/public/app/plugins/datasource/prometheus/language_utils.ts +++ b/public/app/plugins/datasource/prometheus/language_utils.ts @@ -42,7 +42,7 @@ export function processLabels(labels: Array<{ [key: string]: string }>, withName } // const cleanSelectorRegexp = /\{(\w+="[^"\n]*?")(,\w+="[^"\n]*?")*\}/; -export const selectorRegexp = /\{[^}]*?\}/; +export const selectorRegexp = /\{[^}]*?(\}|$)/; export const labelRegexp = /\b(\w+)(!?=~?)("[^"\n]*?")/g; export function parseSelector(query: string, cursorOffset = 1): { labelKeys: any[]; selector: string } { if (!query.match(selectorRegexp)) { diff --git a/public/app/plugins/datasource/prometheus/promql.ts b/public/app/plugins/datasource/prometheus/promql.ts index c0b3f87fc30..3dc5c70dfb5 100644 --- a/public/app/plugins/datasource/prometheus/promql.ts +++ b/public/app/plugins/datasource/prometheus/promql.ts @@ -393,7 +393,7 @@ const tokenizer: Grammar = { }, }, 'context-labels': { - pattern: /\{[^}]*(?=})/, + pattern: /\{[^}]*(?=}?)/, greedy: true, inside: { comment: {