Beispiel #1
0
        private static void GenerateTryCatchFinallyStatement(ScriptGenerator generator, MemberSymbol symbol,
                                                             TryCatchFinallyStatement statement)
        {
            ScriptTextWriter writer = generator.Writer;

            writer.WriteLine("try {");
            writer.Indent++;
            GenerateStatement(generator, symbol, statement.Body);
            writer.Indent--;
            writer.WriteLine("}");

            if (statement.Catch != null)
            {
                writer.Write("catch (");
                writer.Write(statement.ExceptionVariable.GeneratedName);
                writer.WriteLine(") {");
                writer.Indent++;
                GenerateStatement(generator, symbol, statement.Catch);
                writer.Indent--;
                writer.WriteLine("}");
            }

            if (statement.Finally != null)
            {
                writer.WriteLine("finally {");
                writer.Indent++;
                GenerateStatement(generator, symbol, statement.Finally);
                writer.Indent--;
                writer.WriteLine("}");
            }
        }
Beispiel #2
0
        static public TryCatchFinallyStatement Guard(Type expectedExceptionType)
        {
            TryCatchFinallyStatement try_ = Try();

            try_.CatchClauses.Add(Catch(expectedExceptionType, ""));
            return(try_);
        }
 private void RemoveUnconditionalBranchesToLabelImmediatelyFollowing(TryCatchFinallyStatement trycf, DecompiledBlock followingBlock)
 {
     Contract.Requires(trycf != null);
     while (followingBlock != null)
     {
         if (followingBlock.Statements.Count == 0)
         {
             return;
         }
         var label = followingBlock.Statements[0] as LabeledStatement;
         if (label != null)
         {
             this.unconditionalBranchRemover.StopTraversal = false;
             this.unconditionalBranchRemover.targetLabel   = label;
             this.unconditionalBranchRemover.Traverse(trycf);
             var gotos = this.gotosThatTarget.Find((uint)label.Label.UniqueKey);
             if (gotos == null || gotos.Count == 0)
             {
                 followingBlock.Statements.RemoveAt(0);
             }
             return;
         }
         followingBlock = followingBlock.Statements[0] as DecompiledBlock;
     }
 }
        // TODO: Wait until Roslyn gets this implemented
        public override IStatement VisitTryStatement(TryStatementSyntax node)
        {
            var catches = new List <ICatchClause>();

            foreach (var c in node.Catches)
            {
                var c_prime = new CatchClause()
                {
                    //Body = MkBlockStatement(this.Visit(c.Block, arg)),
                };
                if (c.Declaration != null)
                {
                    var cDecl = c.Declaration;
                }
            }
            var tcf = new TryCatchFinallyStatement()
            {
                CatchClauses = catches,
                Locations    = Helper.SourceLocation(this.tree, node),
                TryBody      = Helper.MkBlockStatement(this.Visit(node.Block)),
            };

            if (node.Finally != null)
            {
                tcf.FinallyBody = Helper.MkBlockStatement(this.Visit(node.Finally.Block));
            }
            return(tcf);
        }
        internal TryCatchReplacer(SourceMethodBody sourceMethodBody, DecompiledBlock block)
        {
            Contract.Requires(sourceMethodBody != null);
            Contract.Requires(block != null);
            this.host            = sourceMethodBody.host; Contract.Assume(sourceMethodBody.host != null);
            this.gotosThatTarget = sourceMethodBody.gotosThatTarget; Contract.Assume(this.gotosThatTarget != null);
            this.unconditionalBranchRemover.gotosThatTarget = sourceMethodBody.gotosThatTarget;

            Contract.Assume(sourceMethodBody.ilMethodBody != null);
            foreach (var exInfo in sourceMethodBody.ilMethodBody.OperationExceptionInformation)
            {
                var tryCatchF = this.tryCatchFinallyMap.Find(exInfo.TryStartOffset, exInfo.TryEndOffset);
                if (tryCatchF == null)
                {
                    tryCatchF = new TryCatchFinallyStatement();
                    this.tryCatchFinallyMap.Add(exInfo.TryStartOffset, exInfo.TryEndOffset, tryCatchF);
                }
                if (exInfo.HandlerKind == HandlerKind.Filter)
                {
                    this.tryCatchFinallyMap.Add(exInfo.FilterDecisionStartOffset, exInfo.HandlerEndOffset, tryCatchF);
                    this.handlerMap.Add(exInfo.FilterDecisionStartOffset, exInfo.HandlerEndOffset, exInfo);
                }
                this.tryCatchFinallyMap.Add(exInfo.HandlerStartOffset, exInfo.HandlerEndOffset, tryCatchF);
                this.handlerMap.Add(exInfo.HandlerStartOffset, exInfo.HandlerEndOffset, exInfo);
            }
        }
