提交 4045852b 编写于 作者: C chandera

Expose the compiler's helper to find ConditionalAccessExpressions at the...

Expose the compiler's helper to find ConditionalAccessExpressions at the Workspace layer. 1113971 tracks making this a public API in the compiler. (changeset 1411035)
上级 fcac7546
......@@ -5319,7 +5319,64 @@ End Module
VerifyItemExists(text, "ToString")
End Sub
<WorkItem(1079694)>
<WorkItem(1109319)>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Sub UnwrapNullableForConditionalFromStructure()
Dim text =
<code><![CDATA[
Module Program
Sub Main(args As String())
Dim x As A
x?.$$b?.c
End Sub
End Module
Structure A
Public b As B
End Structure
Public Class B
Public c As C
End Class
Public Class C
End Class
]]></code>.Value
VerifyItemExists(text, "b")
VerifyItemIsAbsent(text, "c")
End Sub
<WorkItem(1109319)>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Sub WithinChainOfConditionalAccess()
Dim text =
<code><![CDATA[
Module Program
Sub Main(args As String())
Dim x As A
x?.$$b?.c
End Sub
End Module
Class A
Public b As B
End Class
Public Class B
Public c As C
End Class
Public Class C
End Class
]]></code>.Value
VerifyItemExists(text, "b")
VerifyItemIsAbsent(text, "c")
End Sub
<WorkItem(1079694)>
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Sub DontThrowForNullPropagatingOperatorOnTypeParameter()
Dim text =
......
......@@ -68,15 +68,27 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
End Function
<Extension>
Public Function GetExpressionOfMemberAccessExpression(memberAccessExpression As MemberAccessExpressionSyntax) As ExpressionSyntax
If memberAccessExpression Is Nothing Then
Return Nothing
End If
<Extension>
Public Function GetExpressionOfMemberAccessExpression(memberAccessExpression As MemberAccessExpressionSyntax) As ExpressionSyntax
If memberAccessExpression Is Nothing Then
Return Nothing
End If
If memberAccessExpression.Expression IsNot Nothing Then
Return memberAccessExpression.Expression
End If
If memberAccessExpression.Expression IsNot Nothing Then
Return memberAccessExpression.Expression
End If
' Maybe we're part of a ConditionalAccessExpression
Dim conditional = memberAccessExpression.GetCorrespondingConditionalAccessExpression()
If conditional IsNot Nothing Then
If conditional.Parent.IsKind(SyntaxKind.ExpressionStatement) AndAlso conditional.Parent.Parent.IsKind(SyntaxKind.WithBlock) AndAlso
conditional.Expression Is Nothing Then
Return DirectCast(conditional.Parent.Parent, WithBlockSyntax).WithStatement.Expression
End If
Return conditional.Expression
End If
' we have a member access expression with a null expression, this may be one of the
' following forms:
......@@ -84,33 +96,26 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
' 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
' 4) With obj : ?.m <-- .m refers to the obj type
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)
ElseIf current.IsKind(SyntaxKind.ConditionalAccessExpression) Then
Dim conditionalAccess = DirectCast(current, ConditionalAccessExpressionSyntax)
If conditionalAccess.Expression IsNot Nothing Then
Return conditionalAccess.Expression
End If
End If
current = current.Parent
End While
Return Nothing
End Function
End Module
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
Return Nothing
End Function
End Module
End Namespace
......@@ -1085,23 +1085,77 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
Return SpecializedCollections.EmptyEnumerable(Of SyntaxNode)()
End Function
<Extension()>
Public Iterator Function GetAliasImportsClauses(root As CompilationUnitSyntax) As IEnumerable(Of SimpleImportsClauseSyntax)
For i = 0 To root.Imports.Count - 1
Dim statement = root.Imports(i)
For j = 0 To statement.ImportsClauses.Count - 1
Dim importsClause = statement.ImportsClauses(j)
If importsClause.Kind = SyntaxKind.SimpleImportsClause Then
Dim simpleImportsClause = DirectCast(importsClause, SimpleImportsClauseSyntax)
If simpleImportsClause.Alias IsNot Nothing Then
Yield simpleImportsClause
End If
End If
Next
Next
End Function
End Module
<Extension()>
Public Iterator Function GetAliasImportsClauses(root As CompilationUnitSyntax) As IEnumerable(Of SimpleImportsClauseSyntax)
For i = 0 To root.Imports.Count - 1
Dim statement = root.Imports(i)
For j = 0 To statement.ImportsClauses.Count - 1
Dim importsClause = statement.ImportsClauses(j)
If importsClause.Kind = SyntaxKind.SimpleImportsClause Then
Dim simpleImportsClause = DirectCast(importsClause, SimpleImportsClauseSyntax)
If simpleImportsClause.Alias IsNot Nothing Then
Yield simpleImportsClause
End If
End If
Next
Next
End Function
''' <summary>
''' Given an expression within a tree of <see cref="ConditionalAccessExpressionSyntax"/>s,
''' finds the <see cref="ConditionalAccessExpressionSyntax"/> that it is part of.
''' </summary>
''' <param name="node"></param>
''' <returns></returns>
<Extension>
Friend Function GetCorrespondingConditionalAccessExpression(node As ExpressionSyntax) As ConditionalAccessExpressionSyntax
Dim access As SyntaxNode = node
Dim parent As SyntaxNode = access.Parent
While parent IsNot Nothing
Select Case parent.Kind
Case SyntaxKind.DictionaryAccessExpression,
SyntaxKind.SimpleMemberAccessExpression
If DirectCast(parent, MemberAccessExpressionSyntax).Expression IsNot access Then
Return Nothing
End If
Case SyntaxKind.XmlElementAccessExpression,
SyntaxKind.XmlDescendantAccessExpression,
SyntaxKind.XmlAttributeAccessExpression
If DirectCast(parent, XmlMemberAccessExpressionSyntax).Base IsNot access Then
Return Nothing
End If
Case SyntaxKind.InvocationExpression
If DirectCast(parent, InvocationExpressionSyntax).Expression IsNot access Then
Return Nothing
End If
Case SyntaxKind.ConditionalAccessExpression
Dim conditional = DirectCast(parent, ConditionalAccessExpressionSyntax)
If conditional.WhenNotNull Is access Then
Return conditional
ElseIf conditional.Expression IsNot access Then
Return Nothing
End If
Case Else
Return Nothing
End Select
access = parent
parent = access.Parent
End While
Return Nothing
End Function
End Module
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册