| File: Binder\ForLoopBinder.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System.Collections.Immutable; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; using System.Diagnostics; namespace Microsoft.CodeAnalysis.CSharp { internal sealed class ForLoopBinder : LoopBinder { private readonly ForStatementSyntax _syntax; public ForLoopBinder(Binder enclosing, ForStatementSyntax syntax) : base(enclosing, syntax) { Debug.Assert(syntax != null); _syntax = syntax; } protected override ImmutableArray<LocalSymbol> BuildLocals() { var locals = ArrayBuilder<LocalSymbol>.GetInstance(); // Declaration and Initializers are mutually exclusive. if (_syntax.Declaration != null) { _syntax.Declaration.Type.VisitRankSpecifiers((rankSpecifier, args) => { foreach (var size in rankSpecifier.Sizes) { if (size.Kind() != SyntaxKind.OmittedArraySizeExpression) { ExpressionVariableFinder.FindExpressionVariables(args.binder, args.locals, size); } } }, (binder: this, locals: locals)); foreach (var vdecl in _syntax.Declaration.Variables) { var localSymbol = MakeLocal(_syntax.Declaration, vdecl, LocalDeclarationKind.RegularVariable, allowScoped: true); locals.Add(localSymbol); // also gather expression-declared variables from the bracketed argument lists and the initializers ExpressionVariableFinder.FindExpressionVariables(this, locals, vdecl); } } else { ExpressionVariableFinder.FindExpressionVariables(this, locals, _syntax.Initializers); } return locals.ToImmutableAndFree(); } internal override BoundForStatement BindForParts(BindingDiagnosticBag diagnostics, Binder originalBinder) { BoundForStatement result = BindForParts(_syntax, originalBinder, diagnostics); return result; } private BoundForStatement BindForParts(ForStatementSyntax node, Binder originalBinder, BindingDiagnosticBag diagnostics) { BoundStatement initializer; // Declaration and Initializers are mutually exclusive. if (_syntax.Declaration != null) { var type = _syntax.Declaration.Type.SkipScoped(out _); if (type is RefTypeSyntax) { // Checking for 'ref for' (7.3) automatically checks for 'ref' (7.0), so no need for an explicit // check feature as well here. MessageID.IDS_FeatureRefFor.CheckFeatureAvailability(diagnostics, type); } initializer = originalBinder.BindForOrUsingOrFixedDeclarations(node.Declaration, LocalDeclarationKind.RegularVariable, diagnostics, out _); } else { initializer = originalBinder.BindStatementExpressionList(node.Initializers, diagnostics); } BoundExpression condition = null; var innerLocals = ImmutableArray<LocalSymbol>.Empty; ExpressionSyntax conditionSyntax = node.Condition; if (conditionSyntax != null) { originalBinder = originalBinder.GetBinder(conditionSyntax); condition = originalBinder.BindBooleanExpression(conditionSyntax, diagnostics); innerLocals = originalBinder.GetDeclaredLocalsForScope(conditionSyntax); } BoundStatement increment = null; SeparatedSyntaxList<ExpressionSyntax> incrementors = node.Incrementors; if (incrementors.Count > 0) { var scopeDesignator = incrementors.First(); var incrementBinder = originalBinder.GetBinder(scopeDesignator); increment = incrementBinder.BindStatementExpressionList(incrementors, diagnostics); Debug.Assert(increment.Kind != BoundKind.StatementList || ((BoundStatementList)increment).Statements.Length > 1); var locals = incrementBinder.GetDeclaredLocalsForScope(scopeDesignator); if (!locals.IsEmpty) { if (increment.Kind == BoundKind.StatementList) { increment = new BoundBlock(scopeDesignator, locals, ((BoundStatementList)increment).Statements) { WasCompilerGenerated = true }; } else { increment = new BoundBlock(increment.Syntax, locals, ImmutableArray.Create(increment)) { WasCompilerGenerated = true }; } } } var body = originalBinder.BindPossibleEmbeddedStatement(node.Statement, diagnostics); Debug.Assert(this.Locals == this.GetDeclaredLocalsForScope(node)); return new BoundForStatement(node, this.Locals, initializer, innerLocals, condition, increment, body, this.BreakLabel, this.ContinueLabel); } internal override ImmutableArray<LocalSymbol> GetDeclaredLocalsForScope(SyntaxNode scopeDesignator) { if (_syntax == scopeDesignator) { return this.Locals; } throw ExceptionUtilities.Unreachable(); } internal override ImmutableArray<LocalFunctionSymbol> GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode scopeDesignator) { throw ExceptionUtilities.Unreachable(); } internal override SyntaxNode ScopeDesignator { get { return _syntax; } } } }