Microsoft.Zing.Splicer.PatchSourceContextProperty C# (CSharp) Method

PatchSourceContextProperty() private method

private PatchSourceContextProperty ( ZMethod zMethod, Class methodClass, List basicBlocks ) : void
zMethod ZMethod
methodClass Class
basicBlocks List
return void
        private void PatchSourceContextProperty(ZMethod zMethod, Class methodClass, List<BasicBlock> basicBlocks)
        {
            Property contextProperty = (Property)Templates.GetMemberByName(methodClass.Members, "Context");
            Method contextMethod = contextProperty.Getter;
            Debug.Assert(contextMethod.Body.Statements[0] is System.Compiler.Switch);
            System.Compiler.Switch switchStmt = (System.Compiler.Switch)contextMethod.Body.Statements[0];

            foreach (BasicBlock block in basicBlocks)
            {
                SourceContext ctxt = new SourceContext(null, 0, 0);

                //ctxt.Document = null;
                //ctxt.StartPos = 0;
                //ctxt.EndPos = 0;

                if (block.SourceContext.StartPos != 0 || block.SourceContext.EndPos != 0)
                {
                    // If the block says something explicit about its context, take that
                    // as final.
                    ctxt = block.SourceContext;
                }
                else
                {
                    // The block doesn't say anything, so figure it out from the statements
                    // inside the block.

                    BasicBlock effectiveBlock = block;
                    //
                    // If we only fall through to another BB without any executable code,
                    // conditional branching, interleaving, or return - then consider our
                    // source context to be the next "real" thing that happens.
                    //
                    while ((effectiveBlock.Statement == null || effectiveBlock.SkipNormalizer) &&
                        effectiveBlock.ConditionalExpression == null &&
                        effectiveBlock.SourceContext.SourceText == null &&
                        effectiveBlock.MiddleOfTransition &&
                        !effectiveBlock.IsReturn && !effectiveBlock.PropagatesException)
                    {
                        effectiveBlock = effectiveBlock.UnconditionalTarget;
                    }

                    // See which source context is the most appropriate for this block.
                    if (effectiveBlock.Statement != null)
                    {
                        if (effectiveBlock.Statement.SourceContext.SourceText != null)
                            ctxt = effectiveBlock.Statement.SourceContext;
                        else
                        {
                            Block b = effectiveBlock.Statement as Block;
                            if (b != null)
                            {
                                for (int i = 0, n = b.Statements.Count; i < n; i++)
                                {
                                    if (b.Statements[i] != null)
                                    {
                                        ctxt = b.Statements[i].SourceContext;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    else if (effectiveBlock.ConditionalExpression != null)
                        ctxt = effectiveBlock.ConditionalExpression.SourceContext;
                    else if (effectiveBlock.SourceContext.SourceText != null)
                        ctxt = effectiveBlock.SourceContext;
                    else
                    {
                        // For "return" blocks, show the closing brace as the source context.
                        ctxt.Document = zMethod.SourceContext.Document;
                        ctxt.EndPos = zMethod.SourceContext.EndPos;
                        ctxt.StartPos = ctxt.EndPos - 1;
                    }
                }

                if (ctxt.StartPos < 0)
                    ctxt.StartPos = 0;

                SwitchCase newCase = new SwitchCase(
                    new QualifiedIdentifier(Identifier.For("Blocks"), Identifier.For(block.Name)),
                    new Block(new StatementList(
                        new Return(SourceContextConstructor(ctxt))))
                    );

                switchStmt.Cases.Add(newCase);
            }
        }