88import org .antlr .v4 .runtime .misc .Interval ;
99
1010import java .util .ArrayList ;
11+ import java .util .BitSet ;
1112import java .util .HashMap ;
1213import java .util .List ;
1314import java .util .Map ;
@@ -478,32 +479,53 @@ public String getText(String programName, Interval interval) {
478479 protected Map <Integer , RewriteOperation > reduceToSingleOperationPerIndex (List <RewriteOperation > rewrites ) {
479480// System.out.println("rewrites="+rewrites);
480481
482+ // BitSets are used here to track ReplaceOps and InsertBeforeOps
483+ final BitSet replaceOpSet = new BitSet (rewrites .size ());
484+ final BitSet insertBeforeSet = new BitSet (rewrites .size ());
485+
481486 // WALK REPLACES
482487 for (int i = 0 ; i < rewrites .size (); i ++) {
483488 RewriteOperation op = rewrites .get (i );
484- if ( op ==null ) continue ;
485- if ( !(op instanceof ReplaceOp ) ) continue ;
489+ if ( op ==null ){
490+ continue ;
491+ }
492+ if ( !(op instanceof ReplaceOp ) ) {
493+ if (op instanceof InsertBeforeOp ) {
494+ insertBeforeSet .set (i );
495+ }
496+ continue ;
497+ }
486498 ReplaceOp rop = (ReplaceOp )rewrites .get (i );
499+ replaceOpSet .set (i );
500+
487501 // Wipe prior inserts within range
488- List <? extends InsertBeforeOp > inserts = getKindOfOps (rewrites , InsertBeforeOp .class , i );
489- for (InsertBeforeOp iop : inserts ) {
502+ for (int j = insertBeforeSet .nextSetBit (0 ); j >= 0 && j < i ; j = insertBeforeSet .nextSetBit (j + 1 )) {
503+ RewriteOperation roj = rewrites .get (j );
504+ InsertBeforeOp iop = (InsertBeforeOp ) roj ;
490505 if ( iop .index == rop .index ) {
491506 // E.g., insert before 2, delete 2..2; update replace
492507 // text to include insert before, kill insert
493508 rewrites .set (iop .instructionIndex , null );
509+ replaceOpSet .clear (iop .instructionIndex );
510+ insertBeforeSet .clear (iop .instructionIndex );
494511 rop .text = iop .text .toString () + (rop .text !=null ?rop .text .toString ():"" );
495512 }
496513 else if ( iop .index > rop .index && iop .index <= rop .lastIndex ) {
497514 // delete insert as it's a no-op.
498515 rewrites .set (iop .instructionIndex , null );
516+ replaceOpSet .clear (iop .instructionIndex );
517+ insertBeforeSet .clear (iop .instructionIndex );
499518 }
500519 }
501520 // Drop any prior replaces contained within
502- List <? extends ReplaceOp > prevReplaces = getKindOfOps (rewrites , ReplaceOp .class , i );
503- for (ReplaceOp prevRop : prevReplaces ) {
521+ for (int j = replaceOpSet .nextSetBit (0 ); j >=0 && j < i ; j = replaceOpSet .nextSetBit (j + 1 )) {
522+ RewriteOperation roj = rewrites .get (j );
523+ ReplaceOp prevRop = (ReplaceOp ) roj ;
504524 if ( prevRop .index >=rop .index && prevRop .lastIndex <= rop .lastIndex ) {
505525 // delete replace as it's a no-op.
506526 rewrites .set (prevRop .instructionIndex , null );
527+ replaceOpSet .clear (prevRop .instructionIndex );
528+ insertBeforeSet .clear (prevRop .instructionIndex );
507529 continue ;
508530 }
509531 // throw exception unless disjoint or identical
@@ -514,9 +536,11 @@ else if ( iop.index > rop.index && iop.index <= rop.lastIndex ) {
514536 if ( prevRop .text ==null && rop .text ==null && !disjoint ) {
515537 //System.out.println("overlapping deletes: "+prevRop+", "+rop);
516538 rewrites .set (prevRop .instructionIndex , null ); // kill first delete
539+ replaceOpSet .clear (prevRop .instructionIndex );
540+ insertBeforeSet .clear (prevRop .instructionIndex );
517541 rop .index = Math .min (prevRop .index , rop .index );
518542 rop .lastIndex = Math .max (prevRop .lastIndex , rop .lastIndex );
519- System .out .println ("new rop " +rop );
543+ // System.out.println("new rop "+rop);
520544 }
521545 else if ( !disjoint ) {
522546 throw new IllegalArgumentException ("replace op boundaries of " +rop +" overlap with previous " +prevRop );
@@ -528,31 +552,44 @@ else if ( !disjoint ) {
528552 for (int i = 0 ; i < rewrites .size (); i ++) {
529553 RewriteOperation op = rewrites .get (i );
530554 if ( op ==null ) continue ;
531- if ( !(op instanceof InsertBeforeOp ) ) continue ;
555+ if ( !(op instanceof InsertBeforeOp ) ) {
556+ if (op instanceof ReplaceOp ) {
557+ replaceOpSet .set (i );
558+ }
559+ continue ;
560+ }
561+ insertBeforeSet .set (i );
532562 InsertBeforeOp iop = (InsertBeforeOp )rewrites .get (i );
533563 // combine current insert with prior if any at same index
534- List <? extends InsertBeforeOp > prevInserts = getKindOfOps (rewrites , InsertBeforeOp .class , i );
535- for (InsertBeforeOp prevIop : prevInserts ) {
564+
565+ for (int j = insertBeforeSet .nextSetBit (0 ); j >= 0 && j < i ; j = insertBeforeSet .nextSetBit (j + 1 )) {
566+ InsertBeforeOp prevIop = (InsertBeforeOp ) rewrites .get (j );
536567 if ( prevIop .index ==iop .index ) {
537- if ( InsertAfterOp . class . isInstance ( prevIop ) ) {
568+ if (prevIop instanceof InsertAfterOp ) {
538569 iop .text = catOpText (prevIop .text , iop .text );
539570 rewrites .set (prevIop .instructionIndex , null );
571+ insertBeforeSet .clear (prevIop .instructionIndex );
572+ replaceOpSet .clear (prevIop .instructionIndex );
540573 }
541- else if ( InsertBeforeOp . class . isInstance ( prevIop ) ) { // combine objects
574+ else { // combine objects
542575 // convert to strings...we're in process of toString'ing
543576 // whole token buffer so no lazy eval issue with any templates
544577 iop .text = catOpText (iop .text , prevIop .text );
545578 // delete redundant prior insert
546579 rewrites .set (prevIop .instructionIndex , null );
580+ insertBeforeSet .clear (prevIop .instructionIndex );
581+ replaceOpSet .clear (prevIop .instructionIndex );
547582 }
548583 }
549584 }
550585 // look for replaces where iop.index is in range; error
551- List <? extends ReplaceOp > prevReplaces = getKindOfOps ( rewrites , ReplaceOp . class , i );
552- for ( ReplaceOp rop : prevReplaces ) {
586+ for ( int j = replaceOpSet . nextSetBit ( 0 ); j >= 0 && j < i ; j = replaceOpSet . nextSetBit ( j + 1 )) {
587+ ReplaceOp rop = ( ReplaceOp ) rewrites . get ( j );
553588 if ( iop .index == rop .index ) {
554589 rop .text = catOpText (iop .text ,rop .text );
555590 rewrites .set (i , null ); // delete current insert
591+ insertBeforeSet .clear (i );
592+ replaceOpSet .clear (i );
556593 continue ;
557594 }
558595 if ( iop .index >= rop .index && iop .index <= rop .lastIndex ) {
@@ -562,13 +599,12 @@ else if ( InsertBeforeOp.class.isInstance(prevIop) ) { // combine objects
562599 }
563600 // System.out.println("rewrites after="+rewrites);
564601 Map <Integer , RewriteOperation > m = new HashMap <Integer , RewriteOperation >();
565- for (int i = 0 ; i < rewrites .size (); i ++) {
566- RewriteOperation op = rewrites .get (i );
602+ for (int k = 0 ; k < rewrites .size (); k ++) {
603+ RewriteOperation op = rewrites .get (k );
567604 if ( op ==null ) continue ; // ignore deleted ops
568- if ( m .get (op .index )!=null ) {
605+ if ( m .put (op .index , op )!=null ) {
569606 throw new Error ("should only be one op per index" );
570607 }
571- m .put (op .index , op );
572608 }
573609 //System.out.println("index to op: "+m);
574610 return m ;
@@ -581,17 +617,4 @@ protected String catOpText(Object a, Object b) {
581617 if ( b !=null ) y = b .toString ();
582618 return x +y ;
583619 }
584-
585- /** Get all operations before an index of a particular kind */
586- protected <T extends RewriteOperation > List <? extends T > getKindOfOps (List <? extends RewriteOperation > rewrites , Class <T > kind , int before ) {
587- List <T > ops = new ArrayList <T >();
588- for (int i =0 ; i <before && i <rewrites .size (); i ++) {
589- RewriteOperation op = rewrites .get (i );
590- if ( op ==null ) continue ; // ignore deleted
591- if ( kind .isInstance (op ) ) {
592- ops .add (kind .cast (op ));
593- }
594- }
595- return ops ;
596- }
597620}
0 commit comments