Datasource/CloudWatch: Fixes various autocomplete issues (#24583)

This commit is contained in:
kay delaney 2020-05-12 16:32:48 +01:00 committed by GitHub
parent a50cb6aa1f
commit c1919944ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 19 additions and 24 deletions

View File

@ -295,8 +295,8 @@ const handleTypeahead = async (
} }
} }
// Filter out the already typed value (prefix) unless it inserts custom text // Filter out the already typed value (prefix) unless it inserts custom text not matching the prefix
newGroup.items = newGroup.items.filter(c => c.insertText || (c.filterText || c.label) !== prefix); newGroup.items = newGroup.items.filter(c => !(c.insertText === prefix || (c.filterText ?? c.label) === prefix));
} }
if (!group.skipSort) { if (!group.skipSort) {

View File

@ -8,11 +8,11 @@ import {
AGGREGATION_FUNCTIONS_STATS, AGGREGATION_FUNCTIONS_STATS,
BOOLEAN_FUNCTIONS, BOOLEAN_FUNCTIONS,
DATETIME_FUNCTIONS, DATETIME_FUNCTIONS,
FUNCTIONS,
IP_FUNCTIONS, IP_FUNCTIONS,
NUMERIC_OPERATORS, NUMERIC_OPERATORS,
QUERY_COMMANDS, QUERY_COMMANDS,
STRING_FUNCTIONS, STRING_FUNCTIONS,
FIELD_AND_FILTER_FUNCTIONS,
} from './syntax'; } from './syntax';
const fields = ['field1', '@message']; const fields = ['field1', '@message'];
@ -33,19 +33,19 @@ describe('CloudWatchLanguageProvider', () => {
}); });
it('should suggest fields and functions after field command', async () => { it('should suggest fields and functions after field command', async () => {
await runSuggestionTest('fields \\', [fields, FUNCTIONS.map(v => v.label)]); await runSuggestionTest('fields \\', [fields, FIELD_AND_FILTER_FUNCTIONS.map(v => v.label)]);
}); });
it('should suggest fields and functions after comma', async () => { it('should suggest fields and functions after comma', async () => {
await runSuggestionTest('fields field1, \\', [fields, FUNCTIONS.map(v => v.label)]); await runSuggestionTest('fields field1, \\', [fields, FIELD_AND_FILTER_FUNCTIONS.map(v => v.label)]);
}); });
it('should suggest fields and functions after comma with prefix', async () => { it('should suggest fields and functions after comma with prefix', async () => {
await runSuggestionTest('fields field1, @mess\\', [fields, FUNCTIONS.map(v => v.label)]); await runSuggestionTest('fields field1, @mess\\', [fields, FIELD_AND_FILTER_FUNCTIONS.map(v => v.label)]);
}); });
it('should suggest fields and functions after display command', async () => { it('should suggest fields and functions after display command', async () => {
await runSuggestionTest('display \\', [fields, FUNCTIONS.map(v => v.label)]); await runSuggestionTest('display \\', [fields, FIELD_AND_FILTER_FUNCTIONS.map(v => v.label)]);
}); });
it('should suggest functions after stats command', async () => { it('should suggest functions after stats command', async () => {
@ -62,8 +62,7 @@ describe('CloudWatchLanguageProvider', () => {
it('should suggest fields and some functions after comparison operator', async () => { it('should suggest fields and some functions after comparison operator', async () => {
await runSuggestionTest('filter field1 >= \\', [ await runSuggestionTest('filter field1 >= \\', [
fields, fields,
BOOLEAN_FUNCTIONS.map(v => v.label), [...NUMERIC_OPERATORS.map(v => v.label), ...BOOLEAN_FUNCTIONS.map(v => v.label)],
NUMERIC_OPERATORS.map(v => v.label),
]); ]);
}); });

View File

@ -4,13 +4,13 @@ import _ from 'lodash';
// Services & Utils // Services & Utils
import syntax, { import syntax, {
QUERY_COMMANDS, QUERY_COMMANDS,
FUNCTIONS,
AGGREGATION_FUNCTIONS_STATS, AGGREGATION_FUNCTIONS_STATS,
STRING_FUNCTIONS, STRING_FUNCTIONS,
DATETIME_FUNCTIONS, DATETIME_FUNCTIONS,
IP_FUNCTIONS, IP_FUNCTIONS,
BOOLEAN_FUNCTIONS, BOOLEAN_FUNCTIONS,
NUMERIC_OPERATORS, NUMERIC_OPERATORS,
FIELD_AND_FILTER_FUNCTIONS,
} from './syntax'; } from './syntax';
// Types // Types
@ -210,7 +210,7 @@ export class CloudWatchLanguageProvider extends LanguageProvider {
if (['display', 'fields'].includes(queryCommand)) { if (['display', 'fields'].includes(queryCommand)) {
const typeaheadOutput = await this.getFieldCompletionItems(context.logGroupNames ?? []); const typeaheadOutput = await this.getFieldCompletionItems(context.logGroupNames ?? []);
typeaheadOutput.suggestions.push(...this.getFunctionCompletionItems().suggestions); typeaheadOutput.suggestions.push(...this.getFieldAndFilterFunctionCompletionItems().suggestions);
return typeaheadOutput; return typeaheadOutput;
} }
@ -264,10 +264,8 @@ export class CloudWatchLanguageProvider extends LanguageProvider {
private handleComparison = async (context?: TypeaheadContext) => { private handleComparison = async (context?: TypeaheadContext) => {
const fieldsSuggestions = await this.getFieldCompletionItems(context?.logGroupNames ?? []); const fieldsSuggestions = await this.getFieldCompletionItems(context?.logGroupNames ?? []);
const boolFuncSuggestions = this.getBoolFuncCompletionItems(); const comparisonSuggestions = this.getComparisonCompletionItems();
const numFuncSuggestions = this.getNumericFuncCompletionItems(); fieldsSuggestions.suggestions.push(...comparisonSuggestions.suggestions);
fieldsSuggestions.suggestions.push(...boolFuncSuggestions.suggestions, ...numFuncSuggestions.suggestions);
return fieldsSuggestions; return fieldsSuggestions;
}; };
@ -275,8 +273,8 @@ export class CloudWatchLanguageProvider extends LanguageProvider {
return { suggestions: [{ prefixMatch: true, label: 'Commands', items: QUERY_COMMANDS }] }; return { suggestions: [{ prefixMatch: true, label: 'Commands', items: QUERY_COMMANDS }] };
}; };
private getFunctionCompletionItems = (): TypeaheadOutput => { private getFieldAndFilterFunctionCompletionItems = (): TypeaheadOutput => {
return { suggestions: [{ prefixMatch: true, label: 'Functions', items: FUNCTIONS }] }; return { suggestions: [{ prefixMatch: true, label: 'Functions', items: FIELD_AND_FILTER_FUNCTIONS }] };
}; };
private getStatsAggCompletionItems = (): TypeaheadOutput => { private getStatsAggCompletionItems = (): TypeaheadOutput => {
@ -295,13 +293,13 @@ export class CloudWatchLanguageProvider extends LanguageProvider {
}; };
}; };
private getNumericFuncCompletionItems = (): TypeaheadOutput => { private getComparisonCompletionItems = (): TypeaheadOutput => {
return { return {
suggestions: [ suggestions: [
{ {
prefixMatch: true, prefixMatch: true,
label: 'Functions', label: 'Functions',
items: NUMERIC_OPERATORS, items: NUMERIC_OPERATORS.concat(BOOLEAN_FUNCTIONS),
}, },
], ],
}; };

View File

@ -9,12 +9,10 @@ export const QUERY_COMMANDS: CompletionItem[] = [
{ label: 'display', documentation: 'Specifies which fields to display in the query results' }, { label: 'display', documentation: 'Specifies which fields to display in the query results' },
{ {
label: 'filter', label: 'filter',
insertText: 'filter',
documentation: 'Filters the results of a query based on one or more conditions', documentation: 'Filters the results of a query based on one or more conditions',
}, },
{ {
label: 'stats', label: 'stats',
insertText: 'stats',
documentation: 'Calculates aggregate statistics based on the values of log fields', documentation: 'Calculates aggregate statistics based on the values of log fields',
}, },
{ label: 'sort', documentation: 'Sorts the retrieved log events' }, { label: 'sort', documentation: 'Sorts the retrieved log events' },
@ -205,7 +203,6 @@ export const IP_FUNCTIONS = [
}, },
{ {
label: 'isIpv6InSubnet', label: 'isIpv6InSubnet',
insertText: 'isIpv6InSubnet',
detail: 'isIpv6InSubnet(fieldname, string)', detail: 'isIpv6InSubnet(fieldname, string)',
documentation: 'Returns true if the field is a valid v6 IP address within the specified v6 subnet.', documentation: 'Returns true if the field is a valid v6 IP address within the specified v6 subnet.',
}, },
@ -306,15 +303,16 @@ export const NON_AGGREGATION_FUNCS_STATS = [
export const STATS_FUNCS = [...AGGREGATION_FUNCTIONS_STATS, ...NON_AGGREGATION_FUNCS_STATS]; export const STATS_FUNCS = [...AGGREGATION_FUNCTIONS_STATS, ...NON_AGGREGATION_FUNCS_STATS];
export const KEYWORDS = ['as', 'like', 'by', 'in', 'desc', 'asc']; export const KEYWORDS = ['as', 'like', 'by', 'in', 'desc', 'asc'];
export const FUNCTIONS = [ export const FIELD_AND_FILTER_FUNCTIONS = [
...NUMERIC_OPERATORS, ...NUMERIC_OPERATORS,
...GENERAL_FUNCTIONS, ...GENERAL_FUNCTIONS,
...STRING_FUNCTIONS, ...STRING_FUNCTIONS,
...DATETIME_FUNCTIONS, ...DATETIME_FUNCTIONS,
...IP_FUNCTIONS, ...IP_FUNCTIONS,
...STATS_FUNCS,
]; ];
export const FUNCTIONS = [...FIELD_AND_FILTER_FUNCTIONS, ...STATS_FUNCS];
const tokenizer: Grammar = { const tokenizer: Grammar = {
comment: { comment: {
pattern: /^#.*/, pattern: /^#.*/,