提交 a623e787 编写于 作者: P Petr Houska

Move invertIf to helpers + tests.

上级 da262c1c
......@@ -479,6 +479,123 @@ void Goo()
}");
}
[WorkItem(35525, "https://github.com/dotnet/roslyn/issues/35525")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInvertIf)]
public async Task TestMultiline_IfElseIfElseSelection1()
{
await TestInRegularAndScriptAsync(
@"class A
{
void Goo()
{
[|if (a)
{
a();
}
else if (b)
{
b();
}
else
{
c();
}|]
}
}",
@"class A
{
void Goo()
{
if (!a)
{
if (b)
{
b();
}
else
{
c();
}
}
else
{
a();
}
}
}");
}
[WorkItem(35525, "https://github.com/dotnet/roslyn/issues/35525")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInvertIf)]
public async Task TestMultiline_IfElseIfElseSelection2()
{
await TestInRegularAndScriptAsync(
@"class A
{
void Goo()
{
[|if (a)
{
a();
}|]
else if (b)
{
b();
}
else
{
c();
}
}
}",
@"class A
{
void Goo()
{
if (!a)
{
if (b)
{
b();
}
else
{
c();
}
}
else
{
a();
}
}
}");
}
[WorkItem(35525, "https://github.com/dotnet/roslyn/issues/35525")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInvertIf)]
public async Task TestMultilineMissing_IfElseIfElseSubSelection()
{
await TestMissingInRegularAndScriptAsync(
@"class A
{
void Goo()
{
if (a)
{
a();
}
[|else if (b)
{
b();
}
else
{
c();
}|]
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInvertIf)]
public async Task TestMultiline_IfElse()
{
......
......@@ -1187,5 +1187,83 @@ C LocalFunction(C c)
await TestMissingAsync<LocalDeclarationStatementSyntax>(testText);
}
#endregion
#region Test Ifs
[WorkItem(35525, "https://github.com/dotnet/roslyn/issues/35525")]
[Fact]
public async Task TestMultiline_IfElseIfElseSelection1()
{
await TestAsync<IfStatementSyntax>(
@"class A
{
void Goo()
{
{|result:[|if (a)
{
a();
}|]
else if (b)
{
b();
}
else
{
c();
}|}
}
}");
}
[WorkItem(35525, "https://github.com/dotnet/roslyn/issues/35525")]
[Fact]
public async Task TestMultiline_IfElseIfElseSelection2()
{
await TestAsync<IfStatementSyntax>(
@"class A
{
void Goo()
{
{|result:[|if (a)
{
a();
}
else if (b)
{
b();
}
else
{
c();
}|]|}
}
}");
}
[WorkItem(35525, "https://github.com/dotnet/roslyn/issues/35525")]
[Fact]
public async Task TestMissingMultiline_IfElseIfElseSelection()
{
await TestMissingAsync<IfStatementSyntax>(
@"class A
{
void Goo()
{
if (a)
{
a();
}
[|else if (b)
{
b();
}
else
{
c();
}|]
}
}");
}
#endregion
}
}
......@@ -58,13 +58,6 @@ protected override StatementSyntax GetEmptyEmbeddedStatement()
protected override StatementSyntax GetElseBody(IfStatementSyntax ifNode)
=> ifNode.Else.Statement;
protected override TextSpan GetHeaderSpan(IfStatementSyntax ifNode)
{
return TextSpan.FromBounds(
ifNode.IfKeyword.SpanStart,
ifNode.CloseParenToken.Span.End);
}
protected override bool CanControlFlowOut(SyntaxNode node)
{
switch (node.Kind())
......
......@@ -13,6 +13,9 @@ namespace Microsoft.CodeAnalysis.CodeRefactorings
{
internal abstract class AbstractRefactoringHelpersService : IRefactoringHelpersService
{
public async Task<TSyntaxNode> TryGetSelectedNodeAsync<TSyntaxNode>(CodeRefactoringContext context) where TSyntaxNode : SyntaxNode
=> await TryGetSelectedNodeAsync<TSyntaxNode>(context.Document, context.Span, context.CancellationToken).ConfigureAwait(false);
public async Task<TSyntaxNode> TryGetSelectedNodeAsync<TSyntaxNode>(
Document document, TextSpan selection, CancellationToken cancellationToken) where TSyntaxNode : SyntaxNode
{
......@@ -389,6 +392,12 @@ protected virtual IEnumerable<SyntaxNode> ExtractNodesIfInHeader(SyntaxNode root
{
yield return localDeclaration;
}
// Header: `if(...)`{ };
if (syntaxFacts.IsOnIfStatementHeader(root, location, out var ifStatement))
{
yield return ifStatement;
}
}
}
}
......@@ -34,5 +34,6 @@ internal interface IRefactoringHelpersService : ILanguageService
/// </para>
/// </summary>
Task<TSyntaxNode> TryGetSelectedNodeAsync<TSyntaxNode>(Document document, TextSpan selection, CancellationToken cancellationToken) where TSyntaxNode : SyntaxNode;
Task<TSyntaxNode> TryGetSelectedNodeAsync<TSyntaxNode>(CodeRefactoringContext context) where TSyntaxNode : SyntaxNode;
}
}
......@@ -37,30 +37,14 @@ private enum InvertIfStyle
public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
{
var textSpan = context.Span;
if (!textSpan.IsEmpty)
{
return;
}
var document = context.Document;
var cancellationToken = context.CancellationToken;
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var token = root.FindToken(textSpan.Start);
var ifNode = token.GetAncestor<TIfStatementSyntax>();
if (ifNode == null)
{
return;
}
if (ifNode.OverlapsHiddenPosition(cancellationToken))
{
return;
}
var helperService = document.GetLanguageService<IRefactoringHelpersService>();
var ifNode = await helperService.TryGetSelectedNodeAsync<TIfStatementSyntax>(context).ConfigureAwait(false);
var headerSpan = GetHeaderSpan(ifNode);
if (!headerSpan.IntersectsWith(textSpan))
if (ifNode == null || ifNode.OverlapsHiddenPosition(cancellationToken))
{
return;
}
......@@ -417,7 +401,6 @@ private ImmutableArray<StatementRange> GetSubsequentStatementRanges(TIfStatement
protected abstract StatementRange GetIfBodyStatementRange(TIfStatementSyntax ifNode);
protected abstract SyntaxNode GetCondition(TIfStatementSyntax ifNode);
protected abstract TextSpan GetHeaderSpan(TIfStatementSyntax ifNode);
protected abstract IEnumerable<TStatementSyntax> UnwrapBlock(TEmbeddedStatement ifBody);
protected abstract TEmbeddedStatement GetIfBody(TIfStatementSyntax ifNode);
......
......@@ -14,12 +14,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.InvertIf
Public Sub New()
End Sub
Protected Overrides Function GetHeaderSpan(ifNode As MultiLineIfBlockSyntax) As TextSpan
Return TextSpan.FromBounds(
ifNode.IfStatement.IfKeyword.SpanStart,
ifNode.IfStatement.Condition.Span.End)
End Function
Protected Overrides Function IsElseless(ifNode As MultiLineIfBlockSyntax) As Boolean
Return ifNode.ElseBlock Is Nothing
End Function
......
......@@ -14,12 +14,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.InvertIf
Public Sub New()
End Sub
Protected Overrides Function GetHeaderSpan(ifNode As SingleLineIfStatementSyntax) As TextSpan
Return TextSpan.FromBounds(
ifNode.IfKeyword.SpanStart,
ifNode.Condition.Span.End)
End Function
Protected Overrides Function IsElseless(ifNode As SingleLineIfStatementSyntax) As Boolean
Return ifNode.ElseClause Is Nothing
End Function
......
......@@ -1757,6 +1757,18 @@ public bool IsOnLocalDeclarationHeader(SyntaxNode root, int position, out Syntax
return IsOnHeader(position, node, node, holes: initializersExpressions);
}
public bool IsOnIfStatementHeader(SyntaxNode root, int position, out SyntaxNode ifStatement)
{
var node = TryGetAncestorForLocation<IfStatementSyntax>(position, root);
ifStatement = node;
if (ifStatement == null)
{
return false;
}
return IsOnHeader(position, node, node.CloseParenToken);
}
public bool IsBetweenTypeMembers(SourceText sourceText, SyntaxNode root, int position)
{
var token = root.FindToken(position);
......
......@@ -418,6 +418,7 @@ internal interface ISyntaxFactsService : ILanguageService
bool IsOnMethodHeader(SyntaxNode root, int position, out SyntaxNode method);
bool IsOnLocalFunctionHeader(SyntaxNode root, int position, out SyntaxNode localFunction);
bool IsOnLocalDeclarationHeader(SyntaxNode root, int position, out SyntaxNode localDeclaration);
bool IsOnIfStatementHeader(SyntaxNode root, int position, out SyntaxNode ifStatement);
bool IsBetweenTypeMembers(SourceText sourceText, SyntaxNode root, int position);
// Walks the tree, starting from contextNode, looking for the first construct
......
......@@ -1796,6 +1796,24 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return IsOnHeader(position, node, node, initializersExpressions)
End Function
Public Function IsOnIfStatementHeader(root As SyntaxNode, position As Integer, ByRef ifStatement As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsOnIfStatementHeader
ifStatement = Nothing
Dim multipleLineNode = TryGetAncestorForLocation(Of MultiLineIfBlockSyntax)(position, root)
If multipleLineNode IsNot Nothing Then
ifStatement = multipleLineNode
Return IsOnHeader(position, multipleLineNode.IfStatement, multipleLineNode.IfStatement)
End If
Dim singleLineNode = TryGetAncestorForLocation(Of SingleLineIfStatementSyntax)(position, root)
If singleLineNode IsNot Nothing Then
ifStatement = singleLineNode
Return IsOnHeader(position, singleLineNode, singleLineNode.Condition)
End If
Return False
End Function
Public Function IsBetweenTypeMembers(sourceText As SourceText, root As SyntaxNode, position As Integer) As Boolean Implements ISyntaxFactsService.IsBetweenTypeMembers
Dim token = root.FindToken(position)
Dim typeDecl = token.GetAncestor(Of TypeBlockSyntax)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册