|
' 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 System.Threading
Imports Microsoft.CodeAnalysis.CodeGen
Imports Microsoft.CodeAnalysis.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
''' <summary>
''' Represents a local variable (typically inside a method body). This could also be a local variable implicitly
''' declared by a For, Using, etc. When used as a temporary variable, its container can also be a Field or Property Symbol.
''' </summary>
Friend MustInherit Class LocalSymbol
Inherits Symbol
Implements ILocalSymbol, ILocalSymbolInternal
Friend Shared ReadOnly UseBeforeDeclarationResultType As ErrorTypeSymbol = New ErrorTypeSymbol()
Private ReadOnly _container As Symbol ' the method, field or property that contains the declaration of this variable
Private _lazyType As TypeSymbol
''' <summary>
''' Create a local symbol from a local variable declaration.
''' </summary>
Friend Shared Function Create(container As Symbol,
binder As Binder,
declaringIdentifier As SyntaxToken,
modifiedIdentifierOpt As ModifiedIdentifierSyntax,
asClauseOpt As AsClauseSyntax,
initializerOpt As EqualsValueSyntax,
declarationKind As LocalDeclarationKind) As LocalSymbol
Return New VariableLocalSymbol(container, binder, declaringIdentifier, modifiedIdentifierOpt, asClauseOpt, initializerOpt, declarationKind)
End Function
''' <summary>
''' Create a local symbol associated with an identifier token.
''' </summary>
Friend Shared Function Create(container As Symbol,
binder As Binder,
declaringIdentifier As SyntaxToken,
declarationKind As LocalDeclarationKind,
type As TypeSymbol) As LocalSymbol
Return New SourceLocalSymbol(container, binder, declaringIdentifier, declarationKind, type)
End Function
''' <summary>
''' Create a local symbol associated with an identifier token and a different name.
''' Used for WinRT event handler return value variable).
''' </summary>
Friend Shared Function Create(container As Symbol,
binder As Binder,
declaringIdentifier As SyntaxToken,
declarationKind As LocalDeclarationKind,
type As TypeSymbol,
name As String) As LocalSymbol
Return New SourceLocalSymbolWithNonstandardName(container, binder, declaringIdentifier, declarationKind, type, name)
End Function
''' <summary>
''' Create a local symbol with substituted type.
''' </summary>
Friend Shared Function Create(originalVariable As LocalSymbol, type As TypeSymbol) As LocalSymbol
Return New TypeSubstitutedLocalSymbol(originalVariable, type)
End Function
''' <summary>
''' Create an inferred local symbol from a For from-to statement.
''' </summary>
Friend Shared Function CreateInferredForFromTo(container As Symbol,
binder As Binder,
declaringIdentifier As SyntaxToken,
fromValue As ExpressionSyntax,
toValue As ExpressionSyntax,
stepClauseOpt As ForStepClauseSyntax) As LocalSymbol
Return New InferredForFromToLocalSymbol(container, binder, declaringIdentifier, fromValue, toValue, stepClauseOpt)
End Function
''' <summary>
''' Create an inferred local symbol from a For-each statement.
''' </summary>
Friend Shared Function CreateInferredForEach(container As Symbol,
binder As Binder,
declaringIdentifier As SyntaxToken,
expression As ExpressionSyntax) As LocalSymbol
Return New InferredForEachLocalSymbol(container, binder, declaringIdentifier, expression)
End Function
''' <summary>
''' Create a local variable symbol. Note: this does not insert it automatically into a
''' local binder so that it can be found by lookup.
''' </summary>
Friend Sub New(container As Symbol, type As TypeSymbol)
Debug.Assert(container IsNot Nothing, "local must belong to a method, field or property")
Debug.Assert(container.Kind = SymbolKind.Method OrElse
container.Kind = SymbolKind.Field OrElse
container.Kind = SymbolKind.Property,
"Unsupported container. Must be method, field or property.")
_container = container
_lazyType = type
End Sub
Friend Overridable ReadOnly Property IsImportedFromMetadata As Boolean
Get
Return False
End Get
End Property
Friend MustOverride ReadOnly Property DeclarationKind As LocalDeclarationKind
Friend MustOverride ReadOnly Property SynthesizedKind As SynthesizedLocalKind
Public Overridable ReadOnly Property Type As TypeSymbol
Get
If _lazyType Is Nothing Then
Interlocked.CompareExchange(_lazyType, ComputeType(), Nothing)
End If
Return _lazyType
End Get
End Property
Friend ReadOnly Property ConstHasType As Boolean
Get
Debug.Assert(Me.IsConst)
Return Me._lazyType IsNot Nothing
End Get
End Property
''' <summary>
''' Returns true if this local is a ReadOnly local. Compiler has a concept of ReadOnly locals.
''' </summary>
Friend Overridable ReadOnly Property IsReadOnly As Boolean
Get
' locals declared in the resource list of a using statement are considered to be read only.
Return IsUsing OrElse IsConst
End Get
End Property
' Set the type of this variable. This is used by the expression binder to set the type of the variable.
' If the type has already been computed, it should have been computed to be the same type.
Public Sub SetType(type As TypeSymbol)
If _lazyType Is Nothing Then
Interlocked.CompareExchange(_lazyType, type, Nothing)
Debug.Assert((Me.IsFunctionValue AndAlso _container.Kind = SymbolKind.Method AndAlso DirectCast(_container, MethodSymbol).MethodKind = MethodKind.LambdaMethod) OrElse type.Equals(ComputeType()))
Else
Debug.Assert(type.Equals(_lazyType), "Attempted to set a local variable with a different type")
End If
End Sub
' Compute the type of this variable.
Friend Overridable Function ComputeType(Optional containingBinder As Binder = Nothing) As TypeSymbol
Debug.Assert(_lazyType IsNot Nothing)
Return _lazyType
End Function
Public MustOverride Overrides ReadOnly Property Name As String
' Get the identifier token that defined this local symbol. This is useful for robustly checking
' if a local symbol actually matches a particular definition, even in the presence of duplicates.
Friend MustOverride ReadOnly Property IdentifierToken As SyntaxToken
''' <summary>
''' Returns the syntax node that declares the variable.
''' </summary>
''' <remarks>
''' All user-defined and long-lived synthesized variables must return a reference to a node that is
''' tracked by the EnC diffing algorithm. For example, for <see cref="LocalDeclarationKind.Catch"/> variable
''' the declarator is the <see cref="CatchStatementSyntax"/> node, not the <see cref="IdentifierNameSyntax"/>
''' that immediately contains the variable.
'''
''' The location of the declarator is used to calculate <see cref="LocalDebugId.SyntaxOffset"/> during emit.
''' </remarks>
Friend MustOverride Function GetDeclaratorSyntax() As SyntaxNode
Public NotOverridable Overrides ReadOnly Property Kind As SymbolKind
Get
Return SymbolKind.Local
End Get
End Property
Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location)
Get
Return ImmutableArray.Create(Me.IdentifierLocation)
End Get
End Property
Friend MustOverride ReadOnly Property IdentifierLocation As Location
Public Overrides ReadOnly Property ContainingSymbol As Symbol
Get
Return _container
End Get
End Property
Public Overrides ReadOnly Property DeclaredAccessibility As Accessibility
Get
Return Accessibility.NotApplicable
End Get
End Property
Public Overrides ReadOnly Property IsShared As Boolean
Get
Return False
End Get
End Property
Public Overrides ReadOnly Property IsOverridable As Boolean
Get
Return False
End Get
End Property
Public Overrides ReadOnly Property IsMustOverride As Boolean
Get
Return False
End Get
End Property
Public Overrides ReadOnly Property IsNotOverridable As Boolean
Get
Return False
End Get
End Property
Public Overrides ReadOnly Property IsOverrides As Boolean
Get
Return False
End Get
End Property
Public ReadOnly Property IsUsing As Boolean
Get
Return Me.DeclarationKind = LocalDeclarationKind.Using
End Get
End Property
Public ReadOnly Property IsCatch As Boolean
Get
Return Me.DeclarationKind = LocalDeclarationKind.Catch
End Get
End Property
Public ReadOnly Property IsConst As Boolean
Get
Return Me.DeclarationKind = LocalDeclarationKind.Constant
End Get
End Property
Private ReadOnly Property ILocalSymbol_IsFixed As Boolean Implements ILocalSymbol.IsFixed
Get
Return False
End Get
End Property
Friend Overridable ReadOnly Property CanScheduleToStack As Boolean
Get
' cannot schedule constants and catch variables
' in theory catch vars could be scheduled, but are not worth the trouble.
Return Not IsConst AndAlso Not IsCatch
End Get
End Property
Public ReadOnly Property IsStatic As Boolean
Get
Return Me.DeclarationKind = LocalDeclarationKind.Static
End Get
End Property
Public ReadOnly Property IsFor As Boolean
Get
Return Me.DeclarationKind = LocalDeclarationKind.For
End Get
End Property
Public ReadOnly Property IsForEach As Boolean
Get
Return Me.DeclarationKind = LocalDeclarationKind.ForEach
End Get
End Property
Public ReadOnly Property IsRef As Boolean Implements ILocalSymbol.IsRef
Get
Return False
End Get
End Property
Public ReadOnly Property RefKind As RefKind Implements ILocalSymbol.RefKind
Get
Return RefKind.None
End Get
End Property
Private ReadOnly Property ILocalSymbol_ScopedKind As ScopedKind Implements ILocalSymbol.ScopedKind
Get
Return ScopedKind.None
End Get
End Property
Public MustOverride ReadOnly Property IsFunctionValue As Boolean Implements ILocalSymbol.IsFunctionValue
Friend ReadOnly Property IsCompilerGenerated As Boolean
Get
Return Me.DeclarationKind = LocalDeclarationKind.None
End Get
End Property
''' <summary>
''' Was this local variable implicitly declared, because Option Explicit Off
''' was in effect, and no other symbol was found with this name.
''' </summary>
Public Overrides ReadOnly Property IsImplicitlyDeclared As Boolean
Get
Return Me.DeclarationKind = LocalDeclarationKind.ImplicitVariable
End Get
End Property
Friend Overrides Function Accept(Of TArgument, TResult)(visitor As VisualBasicSymbolVisitor(Of TArgument, TResult), arg As TArgument) As TResult
Return visitor.VisitLocal(Me, arg)
End Function
Friend Overridable ReadOnly Property IsByRef As Boolean
Get
Return False
End Get
End Property
Friend Overridable ReadOnly Property IsPinned As Boolean
Get
Return False
End Get
End Property
Public ReadOnly Property HasConstantValue As Boolean Implements ILocalSymbol.HasConstantValue
Get
If Not Me.IsConst Then
Return Nothing
End If
Return GetConstantValue(Nothing) IsNot Nothing
End Get
End Property
Public ReadOnly Property ConstantValue As Object Implements ILocalSymbol.ConstantValue
Get
If Not Me.IsConst Then
Return Nothing
End If
Dim constant As ConstantValue = Me.GetConstantValue(Nothing)
Return If(constant Is Nothing, Nothing, constant.Value)
End Get
End Property
Friend Overridable Function GetConstantValueDiagnostics(binder As Binder) As ReadOnlyBindingDiagnostic(Of AssemblySymbol)
Throw ExceptionUtilities.Unreachable
End Function
Friend Overridable Function GetConstantExpression(binder As Binder) As BoundExpression
Throw ExceptionUtilities.Unreachable
End Function
Friend Overridable Function GetConstantValue(binder As Binder) As ConstantValue
Return Nothing
End Function
Friend Overridable ReadOnly Property HasInferredType As Boolean
Get
Return False
End Get
End Property
''' <summary>
''' Returns data decoded from Obsolete attribute or null if there is no Obsolete attribute.
''' This property returns ObsoleteAttributeData.Uninitialized if attribute arguments haven't been decoded yet.
''' </summary>
Friend NotOverridable Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
Get
Return Nothing
End Get
End Property
#Region "ILocalSymbol"
Private ReadOnly Property ILocalSymbol_Type As ITypeSymbol Implements ILocalSymbol.Type
Get
Return Me.Type
End Get
End Property
Private ReadOnly Property ILocalSymbol_NullableAnnotation As NullableAnnotation Implements ILocalSymbol.NullableAnnotation
Get
Return NullableAnnotation.None
End Get
End Property
Private ReadOnly Property ILocalSymbol_IsConst As Boolean Implements ILocalSymbol.IsConst
Get
Return Me.IsConst
End Get
End Property
Private ReadOnly Property ILocalSymbol_IsForEach As Boolean Implements ILocalSymbol.IsForEach
Get
Return Me.IsForEach
End Get
End Property
Private ReadOnly Property ILocalSymbol_IsUsing As Boolean Implements ILocalSymbol.IsUsing
Get
Return Me.IsUsing
End Get
End Property
#End Region
#Region "ISymbol"
Protected Overrides ReadOnly Property ISymbol_IsStatic As Boolean
Get
Return Me.IsStatic
End Get
End Property
Public Overrides Sub Accept(visitor As SymbolVisitor)
visitor.VisitLocal(Me)
End Sub
Public Overrides Function Accept(Of TResult)(visitor As SymbolVisitor(Of TResult)) As TResult
Return visitor.VisitLocal(Me)
End Function
Public Overrides Function Accept(Of TArgument, TResult)(visitor As SymbolVisitor(Of TArgument, TResult), argument As TArgument) As TResult
Return visitor.VisitLocal(Me, argument)
End Function
Public Overrides Sub Accept(visitor As VisualBasicSymbolVisitor)
visitor.VisitLocal(Me)
End Sub
Public Overrides Function Accept(Of TResult)(visitor As VisualBasicSymbolVisitor(Of TResult)) As TResult
Return visitor.VisitLocal(Me)
End Function
#End Region
#Region "ILocalSymbolInternal"
Private ReadOnly Property ILocalSymbolInternal_IsImportedFromMetadata As Boolean Implements ILocalSymbolInternal.IsImportedFromMetadata
Get
Return Me.IsImportedFromMetadata
End Get
End Property
Private ReadOnly Property ILocalSymbolInternal_SynthesizedKind As SynthesizedLocalKind Implements ILocalSymbolInternal.SynthesizedKind
Get
Return Me.SynthesizedKind
End Get
End Property
Private Function ILocalSymbolInternal_GetDeclaratorSyntax() As SyntaxNode Implements ILocalSymbolInternal.GetDeclaratorSyntax
Return Me.GetDeclaratorSyntax()
End Function
#End Region
#Region "SourceLocalSymbol"
''' <summary>
''' Base class for any local symbol that can be referenced in source, might be implicitly declared.
''' </summary>
Private Class SourceLocalSymbol
Inherits LocalSymbol
Private ReadOnly _declarationKind As LocalDeclarationKind
Protected ReadOnly _identifierToken As SyntaxToken
Protected ReadOnly _binder As Binder
Public Sub New(containingSymbol As Symbol,
binder As Binder,
identifierToken As SyntaxToken,
declarationKind As LocalDeclarationKind,
type As TypeSymbol)
MyBase.New(containingSymbol, type)
Debug.Assert(identifierToken.Kind <> SyntaxKind.None)
Debug.Assert(declarationKind <> LocalDeclarationKind.None)
Debug.Assert(binder IsNot Nothing)
_identifierToken = identifierToken
_declarationKind = declarationKind
_binder = binder
End Sub
Friend Overrides ReadOnly Property DeclarationKind As LocalDeclarationKind
Get
Return _declarationKind
End Get
End Property
Public Overrides ReadOnly Property IsFunctionValue As Boolean
Get
Return _declarationKind = LocalDeclarationKind.FunctionValue
End Get
End Property
Friend Overrides ReadOnly Property SynthesizedKind As SynthesizedLocalKind
Get
Return SynthesizedLocalKind.UserDefined
End Get
End Property
Public Overrides ReadOnly Property Name As String
Get
Return _identifierToken.GetIdentifierText()
End Get
End Property
Friend Overrides Function GetDeclaratorSyntax() As SyntaxNode
Dim node As SyntaxNode
Select Case Me.DeclarationKind
Case LocalDeclarationKind.Variable,
LocalDeclarationKind.Constant,
LocalDeclarationKind.Using,
LocalDeclarationKind.Static
node = _identifierToken.Parent
Debug.Assert(TypeOf node Is ModifiedIdentifierSyntax)
Case LocalDeclarationKind.ImplicitVariable
node = _identifierToken.Parent
Debug.Assert(TypeOf node Is IdentifierNameSyntax)
Case LocalDeclarationKind.FunctionValue
node = _identifierToken.Parent
If node.IsKind(SyntaxKind.PropertyStatement) Then
Dim propertyBlock = DirectCast(node.Parent, PropertyBlockSyntax)
Return propertyBlock.Accessors.Where(Function(a) a.IsKind(SyntaxKind.GetAccessorBlock)).Single().BlockStatement
ElseIf node.IsKind(SyntaxKind.EventStatement) Then
Dim eventBlock = DirectCast(node.Parent, EventBlockSyntax)
Return eventBlock.Accessors.Where(Function(a) a.IsKind(SyntaxKind.AddHandlerAccessorBlock)).Single().BlockStatement
End If
Debug.Assert(node.IsKind(SyntaxKind.FunctionStatement))
Case LocalDeclarationKind.Catch
node = _identifierToken.Parent.Parent
Debug.Assert(TypeOf node Is CatchStatementSyntax)
Case LocalDeclarationKind.For
node = _identifierToken.Parent
If Not node.IsKind(SyntaxKind.ModifiedIdentifier) Then
node = node.Parent
Debug.Assert(node.IsKind(SyntaxKind.ForStatement))
End If
Case LocalDeclarationKind.ForEach
node = _identifierToken.Parent
If Not node.IsKind(SyntaxKind.ModifiedIdentifier) Then
node = node.Parent
Debug.Assert(node.IsKind(SyntaxKind.ForEachStatement))
End If
Case Else
Throw ExceptionUtilities.UnexpectedValue(Me.DeclarationKind)
End Select
Return node
End Function
Public Overrides ReadOnly Property DeclaringSyntaxReferences As ImmutableArray(Of SyntaxReference)
Get
If Me.DeclarationKind = LocalDeclarationKind.FunctionValue Then
Return ImmutableArray(Of SyntaxReference).Empty
End If
Return ImmutableArray.Create(_identifierToken.Parent.GetReference())
End Get
End Property
Friend NotOverridable Overrides ReadOnly Property IdentifierLocation As Location
Get
Return _identifierToken.GetLocation()
End Get
End Property
Friend NotOverridable Overrides ReadOnly Property IdentifierToken As SyntaxToken
Get
Return _identifierToken
End Get
End Property
Friend Overrides Function ComputeType(Optional containingBinder As Binder = Nothing) As TypeSymbol
containingBinder = If(containingBinder, _binder)
Dim type As TypeSymbol = ComputeTypeInternal(If(containingBinder, _binder))
Return type
End Function
Friend Overridable Function ComputeTypeInternal(containingBinder As Binder) As TypeSymbol
Debug.Assert(_lazyType IsNot Nothing)
Return _lazyType
End Function
Public Overrides Function Equals(obj As Object) As Boolean
If Me Is obj Then
Return True
End If
Dim other = TryCast(obj, SourceLocalSymbol)
Return other IsNot Nothing AndAlso other._identifierToken.Equals(Me._identifierToken) AndAlso Equals(other._container, Me._container) AndAlso String.Equals(other.Name, Me.Name)
End Function
Public Overrides Function GetHashCode() As Integer
Return Hash.Combine(_identifierToken.GetHashCode(), Me._container.GetHashCode())
End Function
End Class
#End Region
#Region "SourceLocalSymbolWithNonstandardName"
''' <summary>
''' Class for a local symbol that has a different name than the identifier token.
''' In this case the real name is returned by the name property and the "VB User visible name" can be
''' obtained by accessing the IdentifierToken.
''' </summary>
Private NotInheritable Class SourceLocalSymbolWithNonstandardName
Inherits SourceLocalSymbol
Private ReadOnly _name As String
''' <summary>
''' Create a local variable symbol. Note: this does not insert it automatically into a
''' local binder so that it can be found by lookup.
''' </summary>
Public Sub New(container As Symbol,
binder As Binder,
declaringIdentifier As SyntaxToken,
declarationKind As LocalDeclarationKind,
type As TypeSymbol,
name As String)
MyBase.New(container, binder, declaringIdentifier, declarationKind, type)
Debug.Assert(name IsNot Nothing)
Debug.Assert(type IsNot Nothing)
_name = name
End Sub
Public Overrides ReadOnly Property Name As String
Get
Return _name
End Get
End Property
End Class
#End Region
#Region "InferredForEachLocalSymbol"
''' <summary>
''' A local symbol created by a for-each statement when Option Infer is on.
''' </summary>
''' <remarks></remarks>
Private NotInheritable Class InferredForEachLocalSymbol
Inherits SourceLocalSymbol
Private ReadOnly _collectionExpressionSyntax As ExpressionSyntax
''' <summary>
''' Create a local variable symbol. Note: this does not insert it automatically into a
''' local binder so that it can be found by lookup.
''' </summary>
Public Sub New(container As Symbol,
binder As Binder,
declaringIdentifier As SyntaxToken,
collectionExpressionSyntax As ExpressionSyntax)
MyBase.New(container, binder, declaringIdentifier, LocalDeclarationKind.ForEach, Nothing)
Debug.Assert(collectionExpressionSyntax IsNot Nothing)
_collectionExpressionSyntax = collectionExpressionSyntax
End Sub
' Compute the type of this variable.
Friend Overrides Function ComputeTypeInternal(localBinder As Binder) As TypeSymbol
Dim type As TypeSymbol = Nothing
type = localBinder.InferForEachVariableType(Me,
_collectionExpressionSyntax,
collectionExpression:=Nothing,
currentType:=Nothing,
elementType:=Nothing,
isEnumerable:=Nothing,
boundGetEnumeratorCall:=Nothing,
boundEnumeratorPlaceholder:=Nothing,
boundMoveNextCall:=Nothing,
boundCurrentAccess:=Nothing,
collectionPlaceholder:=Nothing,
needToDispose:=Nothing,
isOrInheritsFromOrImplementsIDisposable:=Nothing,
BindingDiagnosticBag.Discarded)
Return type
End Function
Friend Overrides ReadOnly Property HasInferredType As Boolean
Get
Return True
End Get
End Property
Public Overrides ReadOnly Property DeclaringSyntaxReferences As ImmutableArray(Of SyntaxReference)
Get
Return GetDeclaringSyntaxReferenceHelper(Of ForEachStatementSyntax)(Me.Locations)
End Get
End Property
End Class
#End Region
#Region "InferredForFromToLocalSymbol"
''' <summary>
''' A local symbol created by For from-to statement when Option Infer is on.
''' </summary>
Private NotInheritable Class InferredForFromToLocalSymbol
Inherits SourceLocalSymbol
Private ReadOnly _fromValue As ExpressionSyntax
Private ReadOnly _toValue As ExpressionSyntax
Private ReadOnly _stepClauseOpt As ForStepClauseSyntax
''' <summary>
''' Create a local variable symbol. Note: this does not insert it automatically into a
''' local binder so that it can be found by lookup.
''' </summary>
Public Sub New(container As Symbol,
binder As Binder,
declaringIdentifier As SyntaxToken,
fromValue As ExpressionSyntax,
toValue As ExpressionSyntax,
stepClauseOpt As ForStepClauseSyntax)
MyBase.New(container, binder, declaringIdentifier, LocalDeclarationKind.For, Nothing)
Debug.Assert(fromValue IsNot Nothing AndAlso toValue IsNot Nothing)
_fromValue = fromValue
_toValue = toValue
_stepClauseOpt = stepClauseOpt
End Sub
' Compute the type of this variable.
Friend Overrides Function ComputeType(Optional containingBinder As Binder = Nothing) As TypeSymbol
Dim fromValueExpression As BoundExpression = Nothing
Dim toValueExpression As BoundExpression = Nothing
Dim stepValueExpression As BoundExpression = Nothing
Dim type As TypeSymbol = Nothing
Dim localBinder = If(containingBinder, _binder)
type = localBinder.InferForFromToVariableType(Me,
_fromValue,
_toValue,
_stepClauseOpt,
fromValueExpression,
toValueExpression,
stepValueExpression,
BindingDiagnosticBag.Discarded)
Return type
End Function
Friend Overrides ReadOnly Property HasInferredType As Boolean
Get
Return True
End Get
End Property
Public Overrides ReadOnly Property DeclaringSyntaxReferences As ImmutableArray(Of SyntaxReference)
Get
Return GetDeclaringSyntaxReferenceHelper(Of ForStatementSyntax)(Me.Locations)
End Get
End Property
End Class
#End Region
#Region "VariableLocalSymbol"
''' <summary>
''' A local symbol created from a variable declaration or a for statement with an as clause.
''' </summary>
Private NotInheritable Class VariableLocalSymbol
Inherits SourceLocalSymbol
Private ReadOnly _modifiedIdentifierOpt As ModifiedIdentifierSyntax ' either Nothing or a modifier identifier containing the type modifiers.
Private ReadOnly _asClauseOpt As AsClauseSyntax ' can be Nothing if no AsClause
Private ReadOnly _initializerOpt As EqualsValueSyntax ' can be Nothing if no initializer
Private _evaluatedConstant As EvaluatedConstantInfo
Private NotInheritable Class EvaluatedConstantInfo
Inherits EvaluatedConstant
Public Sub New(value As ConstantValue, type As TypeSymbol, expression As BoundExpression, diagnostics As ReadOnlyBindingDiagnostic(Of AssemblySymbol))
MyBase.New(value, type)
Debug.Assert(expression IsNot Nothing)
Me.Expression = expression
Me.Diagnostics = diagnostics
End Sub
Public ReadOnly Expression As BoundExpression
Public ReadOnly Diagnostics As ReadOnlyBindingDiagnostic(Of AssemblySymbol)
End Class
''' <summary>
''' Create a local variable symbol. Note: this does not insert it automatically into a
''' local binder so that it can be found by lookup.
''' </summary>
Public Sub New(container As Symbol,
binder As Binder,
declaringIdentifier As SyntaxToken,
modifiedIdentifierOpt As ModifiedIdentifierSyntax,
asClauseOpt As AsClauseSyntax,
initializerOpt As EqualsValueSyntax,
declarationKind As LocalDeclarationKind)
MyBase.New(container, binder, declaringIdentifier, declarationKind, Nothing)
_modifiedIdentifierOpt = modifiedIdentifierOpt
_asClauseOpt = asClauseOpt
_initializerOpt = initializerOpt
End Sub
' Compute the type of this variable.
Friend Overrides Function ComputeTypeInternal(localBinder As Binder) As TypeSymbol
Dim declType As TypeSymbol = Nothing
Dim type As TypeSymbol = Nothing
Dim valueExpression As BoundExpression = Nothing
type = localBinder.ComputeVariableType(Me,
_modifiedIdentifierOpt,
_asClauseOpt,
_initializerOpt,
valueExpression,
declType,
BindingDiagnosticBag.Discarded)
Return type
End Function
Friend Overrides Function GetConstantExpression(localBinder As Binder) As BoundExpression
Debug.Assert(localBinder IsNot Nothing)
If IsConst Then
If _evaluatedConstant Is Nothing Then
Dim diagBag = BindingDiagnosticBag.GetInstance()
' BindLocalConstantInitializer may be called before or after the constant's type has been set.
' It is called before when we are inferring the constant's type. In that case the constant has no explicit type
' or the explicit type is object. i.e.
' const x = 1
' const y as object = 2.0
' We do not use the Type property because that would cause the type to be computed.
Dim constValue As ConstantValue = Nothing
Dim valueExpression As BoundExpression =
localBinder.BindLocalConstantInitializer(Me,
_lazyType,
_modifiedIdentifierOpt,
_initializerOpt,
diagBag,
constValue)
Debug.Assert(valueExpression IsNot Nothing)
Debug.Assert(constValue Is Nothing OrElse
Not valueExpression.HasErrors AndAlso
(valueExpression.Type Is Nothing OrElse Not valueExpression.Type.IsErrorType))
SetConstantExpression(valueExpression.Type, constValue, valueExpression, diagBag.ToReadOnlyAndFree())
Return valueExpression
End If
Return _evaluatedConstant.Expression
End If
' GetConstantExpression should not be called if this is not a constant.
Throw ExceptionUtilities.Unreachable
End Function
Friend Overrides Function GetConstantValue(containingBinder As Binder) As ConstantValue
If IsConst AndAlso _evaluatedConstant Is Nothing Then
Dim localBinder = If(containingBinder, _binder)
GetConstantExpression(localBinder)
End If
Return If(_evaluatedConstant IsNot Nothing, _evaluatedConstant.Value, Nothing)
End Function
Friend Overrides Function GetConstantValueDiagnostics(containingBinder As Binder) As ReadOnlyBindingDiagnostic(Of AssemblySymbol)
GetConstantValue(containingBinder)
Return If(_evaluatedConstant IsNot Nothing, _evaluatedConstant.Diagnostics, ReadOnlyBindingDiagnostic(Of AssemblySymbol).Empty)
End Function
Private Sub SetConstantExpression(type As TypeSymbol, constantValue As ConstantValue, expression As BoundExpression, diagnostics As ReadOnlyBindingDiagnostic(Of AssemblySymbol))
If _evaluatedConstant Is Nothing Then
Interlocked.CompareExchange(_evaluatedConstant, New EvaluatedConstantInfo(constantValue, type, expression, diagnostics), Nothing)
End If
End Sub
Public Overrides ReadOnly Property DeclaringSyntaxReferences As ImmutableArray(Of SyntaxReference)
Get
Select Case DeclarationKind
Case LocalDeclarationKind.None, LocalDeclarationKind.FunctionValue
Return ImmutableArray(Of SyntaxReference).Empty
Case Else
If _modifiedIdentifierOpt IsNot Nothing Then
Return ImmutableArray.Create(Of SyntaxReference)(_modifiedIdentifierOpt.GetReference())
Else
Return ImmutableArray(Of SyntaxReference).Empty
End If
End Select
End Get
End Property
End Class
#End Region
#Region "TypeSubstitutedLocalSymbol"
''' <summary>
''' Local symbol that is not associated with any source.
''' </summary>
''' <remarks>Generally used for temporary locals past the initial binding phase.</remarks>
Private NotInheritable Class TypeSubstitutedLocalSymbol
Inherits LocalSymbol
Private ReadOnly _originalVariable As LocalSymbol
Public Sub New(originalVariable As LocalSymbol, type As TypeSymbol)
MyBase.New(originalVariable._container, type)
Debug.Assert(originalVariable IsNot Nothing)
Debug.Assert(type IsNot Nothing)
_originalVariable = originalVariable
End Sub
Friend Overrides ReadOnly Property DeclarationKind As LocalDeclarationKind
Get
Return _originalVariable.DeclarationKind
End Get
End Property
Friend Overrides ReadOnly Property SynthesizedKind As SynthesizedLocalKind
Get
Return _originalVariable.SynthesizedKind
End Get
End Property
Public Overrides ReadOnly Property IsFunctionValue As Boolean
Get
Return _originalVariable.IsFunctionValue
End Get
End Property
Public Overrides ReadOnly Property Name As String
Get
Return _originalVariable.Name
End Get
End Property
Public Overrides ReadOnly Property DeclaringSyntaxReferences As ImmutableArray(Of SyntaxReference)
Get
Return _originalVariable.DeclaringSyntaxReferences
End Get
End Property
Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location)
Get
Return _originalVariable.Locations
End Get
End Property
Friend Overrides ReadOnly Property IdentifierToken As SyntaxToken
Get
Return _originalVariable.IdentifierToken
End Get
End Property
Friend Overrides ReadOnly Property IdentifierLocation As Location
Get
Return _originalVariable.IdentifierLocation
End Get
End Property
Friend Overrides ReadOnly Property IsByRef As Boolean
Get
Return _originalVariable.IsByRef
End Get
End Property
Friend Overrides Function GetConstantValue(binder As Binder) As ConstantValue
Return _originalVariable.GetConstantValue(binder)
End Function
Friend Overrides Function GetConstantValueDiagnostics(binder As Binder) As ReadOnlyBindingDiagnostic(Of AssemblySymbol)
Return _originalVariable.GetConstantValueDiagnostics(binder)
End Function
Friend Overrides Function GetDeclaratorSyntax() As SyntaxNode
Return _originalVariable.GetDeclaratorSyntax()
End Function
End Class
#End Region
End Class
End Namespace
|