in src/Kusto.Language/Editor/Kusto/KustoCompleter.cs [498:632]
private CompletionItem GetSymbolCompletionItem(Symbol symbol, SyntaxNode contextNode, bool nameOnly)
{
var kind = GetCompletionKind(symbol);
string editName = KustoFacts.BracketNameIfNecessary(symbol.Name);
switch (symbol)
{
case TableSymbol t:
var addExternalTableFuncText = !nameOnly && t.IsExternal;
// editName gets bracketted: ['name with blanks']
// when the name has characters that cannot be represented in a variable name.
// This problem doesn't exist in external tables case as their name is put into a string anyway.
var insertionText =
addExternalTableFuncText
? $"external_table('{t.Name}')"
: editName;
var displayText =
addExternalTableFuncText
? $"external_table('{t.Name}')"
: t.Name;
// Lower ordering priority for external tables so that
// “regular” tables are displayed first and then the external ones.
var priority = t.IsExternal ? CompletionPriority.Low : CompletionPriority.Normal;
// Enables the user to be able to just type the name of the external table
// and not the entire expression (including the external_table('...') part)
var matchText = t.Name;
if (IsStartOfQuery(contextNode))
{
return new CompletionItem(
kind,
displayText,
insertionText + AfterQueryStart, // add | for start of query
matchText: matchText,
priority: priority);
}
else
{
return new CompletionItem(
kind,
displayText,
insertionText,
matchText: matchText,
priority: priority);
}
case FunctionSymbol f:
if (nameOnly)
{
return new CompletionItem(kind, f.Name, editName);
}
var builtIn = this.code.Globals.IsBuiltInFunction(f);
if (builtIn)
{
// built-in functions don't need to be escaped even if they are keywords
editName = f.Name;
}
var fdisplay = f.Display;
if (f.Signatures.Max(s => s.Parameters.Count) == 0)
{
if (builtIn)
{
editName = editName + "()";
}
if (IsStartOfQuery(contextNode))
{
return new CompletionItem(kind, fdisplay, editName + AfterQueryStart, matchText: f.Name);
}
else
{
return new CompletionItem(kind, fdisplay, editName, matchText: f.Name);
}
}
else
{
var isInvoke = IsInvokeFunctionContext(contextNode);
if (this.options.EnableParameterInjection && f.MaxArgumentCount == 1 && !builtIn && !isInvoke)
{
return new CompletionItem(kind, fdisplay, editName + "({parameter})", matchText: f.Name);
}
else
{
return new CompletionItem(kind, fdisplay, editName + "(", ")", matchText: f.Name);
}
}
case PatternSymbol p:
return new CompletionItem(kind, p.Display, editName + "(", ")", matchText: p.Name);
case VariableSymbol v:
if (v.Type is FunctionSymbol)
{
return GetSymbolCompletionItem(v.Type, contextNode, nameOnly);
}
else if (v.Type is TableSymbol && IsStartOfQuery(contextNode))
{
return new CompletionItem(kind, v.Name, editName + AfterQueryStart);
}
else
{
return new CompletionItem(kind, v.Name, editName);
}
case ParameterSymbol p:
if (p.Type is FunctionSymbol)
{
return GetSymbolCompletionItem(p.Type, contextNode, nameOnly);
}
else
{
return new CompletionItem(kind, symbol.Name, editName);
}
case DatabaseSymbol d:
return new CompletionItem(CompletionKind.Database, d.Name, editName);
case ClusterSymbol cl:
return new CompletionItem(CompletionKind.Cluster, cl.Name, KustoFacts.GetBracketedName(cl.Name));
case OptionSymbol opt:
return new CompletionItem(CompletionKind.Option, opt.Name, editName);
default:
return new CompletionItem(kind, symbol.Name, editName);
}
}