From 9cdf7e71f9fd3247a15b4a73db37bea5cf358576 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 5 Oct 2012 00:18:36 +0200 Subject: [PATCH] Don't show 'method never returns' for iterators containing 'yield break;' --- .../Analysis/ReachabilityAnalysis.cs | 4 +++ .../CodeIssues/MethodNeverReturnsIssue.cs | 34 ++++++------------- .../MethodNeverReturnsIssueTests.cs | 14 ++++++++ 3 files changed, 28 insertions(+), 24 deletions(-) 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); + } } }