| File: Binding\Binder_ConditionalAccess.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 System.Runtime.InteropServices Imports System.Threading Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports TypeKind = Microsoft.CodeAnalysis.TypeKind Namespace Microsoft.CodeAnalysis.VisualBasic Partial Friend Class Binder Private Function BindConditionalAccessExpression(node As ConditionalAccessExpressionSyntax, diagnostics As BindingDiagnosticBag) As BoundExpression Dim placeholder As BoundRValuePlaceholder = Nothing Dim boundExpression As BoundExpression = BindConditionalAccessReceiver(node, diagnostics, placeholder) Dim accessBinder As New ConditionalAccessBinder(Me, node, placeholder) Dim whenNotNull As BoundExpression = accessBinder.BindExpression(node.WhenNotNull, diagnostics) ' Do not know result type yet, it will be determined based on usage. Return New BoundConditionalAccess(node, boundExpression, placeholder, whenNotNull, Nothing) End Function Private Function BindConditionalAccessReceiver(node As ConditionalAccessExpressionSyntax, diagnostics As BindingDiagnosticBag, <Out> ByRef placeholder As BoundRValuePlaceholder) As BoundExpression Dim boundExpression As BoundExpression If node.Expression Is Nothing Then boundExpression = TryBindOmittedLeftForConditionalAccess(node, Me, diagnostics) If boundExpression Is Nothing Then ' Didn't find binder that can handle conditional access with omitted left part boundExpression = ReportDiagnosticAndProduceBadExpression(diagnostics, node, ERRID.ERR_BadConditionalWithRef).MakeCompilerGenerated() End If Else ' Bind the expression as a value boundExpression = BindValue(node.Expression, diagnostics) ' NOTE: If the expression is not an l-value we should make an r-value of it If Not boundExpression.IsLValue Then boundExpression = Me.MakeRValue(boundExpression, diagnostics) End If End If Dim type As TypeSymbol = boundExpression.Type Dim placeholderType As TypeSymbol = type If type.IsValueType Then If type.IsNullableType() Then placeholderType = type.GetNullableUnderlyingType() Else ' Operator '{0}' is not defined for type '{1}'. ReportDiagnostic(diagnostics, node.QuestionMarkToken, ERRID.ERR_UnaryOperand2, node.QuestionMarkToken.ValueText, type) End If End If ' Create a placeholder placeholder = New BoundRValuePlaceholder(node, placeholderType) placeholder.SetWasCompilerGenerated() Return boundExpression End Function Protected Overridable Function TryBindOmittedLeftForConditionalAccess(node As ConditionalAccessExpressionSyntax, accessingBinder As Binder, diagnostics As BindingDiagnosticBag) As BoundExpression Debug.Assert(Me.ContainingBinder IsNot Nothing) Return Me.ContainingBinder.TryBindOmittedLeftForConditionalAccess(node, accessingBinder, diagnostics) End Function Protected Function GetConditionalAccessReceiver(node As ConditionalAccessExpressionSyntax) As BoundExpression Dim result As BoundExpression = TryGetConditionalAccessReceiver(node) If result Is Nothing Then Dim placeholder As BoundRValuePlaceholder = Nothing BindConditionalAccessReceiver(node, BindingDiagnosticBag.Discarded, placeholder) Return placeholder End If Return result End Function Protected Overridable Function TryGetConditionalAccessReceiver(node As ConditionalAccessExpressionSyntax) As BoundExpression Return Me.ContainingBinder.TryGetConditionalAccessReceiver(node) End Function End Class ''' <summary> ''' A helper to bind conditional access. ''' </summary> Friend NotInheritable Class ConditionalAccessBinder Inherits Binder Private ReadOnly _conditionalAccess As ConditionalAccessExpressionSyntax Private ReadOnly _placeholder As BoundValuePlaceholderBase Public Sub New(containingBinder As Binder, conditionalAccess As ConditionalAccessExpressionSyntax, placeholder As BoundValuePlaceholderBase) MyBase.New(containingBinder) _conditionalAccess = conditionalAccess _placeholder = placeholder End Sub Protected Overrides Function TryGetConditionalAccessReceiver(node As ConditionalAccessExpressionSyntax) As BoundExpression If node Is _conditionalAccess Then Return _placeholder End If Return MyBase.TryGetConditionalAccessReceiver(node) End Function End Class End Namespace