private BoundFunctionDeclaration BindFunctionDeclaration(FunctionDeclarationSyntax declaration, Symbol parent) { BindAttributes(declaration.Attributes); var boundReturnType = Bind(declaration.ReturnType, x => BindType(x, parent)); var functionSymbol = LocalSymbols.OfType <SourceFunctionSymbol>() .FirstOrDefault(x => SyntaxFacts.HaveMatchingSignatures( x.DefinitionSyntax as FunctionSyntax ?? x.DeclarationSyntaxes[0], declaration)); if (functionSymbol != null) { functionSymbol.DeclarationSyntaxes.Add(declaration); } else { functionSymbol = new SourceFunctionSymbol(declaration, parent, boundReturnType.TypeSymbol); AddSymbol(functionSymbol, declaration.Name.SourceRange, true); } if (declaration.Semantic != null) { Bind(declaration.Semantic, BindVariableQualifier); } var functionBinder = new FunctionBinder(_sharedBinderState, this, functionSymbol); var boundParameters = BindParameters(declaration.ParameterList, functionBinder, functionSymbol); return(new BoundFunctionDeclaration(functionSymbol, boundReturnType, boundParameters.ToImmutableArray())); }
internal BoundFunctionDeclStatement Update(SourceFunctionSymbol function) { if (function == _function) { return(this); } else { return(new BoundFunctionDeclStatement(function)); } }
/// <summary> /// Get global function symbol by its name in current context. /// Can be <c>null</c> if function could not be found. /// Can be an <see cref="AmbiguousMethodSymbol"/> in case there are more functions possible or possible overrides. /// </summary> public static IPhpRoutineSymbol ResolveFunction(this PhpCompilation compilation, QualifiedName name, SourceRoutineSymbol routine) { var symbol = compilation.GlobalSemantics.ResolveFunction(name); if (symbol != null) { if (symbol is AmbiguousMethodSymbol ambiguous && !ambiguous.IsOverloadable && ambiguous.Ambiguities.All(a => a is SourceFunctionSymbol)) { // there are more functions with same name within the compilation (in sources), // we can pick the right one if it is declared unconditionally and in current file or included from within current routine: var candidates = ambiguous.Ambiguities; SourceFunctionSymbol result = null; for (int i = 0; i < candidates.Length; i++) { var c = (SourceFunctionSymbol)candidates[i]; // function is unconditionally declared in this file: if (c.IsUnreachable == false && !c.IsConditional && routine != null && routine.ContainingFile == c.ContainingFile) // TODO: or {c.ContainingFile} included unconditionally { if (result == null) { result = c; } else { result = null; break; } } } if (result != null) { symbol = result; } } } return(symbol); }
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.SourceRange, 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.SourceRange, true); } if (declaration.Semantic != null) { Bind(declaration.Semantic, BindVariableQualifier); } var functionBinder = (functionOwner != null && (functionOwner.Kind == SymbolKind.Class || functionOwner.Kind == SymbolKind.Struct)) ? new StructMethodBinder(_sharedBinderState, this, (StructSymbol)functionOwner, functionSymbol) : new FunctionBinder(_sharedBinderState, this, functionSymbol); if (isQualifiedName) { functionBinder = new ContainedFunctionBinder(_sharedBinderState, functionBinder, containerSymbol.Binder, functionSymbol); } var boundParameters = BindParameters(declaration.ParameterList, functionBinder, functionSymbol); var boundBody = functionBinder.Bind(declaration.Body, x => functionBinder.BindBlock(x, functionSymbol)); if (boundReturnType.Type != IntrinsicTypes.Void && !ContainsReturnStatement(boundBody)) { Diagnostics.Report(declaration.Name.SourceRange, DiagnosticId.ReturnExpected, functionSymbol.Name); } return(new BoundFunctionDefinition(functionSymbol, boundReturnType, boundParameters.ToImmutableArray(), boundBody)); }
private static bool IsInterfaceMethod(SourceFunctionSymbol symbol) { return(symbol.Parent != null && symbol.Parent.Kind == SymbolKind.Interface); }