Beispiel #6
0
        private Statement ProcessTryCatchFinallyStatement(TryNode node)
        {
            Debug.Assert(node.CatchClauses.Count < 2);
            Debug.Assert(node.CatchClauses.Count == 1 || node.FinallyClause != null);

            TryCatchFinallyStatement statement = new TryCatchFinallyStatement();

            Statement body = BuildStatement((StatementNode)node.Body);

            statement.AddBody(body);

            if (node.CatchClauses.Count == 1)
            {
                CatchNode catchNode = (CatchNode)node.CatchClauses[0];

                VariableSymbol exceptionVariableSymbol = null;

                if (catchNode.Name != null)
                {
                    TypeSymbol exceptionVariableType =
                        symbolSet.ResolveType(catchNode.Type, symbolTable, memberContext);
                    Debug.Assert(exceptionVariableType != null);

                    exceptionVariableSymbol =
                        new VariableSymbol(catchNode.Name.Name, memberContext, exceptionVariableType);
                }
                else
                {
                    TypeSymbol exceptionVariableType =
                        symbolSet.ResolveIntrinsicType(IntrinsicType.Exception);
                    Debug.Assert(exceptionVariableType != null);

                    exceptionVariableSymbol =
                        new VariableSymbol(symbolTable.CreateSymbolName("e"), memberContext, exceptionVariableType);
                }

                symbolTable.PushScope();
                symbolTable.AddSymbol(exceptionVariableSymbol);

                Statement catchStatement = BuildStatement((StatementNode)catchNode.Body);
                statement.AddCatch(exceptionVariableSymbol, catchStatement);

                symbolTable.PopScope();
            }

            if (node.FinallyClause != null)
            {
                Statement finallyStatement = BuildStatement((StatementNode)node.FinallyClause);
                statement.AddFinally(finallyStatement);
            }

            return(statement);
        }
Beispiel #7
0
            public override IStatement Rewrite(ITryCatchFinallyStatement operation)
            {
                _log.Info("Rewriting ITryCatchFinallyStatement: " + operation + " Pass: "******"Finally")
                {
                    tryCatch.FinallyBody = null;
                }
                else
                {
                    tryCatch.CatchClauses.RemoveAt(int.Parse(MutationTarget.PassInfo));
                }
                return(tryCatch);
            }
Beispiel #8
0
            public override IStatement Rewrite(ITryCatchFinallyStatement operation)
            {
                _log.Info("Rewriting ITryCatchFinallyStatement: " + operation + " Pass: " + MutationTarget.PassInfo);
                var systemException = CurrentMethod.ContainingTypeDefinition.PlatformType.SystemException;
                var tryCatch        = new TryCatchFinallyStatement(operation);

                tryCatch.CatchClauses.Add(new CatchClause
                {
                    ExceptionType = systemException,
                    Body          = new BlockStatement()
                    {
                        Statements = new List <IStatement> {
                            new EmptyStatement()
                        },
                    }
                });
                return(tryCatch);
            }
