Commit 2a4a1938 by Michael Huynh

Fix label suggestions for multi-line aggregation queries

No label suggestions were being returned for multi-line aggregation
contexts because the parsed selector string does not see the full
context before a `by` or `without` clause.

This solution stitches together all text nodes that comprise the query
editor to ensure the selector has sufficient context to generate
suggestions.

Also, an additional workaround has been included to ensure range vector
syntax does not disrupt label suggestions in aggregation contexts.

Related: #12890
parent 58a56717
...@@ -162,16 +162,29 @@ export default class PromQlLanguageProvider extends LanguageProvider { ...@@ -162,16 +162,29 @@ export default class PromQlLanguageProvider extends LanguageProvider {
let refresher: Promise<any> = null; let refresher: Promise<any> = null;
const suggestions: CompletionItemGroup[] = []; const suggestions: CompletionItemGroup[] = [];
// sum(foo{bar="1"}) by (|) // Stitch all query lines together to support multi-line queries
const line = value.anchorBlock.getText(); let queryOffset;
const cursorOffset: number = value.anchorOffset; const queryText = value.document.getBlocks().reduce((text, block) => {
// sum(foo{bar="1"}) by ( const blockText = block.getText();
const leftSide = line.slice(0, cursorOffset); if (value.anchorBlock.key === block.key) {
// Newline characters are not accounted for but this is irrelevant
// for the purpose of extracting the selector string
queryOffset = value.anchorOffset + text.length;
}
text += blockText;
return text;
}, '');
const leftSide = queryText.slice(0, queryOffset);
const openParensAggregationIndex = leftSide.lastIndexOf('('); const openParensAggregationIndex = leftSide.lastIndexOf('(');
const openParensSelectorIndex = leftSide.slice(0, openParensAggregationIndex).lastIndexOf('('); const openParensSelectorIndex = leftSide.slice(0, openParensAggregationIndex).lastIndexOf('(');
const closeParensSelectorIndex = leftSide.slice(openParensSelectorIndex).indexOf(')') + openParensSelectorIndex; const closeParensSelectorIndex = leftSide.slice(openParensSelectorIndex).indexOf(')') + openParensSelectorIndex;
// foo{bar="1"}
const selectorString = leftSide.slice(openParensSelectorIndex + 1, closeParensSelectorIndex); let selectorString = leftSide.slice(openParensSelectorIndex + 1, closeParensSelectorIndex);
// Range vector syntax not accounted for by subsequent parse so discard it if present
selectorString = selectorString.replace(/\[[^\]]+\]$/, '');
const selector = parseSelector(selectorString, selectorString.length - 2).selector; const selector = parseSelector(selectorString, selectorString.length - 2).selector;
const labelKeys = this.labelKeys[selector]; const labelKeys = this.labelKeys[selector];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment