diff --git a/public/app/plugins/datasource/cloudwatch/language_provider.ts b/public/app/plugins/datasource/cloudwatch/language_provider.ts index 570b409c584..6526e85b663 100644 --- a/public/app/plugins/datasource/cloudwatch/language_provider.ts +++ b/public/app/plugins/datasource/cloudwatch/language_provider.ts @@ -126,52 +126,15 @@ export class CloudWatchLanguageProvider extends LanguageProvider { (token: any) => token.offsets.start <= value!.selection?.start?.offset && token.offsets.end >= value!.selection?.start?.offset )[0]; + const isFirstToken = curToken.prev === null || curToken.prev === undefined; const prevToken = prevNonWhitespaceToken(curToken); - const funcsWithFieldArgs = [ - 'avg', - 'count', - 'count_distinct', - 'earliest', - 'latest', - 'sortsFirst', - 'sortsLast', - 'max', - 'min', - 'pct', - 'stddev', - 'ispresent', - 'fromMillis', - 'toMillis', - 'isempty', - 'isblank', - 'isValidIp', - 'isValidIpV4', - 'isValidIpV6', - 'isIpInSubnet', - 'isIpv4InSubnet', - 'isIpv6InSubnet', - ].map(funcName => funcName.toLowerCase()); - if (curToken.content === '(' && prevToken != null) { - if (funcsWithFieldArgs.includes(prevToken.content.toLowerCase()) && prevToken.types.includes('function')) { - const suggs = await this.getFieldCompletionItems(context?.logGroupNames ?? []); - return suggs; - } + if (isInsideFunctionParenthesis(curToken)) { + return await this.getFieldCompletionItems(context?.logGroupNames ?? []); } - // if (prevToken === null) { - // return { - // suggestions: [], - // }; - // } - - // if (prevToken) { - // console.log(`Previous token: '${prevToken.content}'`); - // } - const isCommandStart = isFirstToken || (!isFirstToken && prevToken?.types.includes('command-separator')); - //console.log(`Is command start? ${isCommandStart}`); if (isCommandStart) { return this.getCommandCompletionItems(); } else if (!isFirstToken) { @@ -427,3 +390,52 @@ function prevNonWhitespaceToken(token: Token): Token | null { return null; } + +const funcsWithFieldArgs = [ + 'avg', + 'count', + 'count_distinct', + 'earliest', + 'latest', + 'sortsFirst', + 'sortsLast', + 'max', + 'min', + 'pct', + 'stddev', + 'ispresent', + 'fromMillis', + 'toMillis', + 'isempty', + 'isblank', + 'isValidIp', + 'isValidIpV4', + 'isValidIpV6', + 'isIpInSubnet', + 'isIpv4InSubnet', + 'isIpv6InSubnet', +].map(funcName => funcName.toLowerCase()); + +/** + * Returns true if cursor is currently inside a function parenthesis for example `count(|)` or `count(@mess|)` should + * return true. + */ +function isInsideFunctionParenthesis(curToken: Token): boolean { + const prevToken = prevNonWhitespaceToken(curToken); + + if (!prevToken) { + return false; + } + + const parenthesisToken = curToken.content === '(' ? curToken : prevToken.content === '(' ? prevToken : undefined; + if (parenthesisToken) { + const maybeFunctionToken = prevNonWhitespaceToken(parenthesisToken); + if (maybeFunctionToken) { + return ( + funcsWithFieldArgs.includes(maybeFunctionToken.content.toLowerCase()) && + maybeFunctionToken.types.includes('function') + ); + } + } + return false; +}