Ejemplo n.º 1
0
 private Statement ParseUsing(TokenSet followers)
   //^ requires this.currentToken == Token.Using;
   //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile;
 {
   SourceLocationBuilder slb = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken);
   this.GetNextToken();
   if (Parser.IdentifierOrNonReservedKeyword[this.currentToken]) {
     this.HandleError(Error.SyntaxError, "(");
     this.GetNextToken();
     if (this.currentToken == Token.Semicolon)
       this.GetNextToken();
     slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken);
     EmptyStatement es = new EmptyStatement(false, slb);
     this.SkipTo(followers);
     return es;
   }
   this.Skip(Token.LeftParenthesis);
   Statement resourceAcquisition = this.ParseExpressionStatementOrDeclaration(false, false, followers|Token.RightParenthesis|Parser.StatementStart, false);
   //^ assert resourceAcquisition is ExpressionStatement || resourceAcquisition is LocalDeclarationsStatement;
   this.Skip(Token.RightParenthesis);
   Statement body = this.ParseStatement(followers);
   slb.UpdateToSpan(body.SourceLocation);
   Statement result = new ResourceUseStatement(resourceAcquisition, body, slb);
   //^ assume followers[this.currentToken] || this.currentToken == Token.EndOfFile;
   return result;
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Looking for the pattern:
        /// IDisposable&lt;T&gt; 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);
        }