File: src\Workspaces\SharedUtilitiesAndExtensions\Compiler\VisualBasic\Extensions\MemberAccessExpressionSyntaxExtensions.vb
Web Access
Project: src\src\Workspaces\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.Workspaces.vbproj (Microsoft.CodeAnalysis.VisualBasic.Workspaces)
' 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.Runtime.CompilerServices
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
    Partial Friend Module MemberAccessExpressionSyntaxExtensions
        <Extension()>
        Public Function IsConstructorInitializer(memberAccess As MemberAccessExpressionSyntax) As Boolean
            Return memberAccess.IsThisConstructorInitializer() OrElse memberAccess.IsBaseConstructorInitializer()
        End Function
 
        <Extension()>
        Public Function IsThisConstructorInitializer(memberAccess As MemberAccessExpressionSyntax) As Boolean
            If memberAccess IsNot Nothing Then
                If IsFirstStatementInConstructor(memberAccess) Then
                    If memberAccess.Expression.IsKind(SyntaxKind.MeExpression) OrElse
                       memberAccess.Expression.IsKind(SyntaxKind.MyClassExpression) Then
                        If memberAccess.Name.IsKind(SyntaxKind.IdentifierName) Then
                            Return memberAccess.Name.Identifier.HasMatchingText(SyntaxKind.NewKeyword)
                        End If
                    End If
                End If
            End If
 
            Return False
        End Function
 
        <Extension()>
        Public Function IsBaseConstructorInitializer(memberAccess As MemberAccessExpressionSyntax) As Boolean
            If memberAccess IsNot Nothing Then
                If IsFirstStatementInConstructor(memberAccess) Then
                    If memberAccess.Expression.IsKind(SyntaxKind.MyBaseExpression) Then
                        If memberAccess.Name.IsKind(SyntaxKind.IdentifierName) Then
                            Return memberAccess.Name.Identifier.HasMatchingText(SyntaxKind.NewKeyword)
                        End If
                    End If
                End If
            End If
 
            Return False
        End Function
 
        Private Function IsFirstStatementInConstructor(memberAccess As MemberAccessExpressionSyntax) As Boolean
            Dim isCall As Boolean
            Dim statement As SyntaxNode
            If TypeOf memberAccess.Parent Is InvocationExpressionSyntax Then
                statement = memberAccess.Parent.Parent
                isCall = statement IsNot Nothing AndAlso (statement.Kind = SyntaxKind.CallStatement OrElse statement.Kind = SyntaxKind.ExpressionStatement)
            Else
                statement = memberAccess.Parent
                isCall = statement.IsKind(SyntaxKind.CallStatement)
            End If
 
            If isCall Then
                Return statement.IsParentKind(SyntaxKind.ConstructorBlock) AndAlso
                    DirectCast(statement.Parent, ConstructorBlockSyntax).Statements.First() Is statement
            End If
 
            Return False
        End Function
 
        <Extension>
        Public Function GetExpressionOfMemberAccessExpression(
                memberAccessExpression As MemberAccessExpressionSyntax,
                Optional allowImplicitTarget As Boolean = False) As ExpressionSyntax
            If memberAccessExpression Is Nothing Then
                Return Nothing
            End If
 
            If memberAccessExpression.Expression IsNot Nothing Then
                Return memberAccessExpression.Expression
            End If
 
            ' we have a member access expression with a null expression, this may be one of the
            ' following forms:
            '
            ' 1) new With { .a = 1, .b = .a     <-- .a refers to the anonymous type
            ' 2) With obj : .m                  <-- .m refers to the obj type
            ' 3) new T() With { .a = 1, .b = .a <-- 'a refers to the T type
 
            If allowImplicitTarget Then
                Dim conditional = memberAccessExpression.GetRootConditionalAccessExpression()
                If conditional IsNot Nothing Then
                    If conditional.Expression Is Nothing Then
 
                        ' No expression, maybe we're in a with block
                        Dim withBlock = conditional.GetAncestor(Of WithBlockSyntax)()
                        If withBlock IsNot Nothing Then
                            Return withBlock.WithStatement.Expression
                        End If
                    End If
 
                    Return conditional.Expression
                End If
 
                Dim current As SyntaxNode = memberAccessExpression
 
                While current IsNot Nothing
                    If TypeOf current Is AnonymousObjectCreationExpressionSyntax Then
                        Return DirectCast(current, ExpressionSyntax)
                    ElseIf TypeOf current Is WithBlockSyntax Then
                        Dim withBlock = DirectCast(current, WithBlockSyntax)
                        If memberAccessExpression IsNot withBlock.WithStatement.Expression Then
                            Return withBlock.WithStatement.Expression
                        End If
                    ElseIf TypeOf current Is ObjectMemberInitializerSyntax AndAlso
                           TypeOf current.Parent Is ObjectCreationExpressionSyntax Then
                        Return DirectCast(current.Parent, ExpressionSyntax)
                    End If
 
                    current = current.Parent
                End While
            End If
 
            Return Nothing
        End Function
    End Module
End Namespace