示例#1
0
  /*
   * Creates a <code>RangeDifference3</code> given the state of two
   * DifferenceIterators.
   */
  private static RangeDifference createRangeDifference3(
      DifferencesIterator myIter,
      DifferencesIterator yourIter,
      List diff3,
      IRangeComparator right,
      IRangeComparator left,
      int changeRangeStart,
      int changeRangeEnd) {

    int rightStart, rightEnd;
    int leftStart, leftEnd;
    int kind = RangeDifference.ERROR;
    RangeDifference last = (RangeDifference) diff3.get(diff3.size() - 1);

    Assert.isTrue((myIter.getCount() != 0 || yourIter.getCount() != 0)); // At
    // least
    // one
    // range
    // array
    // must
    // be
    // non-empty
    //
    // find corresponding lines to fChangeRangeStart/End in right and left
    //
    if (myIter.getCount() == 0) { // only left changed
      rightStart = changeRangeStart - last.ancestorEnd() + last.rightEnd();
      rightEnd = changeRangeEnd - last.ancestorEnd() + last.rightEnd();
      kind = RangeDifference.LEFT;
    } else {
      RangeDifference f = (RangeDifference) myIter.fRange.get(0);
      RangeDifference l = (RangeDifference) myIter.fRange.get(myIter.fRange.size() - 1);
      rightStart = changeRangeStart - f.fLeftStart + f.fRightStart;
      rightEnd = changeRangeEnd - l.leftEnd() + l.rightEnd();
    }

    if (yourIter.getCount() == 0) { // only right changed
      leftStart = changeRangeStart - last.ancestorEnd() + last.leftEnd();
      leftEnd = changeRangeEnd - last.ancestorEnd() + last.leftEnd();
      kind = RangeDifference.RIGHT;
    } else {
      RangeDifference f = (RangeDifference) yourIter.fRange.get(0);
      RangeDifference l = (RangeDifference) yourIter.fRange.get(yourIter.fRange.size() - 1);
      leftStart = changeRangeStart - f.fLeftStart + f.fRightStart;
      leftEnd = changeRangeEnd - l.leftEnd() + l.rightEnd();
    }

    if (kind == RangeDifference.ERROR) { // overlapping change (conflict)
      // -> compare the changed ranges
      if (rangeSpansEqual(
          right, rightStart, rightEnd - rightStart, left, leftStart, leftEnd - leftStart))
        kind = RangeDifference.ANCESTOR;
      else kind = RangeDifference.CONFLICT;
    }
    return new RangeDifference(
        kind,
        rightStart,
        rightEnd - rightStart,
        leftStart,
        leftEnd - leftStart,
        changeRangeStart,
        changeRangeEnd - changeRangeStart);
  }
示例#2
0
  /**
   * Finds the differences among three <code>IRangeComparator</code>s. The differences are returned
   * as a list of <code>RangeDifference</code>s. If no differences are detected an empty list is
   * returned. If the ancestor range comparator is <code>null</code>, a two-way comparison is
   * performed.
   *
   * @param pm if not <code>null</code> used to report progress
   * @param ancestor the ancestor range comparator or <code>null</code>
   * @param left the left range comparator
   * @param right the right range comparator
   * @return an array of range differences, or an empty array if no differences were found
   * @since 2.0
   */
  public static RangeDifference[] findDifferences(
      IProgressMonitor pm,
      LCSSettings settings,
      IRangeComparator ancestor,
      IRangeComparator left,
      IRangeComparator right) {
    try {
      if (ancestor == null) return findDifferences(pm, settings, left, right);
      SubMonitor monitor = SubMonitor.convert(pm, CompareMessages.RangeComparatorLCS_0, 100);
      RangeDifference[] leftAncestorScript = null;
      RangeDifference[] rightAncestorScript =
          findDifferences(monitor.newChild(50), settings, ancestor, right);
      if (rightAncestorScript != null) {
        monitor.setWorkRemaining(100);
        leftAncestorScript = findDifferences(monitor.newChild(50), settings, ancestor, left);
      }
      if (rightAncestorScript == null || leftAncestorScript == null) return null;

      DifferencesIterator myIter = new DifferencesIterator(rightAncestorScript);
      DifferencesIterator yourIter = new DifferencesIterator(leftAncestorScript);

      List diff3 = new ArrayList();
      diff3.add(new RangeDifference(RangeDifference.ERROR)); // add a
      // sentinel

      int changeRangeStart = 0;
      int changeRangeEnd = 0;
      //
      // Combine the two two-way edit scripts into one
      //
      monitor.setWorkRemaining(rightAncestorScript.length + leftAncestorScript.length);
      while (myIter.fDifference != null || yourIter.fDifference != null) {

        DifferencesIterator startThread;
        myIter.removeAll();
        yourIter.removeAll();
        //
        // take the next diff that is closer to the start
        //
        if (myIter.fDifference == null) startThread = yourIter;
        else if (yourIter.fDifference == null) startThread = myIter;
        else { // not at end of both scripts take the lowest range
          if (myIter.fDifference.fLeftStart <= yourIter.fDifference.fLeftStart) // 2
            // ->
            // common
            // (Ancestor)
            // change
            // range
            startThread = myIter;
          else startThread = yourIter;
        }
        changeRangeStart = startThread.fDifference.fLeftStart;
        changeRangeEnd = startThread.fDifference.leftEnd();

        startThread.next();
        monitor.worked(1);
        //
        // check for overlapping changes with other thread
        // merge overlapping changes with this range
        //
        DifferencesIterator other = startThread.other(myIter, yourIter);
        while (other.fDifference != null && other.fDifference.fLeftStart <= changeRangeEnd) {
          int newMax = other.fDifference.leftEnd();
          other.next();
          monitor.worked(1);
          if (newMax >= changeRangeEnd) {
            changeRangeEnd = newMax;
            other = other.other(myIter, yourIter);
          }
        }
        diff3.add(
            createRangeDifference3(
                myIter, yourIter, diff3, right, left, changeRangeStart, changeRangeEnd));
      }

      // remove sentinel
      diff3.remove(0);
      return (RangeDifference[]) diff3.toArray(EMPTY_RESULT);
    } finally {
      if (pm != null) pm.done();
    }
  }