Пример #1
0
        internal BinderFactory(CSharpCompilation compilation, SyntaxTree syntaxTree)
        {
            _compilation = compilation;
            _syntaxTree  = syntaxTree;

            _binderFactoryVisitorPool = new ObjectPool <BinderFactoryVisitor>(() => new BinderFactoryVisitor(this), 64);

            // 50 is more or less a guess, but it seems to work fine for scenarios that I tried.
            // we need something big enough to keep binders for most classes and some methods
            // in a typical syntax tree.
            // On the other side, note that the whole factory is weakly referenced and therefore short lived,
            // making this cache big is not very useful.
            // I noticed that while compiling Roslyn C# compiler most caches never see
            // more than 50 items added before getting collected.
            _binderCache = new ConcurrentCache <BinderCacheKey, Binder>(50);

            _buckStopsHereBinder = new BuckStopsHereBinder(compilation);
        }
            // NOTE: We're not sharing code with the BinderFactory visitor, because we already have the
            // member symbol in hand, which makes things much easier.
            private static Binder MakeNameBinder(bool isParameter, bool isTypeParameterRef, Symbol memberSymbol, CSharpCompilation compilation)
            {
                Binder binder = new BuckStopsHereBinder(compilation);

                // All binders should have a containing symbol.
                Symbol containingSymbol = memberSymbol.ContainingSymbol;

                Debug.Assert((object)containingSymbol != null);
                binder = binder.WithContainingMemberOrLambda(containingSymbol);

                if (isParameter)
                {
                    ImmutableArray <ParameterSymbol> parameters = ImmutableArray <ParameterSymbol> .Empty;

                    switch (memberSymbol.Kind)
                    {
                    case SymbolKind.Method:
                        parameters = ((MethodSymbol)memberSymbol).Parameters;
                        break;

                    case SymbolKind.Property:
                        parameters = ((PropertySymbol)memberSymbol).Parameters;
                        break;

                    case SymbolKind.NamedType:
                    case SymbolKind.ErrorType:
                        NamedTypeSymbol typeSymbol = (NamedTypeSymbol)memberSymbol;
                        if (typeSymbol.IsDelegateType())
                        {
                            parameters = typeSymbol.DelegateInvokeMethod.Parameters;
                        }
                        break;
                    }

                    if (parameters.Length > 0)
                    {
                        binder = new WithParametersBinder(parameters, binder);
                    }
                }
                else
                {
                    Symbol currentSymbol = memberSymbol;
                    do
                    {
                        switch (currentSymbol.Kind)
                        {
                        case SymbolKind.NamedType:     // Includes delegates.
                        case SymbolKind.ErrorType:
                            NamedTypeSymbol typeSymbol = (NamedTypeSymbol)currentSymbol;
                            if (typeSymbol.Arity > 0)
                            {
                                binder = new WithClassTypeParametersBinder(typeSymbol, binder);
                            }
                            break;

                        case SymbolKind.Method:
                            MethodSymbol methodSymbol = (MethodSymbol)currentSymbol;
                            if (methodSymbol.Arity > 0)
                            {
                                binder = new WithMethodTypeParametersBinder(methodSymbol, binder);
                            }
                            break;
                        }
                        currentSymbol = currentSymbol.ContainingSymbol;
                    } while (isTypeParameterRef && !(currentSymbol is null));
                }

                return(binder);
            }