Beispiel #9
0
        private void DecompileTryBody(BasicBlock b, BasicBlock firstHandler, TryCatchFinallyStatement tryStatement)
        {
            tryStatement.TryBody = GetBasicBlockUpto(b, firstHandler.StartOffset);
            BasicBlock tryBody    = tryStatement.TryBody as BasicBlock;
            int        startPoint = 0;

            if (tryBody != null && tryBody.Statements.Count > 0)
            {
                ILabeledStatement labeledStatement = tryBody.Statements[0] as ILabeledStatement;
                if (labeledStatement != null)
                {
                    tryBody.Statements.RemoveAt(0);
                    b.Statements.Insert(startPoint, labeledStatement);
                    startPoint++;
                }
            }
            b.Statements.Insert(startPoint, tryStatement);
        }
 private void ConsolidateScopes(TryCatchFinallyStatement trycf)
 {
     Contract.Requires(trycf != null);
     ConsolidateScopes((DecompiledBlock)trycf.TryBody);
     if (trycf.FaultBody != null)
     {
         ConsolidateScopes((DecompiledBlock)trycf.FaultBody);
     }
     if (trycf.FinallyBody != null)
     {
         ConsolidateScopes((DecompiledBlock)trycf.FinallyBody);
     }
     foreach (var catchClause in trycf.CatchClauses)
     {
         Contract.Assume(catchClause != null);
         var cb = (DecompiledBlock)catchClause.Body;
         ConsolidateScopes(cb);
     }
 }
