Exemple #1
0
        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;
        }
Exemple #2
0
        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);
        }
Exemple #4
0
        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);
                }
            }
        }
Exemple #5
0
        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;
        }