public override void VisitLocalFunctionStatement(LocalFunctionStatementSyntax node) { Symbol oldMethod = _containingMemberOrLambda; Binder binder = _enclosing; LocalFunctionSymbol match = FindLocalFunction(node, _enclosing); if ((object)match != null) { _containingMemberOrLambda = match; binder = match.IsGenericMethod ? new WithMethodTypeParametersBinder(match, _enclosing) : _enclosing; binder = binder.WithUnsafeRegionIfNecessary(node.Modifiers); binder = new InMethodBinder(match, binder); } BlockSyntax blockBody = node.Body; if (blockBody != null) { Visit(blockBody, binder); } ArrowExpressionClauseSyntax arrowBody = node.ExpressionBody; if (arrowBody != null) { Visit(arrowBody, binder); } _containingMemberOrLambda = oldMethod; }
private void ComputeBinderMap() { SmallDictionary <SyntaxNode, Binder> map; ImmutableArray <MethodSymbol> methodSymbolsWithYield; // Ensure that the member symbol is a method symbol. if ((object)_memberSymbol != null && _root != null) { var methodsWithYield = ArrayBuilder <SyntaxNode> .GetInstance(); var symbolsWithYield = ArrayBuilder <MethodSymbol> .GetInstance(); map = LocalBinderFactory.BuildMap(_memberSymbol, _root, this, methodsWithYield, _binderUpdatedHandler); foreach (var methodWithYield in methodsWithYield) { Binder binder = this; if (methodWithYield.Kind() != SyntaxKind.GlobalStatement && (methodWithYield == _root || map.TryGetValue(methodWithYield, out binder))) { Symbol containing = binder.ContainingMemberOrLambda; // get the closest enclosing InMethodBinder and make it an iterator InMethodBinder inMethod = null; while (binder != null) { inMethod = binder as InMethodBinder; if (inMethod != null) { break; } binder = binder.Next; } if (inMethod != null && (object)inMethod.ContainingMemberOrLambda == containing) { inMethod.MakeIterator(); symbolsWithYield.Add((MethodSymbol)inMethod.ContainingMemberOrLambda); } else { Debug.Assert(methodWithYield == _root && methodWithYield is ExpressionSyntax); } } else { // skip over it, this is an error } } methodsWithYield.Free(); methodSymbolsWithYield = symbolsWithYield.ToImmutableAndFree(); } else { map = SmallDictionary <SyntaxNode, Binder> .Empty; methodSymbolsWithYield = ImmutableArray <MethodSymbol> .Empty; } Interlocked.CompareExchange(ref _lazyBinderMap, map, null); ImmutableInterlocked.InterlockedCompareExchange(ref _methodSymbolsWithYield, methodSymbolsWithYield, default(ImmutableArray <MethodSymbol>)); }
internal override bool EnsureSingleDefinition(Symbol symbol, string name, Location location, DiagnosticBag diagnostics) { ParameterSymbol existingDeclaration; var map = this.definitionMap; if (map != null && map.TryGetValue(name, out existingDeclaration)) { return(InMethodBinder.ReportConflictWithParameter(existingDeclaration, symbol, name, location, diagnostics)); } return(false); }
public void ValidateIteratorMethods(DiagnosticBag diagnostics) { foreach (var iterator in MethodSymbolsWithYield) { foreach (var parameter in iterator.Parameters) { if (parameter.RefKind != RefKind.None) { diagnostics.Add(ErrorCode.ERR_BadIteratorArgType, parameter.Locations[0]); } else if (parameter.Type.IsUnsafe()) { diagnostics.Add(ErrorCode.ERR_UnsafeIteratorArgType, parameter.Locations[0]); } } Location errorLocation = iterator.Locations[0]; if (iterator.IsVararg) { // error CS1636: __arglist is not allowed in the parameter list of iterators diagnostics.Add(ErrorCode.ERR_VarargsIterator, errorLocation); } if (((iterator as SourceMemberMethodSymbol)?.IsUnsafe == true || (iterator as LocalFunctionSymbol)?.IsUnsafe == true) && Compilation.Options.AllowUnsafe) // Don't cascade { diagnostics.Add(ErrorCode.ERR_IllegalInnerUnsafe, errorLocation); } var returnType = iterator.ReturnType; RefKind refKind = iterator.RefKind; TypeWithAnnotations elementType = InMethodBinder.GetIteratorElementTypeFromReturnType(Compilation, refKind, returnType, errorLocation, diagnostics); if (elementType.IsDefault) { if (refKind != RefKind.None) { Error(diagnostics, ErrorCode.ERR_BadIteratorReturnRef, errorLocation, iterator); } else if (!returnType.IsErrorType()) { Error(diagnostics, ErrorCode.ERR_BadIteratorReturn, errorLocation, iterator, returnType); } } bool asyncInterface = InMethodBinder.IsAsyncStreamInterface(Compilation, refKind, returnType); if (asyncInterface && !iterator.IsAsync) { diagnostics.Add(ErrorCode.ERR_IteratorMustBeAsync, errorLocation, iterator, returnType); } } }
internal Binder GetFieldInitializerBinder(FieldSymbol fieldSymbol, bool suppressBinderFlagsFieldInitializer = false) { Debug.Assert((ContainingMemberOrLambda is TypeSymbol containing && TypeSymbol.Equals(containing, fieldSymbol.ContainingType, TypeCompareKind.ConsiderEverything2)) || //should be the binder for the type fieldSymbol.ContainingType.IsImplicitClass); //however, we also allow fields in namespaces to help support script scenarios Binder binder = this; if (!fieldSymbol.IsStatic && fieldSymbol.ContainingType.GetMembersUnordered().OfType <SynthesizedRecordConstructor>().SingleOrDefault() is SynthesizedRecordConstructor recordCtor) { binder = new InMethodBinder(recordCtor, binder); } return(new LocalScopeBinder(binder).WithAdditionalFlagsAndContainingMemberOrLambda(suppressBinderFlagsFieldInitializer ? BinderFlags.None : BinderFlags.FieldInitializer, fieldSymbol)); }
internal InMethodBinder GetRecordConstructorInMethodBinder(SynthesizedRecordConstructor constructor) { RecordDeclarationSyntax typeDecl = constructor.GetSyntax(); var extraInfo = NodeUsage.ConstructorBodyOrInitializer; var key = BinderFactoryVisitor.CreateBinderCacheKey(typeDecl, extraInfo); if (!_binderCache.TryGetValue(key, out Binder resultBinder)) { // Ctors cannot be generic Debug.Assert(constructor.Arity == 0, "Generic Ctor, What to do?"); resultBinder = new InMethodBinder(constructor, GetInRecordBodyBinder(typeDecl)); _binderCache.TryAdd(key, resultBinder); } return((InMethodBinder)resultBinder); }
public override void VisitLocalFunctionStatement(LocalFunctionStatementSyntax node) { var body = (CSharpSyntaxNode)node.Body ?? node.ExpressionBody; LocalFunctionSymbol match = null; // Don't use LookupLocalFunction because it recurses up the tree, as it // should be defined in the directly enclosing block (see note below) foreach (var candidate in _enclosing.LocalFunctions) { if (candidate.Locations[0] == node.Identifier.GetLocation()) { match = candidate; } } bool oldSawYield = _sawYield; _sawYield = false; if (match != null) { var oldMethod = _method; _method = match; Binder addToMap; if (match.IsGenericMethod) { addToMap = new WithMethodTypeParametersBinder(match, _enclosing); } else { addToMap = _enclosing; } addToMap = new InMethodBinder(match, addToMap); AddToMap(node, addToMap); if (body != null) { Visit(body, addToMap); } _method = oldMethod; } else { // The enclosing block should have found this node and created a LocalFunctionMethodSymbol // The code that does so is in LocalScopeBinder.BuildLocalFunctions if (body != null) { // do our best to attempt to bind Visit(body); } } if (_sawYield) { _methodsWithYields.Add(node); } _sawYield = oldSawYield; }