Beispiel #11
0
 protected override void Traverse(BasicBlock b)
 {
     if (b.NumberOfTryBlocksStartingHere > 0)
     {
         BasicBlock firstHandler = null;
         TryCatchFinallyStatement /*?*/ tryStatement = new TryCatchFinallyStatement();
         BasicBlock bb = b;
         while (b.NumberOfTryBlocksStartingHere-- > 0)
         {
             if (bb.Statements.Count > 0)
             {
                 BasicBlock bbb = bb.Statements[bb.Statements.Count - 1] as BasicBlock;
                 while (bbb != null)
                 {
                     if (bbb.ExceptionInformation != null)
                     {
                         if (firstHandler == null)
                         {
                             firstHandler = bbb;
                         }
                         if (firstHandler.ExceptionInformation.TryEndOffset < bbb.ExceptionInformation.TryEndOffset)
                         {
                             DecompileTryBody(b, firstHandler, tryStatement);
                             tryStatement = new TryCatchFinallyStatement();
                             firstHandler = bbb;
                         }
                         DecompileHandler(bb, bbb, tryStatement);
                         break;
                     }
                     if (bbb.Statements.Count == 0)
                     {
                         break;
                     }
                     bb  = bbb;
                     bbb = bbb.Statements[bbb.Statements.Count - 1] as BasicBlock;
                 }
             }
         }
         DecompileTryBody(b, firstHandler, tryStatement);
     }
 }
        public void CSharpCodeGenerator_Try_Finally()
        {
            var statement = new TryCatchFinallyStatement
            {
                Try     = new SnippetStatement("TrySnippet"),
                Finally = new SnippetStatement("FinallyStatement")
            };

            var generator = new CSharpCodeGenerator();
            var result    = generator.Write(statement);

            Assert.That.StringEquals(@"try
{
    TrySnippet
}
finally
{
    FinallyStatement
}
", result);
        }
        public void CSharpCodeGenerator_Try_Catch()
        {
            var statement = new TryCatchFinallyStatement();

            statement.Try   = new SnippetStatement("TrySnippet");
            statement.Catch = new CatchClauseCollection();
            statement.Catch.Add(new CatchClause()
            {
                Body = new SnippetStatement("Catch1")
            });

            var generator = new CSharpCodeGenerator();
            var result    = generator.Write(statement);

            Assert.That.StringEquals(@"try
{
    TrySnippet
}
catch
{
    Catch1
}
", result);
        }
        public void CSharpCodeGenerator_Try_Catch_WithException()
        {
            var statement = new TryCatchFinallyStatement();

            statement.Try   = new SnippetStatement("TrySnippet");
            statement.Catch = new CatchClauseCollection();
            statement.Catch.Add(new CatchClause()
            {
                ExceptionType         = typeof(NotImplementedException),
                ExceptionVariableName = "nie",
                Body = new SnippetStatement("Catch1")
            });
            statement.Catch.Add(new CatchClause()
            {
                ExceptionType         = typeof(Exception),
                ExceptionVariableName = "ex",
                Body = new ThrowStatement()
            });

            var generator = new CSharpCodeGenerator();
            var result    = generator.Write(statement);

            Assert.That.StringEquals(@"try
{
    TrySnippet
}
catch (System.NotImplementedException nie)
{
    Catch1
}
catch (System.Exception ex)
{
    throw;
}
", result);
        }
Beispiel #15
0
 public virtual void VisitTryCatchFinallyStatement(TryCatchFinallyStatement tryCatchFinallyStatement)
 {
     VisitBlock(tryCatchFinallyStatement.TryBlock);
     VisitBlock(tryCatchFinallyStatement.CatchBlock);
     VisitBlock(tryCatchFinallyStatement.FinallyBlock);
 }
Beispiel #16
0
 private static void DecompileHandler(BasicBlock containingBlock, BasicBlock handlerBlock, TryCatchFinallyStatement tryStatement)
 {
     if (handlerBlock.ExceptionInformation.HandlerKind == HandlerKind.Finally)
     {
         tryStatement.FinallyBody = handlerBlock;
     }
     else if (handlerBlock.ExceptionInformation.HandlerKind == HandlerKind.Fault)
     {
         tryStatement.FaultBody = handlerBlock;
     }
     else
     {
         CatchClause catchClause = new CatchClause();
         catchClause.Body          = handlerBlock;
         catchClause.ExceptionType = handlerBlock.ExceptionInformation.ExceptionType;
         if (handlerBlock.ExceptionInformation.HandlerKind == HandlerKind.Catch)
         {
             catchClause.ExceptionContainer = ExtractExceptionContainer(handlerBlock);
         }
         else if (handlerBlock.ExceptionInformation.HandlerKind == HandlerKind.Filter)
         {
             catchClause.FilterCondition = ExtractFilterCondition(handlerBlock);
         }
         tryStatement.CatchClauses.Add(catchClause);
     }
     //Remove handler from statements in containing block
     containingBlock.Statements[containingBlock.Statements.Count - 1] = GetBasicBlockStartingAt(handlerBlock, handlerBlock.ExceptionInformation.HandlerEndOffset);
     RemoveEndFinally(handlerBlock);
 }
        private static MethodDeclaration GenerateMethod(ClassDeclaration clientClass, Method method, TypeReference requestType)
        {
            var m = clientClass.AddMember(new MethodDeclaration(method.MethodGroup.Name + '_' + GetMethodName(method)));

            m.SetData("Method", method);
            var buildUrlMethod = GenerateBuildUrlMethod(clientClass, method, requestType);

            GenerateMethodSignature(method, m, requestType, out var requestArgument, out var requestOptionsArgument, out var cancellationTokenArgument);
            m.Modifiers = Modifiers.Private;
            if (method.MethodType != MethodType.GetPaged)
            {
                m.Modifiers |= Modifiers.Async;
            }

            // Method body
            m.Statements = new StatementCollection();

            // 1. Create url from parameters
            var buildUrlExpression = new MethodInvokeExpression(new MemberReferenceExpression(new TypeReference(clientClass), buildUrlMethod));

            if (buildUrlMethod.Arguments.Count > 0)
            {
                buildUrlExpression.Arguments.Add(requestArgument);
            }

            var urlVariable = new VariableDeclarationStatement(typeof(string), "url", buildUrlExpression);

            m.Statements.Add(urlVariable);

            if (method.MethodType == MethodType.GetPaged)
            {
                // return new Meziantou.GitLab.PagedResponse<MergeRequest>(this, url, requestOptions);
                m.Statements.Add(new ReturnStatement(new NewObjectExpression(m.ReturnType !.Clone(), new ThisExpression(), urlVariable, requestOptionsArgument)));
            }
            else
            {
                // 2. Create HttpRequestMessage object
                var requestVariable = new VariableDeclarationStatement(typeof(HttpRequestMessage), "requestMessage", new NewObjectExpression(typeof(HttpRequestMessage)));
                var usingStatement  = new UsingStatement()
                {
                    Statement = requestVariable, Body = new StatementCollection()
                };
                m.Statements.Add(usingStatement);
                var statements = usingStatement.Body;

                statements.Add(new AssignStatement(new MemberReferenceExpression(requestVariable, nameof(HttpRequestMessage.Method)), GetHttpMethod(method.MethodType)));
                statements.Add(new AssignStatement(new MemberReferenceExpression(requestVariable, nameof(HttpRequestMessage.RequestUri)), new NewObjectExpression(typeof(Uri), urlVariable, new MemberReferenceExpression(typeof(UriKind), nameof(UriKind.RelativeOrAbsolute)))));

                CreateBodyArgument(method, statements, requestArgument, requestVariable);

                // 3. Send request
                // var response = await SendAsync(request, options, cancellationToken).ConfigureAwait(false);
                var responseVariable = new VariableDeclarationStatement(WellKnownTypes.HttpResponseTypeReference.MakeNullable(), "response", LiteralExpression.Null());
                statements.Add(responseVariable);
                var responseTry = new TryCatchFinallyStatement()
                {
                    Try = new StatementCollection()
                };
                statements.Add(responseTry);
                responseTry.Try.Add(new AssignStatement(responseVariable, new AwaitExpression(new MethodInvokeExpression(new MemberReferenceExpression(new ThisExpression(), "SendAsync"), requestVariable, requestOptionsArgument, cancellationTokenArgument)).ConfigureAwait(false)));

                // Dispose reponse in catch if Stream or in finally if not stream
                var disposeReponseStatements = new ConditionStatement()
                {
                    Condition      = new BinaryExpression(BinaryOperator.NotEquals, responseVariable, LiteralExpression.Null()),
                    TrueStatements = responseVariable.CreateInvokeMethodExpression("Dispose"),
                };

                if (method.ReturnType == ModelRef.File)
                {
                    responseTry.Catch = new CatchClauseCollection
                    {
                        new CatchClause()
                        {
                            Body = disposeReponseStatements,
                        },
                    };

                    responseTry.Catch[0].Body.Add(new ThrowStatement());
                }
                else
                {
                    responseTry.Finally = disposeReponseStatements;
                }

                // 4. Convert and return response object
                //    if (response.StatusCode == HttpStatusCode.NotFound) return default;
                if (method.MethodType == MethodType.Get)
                {
                    responseTry.Try.Add(new ConditionStatement()
                    {
                        Condition      = new BinaryExpression(BinaryOperator.Equals, responseVariable.CreateMemberReferenceExpression("StatusCode"), new MemberReferenceExpression(typeof(HttpStatusCode), "NotFound")),
                        TrueStatements = new ReturnStatement(new DefaultValueExpression()),
                    });
                }

                // await response.EnsureStatusCodeAsync(cancellationToken).ConfigureAwait(false);
                responseTry.Try.Add(new AwaitExpression(new MethodInvokeExpression(new MemberReferenceExpression(responseVariable, "EnsureStatusCodeAsync"), cancellationTokenArgument)).ConfigureAwait(false));

                if (method.ReturnType != null)
                {
                    // var result = await response.ToObjectAsync<T>(cancellationToken).ConfigureAwait(false);
                    var resultVariable = new VariableDeclarationStatement(m.ReturnType.Parameters[0].MakeNullable(), "result");
                    responseTry.Try.Add(resultVariable);
                    if (method.MethodType == MethodType.Get && method.ReturnType == ModelRef.File)
                    {
                        resultVariable.InitExpression = new AwaitExpression(responseVariable.CreateInvokeMethodExpression("ToStreamAsync", cancellationTokenArgument)).ConfigureAwait(false);
                    }
                    else if (method.MethodType == MethodType.GetCollection)
                    {
                        resultVariable.InitExpression = new AwaitExpression(responseVariable.CreateInvokeMethodExpression("ToCollectionAsync", new TypeReference[] { method.ReturnType.ToPropertyTypeReference() }, cancellationTokenArgument)).ConfigureAwait(false);
                    }
                    else
                    {
                        resultVariable.InitExpression = new AwaitExpression(responseVariable.CreateInvokeMethodExpression("ToObjectAsync", new TypeReference[] { method.ReturnType.ToPropertyTypeReference() }, cancellationTokenArgument)).ConfigureAwait(false);
                    }

                    // if (result is null)
                    //   throw new GitLabException(response.RequestMethod, response.RequestUri, response.StatusCode, $"The response cannot be converted to '{typeof(T)}' because the body is null or empty");
                    if (method.MethodType != MethodType.Get)
                    {
                        responseTry.Try.Add(new ConditionStatement()
                        {
                            Condition      = new BinaryExpression(BinaryOperator.Equals, resultVariable, LiteralExpression.Null()),
                            TrueStatements = new ThrowStatement(new NewObjectExpression(WellKnownTypes.GitLabExceptionTypeReference,
                                                                                        responseVariable.CreateMemberReferenceExpression("RequestMethod"),
                                                                                        responseVariable.CreateMemberReferenceExpression("RequestUri"),
                                                                                        responseVariable.CreateMemberReferenceExpression("StatusCode"),
                                                                                        new LiteralExpression($"The response cannot be converted to '{method.ReturnType.ToPropertyTypeReference().ClrFullTypeName}' because the body is null or empty"))),
                        });
                    }

                    responseTry.Try.Add(new ReturnStatement(resultVariable));
                }
            }

            return(m);
        //===========================================================
        //		using の変換
        //===========================================================
        /// <summary>
        /// Using 文を他の構文に変換して、yields に変換後の Statement を書き込みます。
        /// </summary>
        /// <param name="yields">変換後の Statement の書き込み先を指定します。</param>
        /// <param name="state">using 構文を表現する Statement を指定します。</param>
        /// <param name="last">state が Statements の中で最後の Statement か否かを指定します。</param>
        public static void TransformUsingStatement(Gen::List <IStatement> yields, IUsingStatement state, bool last)
        {
            // 変数の宣言の場合
            IAssignExpression assig = state.Expression as IAssignExpression;

            if (assig != null)
            {
                do
                {
                    IVariableDeclarationExpression var_decl_x = assig.Target as IVariableDeclarationExpression;
                    if (var_decl_x == null)
                    {
                        continue;
                    }

                    IVariableDeclaration var_decl = var_decl_x.Variable as IVariableDeclaration;
                    if (var_decl == null)
                    {
                        continue;
                    }

                    IObjectCreateExpression exp_create = assig.Expression as IObjectCreateExpression;
                    if (exp_create != null)
                    {
                        LocalRefVariableStatement s_lr = new LocalRefVariableStatement(var_decl, assig.Expression, state.Body);
                        s_lr.noblock = last;
                        yields.Add(s_lr);
                    }
                    else
                    {
                        //yields.Add(new ExpressionStatement(assig));
                        //yields.Add(state.Body);
                        //yields.Add(new DeleteStatement(new VariableReferenceExpression(var_decl)));
                        //↑ 中で例外が起こったときのことを考えていない。

                        // 宣言部分と代入部分を分離
                        IStatement s_decl = new ExpressionStatement(var_decl_x);
                        IStatement s_asgn = new ExpressionStatement(
                            new AssignExpression(
                                new VariableReferenceExpression(var_decl),
                                assig.Expression
                                )
                            );
                        IStatement s_delete = new DeleteStatement(new VariableReferenceExpression(var_decl));

                        // 宣言
                        yields.Add(s_decl);

                        // try-finally
                        BlockStatement try_block = new BlockStatement();
                        try_block.Statements.Add(s_asgn);
                        try_block.Statements.AddRange(state.Body.Statements);
                        BlockStatement finally_block = new BlockStatement();
                        finally_block.Statements.Add(s_delete);
                        TryCatchFinallyStatement s_tcf = new TryCatchFinallyStatement(try_block);
                        s_tcf.Finally = finally_block;
                        yields.Add(s_tcf);
                    }
                    return;
                }while(false);

                throw new InterfaceNotImplementedException("×実装中×", typeof(IVariableDeclarationExpression), assig.Target);
            }

            // 変数の参照の場合
            IVariableReferenceExpression varref = state.Expression as IVariableReferenceExpression;

            if (varref != null)
            {
                IStatement s_delete = new DeleteStatement(varref);

                // try-finally
                TryCatchFinallyStatement s_tcf         = new TryCatchFinallyStatement(state.Body);
                BlockStatement           finally_block = new BlockStatement();
                finally_block.Statements.Add(s_delete);
                s_tcf.Finally = finally_block;
                yields.Add(s_tcf);
                return;
            }

            throw new InterfaceNotImplementedException(
                      "Unexpected using-statement expression interface (expects IAssignExpression or IVariableReferenceExpression)",
                      typeof(IAssignExpression), state.Expression);
        }
Beispiel #19
0
 private Statement ParseTry(TokenSet followers)
   //^ requires this.currentToken == Token.Try || this.currentToken == Token.Catch || this.currentToken == Token.Finally;
   //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile;
 {
   bool savedUnmatchedTry = this.unmatchedTry;
   SourceLocationBuilder tryCatchFinallyContext = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken);
   TokenSet tryBlockFollowers = followers|Parser.CatchOrFinally;
   BlockStatement tryBody;
   if (this.currentToken == Token.Try) {
     this.unmatchedTry = true;
     this.GetNextToken();
     if (this.currentToken == Token.LeftBrace)
       tryBody = this.ParseBlock(tryBlockFollowers);
     else {
       List<Statement> tryBlockStatements = new List<Statement>();
       SourceLocationBuilder slb = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken);
       this.HandleError(Error.ExpectedLeftBrace);
       if (Parser.StatementStart[this.currentToken]) {
         this.ParseStatements(tryBlockStatements, tryBlockFollowers|Token.RightBrace);
         slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken);
         this.Skip(Token.RightBrace);
       }
       tryBody = new BlockStatement(tryBlockStatements, slb);
     }
     tryCatchFinallyContext.UpdateToSpan(tryBody.SourceLocation);
   } else {
     if (savedUnmatchedTry && ((this.currentToken == Token.Catch && followers[Token.Catch]) || (this.currentToken == Token.Finally && followers[Token.Finally])))
       return new EmptyStatement(false, tryCatchFinallyContext); //Busy parsing the body of a try. Return an empty statement to signal that the body has come to an end. Leave the catch or finally in place.
     //Complain about missing try and insert a dummy try block before the catch or finally.
     this.HandleError(Error.SyntaxError, "try");
     tryBody = new BlockStatement(new List<Statement>(0), this.scanner.SourceLocationOfLastScannedToken);
   }
   List<CatchClause> catchClauses = new List<CatchClause>();
   bool seenEmptyCatch = false;
   while (this.currentToken == Token.Catch) {
     CatchClause c = this.ParseCatchClause(tryBlockFollowers, ref seenEmptyCatch);
     catchClauses.Add(c);
     tryCatchFinallyContext.UpdateToSpan(c.SourceLocation);
   }
   catchClauses.TrimExcess();
   BlockStatement/*?*/ finallyBody = null;
   if (this.currentToken == Token.Finally) {
     this.GetNextToken();
     finallyBody = this.ParseBlock(followers);
     tryCatchFinallyContext.UpdateToSpan(finallyBody.SourceLocation);
   } else if (catchClauses.Count == 0) {
     this.SkipTo(followers, Error.ExpectedEndTry);
   }
   this.unmatchedTry = savedUnmatchedTry;
   TryCatchFinallyStatement result = new TryCatchFinallyStatement(tryBody, catchClauses, finallyBody, tryCatchFinallyContext);
   //^ assume followers[this.currentToken] || this.currentToken == Token.EndOfFile;
   return result;
 }
Beispiel #20
0
        public IAssembly InstrumentType(CciAssembly assembly, Epa epa)
        {
            Contract.Requires(assembly != null);
            Contract.Requires(epa != null);
            Contract.Requires(assembly.Types().Contains(epa.Type));

            // Clone assembly
            var host   = CciHostEnvironment.GetInstance();
            var module = new CodeAndContractDeepCopier(host).Copy(assembly.Module);

            var contractExtractor = host.GetContractExtractor(module.UnitIdentity);
            var contractProvider  = new AggregatingContractProvider(contractExtractor);

            var preconditions = new Dictionary <string, List <IPrecondition> >();

            var actions = new List <Action>(from transition in epa.Transitions.GroupBy(t => t.Action) select transition.Key);

            Contract.Assert(actions.Any());

            foreach (var action in actions)
            {
                // TODO (lleraromero): Es necesario? NullObject Pattern?
                var mc = action.Contract as MethodContract;
                if (mc == null)
                {
                    continue;
                }

                preconditions.Add(action.Name, action.Contract.Preconditions.ToList());
            }

            var typeDefinition    = epa.Type;
            var cciTypeDefinition =
                module.AllTypes.First(
                    t => TypeHelper.GetTypeName(t, NameFormattingOptions.UseGenericTypeNameSuffix).Equals(typeDefinition.Name)) as NamedTypeDefinition;

            Contract.Assert(cciTypeDefinition != null);

            var typeContract = RemoveInvariantMethods(typeDefinition, cciTypeDefinition);

            // Add a field to represent the state
            var field = CreateStateField(cciTypeDefinition, typeContract);

            cciTypeDefinition.Fields.Add(field);

            // Associate type contract to the contract provider
            contractProvider.AssociateTypeWithContract(cciTypeDefinition, typeContract);

            // Create Ids
            var stateNumberMap = new Dictionary <State, int>();

            foreach (var state in epa.States)
            {
                stateNumberMap.Add(state, stateNumberMap.Keys.Count);
            }

            foreach (var action in actions)
            {
                // voy a agrupar las transiciones que usan esta accion por sourceState.Id
                // transitions = Dicc<int, List<int>> o sea: "Dicc<from, List<to>>"
                var transitionsUsingAction = new List <Transition>(from t in epa.Transitions where t.Action.Equals(action) select t);
                var transitionsSourceIds   = new HashSet <int>(from t in transitionsUsingAction select stateNumberMap[t.SourceState]).Distinct();

                var transitions = new Dictionary <int, List <int> >();
                foreach (var t in transitionsUsingAction)
                {
                    var sourceStateId = stateNumberMap[t.SourceState];
                    if (!transitions.ContainsKey(sourceStateId))
                    {
                        transitions.Add(sourceStateId, new List <int>());
                    }

                    var targetStateId = stateNumberMap[t.TargetState];
                    transitions[sourceStateId].Add(targetStateId);
                }

                var methodContract   = action.Contract as MethodContract ?? new MethodContract();
                var methodDefinition = cciTypeDefinition.Methods.First(m => m.GetUniqueName().Equals(action.Method.GetUniqueName()));

                BlockStatement actionBodyBlock = null;
                if (methodDefinition.Body is SourceMethodBody)
                {
                    var actionBody = (SourceMethodBody)methodDefinition.Body;
                    actionBodyBlock = actionBody.Block as BlockStatement;
                }
                else if (methodDefinition.Body is Microsoft.Cci.MutableCodeModel.SourceMethodBody)
                {
                    var actionBody = (Microsoft.Cci.MutableCodeModel.SourceMethodBody)methodDefinition.Body;
                    actionBodyBlock = actionBody.Block as BlockStatement;
                }
                Contract.Assert(actionBodyBlock != null);

                //Por tratarse de un constructor insertamos en 1 porque en 0 esta base..ctor()
                var insertAtIndex = methodDefinition.IsConstructor ? 1 : 0;

                // CodeContracts no permite utilizar 'this' en los requires de los constructores
                if (!methodDefinition.IsConstructor)
                {
                    var pre = new PreconditionGenerator().GeneratePrecondition(field, transitions.Keys.ToList());
                    methodContract.Preconditions.Add(pre);
                }

                var posts = new PostconditionGenerator(stateNumberMap[epa.Initial]).GeneratePostconditions(field, transitions);
                methodContract.Postconditions.AddRange(posts);

                // Associate contract
                contractProvider.AssociateMethodWithContract(methodDefinition, methodContract);

                var stmt = new SwitchGenerator(epa, stateNumberMap).GenerateSwitch(field, transitions);

                // Se actualiza el $state en un finally porque los if de adentro del switch tienen que ser ejecutados despues del cuerpo de este metodo
                var stmtsCount = actionBodyBlock.Statements.Count - insertAtIndex;
                var tryBlock   = new BlockStatement();
                var bodyStmts  = new List <IStatement>(actionBodyBlock.Statements.GetRange(insertAtIndex, stmtsCount));
                tryBlock.Statements.AddRange(bodyStmts);

                var finallyBlock = new BlockStatement();
                finallyBlock.Statements.Add(stmt);

                var tryStmt = new TryCatchFinallyStatement
                {
                    TryBody     = tryBlock,
                    FinallyBody = finallyBlock
                };

                actionBodyBlock.Statements.RemoveRange(insertAtIndex, stmtsCount);
                actionBodyBlock.Statements.Insert(insertAtIndex, tryStmt);
            }

            return(new CciAssembly(module, contractProvider));
        }