@@ -235,6 +235,36 @@ namespace Js
235235 template <>
236236 bool RangeUnitContains<SourceFunctionNode>(RangeUnit<SourceFunctionNode> unit, SourceFunctionNode n);
237237
238+ template <typename TRangeUnitData>
239+ RangeUnit<TRangeUnitData> GetFullRange ()
240+ {
241+ RangeUnit<TRangeUnitData> unit;
242+ unit.i = INT_MIN;
243+ unit.j = INT_MAX;
244+ return unit;
245+ }
246+
247+ template <>
248+ RangeUnit<SourceFunctionNode> GetFullRange ();
249+
250+ template <typename TRangeUnitData>
251+ TRangeUnitData GetPrevious (TRangeUnitData unit)
252+ {
253+ return unit - 1 ;
254+ }
255+
256+ template <>
257+ SourceFunctionNode GetPrevious (SourceFunctionNode unit);
258+
259+ template <typename TRangeUnitData>
260+ TRangeUnitData GetNext (TRangeUnitData unit)
261+ {
262+ return unit + 1 ;
263+ }
264+
265+ template <>
266+ SourceFunctionNode GetNext (SourceFunctionNode unit);
267+
238268 // /----------------------------------------------------------------------------
239269 // /----------------------------------------------------------------------------
240270 // /
@@ -268,8 +298,9 @@ namespace Js
268298 public:
269299 inline bool InRange (TRangeUnitData i);
270300 inline bool ContainsAll ();
271- inline void Add (TRangeUnitData i);
272- inline void Add (TRangeUnitData i, TRangeUnitData j);
301+ inline void Add (TRangeUnitData i, RangeBase<TRangeUnitData>* oppositeRange = nullptr );
302+ inline void Add (TRangeUnitData i, TRangeUnitData j, RangeBase<TRangeUnitData>* oppositeRange = nullptr );
303+ inline void Clear ();
273304
274305#if DBG_RANGE
275306 template <typename TFunction>
@@ -345,6 +376,7 @@ namespace Js
345376 public:
346377
347378 void Enable (Phase phase);
379+ void Disable (Phase phase);
348380 bool IsEnabled (Phase phase);
349381 bool IsEnabled (Phase phase, uint sourceContextId, Js::LocalFunctionId functionId);
350382 bool IsEnabledForAll (Phase phase);
@@ -394,6 +426,7 @@ namespace Js
394426
395427 String* GetAsString (Flag flag) const ;
396428 Phases* GetAsPhase (Flag flag) const ;
429+ Flag GetOppositePhaseFlag (Flag flag) const ;
397430 Boolean* GetAsBoolean (Flag flag) const ;
398431 Number* GetAsNumber (Flag flag) const ;
399432 NumberSet* GetAsNumberSet (Flag flag) const ;
@@ -812,16 +845,86 @@ namespace Js
812845
813846template <typename TRangeUnitData>
814847void
815- RangeBase<TRangeUnitData>::Add(TRangeUnitData i)
848+ RangeBase<TRangeUnitData>::Add(TRangeUnitData i, RangeBase<TRangeUnitData>* oppositeRange )
816849{
817- Add (i, i);
850+ Add (i, i, oppositeRange );
818851}
819852
820853template <typename TRangeUnitData>
821854void
822- RangeBase<TRangeUnitData>::Add(TRangeUnitData i, TRangeUnitData j)
855+ RangeBase<TRangeUnitData>::Add(TRangeUnitData i, TRangeUnitData j, RangeBase<TRangeUnitData>* oppositeRange )
823856{
824- range.Prepend (RangeUnit<TRangeUnitData>(i, j));
857+ RangeUnit<TRangeUnitData> a (i, j);
858+ range.Prepend (a);
859+ if (oppositeRange)
860+ {
861+ if (oppositeRange->range .Empty ())
862+ {
863+ oppositeRange->range .Prepend (GetFullRange<TRangeUnitData>());
864+ }
865+ // Do an intersection
866+ auto it = oppositeRange->range .GetEditingIterator ();
867+ while (it.Next ())
868+ {
869+ Unit& unit = it.Data ();
870+ bool c1 = RangeUnitContains (unit, i);
871+ bool c2 = RangeUnitContains (unit, j);
872+ bool c3 = RangeUnitContains (a, unit.i );
873+ bool c4 = RangeUnitContains (a, unit.j );
874+ enum IntersectionCase
875+ {
876+ NoIntersection = 0 ,
877+ AddedFullyContained = 3 , // [ u [a] ]
878+ IntersectionAdded_Unit = 6 , // [ a [ ] u ]
879+ CommonLowBound_Unit = 7 , // [[ a ] u ]
880+ IntersectionUnit_Added = 9 , // [ u [ ] a ]
881+ CommonTopBound_Unit = 11 , // [ u [ a ]]
882+ UnitFullyContained = 12 , // [ a [u] ]
883+ CommonLowBound_Added = 13 , // [[ u ] a ]
884+ CommonTopBound_Added = 14 , // [ a [ u ]]
885+ FullIntersection = 15 // [[a, u]]
886+ };
887+ IntersectionCase intersectionCase = (IntersectionCase)((int )c1 | (c2 << 1 ) | (c3 << 2 ) | (c4 << 3 ));
888+ switch (intersectionCase)
889+ {
890+ case NoIntersection:
891+ // Nothing to do
892+ break ;
893+ case AddedFullyContained:
894+ {
895+ // Need to break the current in 2
896+ Unit lowUnit = unit;
897+ Unit topUnit = unit;
898+ lowUnit.j = GetPrevious (a.i );
899+ topUnit.i = GetNext (a.j );
900+ it.InsertBefore (lowUnit);
901+ it.InsertBefore (topUnit);
902+ it.RemoveCurrent ();
903+ break ;
904+ }
905+ case IntersectionAdded_Unit:
906+ case CommonLowBound_Unit:
907+ // Move the unit lower bound after the added upper bound
908+ unit.i = GetNext (a.j );
909+ break ;
910+ case IntersectionUnit_Added:
911+ case CommonTopBound_Unit:
912+ // Move the unit upper bound before the added lower bound
913+ unit.j = GetPrevious (a.i );
914+ break ;
915+ case CommonTopBound_Added:
916+ case CommonLowBound_Added:
917+ case UnitFullyContained:
918+ case FullIntersection:
919+ // Remove the unit
920+ it.RemoveCurrent ();
921+ break ;
922+ default :
923+ Assert (UNREACHED);
924+ break ;
925+ }
926+ }
927+ }
825928}
826929
827930template <typename TRangeUnitData>
@@ -831,6 +934,13 @@ RangeBase<TRangeUnitData>::ContainsAll()
831934 return range.Empty ();
832935}
833936
937+ template <typename TRangeUnitData>
938+ void
939+ Js::RangeBase<TRangeUnitData>::Clear()
940+ {
941+ range.Clear ();
942+ }
943+
834944// /----------------------------------------------------------------------------
835945// /
836946// / RangeBase::InRange
0 commit comments