diff --git a/src/libs/utils/changeset.cpp b/src/libs/utils/changeset.cpp index 614fbbc983d005ce89588890e80e82f7bc7b7b3c..2f8ad44a490617f239452f2735fe09053177333c 100644 --- a/src/libs/utils/changeset.cpp +++ b/src/libs/utils/changeset.cpp @@ -44,196 +44,312 @@ namespace Utils { ChangeSet::ChangeSet() - : m_string(0), m_cursor(0) + : m_string(0), m_cursor(0), m_error(false) { } static bool overlaps(int posA, int lengthA, int posB, int lengthB) { - return (posA < posB + lengthB && posA + lengthA > posB + lengthB) - || (posA < posB && posA + lengthA > posB); + if (lengthB > 0) { + return + // right edge of B contained in A + (posA < posB + lengthB && posA + lengthA >= posB + lengthB) + // left edge of B contained in A + || (posA <= posB && posA + lengthA > posB) + // A contained in B + || (posB < posA && posB + lengthB > posA + lengthA); + } else { + return (posB > posA && posB < posA + lengthA); + } } bool ChangeSet::hasOverlap(int pos, int length) { - { - QListIterator<Replace> i(m_replaceList); - while (i.hasNext()) { - const Replace &cmd = i.next(); - if (overlaps(pos, length, cmd.pos, cmd.length)) + QListIterator<EditOp> i(m_operationList); + while (i.hasNext()) { + const EditOp &cmd = i.next(); + + switch (cmd.type) { + case EditOp::Replace: + if (overlaps(pos, length, cmd.pos1, cmd.length)) return true; - } - } - { - QListIterator<Move> i(m_moveList); - while (i.hasNext()) { - const Move &cmd = i.next(); - if (overlaps(pos, length, cmd.pos, cmd.length)) + break; + + case EditOp::Move: + if (overlaps(pos, length, cmd.pos1, cmd.length)) + return true; + if (cmd.pos2 > pos && cmd.pos2 < pos + length) return true; + break; + + case EditOp::Insert: + if (cmd.pos1 > pos && cmd.pos1 < pos + length) + return true; + break; + + case EditOp::Remove: + if (overlaps(pos, length, cmd.pos1, cmd.length)) + return true; + break; + + case EditOp::Flip: + if (overlaps(pos, length, cmd.pos1, cmd.length)) + return true; + if (overlaps(pos, length, cmd.pos2, cmd.length)) + return true; + break; + + case EditOp::Copy: + if (overlaps(pos, length, cmd.pos1, cmd.length)) + return true; + if (cmd.pos2 > pos && cmd.pos2 < pos + length) + return true; + break; + + case EditOp::Unset: + break; } - return false; } -} -bool ChangeSet::hasMoveInto(int pos, int length) -{ - QListIterator<Move> i(m_moveList); - while (i.hasNext()) { - const Move &cmd = i.next(); - if (cmd.to >= pos && cmd.to < pos + length) - return true; - } return false; } bool ChangeSet::isEmpty() const { - if (m_replaceList.isEmpty() && m_moveList.isEmpty()) - return true; + return m_operationList.isEmpty(); +} - return false; +QList<ChangeSet::EditOp> ChangeSet::operationList() const +{ + return m_operationList; +} + +void ChangeSet::clear() +{ + m_string = 0; + m_cursor = 0; + m_operationList.clear(); + m_error = false; } -QList<ChangeSet::Replace> ChangeSet::replaceList() const +bool ChangeSet::replace(int pos, int length, const QString &replacement) { - return m_replaceList; + if (hasOverlap(pos, length)) + m_error = true; + + EditOp cmd(EditOp::Replace); + cmd.pos1 = pos; + cmd.length = length; + cmd.text = replacement; + m_operationList += cmd; + + return !m_error; } -QList<ChangeSet::Move> ChangeSet::moveList() const +bool ChangeSet::move(int pos, int length, int to) { - return m_moveList; + if (hasOverlap(pos, length) + || hasOverlap(to, 0) + || overlaps(pos, length, to, 0)) + m_error = true; + + EditOp cmd(EditOp::Move); + cmd.pos1 = pos; + cmd.length = length; + cmd.pos2 = to; + m_operationList += cmd; + + return !m_error; } -void ChangeSet::clear() +bool ChangeSet::insert(int pos, const QString &text) { - m_string = 0; - m_cursor = 0; - m_replaceList.clear(); - m_moveList.clear(); + if (hasOverlap(pos, 0)) + m_error = true; + + EditOp cmd(EditOp::Insert); + cmd.pos1 = pos; + cmd.text = text; + m_operationList += cmd; + + return !m_error; } -void ChangeSet::replace(int pos, int length, const QString &replacement) +bool ChangeSet::remove(int pos, int length) { - Q_ASSERT(!hasOverlap(pos, length)); - Q_ASSERT(!hasMoveInto(pos, length)); + if (hasOverlap(pos, length)) + m_error = true; - Replace cmd; - cmd.pos = pos; + EditOp cmd(EditOp::Remove); + cmd.pos1 = pos; cmd.length = length; - cmd.replacement = replacement; - m_replaceList += cmd; + m_operationList += cmd; + + return !m_error; } -void ChangeSet::move(int pos, int length, int to) +bool ChangeSet::flip(int pos1, int length, int pos2) { - Q_ASSERT(!hasOverlap(pos, length)); + if (hasOverlap(pos1, length) + || hasOverlap(pos2, length) + || overlaps(pos1, length, pos2, length)) + m_error = true; - Move cmd; - cmd.pos = pos; + EditOp cmd(EditOp::Flip); + cmd.pos1 = pos1; cmd.length = length; - cmd.to = to; - m_moveList += cmd; + cmd.pos2 = pos2; + m_operationList += cmd; + + return !m_error; } -void ChangeSet::doReplace(const Replace &replace) +bool ChangeSet::copy(int pos, int length, int to) { - int diff = replace.replacement.size() - replace.length; - { - QMutableListIterator<Replace> i(m_replaceList); - while (i.hasNext()) { - Replace &c = i.next(); - if (replace.pos < c.pos) - c.pos += diff; - else if (replace.pos + replace.length < c.pos + c.length) - c.length += diff; - } - } + if (hasOverlap(pos, length) + || hasOverlap(to, 0) + || overlaps(pos, length, to, 0)) + m_error = true; + + EditOp cmd(EditOp::Copy); + cmd.pos1 = pos; + cmd.length = length; + cmd.pos2 = to; + m_operationList += cmd; + + return !m_error; +} + +void ChangeSet::doReplace(const EditOp &replace, QList<EditOp> *replaceList) +{ + Q_ASSERT(replace.type == EditOp::Replace); + + int diff = replace.text.size() - replace.length; { - QMutableListIterator<Move> i(m_moveList); + QMutableListIterator<EditOp> i(*replaceList); while (i.hasNext()) { - Move &c = i.next(); - if (replace.pos < c.pos) - c.pos += diff; - else if (replace.pos + replace.length < c.pos + c.length) - c.length += diff; - - if (replace.pos < c.to) - c.to += diff; + EditOp &c = i.next(); + if (replace.pos1 <= c.pos1) + c.pos1 += diff; } } if (m_string) { - m_string->replace(replace.pos, replace.length, replace.replacement); + m_string->replace(replace.pos1, replace.length, replace.text); } else if (m_cursor) { - m_cursor->setPosition(replace.pos); - m_cursor->setPosition(replace.pos + replace.length, QTextCursor::KeepAnchor); - m_cursor->insertText(replace.replacement); + m_cursor->setPosition(replace.pos1); + m_cursor->setPosition(replace.pos1 + replace.length, QTextCursor::KeepAnchor); + m_cursor->insertText(replace.text); } } -void ChangeSet::doMove(const Move &move) +void ChangeSet::convertToReplace(const EditOp &op, QList<EditOp> *replaceList) { - QString text; - if (m_string) { - text = m_string->mid(move.pos, move.length); - } else if (m_cursor) { - m_cursor->setPosition(move.pos); - m_cursor->setPosition(move.pos + move.length, QTextCursor::KeepAnchor); - text = m_cursor->selectedText(); - } + EditOp replace1(EditOp::Replace); + EditOp replace2(EditOp::Replace); + + switch (op.type) { + case EditOp::Replace: + replaceList->append(op); + break; + + case EditOp::Move: + replace1.pos1 = op.pos1; + replace1.length = op.length; + replaceList->append(replace1); + + replace2.pos1 = op.pos2; + replace2.text = textAt(op.pos1, op.length); + replaceList->append(replace2); + break; + + case EditOp::Insert: + replace1.pos1 = op.pos1; + replace1.text = op.text; + replaceList->append(replace1); + break; - Replace cut; - cut.pos = move.pos; - cut.length = move.length; - Replace paste; - paste.pos = move.to; - paste.length = 0; - paste.replacement = text; - - m_replaceList.append(cut); - m_replaceList.append(paste); - - Replace cmd; - while (!m_replaceList.isEmpty()) { - cmd = m_replaceList.first(); - m_replaceList.removeFirst(); - doReplace(cmd); + case EditOp::Remove: + replace1.pos1 = op.pos1; + replace1.length = op.length; + replaceList->append(replace1); + break; + + case EditOp::Flip: + replace1.pos1 = op.pos1; + replace1.length = op.length; + replace1.text = textAt(op.pos2, op.length); + replaceList->append(replace1); + + replace2.pos1 = op.pos2; + replace2.length = op.length; + replace2.text = textAt(op.pos1, op.length); + replaceList->append(replace2); + break; + + case EditOp::Copy: + replace1.pos1 = op.pos2; + replace1.text = textAt(op.pos1, op.length); + replaceList->append(replace1); + break; + + case EditOp::Unset: + break; } } -void ChangeSet::write(QString *s) +bool ChangeSet::hadErrors() +{ + return m_error; +} + +void ChangeSet::apply(QString *s) { m_string = s; - write_helper(); + apply_helper(); m_string = 0; } -void ChangeSet::write(QTextCursor *textCursor) +void ChangeSet::apply(QTextCursor *textCursor) { m_cursor = textCursor; - write_helper(); + apply_helper(); m_cursor = 0; } -void ChangeSet::write_helper() +QString ChangeSet::textAt(int pos, int length) { - if (m_cursor) - m_cursor->beginEditBlock(); - { - Replace cmd; - while (!m_replaceList.isEmpty()) { - cmd = m_replaceList.first(); - m_replaceList.removeFirst(); - doReplace(cmd); - } + if (m_string) { + return m_string->mid(pos, length); + } else if (m_cursor) { + m_cursor->setPosition(pos); + m_cursor->setPosition(pos + length, QTextCursor::KeepAnchor); + return m_cursor->selectedText(); } + return QString(); +} + +void ChangeSet::apply_helper() +{ + // convert all ops to replace + QList<EditOp> replaceList; { - Move cmd; - while (!m_moveList.isEmpty()) { - cmd = m_moveList.first(); - m_moveList.removeFirst(); - doMove(cmd); + while (!m_operationList.isEmpty()) { + const EditOp cmd(m_operationList.first()); + m_operationList.removeFirst(); + convertToReplace(cmd, &replaceList); } } + + // execute replaces + if (m_cursor) + m_cursor->beginEditBlock(); + + while (!replaceList.isEmpty()) { + const EditOp cmd(replaceList.first()); + replaceList.removeFirst(); + doReplace(cmd, &replaceList); + } + if (m_cursor) m_cursor->endEditBlock(); } diff --git a/src/libs/utils/changeset.h b/src/libs/utils/changeset.h index c68efcdb6e024d7f038f60a007761032724d9ba0..7f953b402a9e5933e7b996dda51c3f47016d2801 100644 --- a/src/libs/utils/changeset.h +++ b/src/libs/utils/changeset.h @@ -46,6 +46,7 @@ #include <QtCore/QString> #include <QtCore/QList> +#include <QtCore/QSharedPointer> #include <QtGui/QTextCursor> namespace Utils { @@ -53,20 +54,26 @@ namespace Utils { class QTCREATOR_UTILS_EXPORT ChangeSet { public: - struct Replace { - Replace(): pos(0), length(0) {} - - int pos; + struct EditOp { + enum Type + { + Unset, + Replace, + Move, + Insert, + Remove, + Flip, + Copy + }; + + EditOp(): type(Unset), pos1(0), pos2(0), length(0) {} + EditOp(Type t): type(t), pos1(0), pos2(0), length(0) {} + + Type type; + int pos1; + int pos2; int length; - QString replacement; - }; - - struct Move { - Move(): pos(0), length(0), to(0) {} - - int pos; - int length; - int to; + QString text; }; public: @@ -74,31 +81,37 @@ public: bool isEmpty() const; - QList<Replace> replaceList() const; - QList<Move> moveList() const; // ### TODO: merge with replaceList + QList<EditOp> operationList() const; void clear(); - void replace(int pos, int length, const QString &replacement); - void move(int pos, int length, int to); + bool replace(int pos, int length, const QString &replacement); + bool move(int pos, int length, int to); + bool insert(int pos, const QString &text); + bool remove(int pos, int length); + bool flip(int pos1, int length, int pos2); + bool copy(int pos, int length, int to); + + bool hadErrors(); - void write(QString *s); - void write(QTextCursor *textCursor); + void apply(QString *s); + void apply(QTextCursor *textCursor); private: bool hasOverlap(int pos, int length); - bool hasMoveInto(int pos, int length); + QString textAt(int pos, int length); - void doReplace(const Replace &replace); - void doMove(const Move &move); + void doReplace(const EditOp &replace, QList<EditOp> *replaceList); + void convertToReplace(const EditOp &op, QList<EditOp> *replaceList); - void write_helper(); + void apply_helper(); private: QString *m_string; QTextCursor *m_cursor; - QList<Replace> m_replaceList; - QList<Move> m_moveList; + + QList<EditOp> m_operationList; + bool m_error; }; } // namespace Utils diff --git a/src/plugins/cppeditor/cppquickfix.cpp b/src/plugins/cppeditor/cppquickfix.cpp index 2240d67e680dcbaa6a80bb63d7aa759e5ef6f902..31420bcff041e747be1cab37b85e6854a9024cd9 100644 --- a/src/plugins/cppeditor/cppquickfix.cpp +++ b/src/plugins/cppeditor/cppquickfix.cpp @@ -769,7 +769,7 @@ void QuickFixOperation::apply() _textCursor.beginEditBlock(); - _changeSet.write(&_textCursor); + _changeSet.apply(&_textCursor); if (_topLevelNode) reindent(range); diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 193c1156ecb46e4197f8154f418e6b1d6eab36f7..28111c1bd38582e1ecc122d970ca16c9eff4d390 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -5,4 +5,5 @@ SUBDIRS += \ debugger \ fakevim \ # profilereader \ - aggregation + aggregation \ + changeset diff --git a/tests/auto/changeset/changeset.pro b/tests/auto/changeset/changeset.pro new file mode 100644 index 0000000000000000000000000000000000000000..5aa2358a65b7fd4ad0fa50488d254d86a47fdf3a --- /dev/null +++ b/tests/auto/changeset/changeset.pro @@ -0,0 +1,18 @@ + +QT += testlib + +# Defines import symbol as empty +DEFINES+=QTCREATOR_UTILS_STATIC_LIB + +UTILSDIR = ../../../src/libs + +SOURCES += \ + tst_changeset.cpp \ + $$UTILSDIR/utils/changeset.cpp + +HEADERS += \ + $$UTILSDIR/utils/changeset.h + +INCLUDEPATH += $$UTILSDIR + +TARGET=tst_$$TARGET diff --git a/tests/auto/changeset/tst_changeset.cpp b/tests/auto/changeset/tst_changeset.cpp new file mode 100644 index 0000000000000000000000000000000000000000..89e7be59d8467dae33eb72806bd9a6faaac2e1b6 --- /dev/null +++ b/tests/auto/changeset/tst_changeset.cpp @@ -0,0 +1,426 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include <utils/changeset.h> + +#include <QtTest/QtTest> + +class tst_ChangeSet : public QObject +{ + Q_OBJECT + +private slots: + void singleReplace(); + void singleMove(); + void singleInsert(); + void singleRemove(); + void singleFlip(); + void singleCopy(); + + void doubleInsert(); + void conflicts(); +}; + + +void tst_ChangeSet::singleReplace() +{ + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.replace(0, 2, "ghi")); + cs.apply(&test); + QCOMPARE(test, QLatin1String("ghicdef")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.replace(4, 2, "ghi")); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abcdghi")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.replace(3, 0, "ghi")); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abcghidef")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.replace(0, 6, "")); + cs.apply(&test); + QCOMPARE(test, QLatin1String("")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.replace(3, 10, "ghi")); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abcghi")); + } +} + +void tst_ChangeSet::singleMove() +{ + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.move(0, 2, 4)); + cs.apply(&test); + QCOMPARE(test, QLatin1String("cdabef")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.move(4, 2, 0)); + cs.apply(&test); + QCOMPARE(test, QLatin1String("efabcd")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.move(3, 10, 0)); + cs.apply(&test); + QCOMPARE(test, QLatin1String("defabc")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.move(3, 0, 0)); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abcdef")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.move(0, 1, 10)); + cs.apply(&test); + // ### maybe this should expand the string or error? + QCOMPARE(test, QLatin1String("bcdef")); + } +} + +void tst_ChangeSet::singleInsert() +{ + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.insert(0, "ghi")); + cs.apply(&test); + QCOMPARE(test, QLatin1String("ghiabcdef")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.insert(6, "ghi")); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abcdefghi")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.insert(3, "")); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abcdef")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.insert(7, "g")); + cs.apply(&test); + // ### maybe this should expand the string or error? + QCOMPARE(test, QLatin1String("abcdef")); + } +} + +void tst_ChangeSet::singleRemove() +{ + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.remove(0, 1)); + cs.apply(&test); + QCOMPARE(test, QLatin1String("bcdef")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.remove(3, 3)); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abc")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.remove(4, 10)); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abcd")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.remove(2, 0)); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abcdef")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.remove(7, 1)); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abcdef")); + } +} + +void tst_ChangeSet::singleFlip() +{ + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.flip(0, 2, 4)); + cs.apply(&test); + QCOMPARE(test, QLatin1String("efcdab")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.flip(1, 2, 3)); + cs.apply(&test); + QCOMPARE(test, QLatin1String("adebcf")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.flip(3, 0, 4)); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abcdef")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.flip(0, 6, 6)); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abcdef")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.flip(0, 6, 7)); + cs.apply(&test); + // ### maybe this should expand the string or error? + QCOMPARE(test, QLatin1String("")); + } + { + Utils::ChangeSet cs; + QCOMPARE(cs.flip(0, 3, 1), false); + } + { + Utils::ChangeSet cs; + QCOMPARE(cs.flip(0, 3, 2), false); + } + { + Utils::ChangeSet cs; + QVERIFY(cs.flip(3, 3, 0)); + QString test("abcdef"); + cs.apply(&test); + QCOMPARE(test, QLatin1String("defabc")); + } + { + Utils::ChangeSet cs; + QVERIFY(cs.flip(0, 3, 3)); + QString test("abcdef"); + cs.apply(&test); + QCOMPARE(test, QLatin1String("defabc")); + } +} + +void tst_ChangeSet::singleCopy() +{ + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.copy(0, 2, 4)); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abcdabef")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.copy(1, 2, 3)); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abcbcdef")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.copy(3, 0, 4)); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abcdef")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.copy(0, 6, 6)); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abcdefabcdef")); + } + { + Utils::ChangeSet cs; + QString test("abcdef"); + QVERIFY(cs.copy(0, 6, 7)); + cs.apply(&test); + // ### maybe this should expand the string or error? + QCOMPARE(test, QLatin1String("abcdef")); + } + { + Utils::ChangeSet cs; + QCOMPARE(cs.copy(0, 3, 1), false); + } + { + Utils::ChangeSet cs; + QCOMPARE(cs.copy(0, 3, 2), false); + } + { + Utils::ChangeSet cs; + QVERIFY(cs.copy(0, 3, 0)); + QString test("abcdef"); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abcabcdef")); + } + { + Utils::ChangeSet cs; + QVERIFY(cs.copy(0, 3, 3)); + QString test("abcdef"); + cs.apply(&test); + QCOMPARE(test, QLatin1String("abcabcdef")); + } +} + +void tst_ChangeSet::doubleInsert() +{ + { + Utils::ChangeSet cs; + QVERIFY(cs.insert(1, "01")); + QVERIFY(cs.insert(1, "234")); + QString test("abcdef"); + cs.apply(&test); + QCOMPARE(test, QLatin1String("a01234bcdef")); + } + { + Utils::ChangeSet cs; + QVERIFY(cs.insert(1, "234")); + QVERIFY(cs.insert(1, "01")); + QString test("abcdef"); + cs.apply(&test); + QCOMPARE(test, QLatin1String("a23401bcdef")); + } + { + Utils::ChangeSet cs; + QVERIFY(cs.insert(1, "01")); + QVERIFY(cs.remove(1, 1)); + QVERIFY(cs.insert(2, "234")); + QString test("abcdef"); + cs.apply(&test); + QCOMPARE(test, QLatin1String("a01234cdef")); + } +} + +void tst_ChangeSet::conflicts() +{ + { + Utils::ChangeSet cs; + QVERIFY(cs.move(1, 3, 5)); + QCOMPARE(cs.replace(0, 2, "abc"), false); + } + { + Utils::ChangeSet cs; + QVERIFY(cs.move(1, 3, 5)); + QCOMPARE(cs.replace(1, 3, "abc"), false); + } + { + Utils::ChangeSet cs; + QVERIFY(cs.move(1, 3, 5)); + QCOMPARE(cs.replace(1, 1, "abc"), false); + } + { + Utils::ChangeSet cs; + QVERIFY(cs.move(1, 3, 5)); + QCOMPARE(cs.replace(2, 0, "abc"), false); + } + { + Utils::ChangeSet cs; + QVERIFY(cs.move(1, 3, 5)); + QCOMPARE(cs.replace(2, 1, "abc"), false); + } + { + Utils::ChangeSet cs; + QVERIFY(cs.move(1, 3, 5)); + QCOMPARE(cs.replace(3, 0, "abc"), false); + } + { + Utils::ChangeSet cs; + QVERIFY(cs.move(1, 3, 5)); + QCOMPARE(cs.replace(3, 1, "abc"), false); + } + { + Utils::ChangeSet cs; + QVERIFY(cs.move(1, 3, 5)); + QCOMPARE(cs.replace(4, 2, "abc"), false); + } + + { + Utils::ChangeSet cs; + QVERIFY(cs.move(1, 3, 5)); + QVERIFY(cs.replace(0, 1, "bla")); + QString test("abcdef"); + cs.apply(&test); + QCOMPARE(test, QLatin1String("blaebcdf")); + } + { + Utils::ChangeSet cs; + QVERIFY(cs.move(1, 3, 5)); + QVERIFY(cs.replace(4, 1, "bla")); + QString test("abcdef"); + cs.apply(&test); + QCOMPARE(test, QLatin1String("ablabcdf")); + } + { + Utils::ChangeSet cs; + QVERIFY(cs.move(1, 3, 5)); + QVERIFY(cs.replace(5, 1, "bla")); + QString test("abcdef"); + cs.apply(&test); + QCOMPARE(test, QLatin1String("aebcdbla")); + } +} + +QTEST_MAIN(tst_ChangeSet) + +#include "tst_changeset.moc"