mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge pull request #13847 from miqh/fix/multi-line-aggregation
Fix label suggestions inside multi-line aggregation contexts
This commit is contained in:
commit
121ac93d08
@ -162,16 +162,29 @@ export default class PromQlLanguageProvider extends LanguageProvider {
|
||||
let refresher: Promise<any> = null;
|
||||
const suggestions: CompletionItemGroup[] = [];
|
||||
|
||||
// sum(foo{bar="1"}) by (|)
|
||||
const line = value.anchorBlock.getText();
|
||||
const cursorOffset: number = value.anchorOffset;
|
||||
// sum(foo{bar="1"}) by (
|
||||
const leftSide = line.slice(0, cursorOffset);
|
||||
// Stitch all query lines together to support multi-line queries
|
||||
let queryOffset;
|
||||
const queryText = value.document.getBlocks().reduce((text, block) => {
|
||||
const blockText = block.getText();
|
||||
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 openParensSelectorIndex = leftSide.slice(0, openParensAggregationIndex).lastIndexOf('(');
|
||||
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 labelKeys = this.labelKeys[selector];
|
||||
|
@ -198,5 +198,76 @@ describe('Language completion provider', () => {
|
||||
expect(result.context).toBe('context-aggregation');
|
||||
expect(result.suggestions).toEqual([{ items: [{ label: 'bar' }], label: 'Labels' }]);
|
||||
});
|
||||
|
||||
it('returns label suggestions inside a multi-line aggregation context', () => {
|
||||
const instance = new LanguageProvider(datasource, {
|
||||
labelKeys: { '{__name__="metric"}': ['label1', 'label2', 'label3'] },
|
||||
});
|
||||
const value = Plain.deserialize('sum(\nmetric\n)\nby ()');
|
||||
const aggregationTextBlock = value.document.getBlocksAsArray()[3];
|
||||
const range = value.selection.moveToStartOf(aggregationTextBlock).merge({ anchorOffset: 4 });
|
||||
const valueWithSelection = value.change().select(range).value;
|
||||
const result = instance.provideCompletionItems({
|
||||
text: '',
|
||||
prefix: '',
|
||||
wrapperClasses: ['context-aggregation'],
|
||||
value: valueWithSelection,
|
||||
});
|
||||
expect(result.context).toBe('context-aggregation');
|
||||
expect(result.suggestions).toEqual([
|
||||
{
|
||||
items: [{ label: 'label1' }, { label: 'label2' }, { label: 'label3' }],
|
||||
label: 'Labels',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns label suggestions inside an aggregation context with a range vector', () => {
|
||||
const instance = new LanguageProvider(datasource, {
|
||||
labelKeys: { '{__name__="metric"}': ['label1', 'label2', 'label3'] },
|
||||
});
|
||||
const value = Plain.deserialize('sum(rate(metric[1h])) by ()');
|
||||
const range = value.selection.merge({
|
||||
anchorOffset: 26,
|
||||
});
|
||||
const valueWithSelection = value.change().select(range).value;
|
||||
const result = instance.provideCompletionItems({
|
||||
text: '',
|
||||
prefix: '',
|
||||
wrapperClasses: ['context-aggregation'],
|
||||
value: valueWithSelection,
|
||||
});
|
||||
expect(result.context).toBe('context-aggregation');
|
||||
expect(result.suggestions).toEqual([
|
||||
{
|
||||
items: [{ label: 'label1' }, { label: 'label2' }, { label: 'label3' }],
|
||||
label: 'Labels',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns label suggestions inside an aggregation context with a range vector and label', () => {
|
||||
const instance = new LanguageProvider(datasource, {
|
||||
labelKeys: { '{__name__="metric",label1="value"}': ['label1', 'label2', 'label3'] },
|
||||
});
|
||||
const value = Plain.deserialize('sum(rate(metric{label1="value"}[1h])) by ()');
|
||||
const range = value.selection.merge({
|
||||
anchorOffset: 42,
|
||||
});
|
||||
const valueWithSelection = value.change().select(range).value;
|
||||
const result = instance.provideCompletionItems({
|
||||
text: '',
|
||||
prefix: '',
|
||||
wrapperClasses: ['context-aggregation'],
|
||||
value: valueWithSelection,
|
||||
});
|
||||
expect(result.context).toBe('context-aggregation');
|
||||
expect(result.suggestions).toEqual([
|
||||
{
|
||||
items: [{ label: 'label1' }, { label: 'label2' }, { label: 'label3' }],
|
||||
label: 'Labels',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user