コード例 #1
0
        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()));
        }
コード例 #2
0
 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);
        }
コード例 #4
0
        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));
        }
コード例 #5
0
 private static bool IsInterfaceMethod(SourceFunctionSymbol symbol)
 {
     return(symbol.Parent != null && symbol.Parent.Kind == SymbolKind.Interface);
 }