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
} }
} }
public IEnumerable<Statement> ReachableStatements {
get { return reachableStatements; }
}
public bool IsReachable(Statement statement) public bool IsReachable(Statement statement)
{ {
return reachableStatements.Contains(statement); return reachableStatements.Contains(statement);

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

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