Skip to content

Commit

Permalink
Fix code fix for CS0162
Browse files Browse the repository at this point in the history
  • Loading branch information
josefpihrt committed Apr 5, 2020
1 parent 6e7b27b commit 2f077da
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 9 deletions.
56 changes: 47 additions & 9 deletions src/CodeFixes/CSharp/CodeFixes/UnreachableCodeCodeFixProvider.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// Copyright (c) Josef Pihrt. All rights reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
Expand Down Expand Up @@ -68,18 +69,17 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
}
else
{
SyntaxRemoveOptions removeOptions = SyntaxRefactorings.DefaultRemoveOptions;
int lastIndex = statements.LastIndexOf(f => !f.IsKind(SyntaxKind.LocalFunctionStatement));

if (statement.GetLeadingTrivia().IsEmptyOrWhitespace())
removeOptions &= ~SyntaxRemoveOptions.KeepLeadingTrivia;
SyntaxList<StatementSyntax> nodes = RemoveRange(statements, index, lastIndex - index + 1, f => !f.IsKind(SyntaxKind.LocalFunctionStatement));

if (statements.Last().GetTrailingTrivia().IsEmptyOrWhitespace())
removeOptions &= ~SyntaxRemoveOptions.KeepTrailingTrivia;

return context.Document.RemoveNodesAsync(statements.Skip(index), removeOptions, cancellationToken);
return context.Document.ReplaceStatementsAsync(
statementsInfo,
nodes,
cancellationToken);
}
},
GetEquivalenceKey(diagnostic));
base.GetEquivalenceKey(diagnostic));

context.RegisterCodeFix(codeAction, diagnostic);
}
Expand Down Expand Up @@ -210,5 +210,43 @@ private CodeAction CreateCodeAction(Document document, Diagnostic diagnostic, If
},
GetEquivalenceKey(diagnostic));
}

//TODO: move to API
private SyntaxList<TNode> RemoveRange<TNode>(
SyntaxList<TNode> list,
int index,
int count,
Func<TNode, bool> predicate) where TNode : SyntaxNode
{
return SyntaxFactory.List(RemoveRange());

IEnumerable<TNode> RemoveRange()
{
SyntaxList<TNode>.Enumerator en = list.GetEnumerator();

int i = 0;

while (i < index
&& en.MoveNext())
{
yield return en.Current;
i++;
}

int endIndex = index + count;

while (i < endIndex
&& en.MoveNext())
{
if (!predicate(en.Current))
yield return en.Current;

i++;
}

while (en.MoveNext())
yield return en.Current;
}
}
}
}
88 changes: 88 additions & 0 deletions src/Tests/CodeFixes.Tests/CS0162UnreachableCodeDetectedTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,94 @@ int M()
return 0;
}
}
", equivalenceKey: EquivalenceKey.Create(DiagnosticId));
}

[Fact, Trait(Traits.CodeFix, CompilerDiagnosticIdentifiers.UnreachableCodeDetected)]
public async Task Test_LocalFunction()
{
await VerifyFixAsync(@"
class C
{
void M()
{
LF();
return;
LF();
void LF()
{
return;
}
}
}
", @"
class C
{
void M()
{
LF();
return;
void LF()
{
return;
}
}
}
", equivalenceKey: EquivalenceKey.Create(DiagnosticId));
}

[Fact, Trait(Traits.CodeFix, CompilerDiagnosticIdentifiers.UnreachableCodeDetected)]
public async Task Test_LocalFunction2()
{
await VerifyFixAsync(@"
class C
{
void M()
{
LF();
return;
LF();
void LF()
{
return;
}
LF2();
void LF2()
{
return;
}
}
}
", @"
class C
{
void M()
{
LF();
return;
void LF()
{
return;
}
void LF2()
{
return;
}
}
}
", equivalenceKey: EquivalenceKey.Create(DiagnosticId));
}
}
Expand Down

0 comments on commit 2f077da

Please sign in to comment.