File: Parser\BlockContexts\PropertyBlockContext.vb
Web Access
Project: src\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 Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
'-----------------------------------------------------------------------------
' Contains the definition of the BlockContext
'-----------------------------------------------------------------------------
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
 
    Friend NotInheritable Class PropertyBlockContext
        Inherits DeclarationContext
 
        Private ReadOnly _isPropertyBlock As Boolean
 
        Friend Sub New(statement As StatementSyntax, prevContext As BlockContext, isPropertyBlock As Boolean)
            MyBase.New(SyntaxKind.PropertyBlock, statement, prevContext)
 
            _isPropertyBlock = isPropertyBlock
        End Sub
 
        Private ReadOnly Property IsPropertyBlock As Boolean
            Get
                Return _isPropertyBlock OrElse Statements.Count > 0
            End Get
        End Property
 
        Friend Overrides Function CreateBlockSyntax(endStmt As StatementSyntax) As VisualBasicSyntaxNode
 
            Dim beginBlockStmt As PropertyStatementSyntax = Nothing
            Dim endBlockStmt As EndBlockStatementSyntax = DirectCast(endStmt, EndBlockStatementSyntax)
 
            GetBeginEndStatements(beginBlockStmt, endBlockStmt)
 
            Dim accessors = _statements.ToList(Of AccessorBlockSyntax)()
            FreeStatements()
 
            ' We can only get here if this is a block property but still check accessor count.
            If accessors.Any Then
                ' Only auto properties can be initialized.  If there is a Get or Set accessor then it is an error.
                beginBlockStmt = ReportErrorIfHasInitializer(beginBlockStmt)
            End If
 
            Return SyntaxFactory.PropertyBlock(beginBlockStmt, accessors, endBlockStmt)
        End Function
 
        Friend Overrides Function ProcessSyntax(node As VisualBasicSyntaxNode) As BlockContext
 
            Select Case node.Kind
                Case SyntaxKind.GetAccessorStatement
                    Return New MethodBlockContext(SyntaxKind.GetAccessorBlock, DirectCast(node, StatementSyntax), Me)
 
                Case SyntaxKind.SetAccessorStatement
                    ' Checks for duplicate GET/SET are deferred to declared per Dev10 code
                    Return New MethodBlockContext(SyntaxKind.SetAccessorBlock, DirectCast(node, StatementSyntax), Me)
 
                Case SyntaxKind.GetAccessorBlock,
                    SyntaxKind.SetAccessorBlock
                    ' Handle any block created by this context
                    Add(node)
 
                Case Else
                    ' TODO - In Dev10, the code tries to report ERRID_PropertyMemberSyntax.  This would occur prior to auto properties
                    ' when the statement was a malformed declaration.  However, due to autoproperties this no longer seems possible.
                    ' test should confirm that this error can no longer be produced in Dev10. Is it worth trying to preserve this behavior?
 
                    Dim context As BlockContext = EndBlock(Nothing)
                    Debug.Assert(context Is PrevBlock)
 
                    If IsPropertyBlock Then
                        ' Property blocks can only contain Get and Set.
                        node = Parser.ReportSyntaxError(node, ERRID.ERR_InvInsideEndsProperty)
                    End If
 
                    ' Let the outer context process this statement
                    Return context.ProcessSyntax(node)
 
            End Select
            Return Me
        End Function
 
        Friend Overrides Function TryLinkSyntax(node As VisualBasicSyntaxNode, ByRef newContext As BlockContext) As LinkResult
            newContext = Nothing
 
            If KindEndsBlock(node.Kind) Then
                Return UseSyntax(node, newContext)
            End If
 
            Select Case node.Kind
 
                Case _
                    SyntaxKind.GetAccessorStatement,
                    SyntaxKind.SetAccessorStatement
                    Return UseSyntax(node, newContext)
 
                Case SyntaxKind.GetAccessorBlock,
                    SyntaxKind.SetAccessorBlock
                    Return UseSyntax(node, newContext, DirectCast(node, AccessorBlockSyntax).End.IsMissing)
 
                Case Else
                    newContext = Me
                    Return LinkResult.Crumble
            End Select
        End Function
 
        Friend Overrides Function EndBlock(endStmt As StatementSyntax) As BlockContext
 
            If IsPropertyBlock OrElse endStmt IsNot Nothing Then
                Return MyBase.EndBlock(endStmt)
            End If
 
            ' This is an auto property.  Do not create a block.  Just add the property statement to the outer block
            ' TODO - Consider changing the kind to AutoProperty.  For now auto properties are just PropertyStatement
            ' whose parent is not a PropertyBlock. Don't create a missing end for an auto property
 
            Debug.Assert(PrevBlock IsNot Nothing)
            Debug.Assert(Statements.Count = 0)
 
            Dim beginBlockStmt As PropertyStatementSyntax = DirectCast(BeginStatement, PropertyStatementSyntax)
 
            ' Check if auto property has params
            If beginBlockStmt.ParameterList IsNot Nothing AndAlso beginBlockStmt.ParameterList.Parameters.Count > 0 Then
                beginBlockStmt = New PropertyStatementSyntax(beginBlockStmt.Kind,
                                                             beginBlockStmt.AttributeLists.Node,
                                                             beginBlockStmt.Modifiers.Node,
                                                             beginBlockStmt.PropertyKeyword,
                                                             beginBlockStmt.Identifier,
                                                             Parser.ReportSyntaxError(beginBlockStmt.ParameterList, ERRID.ERR_AutoPropertyCantHaveParams),
                                                             beginBlockStmt.AsClause,
                                                             beginBlockStmt.Initializer,
                                                             beginBlockStmt.ImplementsClause)
            End If
 
            'Add auto property to Prev context. DO NOT call ProcessSyntax because that will create a PropertyContext.
            '  Just add the statement to the context.
            Dim context = PrevBlock
            context.Add(beginBlockStmt)
            Return context
        End Function
 
        Friend Shared Function ReportErrorIfHasInitializer(propertyStatement As PropertyStatementSyntax) As PropertyStatementSyntax
 
            If propertyStatement.Initializer IsNot Nothing OrElse
               (
                   propertyStatement.AsClause IsNot Nothing AndAlso
                   TryCast(propertyStatement.AsClause, AsNewClauseSyntax) IsNot Nothing
               ) Then
 
                propertyStatement = Parser.ReportSyntaxError(propertyStatement, ERRID.ERR_InitializedExpandedProperty)
 
                'TODO - In Dev10 resources there is an unused resource ERRID.ERR_NewExpandedProperty for the new case.
                ' Is it worthwhile adding to Dev12?
            End If
 
            Return propertyStatement
        End Function
 
    End Class
 
End Namespace