|
|
|
@ -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.")); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|