Code review comment: We dont need to initialize trigger characters in each call as these are known anyway. Lets move these to completion utils

Code before review:
public CompletableFuture<CompletionsResponse> completions(CompletionsArguments args) {
CompletionsResponse completionsResponse = new CompletionsResponse();
BallerinaDebugCompletionContext debugCompletionContext = new BallerinaDebugCompletionContext(suspendedContext);
List<String> triggerCharacters = Arrays.asList(".", ":");
boolean triggerCharactersFound = Arrays.stream(args.getText().split(""))
.anyMatch(triggerCharacters::contains);
if (!triggerCharactersFound) {
CompletionItem[] visibleSymbolCompletions = getVisibleSymbolCompletions(debugCompletionContext);
completionsResponse.setTargets(visibleSymbolCompletions);
return CompletableFuture.completedFuture(completionsResponse);
}
try {
String source = getBalFileContent(clientConfigHolder.getSourcePath());
NonTerminalNode nonTerminalNode = getNonTerminalNode(source, clientConfigHolder.getSourcePath(),
suspendedContext.getLineNumber());
while (!(nonTerminalNode instanceof StatementNode)) {
if (nonTerminalNode instanceof FunctionBodyBlockNode) {
break;
}
nonTerminalNode = nonTerminalNode.parent();
}
String updatedSource = getUpdatedBalFileContent(args, nonTerminalNode, clientConfigHolder.getSourcePath(),
suspendedContext.getLineNumber());
NonTerminalNode updatedNonTerminalNode = getNonTerminalNode(updatedSource,
clientConfigHolder.getSourcePath(), nonTerminalNode, suspendedContext.getLineNumber(),
args.getColumn());
DebugCompletionUtil.route(updatedNonTerminalNode, debugCompletionContext);
Node providerNode = debugCompletionContext.getResolverChain()
.get(debugCompletionContext.getResolverChain().size() - 1);
if (providerNode instanceof FieldAccessExpressionNode) {
FieldAccessDebugCompletionResolver fieldAccessDebugCompletionResolver =
new FieldAccessDebugCompletionResolver(debugCompletionContext);
List<Symbol> visibleEntries = fieldAccessDebugCompletionResolver
.getVisibleEntries(((FieldAccessExpressionNode) providerNode).expression());
CompletionItem[] completions = getCompletions(visibleEntries);
completionsResponse.setTargets(completions);
}
} catch (Exception e) {
LOGGER.error(e.getMessage());
}
return CompletableFuture.completedFuture(completionsResponse);
}

Line under review: List<String> triggerCharacters = Arrays.asList(".", ":");

Code after addressing the review:
public CompletableFuture<CompletionsResponse> completions(CompletionsArguments args) {
return CompletableFuture.supplyAsync(() -> {
CompletionsResponse completionsResponse = new CompletionsResponse();
if (suspendedContext == null) {
return completionsResponse;
}
CompletionContext completionContext = new CompletionContext(suspendedContext);
if (!triggerCharactersFound(args.getText())) {
CompletionItem[] visibleSymbolCompletions = getVisibleSymbolCompletions(completionContext);
completionsResponse.setTargets(visibleSymbolCompletions);
return completionsResponse;
}
try {
NonTerminalNode injectedExpressionNode = getInjectedExpressionNode(completionContext, args,
clientConfigHolder.getSourcePath(), suspendedContext.getLineNumber());
Optional<Node> resolverNode = getResolverNode(injectedExpressionNode);
if (resolverNode.isPresent() && resolverNode.get().kind() == SyntaxKind.FIELD_ACCESS) {
FieldAccessCompletionResolver fieldAccessCompletionResolver =
new FieldAccessCompletionResolver(completionContext);
List<Symbol> visibleEntries = fieldAccessCompletionResolver
.getVisibleEntries(((FieldAccessExpressionNode) resolverNode.get()).expression());
CompletionItem[] completions = getCompletions(visibleEntries);
completionsResponse.setTargets(completions);
}
} catch (Exception e) {
LOGGER.error(e.getMessage());
}
return completionsResponse;
});
}