Browse Source

Don't show 'method never returns' for iterators containing 'yield break;'

newNRvisualizers
Daniel Grunwald 13 years ago
parent
commit
9cdf7e71f9
  1. 4
      ICSharpCode.NRefactory.CSharp/Analysis/ReachabilityAnalysis.cs
  2. 34
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/MethodNeverReturnsIssue.cs
  3. 14
      ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/MethodNeverReturnsIssueTests.cs

4
ICSharpCode.NRefactory.CSharp/Analysis/ReachabilityAnalysis.cs

@ -78,6 +78,10 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -78,6 +78,10 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
}
}
public IEnumerable<Statement> ReachableStatements {
get { return reachableStatements; }
}
public bool IsReachable(Statement statement)
{
return reachableStatements.Contains(statement);

34
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/MethodNeverReturnsIssue.cs

@ -43,8 +43,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -43,8 +43,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
class GatherVisitor : GatherVisitorBase
{
readonly ControlFlowGraphBuilder cfgBuilder = new ControlFlowGraphBuilder ();
public GatherVisitor(BaseRefactoringContext ctx)
: base (ctx)
{
@ -58,30 +56,18 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -58,30 +56,18 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (methodDeclaration.Body.IsNull)
return;
var cfg = cfgBuilder.BuildControlFlowGraph (methodDeclaration.Body, ctx.Resolver,
ctx.CancellationToken);
var stack = new Stack<ControlFlowNode> ();
var visitedNodes = new HashSet<ControlFlowNode> ();
stack.Push (cfg [0]);
while (stack.Count > 0) {
var node = stack.Pop ();
// reach method's end
if (node.PreviousStatement == methodDeclaration.Body)
return;
// reach a return statement
if (node.NextStatement is ReturnStatement ||
node.NextStatement is ThrowStatement)
return;
foreach (var edge in node.Outgoing) {
if (visitedNodes.Add(edge.To))
stack.Push(edge.To);
var reachability = ctx.CreateReachabilityAnalysis(methodDeclaration.Body);
bool hasReachableReturn = false;
foreach (var statement in reachability.ReachableStatements) {
if (statement is ReturnStatement || statement is ThrowStatement || statement is YieldBreakStatement) {
hasReachableReturn = true;
break;
}
}
AddIssue (methodDeclaration.NameToken,
ctx.TranslateString ("Method never reaches its end or a 'return' statement."));
if (!hasReachableReturn && !reachability.IsEndpointReachable(methodDeclaration.Body)) {
AddIssue (methodDeclaration.NameToken,
ctx.TranslateString ("Method never reaches its end or a 'return' statement."));
}
}
}
}

14
ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/MethodNeverReturnsIssueTests.cs

@ -87,5 +87,19 @@ class TestClass @@ -87,5 +87,19 @@ class TestClass
}";
Test<MethodNeverReturnsIssue> (input, 1);
}
[Test]
public void YieldBreak ()
{
var input = @"
class TestClass
{
System.Collections.Generic.IEnumerable<string> TestMethod ()
{
yield break;
}
}";
Test<MethodNeverReturnsIssue> (input, 0);
}
}
}

Loading…
Cancel
Save