提交 200005d3 编写于 作者: C Charles Stoner

Bind sub-expressions for unexpected statements

上级 cbe6309b
......@@ -5780,5 +5780,28 @@ class Test
var comp = CreateCompilationWithMscorlib(source, new[] { SystemCoreRef });
var diag = comp.GetDiagnostics();
}
[Fact]
public void QueryClauseInBadStatement_Catch()
{
var source =
@"using System;
class C
{
static void F(object[] c)
{
catch (Exception) when (from o in c where true)
{
}
}
}";
var comp = CreateCompilationWithMscorlib(source);
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var tokens = tree.GetCompilationUnitRoot().DescendantTokens();
var expr = tokens.Single(t => t.Kind() == SyntaxKind.TrueKeyword).Parent;
Assert.Null(model.GetSymbolInfo(expr).Symbol);
Assert.Equal(SpecialType.System_Boolean, model.GetTypeInfo(expr).Type.SpecialType);
}
}
}
......@@ -131,7 +131,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private Function BindCaseStatement(
node As CaseStatementSyntax,
selectExpression As BoundExpression,
selectExpressionOpt As BoundExpression,
convertCaseElements As Boolean,
diagnostics As DiagnosticBag
) As BoundCaseStatement
......@@ -143,7 +143,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' Bind case clauses.
For Each caseClause In node.Cases
caseClauseBuilder.Add(BindCaseClause(caseClause, selectExpression, convertCaseElements, diagnostics))
caseClauseBuilder.Add(BindCaseClause(caseClause, selectExpressionOpt, convertCaseElements, diagnostics))
Next
caseClauses = caseClauseBuilder.ToImmutableAndFree()
......@@ -157,7 +157,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private Function BindCaseClause(
node As CaseClauseSyntax,
selectExpression As BoundExpression,
selectExpressionOpt As BoundExpression,
convertCaseElements As Boolean,
diagnostics As DiagnosticBag
) As BoundCaseClause
......@@ -166,13 +166,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
SyntaxKind.CaseGreaterThanClause, SyntaxKind.CaseGreaterThanOrEqualClause,
SyntaxKind.CaseLessThanClause, SyntaxKind.CaseLessThanOrEqualClause
Return BindRelationalCaseClause(DirectCast(node, RelationalCaseClauseSyntax), selectExpression, convertCaseElements, diagnostics)
Return BindRelationalCaseClause(DirectCast(node, RelationalCaseClauseSyntax), selectExpressionOpt, convertCaseElements, diagnostics)
Case SyntaxKind.SimpleCaseClause
Return BindSimpleCaseClause(DirectCast(node, SimpleCaseClauseSyntax), selectExpression, convertCaseElements, diagnostics)
Return BindSimpleCaseClause(DirectCast(node, SimpleCaseClauseSyntax), selectExpressionOpt, convertCaseElements, diagnostics)
Case SyntaxKind.RangeCaseClause
Return BindRangeCaseClause(DirectCast(node, RangeCaseClauseSyntax), selectExpression, convertCaseElements, diagnostics)
Return BindRangeCaseClause(DirectCast(node, RangeCaseClauseSyntax), selectExpressionOpt, convertCaseElements, diagnostics)
Case Else
Throw ExceptionUtilities.UnexpectedValue(node.Kind)
......@@ -181,7 +181,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private Function BindRelationalCaseClause(
node As RelationalCaseClauseSyntax,
selectExpression As BoundExpression,
selectExpressionOpt As BoundExpression,
convertCaseElements As Boolean,
diagnostics As DiagnosticBag
) As BoundCaseClause
......@@ -216,7 +216,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim operandE1 As BoundExpression = BindCaseClauseExpression(
expressionSyntax:=node.Value,
caseClauseSyntax:=node,
selectExpression:=selectExpression,
selectExpressionOpt:=selectExpressionOpt,
operatorTokenKind:=node.OperatorToken.Kind,
operatorKind:=operatorKind,
convertCaseElements:=convertCaseElements,
......@@ -228,7 +228,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private Function BindSimpleCaseClause(
node As SimpleCaseClauseSyntax,
selectExpression As BoundExpression,
selectExpressionOpt As BoundExpression,
convertCaseElements As Boolean,
diagnostics As DiagnosticBag
) As BoundCaseClause
......@@ -248,7 +248,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim value As BoundExpression = BindCaseClauseExpression(
expressionSyntax:=node.Value,
caseClauseSyntax:=node,
selectExpression:=selectExpression,
selectExpressionOpt:=selectExpressionOpt,
operatorTokenKind:=SyntaxKind.EqualsToken,
operatorKind:=BinaryOperatorKind.Equals,
convertCaseElements:=convertCaseElements,
......@@ -260,7 +260,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private Function BindRangeCaseClause(
node As RangeCaseClauseSyntax,
selectExpression As BoundExpression,
selectExpressionOpt As BoundExpression,
convertCaseElements As Boolean,
diagnostics As DiagnosticBag
) As BoundCaseClause
......@@ -280,7 +280,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim lowerBound As BoundExpression = BindCaseClauseExpression(
expressionSyntax:=node.LowerBound,
caseClauseSyntax:=node,
selectExpression:=selectExpression,
selectExpressionOpt:=selectExpressionOpt,
operatorTokenKind:=SyntaxKind.GreaterThanEqualsToken,
operatorKind:=BinaryOperatorKind.GreaterThanOrEqual,
convertCaseElements:=convertCaseElements,
......@@ -292,7 +292,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim upperBound As BoundExpression = BindCaseClauseExpression(
expressionSyntax:=node.UpperBound,
caseClauseSyntax:=node,
selectExpression:=selectExpression,
selectExpressionOpt:=selectExpressionOpt,
operatorTokenKind:=SyntaxKind.LessThanEqualsToken,
operatorKind:=BinaryOperatorKind.LessThanOrEqual,
convertCaseElements:=convertCaseElements,
......@@ -305,7 +305,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private Function BindCaseClauseExpression(
expressionSyntax As ExpressionSyntax,
caseClauseSyntax As CaseClauseSyntax,
selectExpression As BoundExpression,
selectExpressionOpt As BoundExpression,
operatorTokenKind As SyntaxKind,
operatorKind As BinaryOperatorKind,
convertCaseElements As Boolean,
......@@ -314,14 +314,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
) As BoundExpression
Dim caseExpr As BoundExpression = BindValue(expressionSyntax, diagnostics)
Dim caseExprType = caseExpr.Type
If convertCaseElements AndAlso caseExprType.IsIntrinsicOrEnumType() Then
If selectExpressionOpt Is Nothing Then
' In error scenarios, such as a Case statement outside of a
' Select statement, the Select expression may be Nothing.
conditionOpt = Nothing
Return MakeRValue(caseExpr, diagnostics)
End If
If convertCaseElements AndAlso caseExpr.Type.IsIntrinsicOrEnumType() Then
' SPEC: The expression is converted to the type of the Select expression;
' SPEC: if the expression is not implicitly convertible to the type of the Select expression, a compile-time error occurs.
Debug.Assert(selectExpression.Type IsNot Nothing)
Return ApplyImplicitConversion(expressionSyntax, selectExpression.Type, caseExpr, diagnostics)
Debug.Assert(selectExpressionOpt.Type IsNot Nothing)
Return ApplyImplicitConversion(expressionSyntax, selectExpressionOpt.Type, caseExpr, diagnostics)
Else
' SPEC: If the Select expression is E, the comparison operator is Op,
......@@ -330,7 +336,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' Bind binary operator "selectExpression OP caseExpr" to generate necessary diagnostics.
conditionOpt = BindBinaryOperator(
node:=caseClauseSyntax,
left:=selectExpression,
left:=selectExpressionOpt,
right:=caseExpr,
operatorTokenKind:=operatorTokenKind,
preliminaryOperatorKind:=operatorKind,
......
......@@ -62,16 +62,23 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Case SyntaxKind.MultiLineIfBlock
Return BindMultiLineIfBlock(DirectCast(node, MultiLineIfBlockSyntax), diagnostics)
Case SyntaxKind.ElseIfStatement
' ElseIf without a preceding If.
Debug.Assert(node.ContainsDiagnostics)
Dim condition = BindBooleanExpression(DirectCast(node, ElseIfStatementSyntax).Condition, diagnostics)
Return New BoundBadStatement(node, ImmutableArray.Create(Of BoundNode)(condition), hasErrors:=True)
Case SyntaxKind.SelectBlock
Return BindSelectBlock(DirectCast(node, SelectBlockSyntax), diagnostics)
Case SyntaxKind.CaseStatement,
SyntaxKind.SelectStatement
' Valid select/case statement within select case statement is handled in BindSelectBlock.
' We should reach here only for invalid case statements which are not inside any SelectBlock.
Case SyntaxKind.CaseStatement
' Valid Case statement within Select Case statement is handled in BindSelectBlock.
' We should reach here only for invalid Case statements which are not inside any SelectBlock.
' Parser must have already reported error ERRID.ERR_CaseNoSelect or ERRID.ERR_SubRequiresSingleStatement.
Debug.Assert(node.ContainsDiagnostics)
Return New BoundBadStatement(node, ImmutableArray(Of BoundNode).Empty, hasErrors:=True)
Dim caseStatement = DirectCast(node, CaseStatementSyntax)
Dim statement = BindCaseStatement(caseStatement, selectExpressionOpt:=Nothing, convertCaseElements:=False, diagnostics:=diagnostics)
Return New BoundBadStatement(node, ImmutableArray.Create(Of BoundNode)(statement), hasErrors:=True)
Case SyntaxKind.LocalDeclarationStatement
Return BindLocalDeclaration(DirectCast(node, LocalDeclarationStatementSyntax), diagnostics)
......@@ -219,14 +226,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' a loop statement is legal as long as it is part of a do loop block
If Not SyntaxFacts.IsDoLoopBlock(node.Parent.Kind) Then
Debug.Assert(node.ContainsDiagnostics)
Return New BoundBadStatement(node, ImmutableArray(Of BoundNode).Empty, hasErrors:=True)
Dim whileOrUntilClause = DirectCast(node, LoopStatementSyntax).WhileOrUntilClause
Dim childNodes = If(whileOrUntilClause Is Nothing,
ImmutableArray(Of BoundNode).Empty,
ImmutableArray.Create(Of BoundNode)(BindBooleanExpression(whileOrUntilClause.Condition, diagnostics)))
Return New BoundBadStatement(node, childNodes, hasErrors:=True)
End If
Case SyntaxKind.CatchStatement
' a catch statement is legal as long as it is part of a catch block
If Not node.Parent.Kind = SyntaxKind.CatchBlock Then
Debug.Assert(node.ContainsDiagnostics)
Return New BoundBadStatement(node, ImmutableArray(Of BoundNode).Empty, hasErrors:=True)
Dim whenClause = DirectCast(node, CatchStatementSyntax).WhenClause
Dim childNodes = If(whenClause Is Nothing,
ImmutableArray(Of BoundNode).Empty,
ImmutableArray.Create(Of BoundNode)(BindBooleanExpression(whenClause.Filter, diagnostics)))
Return New BoundBadStatement(node, childNodes, hasErrors:=True)
End If
Case SyntaxKind.ResumeStatement, SyntaxKind.ResumeNextStatement, SyntaxKind.ResumeLabelStatement
......
......@@ -1564,7 +1564,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Debug.Assert(Not binders.IsDefault OrElse Not ShouldHaveFound(func, guard:=True))
Debug.Assert(binders.IsDefault OrElse (binders.Length = 1 AndAlso binders(0) IsNot Nothing))
#End If
If Not binders.IsEmpty Then
If Not binders.IsDefaultOrEmpty Then
binder = binders(0)
End If
End If
......@@ -1583,7 +1583,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Debug.Assert(Not binders.IsDefault OrElse Not ShouldHaveFound(operatorSyntax, guard:=True))
Debug.Assert(binders.IsDefault OrElse (binders.Length = 1 AndAlso binders(0) IsNot Nothing))
#End If
If Not binders.IsEmpty Then
If Not binders.IsDefaultOrEmpty Then
Return binders(0)
End If
End If
......
......@@ -6113,5 +6113,245 @@ BC31138: 'AddHandler', 'RemoveHandler' and 'RaiseEvent' method parameters cannot
Next
End Sub
<WorkItem(233671, "https://devdiv.visualstudio.com/defaultcollection/DevDiv/_workitems#_a=edit&id=233671")>
<Fact()>
Public Sub QueryClauseInBadStatement_ElseIf()
Dim compilation = CreateCompilationWithMscorlib(
<compilation>
<file name="a.vb"><![CDATA[
Class C
Shared Sub F(c As Object)
ElseIf From o In c Where True Then
F(From o in 2 Where False)
End If
End Sub
End Class
]]></file>
</compilation>)
compilation.AssertTheseDiagnostics(
<errors>
BC36005: 'ElseIf' must be preceded by a matching 'If' or 'ElseIf'.
ElseIf From o In c Where True Then
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC36593: Expression of type 'Object' is not queryable. Make sure you are not missing an assembly reference and/or namespace import for the LINQ provider.
ElseIf From o In c Where True Then
~
BC36593: Expression of type 'Integer' is not queryable. Make sure you are not missing an assembly reference and/or namespace import for the LINQ provider.
F(From o in 2 Where False)
~
BC30087: 'End If' must be preceded by a matching 'If'.
End If
~~~~~~
</errors>)
Dim tree = compilation.SyntaxTrees(0)
Dim model = compilation.GetSemanticModel(tree)
Dim tokens = tree.GetCompilationUnitRoot().DescendantTokens()
' ElseIf condition.
Dim expr = tokens.Single(Function(t) t.Kind = SyntaxKind.TrueKeyword).Parent
Assert.Null(model.GetSymbolInfo(expr).Symbol)
Assert.Equal(SpecialType.System_Boolean, model.GetTypeInfo(expr).Type.SpecialType)
' Block statement expression.
expr = tokens.Single(Function(t) t.Kind = SyntaxKind.FalseKeyword).Parent
Assert.Null(model.GetSymbolInfo(expr).Symbol)
Assert.Equal(SpecialType.System_Boolean, model.GetTypeInfo(expr).Type.SpecialType)
End Sub
<WorkItem(233671, "https://devdiv.visualstudio.com/defaultcollection/DevDiv/_workitems#_a=edit&id=233671")>
<Fact()>
Public Sub QueryClauseInBadStatement_Case()
Dim compilation = CreateCompilationWithMscorlib(
<compilation>
<file name="a.vb"><![CDATA[
Imports System
Class C
Shared Sub F(c As Object)
Case 1 To From o In c Where True,
Is < From o In 2 Where False,
P
Case Else
End Select
End Sub
Shared Property P As Object
<Obsolete()>
Get
Return Nothing
End Get
Set
End Set
End Property
End Class
]]></file>
</compilation>)
compilation.AssertTheseDiagnostics(
<errors><![CDATA[
BC30072: 'Case' can only appear inside a 'Select Case' statement.
Case 1 To From o In c Where True,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC36593: Expression of type 'Object' is not queryable. Make sure you are not missing an assembly reference and/or namespace import for the LINQ provider.
Case 1 To From o In c Where True,
~
BC36593: Expression of type 'Integer' is not queryable. Make sure you are not missing an assembly reference and/or namespace import for the LINQ provider.
Is < From o In 2 Where False,
~
BC40020: 'Get' accessor of 'Public Shared Property P As Object' is obsolete.
P
~
BC30071: 'Case Else' can only appear inside a 'Select Case' statement.
Case Else
~~~~~~~~~
BC30088: 'End Select' must be preceded by a matching 'Select Case'.
End Select
~~~~~~~~~~
]]></errors>)
Dim tree = compilation.SyntaxTrees(0)
Dim model = compilation.GetSemanticModel(tree)
Dim tokens = tree.GetCompilationUnitRoot().DescendantTokens()
' First Case clause.
Dim expr = tokens.Single(Function(t) t.Kind = SyntaxKind.TrueKeyword).Parent
Assert.Null(model.GetSymbolInfo(expr).Symbol)
Assert.Equal(SpecialType.System_Boolean, model.GetTypeInfo(expr).Type.SpecialType)
' Second Case clause.
expr = tokens.Single(Function(t) t.Kind = SyntaxKind.FalseKeyword).Parent
Assert.Null(model.GetSymbolInfo(expr).Symbol)
Assert.Equal(SpecialType.System_Boolean, model.GetTypeInfo(expr).Type.SpecialType)
' Third Case clause.
expr = tokens.First(Function(t) t.Kind = SyntaxKind.IdentifierToken AndAlso t.Text = "P").Parent
Assert.Equal("Property C.P As System.Object", model.GetSymbolInfo(expr).Symbol.ToTestDisplayString())
Assert.Equal(SpecialType.System_Object, model.GetTypeInfo(expr).Type.SpecialType)
End Sub
<WorkItem(233671, "https://devdiv.visualstudio.com/defaultcollection/DevDiv/_workitems#_a=edit&id=233671")>
<Fact()>
Public Sub QueryClauseInBadStatement_Select()
Dim compilation = CreateCompilationWithMscorlib(
<compilation>
<file name="a.vb"><![CDATA[
Class C
Shared Sub F(c As Object)
Dim s = Sub() Select Case From o In c Where True : End Select
End Sub
End Class
]]></file>
</compilation>)
compilation.AssertTheseDiagnostics(
<errors>
BC36918: Single-line statement lambdas must include exactly one statement.
Dim s = Sub() Select Case From o In c Where True : End Select
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC36593: Expression of type 'Object' is not queryable. Make sure you are not missing an assembly reference and/or namespace import for the LINQ provider.
Dim s = Sub() Select Case From o In c Where True : End Select
~
</errors>)
Dim tree = compilation.SyntaxTrees(0)
Dim model = compilation.GetSemanticModel(tree)
Dim tokens = tree.GetCompilationUnitRoot().DescendantTokens()
Dim expr = tokens.Single(Function(t) t.Kind = SyntaxKind.TrueKeyword).Parent
Assert.Null(model.GetSymbolInfo(expr).Symbol)
Assert.Equal(SpecialType.System_Boolean, model.GetTypeInfo(expr).Type.SpecialType)
End Sub
<WorkItem(233671, "https://devdiv.visualstudio.com/defaultcollection/DevDiv/_workitems#_a=edit&id=233671")>
<Fact()>
Public Sub QueryClauseInBadStatement_LoopUntil()
Dim compilation = CreateCompilationWithMscorlib(
<compilation>
<file name="a.vb"><![CDATA[
Class C
Shared Sub F(c As Object)
Loop Until From o In c Where True
End Sub
End Class
]]></file>
</compilation>)
compilation.AssertTheseDiagnostics(
<errors>
BC30091: 'Loop' must be preceded by a matching 'Do'.
Loop Until From o In c Where True
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC36593: Expression of type 'Object' is not queryable. Make sure you are not missing an assembly reference and/or namespace import for the LINQ provider.
Loop Until From o In c Where True
~
</errors>)
Dim tree = compilation.SyntaxTrees(0)
Dim model = compilation.GetSemanticModel(tree)
Dim tokens = tree.GetCompilationUnitRoot().DescendantTokens()
Dim expr = tokens.Single(Function(t) t.Kind = SyntaxKind.TrueKeyword).Parent
Assert.Null(model.GetSymbolInfo(expr).Symbol)
Assert.Equal(SpecialType.System_Boolean, model.GetTypeInfo(expr).Type.SpecialType)
End Sub
<WorkItem(233671, "https://devdiv.visualstudio.com/defaultcollection/DevDiv/_workitems#_a=edit&id=233671")>
<Fact()>
Public Sub QueryClauseInBadStatement_LoopWhile()
Dim compilation = CreateCompilationWithMscorlib(
<compilation>
<file name="a.vb"><![CDATA[
Class C
Shared Sub F(c As Object)
Loop While From o In c Where True
End Sub
End Class
]]></file>
</compilation>)
compilation.AssertTheseDiagnostics(
<errors>
BC30091: 'Loop' must be preceded by a matching 'Do'.
Loop While From o In c Where True
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC36593: Expression of type 'Object' is not queryable. Make sure you are not missing an assembly reference and/or namespace import for the LINQ provider.
Loop While From o In c Where True
~
</errors>)
Dim tree = compilation.SyntaxTrees(0)
Dim model = compilation.GetSemanticModel(tree)
Dim tokens = tree.GetCompilationUnitRoot().DescendantTokens()
Dim expr = tokens.Single(Function(t) t.Kind = SyntaxKind.TrueKeyword).Parent
Assert.Null(model.GetSymbolInfo(expr).Symbol)
Assert.Equal(SpecialType.System_Boolean, model.GetTypeInfo(expr).Type.SpecialType)
End Sub
<WorkItem(233671, "https://devdiv.visualstudio.com/defaultcollection/DevDiv/_workitems#_a=edit&id=233671")>
<Fact()>
Public Sub QueryClauseInBadStatement_Catch()
Dim compilation = CreateCompilationWithMscorlib(
<compilation>
<file name="a.vb"><![CDATA[
Class C
Shared Sub F(c As Object)
Catch e As System.Exception When From o In c Where True
F(From o in 2 Where False)
End Try
End Sub
End Class
]]></file>
</compilation>)
compilation.AssertTheseDiagnostics(
<errors>
BC30380: 'Catch' cannot appear outside a 'Try' statement.
Catch e As System.Exception When From o In c Where True
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC36593: Expression of type 'Object' is not queryable. Make sure you are not missing an assembly reference and/or namespace import for the LINQ provider.
Catch e As System.Exception When From o In c Where True
~
BC36593: Expression of type 'Integer' is not queryable. Make sure you are not missing an assembly reference and/or namespace import for the LINQ provider.
F(From o in 2 Where False)
~
BC30383: 'End Try' must be preceded by a matching 'Try'.
End Try
~~~~~~~
</errors>)
Dim tree = compilation.SyntaxTrees(0)
Dim model = compilation.GetSemanticModel(tree)
Dim tokens = tree.GetCompilationUnitRoot().DescendantTokens()
Dim expr = tokens.Single(Function(t) t.Kind = SyntaxKind.TrueKeyword).Parent
Assert.Null(model.GetSymbolInfo(expr).Symbol)
Assert.Equal(SpecialType.System_Boolean, model.GetTypeInfo(expr).Type.SpecialType)
End Sub
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册