Tempo: Fix TraceQL autocompletion with missing `}` (#77365)

pull/77646/head^2
Fabrizio 2 years ago committed by GitHub
parent be436ec6f6
commit 39014e73f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 21
      public/app/plugins/datasource/tempo/traceql/autocomplete.test.ts
  2. 44
      public/app/plugins/datasource/tempo/traceql/situation.ts

@ -342,6 +342,27 @@ describe('CompletionProvider', () => {
[...scopes, ...intrinsics].map((s) => expect.objectContaining({ label: s }))
);
});
it.each([
['{span.ht', 8],
['{span.http', 10],
['{span.http.', 11],
['{span.http.status', 17],
])(
'suggests attributes when containing trigger characters and missing `}`- %s, %i',
async (input: string, offset: number) => {
const { provider, model } = setup(input, offset, undefined, [
{
name: 'span',
tags: ['http.status_code'],
},
]);
const result = await provider.provideCompletionItems(model, emptyPosition);
expect((result! as monacoTypes.languages.CompletionList).suggestions).toEqual([
expect.objectContaining({ label: 'http.status_code', insertText: 'http.status_code' }),
]);
}
);
});
function setup(value: string, offset: number, tagsV1?: string[], tagsV2?: Scope[]) {

@ -202,9 +202,7 @@ const RESOLVERS: Resolver[] = [
},
{
path: [ERROR_NODE_ID, SpansetFilter],
fun: () => ({
type: 'SPANSET_EXPRESSION_OPERATORS_WITH_MISSING_CLOSED_BRACE',
}),
fun: resolveSpansetWithNoClosedBrace,
},
{
path: [ERROR_NODE_ID, Aggregate],
@ -253,16 +251,35 @@ const resolveAttributeCompletion = (node: SyntaxNode, text: string, pos: number)
// The user is completing an expression. We can take advantage of the fact that the Monaco editor is smart
// enough to automatically detect that there are some characters before the cursor and to take them into
// account when providing suggestions.
const endOfPathNode = walk(node, [['firstChild', [FieldExpression]]]);
if (endOfPathNode && text[pos - 1] !== ' ') {
const attributeFieldParent = walk(endOfPathNode, [['firstChild', [AttributeField]]]);
const getAttributeFieldUpToDot = (node: SyntaxNode) => {
const attributeFieldParent = walk(node, [['firstChild', [AttributeField]]]);
const attributeFieldParentText = attributeFieldParent ? getNodeText(attributeFieldParent, text) : '';
const indexOfDot = attributeFieldParentText.indexOf('.');
const attributeFieldUpToDot = attributeFieldParentText.slice(0, indexOfDot);
return attributeFieldParentText.slice(0, indexOfDot);
};
// If there is a space, for sure the attribute is completed and no suggestions to complete it should be provided
if (text[pos - 1] === ' ') {
return;
}
const endOfPathNode = walk(node, [['firstChild', [FieldExpression]]]);
if (endOfPathNode) {
return {
type: 'SPANSET_IN_NAME_SCOPE',
scope: attributeFieldUpToDot,
scope: getAttributeFieldUpToDot(endOfPathNode),
};
}
const endOfPathNode2 = walk(node, [
['parent', [SpansetFilter]],
['firstChild', [FieldExpression]],
]);
// In this case, we also need to check the character at `pos`
if (endOfPathNode2 && text[pos] !== ' ') {
return {
type: 'SPANSET_IN_NAME_SCOPE',
scope: getAttributeFieldUpToDot(endOfPathNode2),
};
}
};
@ -415,3 +432,14 @@ function resolveSpansetPipeline(node: SyntaxNode, _1: string, _2: number): Situa
type: 'NEW_SPANSET',
};
}
function resolveSpansetWithNoClosedBrace(node: SyntaxNode, text: string, originalPos: number): SituationType {
const situation = resolveAttributeCompletion(node, text, originalPos);
if (situation) {
return situation;
}
return {
type: 'SPANSET_EXPRESSION_OPERATORS_WITH_MISSING_CLOSED_BRACE',
};
}

Loading…
Cancel
Save