private BoundNode BindFunctionDefinition(FunctionDefinitionSyntax declaration, Symbol parent)
{
BindAttributes(declaration.Attributes);
var boundReturnType = Bind(declaration.ReturnType, x => BindType(x, parent));
var isQualifiedName = false;
ContainerSymbol containerSymbol;
Symbol functionOwner;
switch (declaration.Name.Kind)
{
case SyntaxKind.IdentifierDeclarationName:
containerSymbol = null;
functionOwner = parent;
break;
case SyntaxKind.QualifiedDeclarationName:
containerSymbol = LookupContainer(((QualifiedDeclarationNameSyntax) declaration.Name).Left);
if (containerSymbol == null)
return new BoundErrorNode();
isQualifiedName = true;
functionOwner = containerSymbol;
break;
default:
throw new InvalidOperationException();
}
var containerBinder = containerSymbol?.Binder ?? this;
var symbolTable = containerBinder.LocalSymbols;
var functionSymbol = symbolTable
.SelectMany(x => x.Value)
.OfType<SourceFunctionSymbol>()
.FirstOrDefault(x => SyntaxFacts.HaveMatchingSignatures(
x.DefinitionSyntax as FunctionSyntax ?? x.DeclarationSyntaxes[0],
declaration));
if (functionSymbol != null)
{
if (functionSymbol.DefinitionSyntax != null)
Diagnostics.ReportSymbolRedefined(declaration.Name.GetTextSpanSafe(), functionSymbol);
else
functionSymbol.DefinitionSyntax = declaration;
}
else
{
if (isQualifiedName)
Diagnostics.ReportUndeclaredFunctionInNamespaceOrClass((QualifiedDeclarationNameSyntax) declaration.Name);
functionSymbol = new SourceFunctionSymbol(declaration, parent, boundReturnType.TypeSymbol);
containerBinder.AddSymbol(functionSymbol, declaration.Name.GetTextSpanSafe(), true);
}
if (declaration.Semantic != null)
Bind(declaration.Semantic, BindVariableQualifier);
var functionBinder = (functionOwner != null && functionOwner.Kind == SymbolKind.Class)
? new ClassMethodBinder(_sharedBinderState, this, (ClassSymbol) functionOwner)
: new Binder(_sharedBinderState, this);
if (isQualifiedName)
functionBinder = new ContainedFunctionBinder(_sharedBinderState, functionBinder, containerSymbol.Binder);
var boundParameters = BindParameters(declaration.ParameterList, functionBinder, functionSymbol);
var boundBody = functionBinder.Bind(declaration.Body, x => functionBinder.BindBlock(x, functionSymbol));
return new BoundFunctionDefinition(functionSymbol, boundReturnType, boundParameters.ToImmutableArray(), boundBody);
}