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("}"); } }
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); } }
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); }
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); }
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); }
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); } }
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); }
public virtual void VisitTryCatchFinallyStatement(TryCatchFinallyStatement tryCatchFinallyStatement) { VisitBlock(tryCatchFinallyStatement.TryBlock); VisitBlock(tryCatchFinallyStatement.CatchBlock); VisitBlock(tryCatchFinallyStatement.FinallyBlock); }
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); }
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; }
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)); }