in src/Kusto.Language/Binder/Binder.cs [710:843]
private void GetSymbolsInContext(SyntaxNode contextNode, SymbolMatch match, IncludeFunctionKind include, List<Symbol> list)
{
if (_pathScope is GroupSymbol g
&& IsPassThrough(g))
{
var savePathScope = _pathScope;
foreach (var s in g.Members)
{
_pathScope = s;
GetSymbolsInContext(contextNode, match, include, list);
}
_pathScope = savePathScope;
}
else if (_pathScope != null)
{
// so far only columns, tables and functions can be dot accessed.
var memberMatch = match & (SymbolMatch.Column | SymbolMatch.Table | SymbolMatch.Function);
// table.column only works in commands
if (_pathScope is TableSymbol && !IsInsideControlCommandProper(contextNode))
{
memberMatch &= ~SymbolMatch.Column;
}
// any columns or tables from left-hand side?
if ((memberMatch & SymbolMatch.Column) != 0)
{
if (_pathScope is TableSymbol table && table.IsOpen)
{
list.AddRange(GetDeclaredAndInferredColumns(table));
}
else if (_pathScope is TupleSymbol tuple && tuple.RelatedTable != null && tuple.RelatedTable.IsOpen)
{
list.AddRange(GetDeclaredAndInferredColumns(tuple.RelatedTable));
}
else
{
GetPathMembers(_pathScope, memberMatch, list);
}
}
else if (memberMatch != 0)
{
GetPathMembers(_pathScope, memberMatch, list);
}
// any special functions from left-hand side?
if ((match & SymbolMatch.Function) != 0)
{
GetSpecialFunctions(null, list);
}
}
else
{
switch (_scopeKind)
{
case ScopeKind.Normal:
// row scope columns
if (_rowScope != null && (match & SymbolMatch.Column) != 0)
{
if (_rightRowScope != null)
{
// add $left and $right variables
list.Add(new VariableSymbol("$left", GetTuple(_rowScope)));
list.Add(new VariableSymbol("$right", GetTuple(_rightRowScope)));
// common columns
GetCommonColumns(GetDeclaredAndInferredColumns(_rowScope), GetDeclaredAndInferredColumns(_rightRowScope), list);
}
else
{
_rowScope.GetMembers(match, list);
}
}
var localMatch = match;
if ((include & IncludeFunctionKind.LocalFunctions) == 0)
localMatch &= ~SymbolMatch.Function;
// local symbols
_localScope.GetSymbols(localMatch, list);
// get any built-in functions
if ((match & SymbolMatch.Function) != 0 && (include & IncludeFunctionKind.BuiltInFunctions) != 0)
{
GetFunctionsInScope(match, null, IncludeFunctionKind.BuiltInFunctions, list);
}
// metadata symbols (tables, etc)
if (_currentDatabase != null)
{
var dbMatch = match;
if ((include & IncludeFunctionKind.DatabaseFunctions) == 0)
dbMatch &= ~SymbolMatch.Function;
_currentDatabase.GetMembers(dbMatch, list);
}
if ((match & SymbolMatch.Database) != 0)
{
_currentCluster.GetMembers(match, list);
}
if ((match & SymbolMatch.Cluster) != 0)
{
list.AddRange(_globals.Clusters);
}
break;
// aggregate scopes only see aggregate functions
case ScopeKind.Aggregate:
if ((match & SymbolMatch.Function) != 0)
{
GetFunctionsInScope(match, null, include, list);
}
break;
// plug-in scopes only see plug-in functions
case ScopeKind.PlugIn:
if ((match & SymbolMatch.Function) != 0)
{
GetFunctionsInScope(match, null, include, list);
}
break;
case ScopeKind.Option:
if ((match & SymbolMatch.Option) != 0)
{
list.AddRange(_globals.Options);
}
break;
}
}
}