diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index 1d3aed67ae1..afe74fbd98f 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -138,9 +138,9 @@ QString DiffEditorPlugin::getFileContents(const QString &fileName) const #include "sidebysidediffeditorwidget.h" -void DiffEditor::Internal::DiffEditorPlugin::testAssemblyRows() +void DiffEditor::Internal::DiffEditorPlugin::testFixPositions() { - SideBySideDiffEditorWidget::testAssemblyRows(); + SideBySideDiffEditorWidget::testFixPositions(); } #endif // WITH_TESTS diff --git a/src/plugins/diffeditor/diffeditorplugin.h b/src/plugins/diffeditor/diffeditorplugin.h index e40a10014d3..703c97496fd 100644 --- a/src/plugins/diffeditor/diffeditorplugin.h +++ b/src/plugins/diffeditor/diffeditorplugin.h @@ -54,7 +54,7 @@ private slots: void diff(); #ifdef WITH_TESTS - void testAssemblyRows(); + void testFixPositions(); #endif // WITH_TESTS private: diff --git a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp index 11c0bd3e8c8..e64fb83c59d 100644 --- a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp +++ b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp @@ -97,6 +97,7 @@ public: ChunkData() : contextChunk(false) {} QList rows; bool contextChunk; + // start position, end position, TextLineData::Separator lines not taken into account QMap changedLeftPositions; // counting from the beginning of the chunk QMap changedRightPositions; // counting from the beginning of the chunk }; @@ -113,49 +114,16 @@ public: ////////////////////// static QList assemblyRows(const QStringList &lines, - const QMap &lineSpans, - const QMap &changedPositions, - QMap *outputChangedPositions) + const QMap &lineSpans) { QList data; - int previousSpanOffset = 0; - int spanOffset = 0; - int pos = 0; - bool usePreviousSpanOffsetForStartPosition = false; - QMap::ConstIterator changedIt = changedPositions.constBegin(); - QMap::ConstIterator changedEnd = changedPositions.constEnd(); const int lineCount = lines.count(); for (int i = 0; i <= lineCount; i++) { - for (int j = 0; j < lineSpans.value(i); j++) { + for (int j = 0; j < lineSpans.value(i); j++) data.append(TextLineData(TextLineData::Separator)); - spanOffset++; - } - if (i < lineCount) { - const int textLength = lines.at(i).count() + 1; - pos += textLength; + if (i < lineCount) data.append(lines.at(i)); - } - while (changedIt != changedEnd) { - if (changedIt.key() >= pos) - break; - - if (changedIt.value() >= pos) { - usePreviousSpanOffsetForStartPosition = true; - previousSpanOffset = spanOffset; - break; - } - - const int startSpanOffset = usePreviousSpanOffsetForStartPosition - ? previousSpanOffset : spanOffset; - usePreviousSpanOffsetForStartPosition = false; - - const int startPos = changedIt.key() + startSpanOffset; - const int endPos = changedIt.value() + spanOffset; - if (outputChangedPositions) - outputChangedPositions->insert(startPos, endPos); - ++changedIt; - } } return data; } @@ -221,9 +189,6 @@ static ChunkData calculateOriginalData(const QList &leftDiffList, QStringList leftLines; QStringList rightLines; - // - QMap leftChangedPositions; - QMap rightChangedPositions; // QMap leftSpans; QMap rightSpans; @@ -248,13 +213,13 @@ static ChunkData calculateOriginalData(const QList &leftDiffList, if (leftDiff.command == Diff::Delete) { // process delete - handleDifference(leftDiff.text, &leftLines, &leftChangedPositions, &leftLineNumber, &leftCharNumber); + handleDifference(leftDiff.text, &leftLines, &chunkData.changedLeftPositions, &leftLineNumber, &leftCharNumber); lastLineEqual = lastLinesEqual(leftLines, rightLines); i++; } if (rightDiff.command == Diff::Insert) { // process insert - handleDifference(rightDiff.text, &rightLines, &rightChangedPositions, &rightLineNumber, &rightCharNumber); + handleDifference(rightDiff.text, &rightLines, &chunkData.changedRightPositions, &rightLineNumber, &rightCharNumber); lastLineEqual = lastLinesEqual(leftLines, rightLines); j++; } @@ -326,13 +291,9 @@ static ChunkData calculateOriginalData(const QList &leftDiffList, } QList leftData = assemblyRows(leftLines, - leftSpans, - leftChangedPositions, - &chunkData.changedLeftPositions); + leftSpans); QList rightData = assemblyRows(rightLines, - rightSpans, - rightChangedPositions, - &chunkData.changedRightPositions); + rightSpans); // fill ending separators for (int i = leftData.count(); i < rightData.count(); i++) @@ -1230,6 +1191,8 @@ FileData SideBySideDiffEditorWidget::calculateContextData(const ChunkData &origi int rightCharCounter = 0; QMap::ConstIterator leftChangedIt = originalData.changedLeftPositions.constBegin(); QMap::ConstIterator rightChangedIt = originalData.changedRightPositions.constBegin(); + const QMap::ConstIterator leftChangedItEnd = originalData.changedLeftPositions.constEnd(); + const QMap::ConstIterator rightChangedItEnd = originalData.changedRightPositions.constEnd(); while (i < originalData.rows.count()) { if (!hiddenRows.contains(i)) { ChunkData chunkData; @@ -1242,11 +1205,13 @@ FileData SideBySideDiffEditorWidget::calculateContextData(const ChunkData &origi RowData rowData = originalData.rows.at(i); chunkData.rows.append(rowData); - leftCharCounter += rowData.leftLine.text.count() + 1; // +1 for '\n' - rightCharCounter += rowData.rightLine.text.count() + 1; // +1 for '\n' + if (rowData.leftLine.textLineType == TextLineData::TextLine) + leftCharCounter += rowData.leftLine.text.count() + 1; // +1 for '\n' + if (rowData.rightLine.textLineType == TextLineData::TextLine) + rightCharCounter += rowData.rightLine.text.count() + 1; // +1 for '\n' i++; } - while (leftChangedIt != originalData.changedLeftPositions.constEnd()) { + while (leftChangedIt != leftChangedItEnd) { if (leftChangedIt.key() < leftOffset || leftChangedIt.key() > leftCharCounter) break; @@ -1256,7 +1221,7 @@ FileData SideBySideDiffEditorWidget::calculateContextData(const ChunkData &origi chunkData.changedLeftPositions.insert(startPos - leftOffset, endPos - leftOffset); leftChangedIt++; } - while (rightChangedIt != originalData.changedRightPositions.constEnd()) { + while (rightChangedIt != rightChangedItEnd) { if (rightChangedIt.key() < rightOffset || rightChangedIt.key() > rightCharCounter) break; @@ -1276,8 +1241,10 @@ FileData SideBySideDiffEditorWidget::calculateContextData(const ChunkData &origi RowData rowData = originalData.rows.at(i); chunkData.rows.append(rowData); - leftCharCounter += rowData.leftLine.text.count() + 1; // +1 for '\n' - rightCharCounter += rowData.rightLine.text.count() + 1; // +1 for '\n' + if (rowData.leftLine.textLineType == TextLineData::TextLine) + leftCharCounter += rowData.leftLine.text.count() + 1; // +1 for '\n' + if (rowData.rightLine.textLineType == TextLineData::TextLine) + rightCharCounter += rowData.rightLine.text.count() + 1; // +1 for '\n' i++; } fileData.chunks.append(chunkData); @@ -1446,6 +1413,86 @@ QList SideBySideDiffEditorWidget::colorPositions( return lineSelections; } +void fixPositions(QMap::ConstIterator *it, + const QMap::ConstIterator &itEnd, + int fileOffset, + int charCounter, + int spanCounter, + int *lastSpanCounter, + QMap *changedPositions) +{ + while (*it != itEnd) { + if (it->key() >= charCounter) + break; + + if (it->value() >= charCounter) { + if (*lastSpanCounter != -1) + break; + + *lastSpanCounter = spanCounter; + break; + } + + const int startSpanOffset = *lastSpanCounter != -1 + ? *lastSpanCounter : spanCounter; + *lastSpanCounter = -1; + + const int startPos = it->key() + startSpanOffset + fileOffset; + const int endPos = it->value() + spanCounter + fileOffset; + changedPositions->insert(startPos, endPos); + ++(*it); + } +} + +static void fixPositions(const ChunkData &chunkData, + const int leftFileOffset, + const int rightFileOffset, + QMap *leftCharPos, + QMap *rightCharPos) +{ + QMap::ConstIterator leftIt = chunkData.changedLeftPositions.constBegin(); + const QMap::ConstIterator leftItEnd = chunkData.changedLeftPositions.constEnd(); + QMap::ConstIterator rightIt = chunkData.changedRightPositions.constBegin(); + const QMap::ConstIterator rightItEnd = chunkData.changedRightPositions.constEnd(); + if (leftIt == leftItEnd && rightIt == rightItEnd) + return; + + int leftCharCounter = 0; + int rightCharCounter = 0; + int leftSpanCounter = 0; + int rightSpanCounter = 0; + int leftLastSpanCounter = -1; + int rightLastSpanCounter = -1; + for (int i = 0; i < chunkData.rows.count(); i++) { + const RowData &row = chunkData.rows.at(i); + + if (row.leftLine.textLineType == TextLineData::TextLine) + leftCharCounter += row.leftLine.text.count() + 1; // +1 for '\n' + else + ++leftSpanCounter; + + if (row.rightLine.textLineType == TextLineData::TextLine) + rightCharCounter += row.rightLine.text.count() + 1; // +1 for '\n' + else + ++rightSpanCounter; + + fixPositions(&leftIt, + leftItEnd, + leftFileOffset, + leftCharCounter, + leftSpanCounter, + &leftLastSpanCounter, + leftCharPos); + fixPositions(&rightIt, + rightItEnd, + rightFileOffset, + rightCharCounter, + rightSpanCounter, + &rightLastSpanCounter, + rightCharPos); + } +} + void SideBySideDiffEditorWidget::colorDiff(const QList &fileDataList) { QPalette pal = m_leftEditor->extraArea()->palette(); @@ -1494,19 +1541,7 @@ void SideBySideDiffEditorWidget::colorDiff(const QList &fileDataList) leftLastSkippedBlockStartPos = leftPos; rightLastSkippedBlockStartPos = rightPos; - QMapIterator itLeft(chunkData.changedLeftPositions); - while (itLeft.hasNext()) { - itLeft.next(); - - leftCharPos[itLeft.key() + leftFileOffset] = itLeft.value() + leftFileOffset; - } - - QMapIterator itRight(chunkData.changedRightPositions); - while (itRight.hasNext()) { - itRight.next(); - - rightCharPos[itRight.key() + rightFileOffset] = itRight.value() + rightFileOffset; - } + fixPositions(chunkData, leftFileOffset, rightFileOffset, &leftCharPos, &rightCharPos); for (int k = 0; k < chunkData.rows.count(); k++) { RowData rowData = chunkData.rows.at(k); @@ -1840,25 +1875,36 @@ void SideBySideDiffEditorWidget::synchronizeFoldings(SideDiffEditorWidget *sourc #ifdef WITH_TESTS #include -void DiffEditor::SideBySideDiffEditorWidget::testAssemblyRows() +void DiffEditor::SideBySideDiffEditorWidget::testFixPositions() { - QStringList lines; - lines << QLatin1String("abcd efgh"); // line 0 - lines << QLatin1String("ijkl mnop"); // line 1 + ChunkData chunkData; + chunkData.rows.append(RowData(TextLineData(QLatin1String("abcd efgh")), TextLineData(QLatin1String("abcd ")))); + chunkData.rows.append(RowData(TextLineData(TextLineData::Separator), TextLineData(QLatin1String("")))); + chunkData.rows.append(RowData(TextLineData(TextLineData::Separator), TextLineData(QLatin1String("")))); + chunkData.rows.append(RowData(TextLineData(TextLineData::Separator), TextLineData(QLatin1String("")))); + chunkData.rows.append(RowData(TextLineData(TextLineData::Separator), TextLineData(QLatin1String("")))); + chunkData.rows.append(RowData(TextLineData(TextLineData::Separator), TextLineData(QLatin1String("")))); + chunkData.rows.append(RowData(TextLineData(TextLineData::Separator), TextLineData(QLatin1String("")))); + chunkData.rows.append(RowData(TextLineData(QLatin1String("ijkl mnop")), TextLineData(QLatin1String(" mnop")))); - QMap lineSpans; - lineSpans[1] = 6; // before line 1 insert 6 span lines + chunkData.changedLeftPositions.insert(5, 14); // changed text from position 5 to position 14, occupy 9 characters: "efgh\nijkl" - QMap changedPositions; - changedPositions[5] = 14; // changed text from position 5 to position 14, occupy 9 characters: "efgh\nijkl" + QMap expectedLeftChangedPositions; + expectedLeftChangedPositions[5] = 20; // "efgh\n[\n\n\n\n\n\n]ijkl" - [\n] means inserted span - QMap expectedChangedPositions; - expectedChangedPositions[5] = 20; // "efgh\n[\n\n\n\n\n\n]ijkl" - [\n] means inserted span + QMap outputLeftChangedPositions; + QMap outputRightChangedPositions; - QMap outputChangedPositions; + fixPositions(chunkData, 0, 0, &outputLeftChangedPositions, &outputRightChangedPositions); + QVERIFY(outputLeftChangedPositions == expectedLeftChangedPositions); - assemblyRows(lines, lineSpans, changedPositions, &outputChangedPositions); - QVERIFY(outputChangedPositions == expectedChangedPositions); + QMap expectedLeftMovedPositions; + expectedLeftMovedPositions[15] = 30; // moved by 10 + outputLeftChangedPositions.clear(); + outputRightChangedPositions.clear(); + + fixPositions(chunkData, 10, 0, &outputLeftChangedPositions, &outputRightChangedPositions); + QVERIFY(outputLeftChangedPositions == expectedLeftMovedPositions); } #endif // WITH_TESTS diff --git a/src/plugins/diffeditor/sidebysidediffeditorwidget.h b/src/plugins/diffeditor/sidebysidediffeditorwidget.h index 5686fbf0a7d..cf7cbbd8849 100644 --- a/src/plugins/diffeditor/sidebysidediffeditorwidget.h +++ b/src/plugins/diffeditor/sidebysidediffeditorwidget.h @@ -63,7 +63,7 @@ public: DiffEditorGuiController *diffEditorGuiController() const; #ifdef WITH_TESTS - static void testAssemblyRows(); + static void testFixPositions(); #endif // WITH_TESTS private slots: