diff --git a/ICSharpCode.NRefactory.CSharp/Analysis/ReachabilityAnalysis.cs b/ICSharpCode.NRefactory.CSharp/Analysis/ReachabilityAnalysis.cs index ebb8d419d3..524966d7fb 100644 --- a/ICSharpCode.NRefactory.CSharp/Analysis/ReachabilityAnalysis.cs +++ b/ICSharpCode.NRefactory.CSharp/Analysis/ReachabilityAnalysis.cs @@ -78,6 +78,10 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis } } + public IEnumerable ReachableStatements { + get { return reachableStatements; } + } + public bool IsReachable(Statement statement) { return reachableStatements.Contains(statement); diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/MethodNeverReturnsIssue.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/MethodNeverReturnsIssue.cs index 68ae2e8529..44c08d3299 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/MethodNeverReturnsIssue.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/MethodNeverReturnsIssue.cs @@ -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 if (methodDeclaration.Body.IsNull) return; - var cfg = cfgBuilder.BuildControlFlowGraph (methodDeclaration.Body, ctx.Resolver, - ctx.CancellationToken); - var stack = new Stack (); - var visitedNodes = new HashSet (); - 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.")); + } } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/MethodNeverReturnsIssueTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/MethodNeverReturnsIssueTests.cs index 2e5e4f5c1f..58b4db6a5d 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/MethodNeverReturnsIssueTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/MethodNeverReturnsIssueTests.cs @@ -87,5 +87,19 @@ class TestClass }"; Test (input, 1); } + + [Test] + public void YieldBreak () + { + var input = @" +class TestClass +{ + System.Collections.Generic.IEnumerable TestMethod () + { + yield break; + } +}"; + Test (input, 0); + } } }