示例#1
0
        public virtual void Replace(string programName, int from, int to, object text)
        {
            if (from > to || from < 0 || to < 0 || to >= tokens.Size)
            {
                throw new ArgumentException("replace: range invalid: " + from + ".." + to + "(size=" + tokens.Size + ")");
            }
            TokenStreamRewriter.RewriteOperation         op       = new TokenStreamRewriter.ReplaceOp(tokens, from, to, text);
            IList <TokenStreamRewriter.RewriteOperation> rewrites = GetProgram(programName);

            op.instructionIndex = rewrites.Count;
            rewrites.Add(op);
        }
示例#2
0
        /// <summary>
        /// We need to combine operations and report invalid operations (like
        /// overlapping replaces that are not completed nested).
        /// </summary>
        /// <remarks>
        /// We need to combine operations and report invalid operations (like
        /// overlapping replaces that are not completed nested). Inserts to
        /// same index need to be combined etc...  Here are the cases:
        /// I.i.u I.j.v								leave alone, nonoverlapping
        /// I.i.u I.i.v								combine: Iivu
        /// R.i-j.u R.x-y.v	| i-j in x-y			delete first R
        /// R.i-j.u R.i-j.v							delete first R
        /// R.i-j.u R.x-y.v	| x-y in i-j			ERROR
        /// R.i-j.u R.x-y.v	| boundaries overlap	ERROR
        /// Delete special case of replace (text==null):
        /// D.i-j.u D.x-y.v	| boundaries overlap	combine to max(min)..max(right)
        /// I.i.u R.x-y.v | i in (x+1)-y			delete I (since insert before
        /// we're not deleting i)
        /// I.i.u R.x-y.v | i not in (x+1)-y		leave alone, nonoverlapping
        /// R.x-y.v I.i.u | i in x-y				ERROR
        /// R.x-y.v I.x.u                           R.x-y.uv (combine, delete I)
        /// R.x-y.v I.i.u | i not in x-y			leave alone, nonoverlapping
        /// I.i.u = insert u before op @ index i
        /// R.x-y.u = replace x-y indexed tokens with u
        /// First we need to examine replaces. For any replace op:
        /// 1. wipe out any insertions before op within that range.
        /// 2. Drop any replace op before that is contained completely within
        /// that range.
        /// 3. Throw exception upon boundary overlap with any previous replace.
        /// Then we can deal with inserts:
        /// 1. for any inserts to same index, combine even if not adjacent.
        /// 2. for any prior replace with same left boundary, combine this
        /// insert with replace and delete this replace.
        /// 3. throw exception if index in same range as previous replace
        /// Don't actually delete; make op null in list. Easier to walk list.
        /// Later we can throw as we add to index &#x2192; op map.
        /// Note that I.2 R.2-2 will wipe out I.2 even though, technically, the
        /// inserted stuff would be before the replace range. But, if you
        /// add tokens in front of a method body '{' and then delete the method
        /// body, I think the stuff before the '{' you added should disappear too.
        /// Return a map from token index to operation.
        /// </remarks>
        protected internal virtual IDictionary <int, TokenStreamRewriter.RewriteOperation> ReduceToSingleOperationPerIndex(IList <TokenStreamRewriter.RewriteOperation> rewrites)
        {
            //		System.out.println("rewrites="+rewrites);
            // WALK REPLACES
            for (int i = 0; i < rewrites.Count; i++)
            {
                TokenStreamRewriter.RewriteOperation op = rewrites[i];
                if (op == null)
                {
                    continue;
                }
                if (!(op is TokenStreamRewriter.ReplaceOp))
                {
                    continue;
                }
                TokenStreamRewriter.ReplaceOp rop = (TokenStreamRewriter.ReplaceOp)rewrites[i];
                // Wipe prior inserts within range
                IList <TokenStreamRewriter.InsertBeforeOp> inserts = GetKindOfOps <TokenStreamRewriter.InsertBeforeOp>(rewrites, i);
                foreach (TokenStreamRewriter.InsertBeforeOp iop in inserts)
                {
                    if (iop.index == rop.index)
                    {
                        // E.g., insert before 2, delete 2..2; update replace
                        // text to include insert before, kill insert
                        rewrites[iop.instructionIndex] = null;
                        rop.text = iop.text.ToString() + (rop.text != null ? rop.text.ToString() : string.Empty);
                    }
                    else
                    {
                        if (iop.index > rop.index && iop.index <= rop.lastIndex)
                        {
                            // delete insert as it's a no-op.
                            rewrites[iop.instructionIndex] = null;
                        }
                    }
                }
                // Drop any prior replaces contained within
                IList <TokenStreamRewriter.ReplaceOp> prevReplaces = GetKindOfOps <TokenStreamRewriter.ReplaceOp>(rewrites, i);
                foreach (TokenStreamRewriter.ReplaceOp prevRop in prevReplaces)
                {
                    if (prevRop.index >= rop.index && prevRop.lastIndex <= rop.lastIndex)
                    {
                        // delete replace as it's a no-op.
                        rewrites[prevRop.instructionIndex] = null;
                        continue;
                    }
                    // throw exception unless disjoint or identical
                    bool disjoint = prevRop.lastIndex <rop.index || prevRop.index> rop.lastIndex;
                    bool same = prevRop.index == rop.index && prevRop.lastIndex == rop.lastIndex;
                    // Delete special case of replace (text==null):
                    // D.i-j.u D.x-y.v	| boundaries overlap	combine to max(min)..max(right)
                    if (prevRop.text == null && rop.text == null && !disjoint)
                    {
                        //System.out.println("overlapping deletes: "+prevRop+", "+rop);
                        rewrites[prevRop.instructionIndex] = null;
                        // kill first delete
                        rop.index     = Math.Min(prevRop.index, rop.index);
                        rop.lastIndex = Math.Max(prevRop.lastIndex, rop.lastIndex);
#if !PORTABLE
                        System.Console.Out.WriteLine("new rop " + rop);
#endif
                    }
                    else
                    {
                        if (!disjoint && !same)
                        {
                            throw new ArgumentException("replace op boundaries of " + rop + " overlap with previous " + prevRop);
                        }
                    }
                }
            }
            // WALK INSERTS
            for (int i_1 = 0; i_1 < rewrites.Count; i_1++)
            {
                TokenStreamRewriter.RewriteOperation op = rewrites[i_1];
                if (op == null)
                {
                    continue;
                }
                if (!(op is TokenStreamRewriter.InsertBeforeOp))
                {
                    continue;
                }
                TokenStreamRewriter.InsertBeforeOp iop = (TokenStreamRewriter.InsertBeforeOp)rewrites[i_1];
                // combine current insert with prior if any at same index
                IList <TokenStreamRewriter.InsertBeforeOp> prevInserts = GetKindOfOps <TokenStreamRewriter.InsertBeforeOp>(rewrites, i_1);
                foreach (TokenStreamRewriter.InsertBeforeOp prevIop in prevInserts)
                {
                    if (prevIop.index == iop.index)
                    {
                        // combine objects
                        // convert to strings...we're in process of toString'ing
                        // whole token buffer so no lazy eval issue with any templates
                        iop.text = CatOpText(iop.text, prevIop.text);
                        // delete redundant prior insert
                        rewrites[prevIop.instructionIndex] = null;
                    }
                }
                // look for replaces where iop.index is in range; error
                IList <TokenStreamRewriter.ReplaceOp> prevReplaces = GetKindOfOps <TokenStreamRewriter.ReplaceOp>(rewrites, i_1);
                foreach (TokenStreamRewriter.ReplaceOp rop in prevReplaces)
                {
                    if (iop.index == rop.index)
                    {
                        rop.text      = CatOpText(iop.text, rop.text);
                        rewrites[i_1] = null;
                        // delete current insert
                        continue;
                    }
                    if (iop.index >= rop.index && iop.index <= rop.lastIndex)
                    {
                        throw new ArgumentException("insert op " + iop + " within boundaries of previous " + rop);
                    }
                }
            }
            // System.out.println("rewrites after="+rewrites);
            IDictionary <int, TokenStreamRewriter.RewriteOperation> m = new Dictionary <int, TokenStreamRewriter.RewriteOperation>();
            for (int i_2 = 0; i_2 < rewrites.Count; i_2++)
            {
                TokenStreamRewriter.RewriteOperation op = rewrites[i_2];
                if (op == null)
                {
                    continue;
                }
                // ignore deleted ops
                if (m.ContainsKey(op.index))
                {
                    throw new InvalidOperationException("should only be one op per index");
                }
                m[op.index] = op;
            }
            //System.out.println("index to op: "+m);
            return(m);
        }