/// <summary> /// Visits the specified resource use statement. /// </summary> /// <param name="resourceUseStatement">The resource use statement.</param> public override void Visit(IResourceUseStatement resourceUseStatement) { ResourceUseStatement mutableResourceUseStatement = new ResourceUseStatement(resourceUseStatement); this.resultStatement = this.myCodeCopier.DeepCopy(mutableResourceUseStatement); }
/// <summary> /// Visits the specified resource use statement. /// </summary> /// <param name="resourceUseStatement">The resource use statement.</param> /// <returns></returns> protected virtual IStatement DeepCopy(ResourceUseStatement resourceUseStatement) { resourceUseStatement.ResourceAcquisitions = this.Substitute(resourceUseStatement.ResourceAcquisitions); resourceUseStatement.Body = this.Substitute(resourceUseStatement.Body); return resourceUseStatement; }
/// <summary> /// Looking for the pattern: /// IDisposable<T> variable = e; /// try { /// using_body /// } finally { /// if (variable != null) { /// variable.Dispose(); /// } /// } /// The type of the variable is *not* actually IDisposable, but some /// type that implements IDisposable. /// The assignment might be a local-declaration statement or else it /// might be an assignment statement. /// </summary> public override void TraverseChildren(IBlockStatement block) { Contract.Assume(block is BlockStatement); var decompiledBlock = (BlockStatement)block; var statements = decompiledBlock.Statements; for (int i = 2; i < statements.Count; ++i) { var tryFinally = statements[i] as TryCatchFinallyStatement; if (tryFinally == null) continue; var finallyBody = tryFinally.FinallyBody; if (finallyBody == null) continue; var finallyStatements = finallyBody.Statements; if (tryFinally.CatchClauses.Any()) continue; ILocalDefinition variable; IStatement resourceAcquisition; var variableDeclaration = statements[i - 2] as ILocalDeclarationStatement; if (variableDeclaration == null) { var es = statements[i - 2] as IExpressionStatement; if (es == null) continue; var assign = es.Expression as IAssignment; if (assign == null) continue; if (assign.Target.Instance != null) continue; var loc = assign.Target.Definition as ILocalDefinition; if (loc == null) continue; variable = loc; resourceAcquisition = es; } else { variable = variableDeclaration.LocalVariable; resourceAcquisition = variableDeclaration; } // finally block either looks like: // variable.Dispose(); // or // if (variable != null) variable.Dispose(); // or // iDisposableLocalVar := variable as IDisposable; // if (iDisposableLocalVar != null) iDisposableLocalVar.Dispose(); var c = finallyStatements.Count(); if (c == 1) { var expression = finallyStatements.Single() as IExpressionStatement; var isDispose = this.MatchMethodCall(expression.Expression, variable, "Dispose"); if (!isDispose) continue; } else if (c == 3 || c == 4) { IBoundExpression be; ILocalDefinition iDisposableVariable = variable; var index = 0; if (c == 4) { var es = finallyStatements.ElementAt(index++) as IExpressionStatement; if (es == null) continue; var assignment = es.Expression as IAssignment; if (assignment == null) continue; var castIfPossible = assignment.Source as ICastIfPossible; if (castIfPossible == null) continue; if (!TypeHelper.TypesAreEquivalent(castIfPossible.TargetType, this.IDisposable)) continue; be = castIfPossible.ValueToCast as IBoundExpression; if (be == null) continue; if (be.Instance != null) continue; if (be.Definition != variable) continue; if (assignment.Target.Instance != null) continue; iDisposableVariable = assignment.Target.Definition as ILocalDefinition; if (iDisposableVariable == null) continue; } var conditional = finallyStatements.ElementAt(index++) as IConditionalStatement; if (conditional == null) continue; var expressionStatement = finallyStatements.ElementAt(index++) as IExpressionStatement; if (expressionStatement == null) continue; var lableledStatement = finallyStatements.ElementAt(index++) as ILabeledStatement; if (lableledStatement == null) continue; var equality = conditional.Condition as IEquality; if (equality == null) continue; be = equality.LeftOperand as IBoundExpression; if (be == null) continue; if (be.Instance != null) continue; if (be.Definition != iDisposableVariable) continue; if (!(conditional.FalseBranch is IEmptyStatement)) continue; var gotoStatement = conditional.TrueBranch as IGotoStatement; if (gotoStatement == null) continue; if (gotoStatement.TargetStatement != lableledStatement) continue; var methodCall = expressionStatement.Expression as IMethodCall; if (methodCall == null) continue; var ct = methodCall.MethodToCall.ContainingType; if (!TypeHelper.TypesAreEquivalent(ct, this.IDisposable)) continue; } else { continue; } var resourceUse = new ResourceUseStatement() { Locations = tryFinally.Locations, ResourceAcquisitions = resourceAcquisition, Body = tryFinally.TryBody }; statements[i] = resourceUse; statements.RemoveAt(i - 2); i--; } base.TraverseChildren(block); }
/// <summary> /// Visits the specified resource use statement. /// </summary> /// <param name="resourceUseStatement">The resource use statement.</param> /// <returns></returns> public virtual IStatement Visit(ResourceUseStatement resourceUseStatement) { resourceUseStatement.ResourceAcquisitions = Visit(resourceUseStatement.ResourceAcquisitions); resourceUseStatement.Body = Visit(resourceUseStatement.Body); return resourceUseStatement; }
/// <summary> /// Rewrites the children of the given resource usage statement. /// </summary> public virtual void RewriteChildren(ResourceUseStatement resourceUseStatement) { this.RewriteChildren((Statement)resourceUseStatement); resourceUseStatement.ResourceAcquisitions = this.Rewrite(resourceUseStatement.ResourceAcquisitions); resourceUseStatement.Body = this.Rewrite(resourceUseStatement.Body); }
/// <summary> /// Visits the specified resource use statement. /// </summary> /// <param name="resourceUseStatement">The resource use statement.</param> public override void Visit(IResourceUseStatement resourceUseStatement) { ResourceUseStatement mutableResourceUseStatement = resourceUseStatement as ResourceUseStatement; if (alwaysMakeACopy || mutableResourceUseStatement == null) mutableResourceUseStatement = new ResourceUseStatement(resourceUseStatement); this.resultStatement = this.myCodeMutator.Visit(mutableResourceUseStatement); }