fix autocompletion when using by/without

Signed-off-by: Augustin Husson <husson.augustin@gmail.com>
This commit is contained in:
Augustin Husson 2024-09-19 16:35:14 +02:00
parent 69619990f8
commit 6e899fbb16
2 changed files with 19 additions and 14 deletions

View file

@ -601,6 +601,18 @@ describe('analyzeCompletion test', () => {
pos: 10, pos: 10,
expectedContext: [{ kind: ContextKind.MetricName, metricName: 'r' }, { kind: ContextKind.Function }, { kind: ContextKind.Aggregation }], expectedContext: [{ kind: ContextKind.MetricName, metricName: 'r' }, { kind: ContextKind.Function }, { kind: ContextKind.Aggregation }],
}, },
{
title: 'autocomplete topk params 4',
expr: 'topk by(instance) ()',
pos: 19,
expectedContext: [{ kind: ContextKind.Number }],
},
{
title: 'autocomplete topk params 5',
expr: 'topk by(instance) (inf,r)',
pos: 24,
expectedContext: [{ kind: ContextKind.MetricName, metricName: 'r' }, { kind: ContextKind.Function }, { kind: ContextKind.Aggregation }],
},
]; ];
testCases.forEach((value) => { testCases.forEach((value) => {
it(value.title, () => { it(value.title, () => {

View file

@ -204,7 +204,7 @@ export function computeStartCompletePosition(state: EditorState, node: SyntaxNod
// So we have to analyze the string about the current node to see if the duration unit is already present or not. // So we have to analyze the string about the current node to see if the duration unit is already present or not.
(node.type.id === NumberDurationLiteralInDurationContext && !durationTerms.map((v) => v.label).includes(currentText[currentText.length - 1])) || (node.type.id === NumberDurationLiteralInDurationContext && !durationTerms.map((v) => v.label).includes(currentText[currentText.length - 1])) ||
(node.type.id === NumberDurationLiteral && node.parent?.type.id === 0 && node.parent.parent?.type.id === SubqueryExpr) || (node.type.id === NumberDurationLiteral && node.parent?.type.id === 0 && node.parent.parent?.type.id === SubqueryExpr) ||
(node.type.id === FunctionCallBody && isItATopKLikeAggregationFunc(node) && node.firstChild !== null) || (node.type.id === FunctionCallBody && isAggregatorWithParam(node) && node.firstChild !== null) ||
(node.type.id === 0 && (node.type.id === 0 &&
(node.parent?.type.id === OffsetExpr || (node.parent?.type.id === OffsetExpr ||
node.parent?.type.id === MatrixSelector || node.parent?.type.id === MatrixSelector ||
@ -215,18 +215,11 @@ export function computeStartCompletePosition(state: EditorState, node: SyntaxNod
return start; return start;
} }
function isItATopKLikeAggregationFunc(functionCallBody: SyntaxNode): boolean { function isAggregatorWithParam(functionCallBody: SyntaxNode): boolean {
const prevSibling = functionCallBody.prevSibling; const parent = functionCallBody.parent;
if (prevSibling !== null && prevSibling.type.id === AggregateOp) { if (parent !== null && parent.firstChild?.type.id === AggregateOp) {
const aggregationOpType = prevSibling.firstChild; const aggregationOpType = parent.firstChild.firstChild;
if ( if (aggregationOpType !== null && [Topk, Bottomk, LimitK, LimitRatio, CountValues].includes(aggregationOpType.type.id)) {
aggregationOpType !== null &&
(aggregationOpType.type.id == Topk ||
aggregationOpType.type.id === Bottomk ||
aggregationOpType.type.id === LimitK ||
aggregationOpType.type.id === LimitRatio ||
aggregationOpType.type.id === CountValues)
) {
return true; return true;
} }
} }
@ -491,7 +484,7 @@ export function analyzeCompletion(state: EditorState, node: SyntaxNode, pos: num
// Unfortunately, as a current node, codemirror doesn't give us the error node but instead the FunctionCallBody // Unfortunately, as a current node, codemirror doesn't give us the error node but instead the FunctionCallBody
// The tree looks like that: PromQL(AggregateExpr(AggregateOp(Topk),FunctionCallBody(NumberDurationLiteral,⚠))) // The tree looks like that: PromQL(AggregateExpr(AggregateOp(Topk),FunctionCallBody(NumberDurationLiteral,⚠)))
// So, we need to figure out if the cursor is on the first parameter or in the second. // So, we need to figure out if the cursor is on the first parameter or in the second.
if (isItATopKLikeAggregationFunc(node)) { if (isAggregatorWithParam(node)) {
if (node.firstChild === null || (node.firstChild.from <= pos && node.firstChild.to >= pos)) { if (node.firstChild === null || (node.firstChild.from <= pos && node.firstChild.to >= pos)) {
// it means the FunctionCallBody has no child, which means we are autocompleting the first parameter // it means the FunctionCallBody has no child, which means we are autocompleting the first parameter
result.push({ kind: ContextKind.Number }); result.push({ kind: ContextKind.Number });