File: Parser\BlockContexts\SingleLineLambdaContext.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.
 
'-----------------------------------------------------------------------------
' Contains the definition of the BlockContext
'-----------------------------------------------------------------------------
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports InternalSyntaxFactory = Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax.SyntaxFactory
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
 
    Friend NotInheritable Class SingleLineLambdaContext
        Inherits MethodBlockContext
 
        Friend Sub New(statement As StatementSyntax, prevContext As BlockContext)
            MyBase.New(If(statement.Kind = SyntaxKind.FunctionLambdaHeader, SyntaxKind.SingleLineFunctionLambdaExpression, SyntaxKind.SingleLineSubLambdaExpression), statement, prevContext)
 
            Debug.Assert(statement.Kind = SyntaxKind.FunctionLambdaHeader OrElse statement.Kind = SyntaxKind.SubLambdaHeader)
            Debug.Assert(SyntaxFacts.IsSingleLineLambdaExpression(BlockKind))
        End Sub
 
        Friend Overrides ReadOnly Property IsLambda As Boolean
            Get
                Return True
            End Get
        End Property
 
        Friend Overrides Function CreateBlockSyntax(endStmt As StatementSyntax) As VisualBasicSyntaxNode
            Dim statements = Body()
            Dim statement As VisualBasicSyntaxNode
            Dim reportRequiresSingleStatement As Boolean
 
            If statements.Count = 0 Then
                statement = InternalSyntaxFactory.EmptyStatement(InternalSyntaxFactory.MissingEmptyToken)
                reportRequiresSingleStatement = True
            Else
                Debug.Assert(statements.Count = 1)
                statement = DirectCast(statements(0), StatementSyntax)
                reportRequiresSingleStatement = Not statement.ContainsDiagnostics() AndAlso Not IsSingleStatement(statement)
            End If
 
            ' Single line sub ignores the endStmt which may be nothing or the statement that was just added to the sub.
            Dim header = DirectCast(BeginStatement, LambdaHeaderSyntax)
            Dim lambdaExpr = SyntaxFactory.SingleLineLambdaExpression(BlockKind, header, statement)
 
            If reportRequiresSingleStatement Then
                lambdaExpr = Parser.ReportSyntaxError(lambdaExpr, ERRID.ERR_SubRequiresSingleStatement)
            ElseIf header.Kind = SyntaxKind.FunctionLambdaHeader AndAlso header.Modifiers.Any(SyntaxKind.IteratorKeyword) Then
                lambdaExpr = Parser.ReportSyntaxError(lambdaExpr, ERRID.ERR_BadIteratorExpressionLambda)
            End If
 
            FreeStatements()
 
            Return lambdaExpr
        End Function
 
        Friend Overrides Function EndBlock(endStmt As StatementSyntax) As BlockContext
 
            'Don't create the lambda block and don't pass it to the previous context.  The previous context is not the
            ' right place to store it because the lambda goes into an expression and not the surrounding statement block.
 
            Return PrevBlock
        End Function
 
        Friend Overrides Function ResyncAndProcessStatementTerminator(statement As StatementSyntax, lambdaContext As BlockContext) As BlockContext
            Return ProcessStatementTerminator(lambdaContext)
        End Function
 
        Friend Overrides Function ProcessStatementTerminator(lambdaContext As BlockContext) As BlockContext
            Dim token = Parser.CurrentToken
            Select Case token.Kind
                Case SyntaxKind.StatementTerminatorToken, SyntaxKind.EndOfFileToken
                    ' A single-line lambda is terminated at the end of the line.
 
                Case SyntaxKind.ColonToken
                    ' A single-line sub with multiple statements. Report ERR_SubRequiresSingleStatement
                    ' on the first statement and end the sub. If there are no statements, we'll report the
                    ' error, on the entire block, in CreateBlockSyntax instead.
                    If _statements.Count > 0 Then
                        _statements(0) = Parser.ReportSyntaxError(_statements(0), ERRID.ERR_SubRequiresSingleStatement)
                    End If
                    Return EndLambda()
 
            End Select
 
            Return PrevBlock
        End Function
 
        Friend Overrides ReadOnly Property IsSingleLine As Boolean
            Get
                Return True
            End Get
        End Property
 
        Private Shared Function IsSingleStatement(statement As VisualBasicSyntaxNode) As Boolean
            Select Case statement.Kind
                Case SyntaxKind.EmptyStatement,
                    SyntaxKind.MultiLineIfBlock,
                    SyntaxKind.SimpleDoLoopBlock,
                    SyntaxKind.DoWhileLoopBlock,
                    SyntaxKind.DoUntilLoopBlock,
                    SyntaxKind.DoLoopWhileBlock,
                    SyntaxKind.DoLoopUntilBlock,
                    SyntaxKind.ForBlock,
                    SyntaxKind.ForEachBlock,
                    SyntaxKind.SelectBlock,
                    SyntaxKind.WhileBlock,
                    SyntaxKind.WithBlock,
                    SyntaxKind.SyncLockBlock,
                    SyntaxKind.UsingBlock,
                    SyntaxKind.TryBlock
                    Return False
                Case Else
                    Return True
            End Select
        End Function
 
    End Class
 
End Namespace