Exemplo n.º 1
0
 private void PreprocessMethod()
 {
     if (ContextAnnotations.AwaitInExceptionHandler(_method.Method))
     {
         AsyncExceptionHandlerRewriter.Rewrite(_method.Method);
     }
     AwaitExpressionSpiller.Rewrite(_method.Method);
 }
Exemplo n.º 2
0
        /// <summary>
        /// Lower a block of code by performing local rewritings.
        /// The goal is to not have exception handlers that contain awaits in them.
        ///
        /// 1) Await containing ensure blocks:
        ///     The general strategy is to rewrite await containing handlers into synthetic handlers.
        ///     Synthetic handlers are not handlers in IL sense so it is ok to have awaits in them.
        ///     Since synthetic handlers are just blocks, we have to deal with pending exception/branch/return manually
        ///     (this is the hard part of the rewrite).
        ///
        ///     try:
        ///        code
        ///     ensure:
        ///        handler
        ///
        /// Into ===>
        ///
        ///     ex as Exception = null
        ///     pendingBranch as int = 0
        ///
        ///     try:
        ///         code  // any gotos/returns are rewritten to code that pends the necessary info and goes to finallyLabel
        ///         goto finallyLabel
        ///     except ex:  // essentially pend the currently active exception
        ///         pass
        ///
        ///     :finallyLabel
        ///        handler
        ///        if ex != null: raise ex     // unpend the exception
        ///        unpend branches/return
        ///
        /// 2) Await containing catches:
        ///     try:
        ///         code
        ///     except ex as Exception:
        ///         handler
        ///         raise
        ///
        ///
        /// Into ===>
        ///
        ///     pendingException as Object
        ///     pendingCatch as int = 0
        ///
        ///     try:
        ///         code
        ///     except temp as Exception:  // essentially pend the currently active exception
        ///         pendingException = temp
        ///         pendingCatch = 1
        ///
        ///     if pendingCatch == 1:
        ///             var ex = pendingException cast Exception
        ///             handler
        ///             raise pendingException
        /// </summary>
        public static void Rewrite(Method containingMethod)
        {
            if (containingMethod == null)
            {
                throw new ArgumentNullException("containingMethod");
            }

            var body     = containingMethod.Body;
            var analysis = new AwaitInFinallyAnalysis(body);

            if (analysis.ContainsAwaitInHandlers())
            {
                var factory  = CompilerContext.Current.CodeBuilder;
                var rewriter = new AsyncExceptionHandlerRewriter(containingMethod, factory, analysis);
                containingMethod.Body = (Block)rewriter.Visit(body);
            }
        }