From 9648890f61c0dadfa201a36c7964db693ad1f160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Fri, 28 Sep 2012 09:27:48 +0200 Subject: [PATCH] [CodeIssues] Fixed concurrency issue in variable reference graph. --- .../CodeIssues/MultipleEnumerationIssue.cs | 5 +-- .../CodeIssues/RedundantAssignmentIssue.cs | 2 +- .../Refactoring/VariableReferenceGraph.cs | 31 ++++++++++++++----- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/MultipleEnumerationIssue.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/MultipleEnumerationIssue.cs index 9ab54cd39e..7b5b79c770 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/MultipleEnumerationIssue.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/MultipleEnumerationIssue.cs @@ -241,12 +241,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring FindReferences (variableDecl, rootNode, resolveResult.Variable); var statements = AnalysisStatementCollector.Collect (variableDecl); + var builder = new VariableReferenceGraphBuilder (ctx); foreach (var statement in statements) { - var vrNode = VariableReferenceGraphBuilder.Build (statement, references, refStatements, ctx); + var vrNode = builder.Build (statement, references, refStatements, ctx); FindMultipleEnumeration (vrNode); } foreach (var lambda in lambdaExpressions) { - var vrNode = VariableReferenceGraphBuilder.Build (references, ctx.Resolver, (Expression)lambda.Body); + var vrNode = builder.Build (references, ctx.Resolver, (Expression)lambda.Body); FindMultipleEnumeration (vrNode); } } diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantAssignmentIssue.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantAssignmentIssue.cs index 96d56b23bd..af2e192431 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantAssignmentIssue.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantAssignmentIssue.cs @@ -121,7 +121,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring if (usedInLambda) return; - var startNode = VariableReferenceGraphBuilder.Build (rootStatement, references, refStatements, ctx); + var startNode = new VariableReferenceGraphBuilder (ctx).Build (rootStatement, references, refStatements, ctx); var variableInitializer = variableDecl as VariableInitializer; if (variableInitializer != null && !variableInitializer.Initializer.IsNull) startNode.References.Insert (0, variableInitializer); diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/VariableReferenceGraph.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/VariableReferenceGraph.cs index 29cb6767db..e53b740359 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/VariableReferenceGraph.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/VariableReferenceGraph.cs @@ -65,23 +65,30 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring class VariableReferenceGraphBuilder { - static ControlFlowGraphBuilder cfgBuilder = new ControlFlowGraphBuilder (); - static CfgVariableReferenceNodeBuilder cfgVrNodeBuilder = new CfgVariableReferenceNodeBuilder (); + ControlFlowGraphBuilder cfgBuilder = new ControlFlowGraphBuilder (); + CfgVariableReferenceNodeBuilder cfgVrNodeBuilder; + BaseRefactoringContext ctx; - public static VariableReferenceNode Build (ISet references, CSharpAstResolver resolver, + public VariableReferenceGraphBuilder(BaseRefactoringContext ctx) + { + this.ctx = ctx; + cfgVrNodeBuilder = new CfgVariableReferenceNodeBuilder (this); + } + + public VariableReferenceNode Build (ISet references, CSharpAstResolver resolver, Expression expression) { return ExpressionNodeCreationVisitor.CreateNode (references, resolver, new [] { expression }); } - public static VariableReferenceNode Build (Statement statement, ISet references, + public VariableReferenceNode Build (Statement statement, ISet references, ISet refStatements, BaseRefactoringContext context) { var cfg = cfgBuilder.BuildControlFlowGraph (statement, context.Resolver, context.CancellationToken); return cfgVrNodeBuilder.Build (cfg [0], references, refStatements, context.Resolver); } - public static VariableReferenceNode Build (Statement statement, ISet references, + public VariableReferenceNode Build (Statement statement, ISet references, ISet refStatements, CSharpAstResolver resolver, CancellationToken cancellationToken = default(CancellationToken)) { var cfg = cfgBuilder.BuildControlFlowGraph (statement, resolver, cancellationToken); @@ -169,13 +176,19 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring class CfgVariableReferenceNodeBuilder { - static GetExpressionsVisitor getExpr = new GetExpressionsVisitor (); + readonly VariableReferenceGraphBuilder variableReferenceGraphBuilder; + GetExpressionsVisitor getExpr = new GetExpressionsVisitor (); ISet references; ISet refStatements; CSharpAstResolver resolver; Dictionary nodeDict; + public CfgVariableReferenceNodeBuilder(VariableReferenceGraphBuilder variableReferenceGraphBuilder) + { + this.variableReferenceGraphBuilder = variableReferenceGraphBuilder; + } + public VariableReferenceNode Build (ControlFlowNode startNode, ISet references, ISet refStatements, CSharpAstResolver resolver) { @@ -214,6 +227,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring var node = new VariableReferenceNode (); var cfNode = startNode; while (true) { + if (variableReferenceGraphBuilder.ctx.CancellationToken.IsCancellationRequested) + return null; if (nodeDict.ContainsKey (cfNode)) { node.AddNextNode (nodeDict [cfNode]); break; @@ -246,12 +261,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring if (tryc != null) { VariableReferenceNode outNode = null; foreach (var n in tryc.CatchClauses) { - var catchNode = VariableReferenceGraphBuilder.Build(n.Body, references, refStatements, this.resolver); + 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); + var finallyNode = variableReferenceGraphBuilder.Build(tryc.FinallyBlock, references, refStatements, this.resolver); (outNode ?? node).AddNextNode (finallyNode); outNode = finallyNode; }