提交 38f60364 编写于 作者: C Charles Stoner

Merge remote-tracking branch 'upstream/master' into 1105626

......@@ -81,7 +81,7 @@ internal static bool IsClosureScope(SyntaxNode node)
}
// TODO: EE expression
if (node is ExpressionSyntax && node.Parent.Parent == null)
if (node is ExpressionSyntax && node.Parent != null && node.Parent.Parent == null)
{
return true;
}
......
......@@ -66,7 +66,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
_scopeSyntaxOpt = scopeSyntaxOpt
End If
AssertIsLambdaScopeSyntax(_scopeSyntaxOpt)
If Not isDelegateRelaxationFrame Then
AssertIsClosureScopeSyntax(_scopeSyntaxOpt)
End If
Me._typeParameters = SynthesizedClonedTypeParameterSymbol.MakeTypeParameters(topLevelMethod.TypeParameters, Me, CreateTypeParameter)
Me.TypeMap = TypeSubstitution.Create(topLevelMethod, topLevelMethod.TypeParameters, Me.TypeArgumentsNoUseSiteDiagnostics)
......@@ -106,8 +108,23 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Function
<Conditional("DEBUG")>
Private Shared Sub AssertIsLambdaScopeSyntax(syntaxOpt As VisualBasicSyntaxNode)
'TODO: Add checks for possible syntax
Private Shared Sub AssertIsClosureScopeSyntax(syntaxOpt As VisualBasicSyntaxNode)
' static lambdas technically have the class scope so the scope syntax is nothing
If syntaxOpt Is Nothing Then
Return
End If
If SyntaxUtilities.IsClosureScope(syntaxOpt) Then
Return
End If
Select Case syntaxOpt.Kind()
Case SyntaxKind.ObjectMemberInitializer
' TODO: Closure capturing a synthesized "with" variable
Return
End Select
ExceptionUtilities.UnexpectedValue(syntaxOpt.Kind())
End Sub
Public ReadOnly Property ScopeSyntax As VisualBasicSyntaxNode
......
......@@ -54,5 +54,100 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Throw ExceptionUtilities.Unreachable
End Select
End Function
''' <summary>
''' Returns true if the specified node can represent a closure scope -- that is a scope of a captured variable.
''' Doesn't validate whether or not the node actually declares any captured variable.
''' </summary>
Friend Shared Function IsClosureScope(node As VisualBasicSyntaxNode) As Boolean
Select Case node.Kind()
Case SyntaxKind.MultiLineSubLambdaExpression,
SyntaxKind.MultiLineFunctionLambdaExpression,
SyntaxKind.SingleLineSubLambdaExpression,
SyntaxKind.SingleLineFunctionLambdaExpression
' lambda parameters, variables defined in lambda body
Return True
Case SyntaxKind.SubBlock,
SyntaxKind.FunctionBlock,
SyntaxKind.ConstructorBlock,
SyntaxKind.OperatorBlock,
SyntaxKind.GetAccessorBlock,
SyntaxKind.SetAccessorBlock,
SyntaxKind.AddHandlerAccessorBlock,
SyntaxKind.RemoveHandlerAccessorBlock,
SyntaxKind.RaiseEventAccessorBlock
' parameters, variables defined in method body
' Note: property parameters, accessor parameters and variables defined in an accessor have all the same scope (the accessor scope).
Return True
Case SyntaxKind.WhileBlock,
SyntaxKind.ForBlock,
SyntaxKind.ForEachBlock,
SyntaxKind.SimpleDoLoopBlock,
SyntaxKind.DoWhileLoopBlock,
SyntaxKind.DoUntilLoopBlock,
SyntaxKind.DoLoopWhileBlock,
SyntaxKind.DoLoopUntilBlock,
SyntaxKind.UsingBlock,
SyntaxKind.SyncLockBlock,
SyntaxKind.WithBlock,
SyntaxKind.CaseBlock,
SyntaxKind.CaseElseBlock,
SyntaxKind.SingleLineIfStatement,
SyntaxKind.SingleLineElseClause,
SyntaxKind.MultiLineIfBlock,
SyntaxKind.ElseIfBlock,
SyntaxKind.ElseBlock,
SyntaxKind.TryBlock,
SyntaxKind.CatchBlock,
SyntaxKind.FinallyBlock
' variable declared in a statement block
Return True
Case SyntaxKind.SelectClause,
SyntaxKind.SimpleJoinClause,
SyntaxKind.GroupJoinClause,
SyntaxKind.GroupByClause,
SyntaxKind.AggregateClause
' range variable captured by the clause
Return True
Case Else
Dim parent = node.Parent
If TypeOf node IsNot ExpressionSyntax OrElse parent Is Nothing Then
Return False
End If
Select Case parent.Kind()
Case SyntaxKind.WhereClause,
SyntaxKind.TakeWhileClause,
SyntaxKind.SkipWhileClause,
SyntaxKind.AscendingOrdering,
SyntaxKind.DescendingOrdering
' captured range variable by the clause
Return True
Case SyntaxKind.FunctionAggregation,
SyntaxKind.GroupAggregation
' range variable captured by IntoClause
Return True
Case SyntaxKind.ExpressionRangeVariable
' range variable captured by Let clause
Return parent.Parent IsNot Nothing AndAlso parent.Parent.IsKind(SyntaxKind.LetClause)
End Select
' TODO: EE expression
If parent.Parent IsNot Nothing AndAlso
parent.Parent.Parent Is Nothing Then
Return True
End If
Return False
End Select
End Function
End Class
End Namespace
\ No newline at end of file
......@@ -3596,6 +3596,271 @@ End Class
}, c.GetMembers().Select(Function(member) member.ToString()))
End Sub)
End Sub
<Fact>
Public Sub DeclarationBlockClosures()
Dim source =
<compilation>
<file name="a.vb">
Imports System
Class C
Sub New(a As Integer)
Dim f = Function() a
End Sub
Sub F1(a As Integer)
Dim f = Function() a
End Sub
Function F2(a As Integer) As Integer
Dim f = Function() a
Return 1
End Function
Property F3(a As Integer) As Integer
Get
Dim f = Function() a
Return 1
End Get
Set(value As Integer)
Dim f1 = Function() a
Dim f2 = Function() value
End Set
End Property
Custom Event F4 As Action
AddHandler(value As Action)
Dim f1 = Function() value
End AddHandler
RemoveHandler(value As Action)
Dim f1 = Function() value
End RemoveHandler
RaiseEvent()
Dim x = 1
Dim f1 = Function() x
End RaiseEvent
End Event
Shared Operator *(a As C, b As C) As C
Dim f1 = Function() a
Return a
End Operator
Shared Widening Operator CType(a As C) As Integer
Dim f1 = Function() a
Return 1
End Operator
End Class </file>
</compilation>
CompileAndVerify(source)
End Sub
<Fact>
Public Sub StatementBlockClosures()
Dim source =
<compilation>
<file name="a.vb">
Imports System
Class D
Public Q As Integer
Shared Function Z(Of T)(f As Func(Of T)) As T
Return f()
End Function
Sub F()
While True
Dim a = 0
Dim f1 = Function() a
End While
For x As Integer = 0 To 1
Dim a = 0
Dim f1 = Function() a
Next
For Each x In {1}
Dim a = 0
Dim f1 = Function() a
Next
Do
Dim a = 0
Dim f1 = Function() a
Loop
Do
Dim a = 0
Dim f1 = Function() a
Loop While True
Do
Dim a = 0
Dim f1 = Function() a
Loop Until True
Do While True
Dim a = 0
Dim f1 = Function() a
Loop
Do Until True
Dim a = 0
Dim f1 = Function() a
Loop
Dim u As IDisposable = Nothing
Using u
Dim a = 0
Dim f1 = Function() a
End Using
SyncLock u
Dim a = 0
Dim f1 = Function() a
End SyncLock
With u
Dim a = 0
Dim f1 = Function() a
End With
Select Case Q
Case 1
Dim a = 0
Dim f1 = Function() a
Case 2
Dim a = 0
Dim f1 = Function() a
Case Else
Dim a = 0
Dim f1 = Function() a
End Select
If True Then _
Dim a As Integer = Z(Function() a) _
Else Dim a As Integer = Z(Function() a)
If True Then
Dim a = 0
Dim f1 = Function() a
ElseIf False
Dim a = 0
Dim f1 = Function() a
Else
Dim a = 0
Dim f1 = Function() a
End If
Try
Dim a = 0
Dim f1 = Function() a
Catch ex As InvalidOperationException When Z(Function() ex) IsNot Nothing
Dim a = 0
Dim f1 = Function() a
Catch
Dim a = 0
Dim f1 = Function() a
Finally
Dim a = 0
Dim f1 = Function() a
End Try
End Sub
End Class
</file>
</compilation>
CompileAndVerify(source)
End Sub
<Fact>
Public Sub ObjectMemberInitializerClosure()
Dim source =
<compilation>
<file name="a.vb">
Imports System
Class C
Public Q As Integer
Shared Function Z(Of T)(f As Func(Of T)) As T
Return f()
End Function
Sub F()
Dim obj = New C With {.Q = Z(Function() .Q)}
End Sub
End Class
</file>
</compilation>
CompileAndVerify(source)
End Sub
<Fact>
Public Sub QueryRangeVariableClosures()
Dim source =
<compilation>
<file name="a.vb">
Imports System
Imports System.Linq
Class C
Function G(Of T)(f As Func(Of T)) As T
Return f()
End Function
Sub F()
Dim result = From c1 In {1}, c2 In {2}
Join c3 In {3} On G(Function() c3) Equals G(Function() c1) And G(Function() c3) Equals G(Function() c2)
Join c4 In {4} On G(Function() c4) Equals G(Function() c1) And G(Function() c4) Equals G(Function() c2)
Group Join c5 In {5} On G(Function() c5) Equals G(Function() c4) Into a1 = Count(G(Function() c1)), Group
Let e3 = G(Function() a1), e4 = G(Function() Group.First())
Group e4 = G(Function() e3), e5 = G(Function() e4 + 1) By e6 = G(Function() e3), e7 = G(Function() e4 + 2) Into a2 = Count(G(Function() e4 + 3)), a3 = LongCount(G(Function() e4 + 4))
Aggregate c6 In {6}, c7 In {7} From c8 In {8} Select G(Function() c6 + c7 + c8) Into a4 = Sum(G(Function() e6 + 9))
Where G(Function() e6) > 0
Take While G(Function() e6) > 0
Skip While G(Function() e6) > 0
Order By G(Function() e6), G(Function() e7)
Select e8 = G(Function() a2), e9 = G(Function() a3), e10 = G(Function() a4)
End Sub
End Class
</file>
</compilation>
CompileAndVerify(source)
End Sub
<Fact>
Public Sub QueryRangeVariableClosures_Aggregate()
Dim source =
<compilation>
<file name="a.vb">
Imports System
Imports System.Linq
Class C
Function G(Of T)(f As Func(Of T)) As T
Return f()
End Function
Sub F()
Dim result = From x In {1} Aggregate y In {2} Into Sum(x + y), z2 = Sum(x + y)
End Sub
End Class
</file>
</compilation>
CompileAndVerify(source)
End Sub
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册