| File: Binding\ForOrForEachBlockBinder.vb | Web Access |
| Project: src\roslyn\src\Compilers\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.vbproj (Microsoft.CodeAnalysis.VisualBasic) |
' 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. Imports System.Collections.Immutable Imports Microsoft.CodeAnalysis.Collections Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic ''' <summary> ''' Binder used to bind For and ForEach blocks. ''' It hosts the control variable (if one is declared) ''' and inherits ExitableStatementBinder to provide Continue/Exit labels if needed. ''' </summary> Friend NotInheritable Class ForOrForEachBlockBinder Inherits ExitableStatementBinder Private ReadOnly _syntax As ForOrForEachBlockSyntax Private _locals As ImmutableArray(Of LocalSymbol) = Nothing Public Sub New(enclosing As Binder, syntax As ForOrForEachBlockSyntax) MyBase.New(enclosing, SyntaxKind.ContinueForStatement, SyntaxKind.ExitForStatement) Debug.Assert(syntax IsNot Nothing) _syntax = syntax End Sub Friend Overrides ReadOnly Property Locals As ImmutableArray(Of LocalSymbol) Get If _locals.IsDefault Then ImmutableInterlocked.InterlockedCompareExchange(_locals, BuildLocals(), Nothing) End If Return _locals End Get End Property ' Build a read only array of all the local variables declared By the For statement. ' There can only be 0 or 1 variable. Private Function BuildLocals() As ImmutableArray(Of LocalSymbol) Dim localVar As LocalSymbol = Nothing Dim controlVariableSyntax As VisualBasicSyntaxNode If _syntax.Kind = SyntaxKind.ForBlock Then controlVariableSyntax = DirectCast(_syntax.ForOrForEachStatement, ForStatementSyntax).ControlVariable Else controlVariableSyntax = DirectCast(_syntax.ForOrForEachStatement, ForEachStatementSyntax).ControlVariable End If Dim declarator = TryCast(controlVariableSyntax, VariableDeclaratorSyntax) If declarator IsNot Nothing Then ' Note: ' if the AsClause is nothing _AND_ a nullable modifier is used _AND_ Option Infer is On ' the control variable will not get an inferred type. ' The only difference for Option Infer On and Off is the fact whether the type (Object) is considered ' implicit or explicit. Debug.Assert(declarator.Names.Count = 1) Dim modifiedIdentifier As ModifiedIdentifierSyntax = declarator.Names(0) localVar = LocalSymbol.Create(Me.ContainingMember, Me, modifiedIdentifier.Identifier, modifiedIdentifier, declarator.AsClause, declarator.Initializer, If(_syntax.Kind = SyntaxKind.ForEachBlock, LocalDeclarationKind.ForEach, LocalDeclarationKind.For)) Else Dim identifierName = TryCast(controlVariableSyntax, IdentifierNameSyntax) If identifierName IsNot Nothing Then Dim identifier = identifierName.Identifier If OptionInfer Then Dim result = LookupResult.GetInstance() ContainingBinder.Lookup(result, identifier.ValueText, 0, LookupOptions.AllMethodsOfAnyArity, useSiteInfo:=CompoundUseSiteInfo(Of AssemblySymbol).Discarded) ' If there was something found we do not create a new local of an inferred type. ' The only exception is if all symbols (should be one only, or the result is not good) are type symbols. ' It's perfectly legal to create a local named with the same name as the enclosing type. If Not (result.IsGoodOrAmbiguous AndAlso result.Symbols(0).Kind <> SymbolKind.NamedType AndAlso result.Symbols(0).Kind <> SymbolKind.TypeParameter) Then localVar = CreateLocalSymbol(identifier) End If result.Free() End If End If End If If localVar IsNot Nothing Then Return ImmutableArray.Create(localVar) End If Return ImmutableArray(Of LocalSymbol).Empty End Function Private Function CreateLocalSymbol(identifier As SyntaxToken) As LocalSymbol If _syntax.Kind = SyntaxKind.ForBlock Then Dim forStatementSyntax = DirectCast(_syntax.ForOrForEachStatement, ForStatementSyntax) Dim localVar = LocalSymbol.CreateInferredForFromTo(Me.ContainingMember, Me, identifier, forStatementSyntax.FromValue, forStatementSyntax.ToValue, forStatementSyntax.StepClause) Return localVar Else Dim forEachStatementSyntax = DirectCast(_syntax.ForOrForEachStatement, ForEachStatementSyntax) Dim localVar = LocalSymbol.CreateInferredForEach(Me.ContainingMember, Me, identifier, forEachStatementSyntax.Expression) Return localVar End If End Function End Class End Namespace