Removes all duplicate changes for a single file, and then returns (via filteredChanges) the filtered duplicates
| 496 | |
| 497 | //Removes all duplicate changes for a single file, and then returns (via filteredChanges) the filtered duplicates |
| 498 | DocumentChangeSet::ChangeResult DocumentChangeSetPrivate::removeDuplicates(const IndexedString& file, |
| 499 | ChangesList& filteredChanges) |
| 500 | { |
| 501 | using ChangesMap = QMultiMap<KTextEditor::Cursor, DocumentChangePointer>; |
| 502 | ChangesMap sortedChanges; |
| 503 | |
| 504 | for (const DocumentChangePointer& change : std::as_const(changes[file])) { |
| 505 | sortedChanges.insert(change->m_range.end(), change); |
| 506 | } |
| 507 | |
| 508 | //Remove duplicates |
| 509 | ChangesMap::iterator previous = sortedChanges.begin(); |
| 510 | for (ChangesMap::iterator it = ++sortedChanges.begin(); it != sortedChanges.end();) { |
| 511 | if ((*previous) && (*previous)->m_range.end() > (*it)->m_range.start()) { |
| 512 | //intersection |
| 513 | if (duplicateChanges((*previous), *it)) { |
| 514 | //duplicate, remove one |
| 515 | it = sortedChanges.erase(it); |
| 516 | continue; |
| 517 | } |
| 518 | //When two changes contain each other, and the container change is set to ignore old text, then it should be safe to |
| 519 | //just ignore the contained change, and apply the bigger change |
| 520 | else if ((*it)->m_range.contains((*previous)->m_range) && (*it)->m_ignoreOldText) { |
| 521 | qCDebug(LANGUAGE) << "Removing change: " << (*previous)->m_oldText << "->" << (*previous)->m_newText |
| 522 | << ", because it is contained by change: " << (*it)->m_oldText << "->" << |
| 523 | (*it)->m_newText; |
| 524 | sortedChanges.erase(previous); |
| 525 | } |
| 526 | //This case is for when both have the same end, either of them could be the containing range |
| 527 | else if ((*previous)->m_range.contains((*it)->m_range) && (*previous)->m_ignoreOldText) { |
| 528 | qCDebug(LANGUAGE) << "Removing change: " << (*it)->m_oldText << "->" << (*it)->m_newText |
| 529 | << ", because it is contained by change: " << (*previous)->m_oldText |
| 530 | << "->" << (*previous)->m_newText; |
| 531 | it = sortedChanges.erase(it); |
| 532 | continue; |
| 533 | } else { |
| 534 | return DocumentChangeSet::ChangeResult( |
| 535 | i18nc("Inconsistent change-request at <document>:" |
| 536 | "intersecting changes: " |
| 537 | "<previous-oldText> -> <previous-newText> @<range> & " |
| 538 | "<new-oldText> -> <new-newText> @<range>", |
| 539 | "Inconsistent change-request at %1; " |
| 540 | "intersecting changes: " |
| 541 | "\"%2\"->\"%3\"@%4 & \"%5\"->\"%6\"@%7 ", |
| 542 | file.str(), |
| 543 | (*previous)->m_oldText, |
| 544 | (*previous)->m_newText, |
| 545 | printRange((*previous)->m_range), |
| 546 | (*it)->m_oldText, |
| 547 | (*it)->m_newText, |
| 548 | printRange((*it)->m_range))); |
| 549 | } |
| 550 | } |
| 551 | previous = it; |
| 552 | ++it; |
| 553 | } |
| 554 | |
| 555 | filteredChanges = sortedChanges.values(); |