From 1a80006cacb793dfbbd5a55015f8ef2f405f276d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Thu, 30 Aug 2012 10:06:22 +0200 Subject: [PATCH] [CodeIssues] Fixed an issue with try/catch statement in redundant assignment issue. --- .../Refactoring/VariableReferenceGraph.cs | 37 ++++++++++++++-- .../RedundantAssignmentIssueTests.cs | 44 +++++++++++++++++++ 2 files changed, 78 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/VariableReferenceGraph.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/VariableReferenceGraph.cs index 0a687f6260..56f99e3a17 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/VariableReferenceGraph.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/VariableReferenceGraph.cs @@ -28,6 +28,7 @@ using System.Collections.Generic; using System.Linq; using ICSharpCode.NRefactory.CSharp.Analysis; using ICSharpCode.NRefactory.CSharp.Resolver; +using System.Threading; namespace ICSharpCode.NRefactory.CSharp.Refactoring { @@ -80,6 +81,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring return cfgVrNodeBuilder.Build (cfg [0], references, refStatements, context.Resolver); } + public static VariableReferenceNode Build (Statement statement, ISet references, + ISet refStatements, CSharpAstResolver resolver, CancellationToken cancellationToken = default(CancellationToken)) + { + var cfg = cfgBuilder.BuildControlFlowGraph (statement, resolver, cancellationToken); + return cfgVrNodeBuilder.Build (cfg [0], references, refStatements, resolver); + } + class GetExpressionsVisitor : DepthFirstAstVisitor> { @@ -153,6 +161,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring yield return yieldReturnStatement.Expression; } + public override IEnumerable VisitBlockStatement(BlockStatement blockStatement) + { + yield break; + } } class CfgVariableReferenceNodeBuilder @@ -216,16 +228,36 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring } nodeDict [cfNode] = node; - if (IsValidControlFlowNode (cfNode) && refStatements.Contains (cfNode.NextStatement)) + if (IsValidControlFlowNode (cfNode) && refStatements.Contains (cfNode.NextStatement)) { node = GetStatementEndNode (node, cfNode.NextStatement); + } if (cfNode.Outgoing.Count == 1) { cfNode = cfNode.Outgoing [0].To; } else { - foreach (var e in cfNode.Outgoing) + foreach (var e in cfNode.Outgoing) { node.AddNextNode (AddNode (e.To)); + } break; } + + // Hack for handling try ... catch ... finally. + var tryc = cfNode.NextStatement as TryCatchStatement; + if (tryc != null) { + VariableReferenceNode outNode = null; + foreach (var n in tryc.CatchClauses) { + var catchNode = VariableReferenceGraphBuilder.Build(n.Body, references, refStatements, this.resolver); + (outNode ?? node).AddNextNode (catchNode); + outNode = catchNode; + } + if (!tryc.FinallyBlock.IsNull) { + var finallyNode = VariableReferenceGraphBuilder.Build(tryc.FinallyBlock, references, refStatements, this.resolver); + (outNode ?? node).AddNextNode (finallyNode); + outNode = finallyNode; + } + if (outNode != null) + return outNode; + } } return nodeDict [startNode]; } @@ -282,7 +314,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring } #region Skipped Expressions - public override void VisitAnonymousMethodExpression (AnonymousMethodExpression anonymousMethodExpression) { } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/RedundantAssignmentIssueTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/RedundantAssignmentIssueTests.cs index b111864055..934d1435f8 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/RedundantAssignmentIssueTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/RedundantAssignmentIssueTests.cs @@ -290,5 +290,49 @@ class TestClass }"; Test (input, 0); } + + + + [Test] + public void TestAssignmentInTryCatch () + { + var input = @"using System; +class TestClass +{ + void TestMethod () + { + var a = new TestClass (); + try { + a = null; + } catch (Exception) { + if (a != null) { + a.TestMethod (); + } + } + } +}"; + Test (input, 0); + } + + [Test] + public void TestAssignmentInTryCatchFinally () + { + var input = @" +class TestClass +{ + void TestMethod () + { + var a = new TestClass (); + try { + a = null; + } finally { + if (a != null) { + a.TestMethod (); + } + } + } +}"; + Test (input, 0); + } } }