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); }