in src/Kusto.Language/Binder/Binder.cs [1299:1441]
private bool GetMatchingSymbols(string name, SymbolMatch match, SyntaxNode location, List<Symbol> list)
{
var allowZeroArgumentInvocation = false;
if (IsFunctionCallName(location))
{
if (_pathScope is DatabaseSymbol ds)
{
if (name == Functions.Table.Name)
{
list.Add(Functions.Table);
}
else if (name == Functions.ExternalTable.Name)
{
list.Add(Functions.ExternalTable);
}
else if (name == Functions.MaterializedView.Name)
{
list.Add(Functions.MaterializedView);
}
else
{
_pathScope.GetMembers(name, SymbolMatch.Function, list);
}
}
else if (_pathScope is ClusterSymbol cs && name == Functions.Database.Name)
{
list.Add(Functions.Database);
}
else
{
GetFunctionsInScope(_scopeKind, name, IncludeFunctionKind.All, list);
}
}
else
{
// don't match the database functions that have same name as database tables
// if we are inside declaration of a database function
if (IsInsideDatabaseFunctionDeclaration(location) &&
_currentDatabase.GetAnyTable(name) != null)
{
match &= ~SymbolMatch.Function;
}
if (_pathScope != null)
{
if (_pathScope is TupleSymbol tuple
&& tuple.RelatedTable != null
&& tuple.RelatedTable.IsOpen
&& TryGetDeclaredOrInferredColumn(tuple.RelatedTable, name, out var col))
{
list.Add(col);
}
else if (_pathScope is DatabaseSymbol ds)
{
// first look for functions
_pathScope.GetMembers(name, match & SymbolMatch.Function, list);
RemoveFunctionsThatCannotBeInvokedWithZeroArgs(list);
// database functions don't require argument lists to invoke
allowZeroArgumentInvocation = list.Count > 0;
if (list.Count == 0)
{
// next look for anything else (tables)
_pathScope.GetMembers(name, match & ~SymbolMatch.Function, list);
}
// otherwise this is possible an open table
if (list.Count == 0 && ds.IsOpen)
{
var table = GetOpenTable(name, ds);
list.Add(table);
return allowZeroArgumentInvocation;
}
}
else if (!(_pathScope is TableSymbol) || IsInsideControlCommandProper(location))
{
_pathScope.GetMembers(name, match, list);
}
}
// check binding against any columns in the row scope
if (list.Count == 0 && _rowScope != null)
{
_rowScope.GetMembers(name, match, list);
}
// try secondary right-side row scope (from join operator)
if (list.Count == 0 && _rightRowScope != null)
{
_rightRowScope.GetMembers(name, match, list);
}
// try local variables (includes any user-defined functions)
if (list.Count == 0)
{
_localScope.GetSymbols(name, match, list);
// user defined functions do not require argument list if it has no arguments
allowZeroArgumentInvocation = list.Count > 0;
}
// look for zero-argument functions
if (list.Count == 0 && IsPossibleInvocableFunctionWithoutArgumentList(location)
&& (match & SymbolMatch.Function) != 0)
{
// database functions only (locally defined functions are already handled above)
GetFunctionsInScope(_scopeKind, name, IncludeFunctionKind.DatabaseFunctions, list);
RemoveFunctionsThatCannotBeInvokedWithZeroArgs(list);
// database functions do not require argument list if it has zero arguments.
allowZeroArgumentInvocation = list.Count > 0;
}
// other items in database (tables, etc)
if (list.Count == 0 && _currentDatabase != null)
{
_currentDatabase.GetMembers(name, match, list);
}
// databases can be directly referenced in commands
if (list.Count == 0 && _currentCluster != null && (match & SymbolMatch.Database) != 0)
{
_currentCluster.GetMembers(name, match, list);
}
// look for any built-in functions with matching name (even with those with parameters)
if (list.Count == 0 && (match & SymbolMatch.Function) != 0)
{
GetFunctionsInScope(_scopeKind, name, IncludeFunctionKind.BuiltInFunctions, list);
}
// infer column for this otherwise unbound reference?
if (list.Count == 0 && _rowScope != null && _rowScope.IsOpen && (match & SymbolMatch.Column) != 0)
{
// table is open, so create a dynamic column for the otherwise unbound name
list.Add(GetOpenColumn(name, _rowScope));
}
}
return allowZeroArgumentInvocation;
}