DiffEditor: Use QtConcurrent invocation for async tasks

Change-Id: I06640837ffee830e60e8dd2a566f9388f8444010
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
Jarek Kobus
2023-02-11 23:21:58 +01:00
parent a8214665fe
commit 5ff073df19
11 changed files with 114 additions and 170 deletions

View File

@@ -14,11 +14,10 @@ publication by Neil Fraser: http://neil.fraser.name/writing/diff/
#include "utilstr.h" #include "utilstr.h"
#include <QList> #include <QList>
#include <QRegularExpression>
#include <QStringList>
#include <QMap> #include <QMap>
#include <QPair> #include <QPair>
#include <QFutureInterfaceBase> #include <QRegularExpression>
#include <QStringList>
namespace Utils { namespace Utils {
@@ -937,10 +936,9 @@ QString Diff::toString() const
/////////////// ///////////////
Differ::Differ(QFutureInterfaceBase *jobController) Differ::Differ(const QFuture<void> &future)
: m_jobController(jobController) : m_future(future)
{ {
} }
QList<Diff> Differ::diff(const QString &text1, const QString &text2) QList<Diff> Differ::diff(const QString &text1, const QString &text2)
@@ -1075,7 +1073,7 @@ QList<Diff> Differ::diffMyers(const QString &text1, const QString &text2)
int kMinReverse = -D; int kMinReverse = -D;
int kMaxReverse = D; int kMaxReverse = D;
for (int d = 0; d <= D; d++) { for (int d = 0; d <= D; d++) {
if (m_jobController && m_jobController->isCanceled()) { if (m_future.isCanceled()) {
delete [] forwardV; delete [] forwardV;
delete [] reverseV; delete [] reverseV;
return QList<Diff>(); return QList<Diff>();
@@ -1193,17 +1191,10 @@ QList<Diff> Differ::diffNonCharMode(const QString &text1, const QString &text2)
QString lastDelete; QString lastDelete;
QString lastInsert; QString lastInsert;
QList<Diff> newDiffList; QList<Diff> newDiffList;
if (m_jobController) {
m_jobController->setProgressRange(0, diffList.count());
m_jobController->setProgressValue(0);
}
for (int i = 0; i <= diffList.count(); i++) { for (int i = 0; i <= diffList.count(); i++) {
if (m_jobController) { if (m_future.isCanceled()) {
if (m_jobController->isCanceled()) { m_currentDiffMode = diffMode;
m_currentDiffMode = diffMode; return {};
return QList<Diff>();
}
m_jobController->setProgressValue(i + 1);
} }
const Diff diffItem = i < diffList.count() const Diff diffItem = i < diffList.count()
? diffList.at(i) ? diffList.at(i)

View File

@@ -5,12 +5,12 @@
#include "utils_global.h" #include "utils_global.h"
#include <QFuture>
#include <QString> #include <QString>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
template <class K, class T> template <class K, class T>
class QMap; class QMap;
class QFutureInterfaceBase;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Utils { namespace Utils {
@@ -42,7 +42,7 @@ public:
WordMode, WordMode,
LineMode LineMode
}; };
Differ(QFutureInterfaceBase *jobController = nullptr); Differ(const QFuture<void> &future = {});
QList<Diff> diff(const QString &text1, const QString &text2); QList<Diff> diff(const QString &text1, const QString &text2);
QList<Diff> unifiedDiff(const QString &text1, const QString &text2); QList<Diff> unifiedDiff(const QString &text1, const QString &text2);
void setDiffMode(DiffMode mode); void setDiffMode(DiffMode mode);
@@ -90,7 +90,7 @@ private:
int subTextStart); int subTextStart);
DiffMode m_diffMode = Differ::LineMode; DiffMode m_diffMode = Differ::LineMode;
DiffMode m_currentDiffMode = Differ::LineMode; DiffMode m_currentDiffMode = Differ::LineMode;
QFutureInterfaceBase *m_jobController = nullptr; QFuture<void> m_future;
}; };
} // namespace Utils } // namespace Utils

View File

@@ -291,8 +291,8 @@ Core::IDocument::OpenResult DiffEditorDocument::open(QString *errorString, const
return OpenResult::ReadError; return OpenResult::ReadError;
} }
bool ok = false; const std::optional<QList<FileData>> fileDataList = DiffUtils::readPatch(patch);
QList<FileData> fileDataList = DiffUtils::readPatch(patch, &ok); bool ok = fileDataList.has_value();
if (!ok) { if (!ok) {
*errorString = Tr::tr("Could not parse patch file \"%1\". " *errorString = Tr::tr("Could not parse patch file \"%1\". "
"The content is not of unified diff format.") "The content is not of unified diff format.")
@@ -302,7 +302,7 @@ Core::IDocument::OpenResult DiffEditorDocument::open(QString *errorString, const
emit temporaryStateChanged(); emit temporaryStateChanged();
setFilePath(filePath.absoluteFilePath()); setFilePath(filePath.absoluteFilePath());
setWorkingDirectory(filePath.absoluteFilePath()); setWorkingDirectory(filePath.absoluteFilePath());
setDiffFiles(fileDataList); setDiffFiles(*fileDataList);
} }
endReload(ok); endReload(ok);
if (!ok && readResult == TextFileFormat::ReadEncodingError) if (!ok && readResult == TextFileFormat::ReadEncodingError)

View File

@@ -47,13 +47,12 @@ public:
m_ignoreWhitespace(ignoreWhitespace) m_ignoreWhitespace(ignoreWhitespace)
{} {}
void operator()(QFutureInterface<FileData> &futureInterface, void operator()(QPromise<FileData> &promise, const ReloadInput &reloadInput) const
const ReloadInput &reloadInput) const
{ {
if (reloadInput.text[LeftSide] == reloadInput.text[RightSide]) if (reloadInput.text[LeftSide] == reloadInput.text[RightSide])
return; // We show "No difference" in this case, regardless if it's binary or not return; // We show "No difference" in this case, regardless if it's binary or not
Differ differ(&futureInterface); Differ differ(QFuture<void>(promise.future()));
FileData fileData; FileData fileData;
if (!reloadInput.binaryFiles) { if (!reloadInput.binaryFiles) {
@@ -85,7 +84,7 @@ public:
fileData.fileInfo = reloadInput.fileInfo; fileData.fileInfo = reloadInput.fileInfo;
fileData.fileOperation = reloadInput.fileOperation; fileData.fileOperation = reloadInput.fileOperation;
fileData.binaryFiles = reloadInput.binaryFiles; fileData.binaryFiles = reloadInput.binaryFiles;
futureInterface.reportResult(fileData); promise.addResult(fileData);
} }
private: private:
@@ -115,7 +114,7 @@ DiffFilesController::DiffFilesController(IDocument *document)
QList<std::optional<FileData>> *outputList = storage.activeStorage(); QList<std::optional<FileData>> *outputList = storage.activeStorage();
const auto setupDiff = [this](AsyncTask<FileData> &async, const ReloadInput &reloadInput) { const auto setupDiff = [this](AsyncTask<FileData> &async, const ReloadInput &reloadInput) {
async.setAsyncCallData(DiffFile(ignoreWhitespace(), contextLineCount()), reloadInput); async.setConcurrentCallData(DiffFile(ignoreWhitespace(), contextLineCount()), reloadInput);
async.setFutureSynchronizer(Internal::DiffEditorPlugin::futureSynchronizer()); async.setFutureSynchronizer(Internal::DiffEditorPlugin::futureSynchronizer());
}; };
const auto onDiffDone = [outputList](const AsyncTask<FileData> &async, int i) { const auto onDiffDone = [outputList](const AsyncTask<FileData> &async, int i) {
@@ -771,13 +770,13 @@ void DiffEditor::Internal::DiffEditorPlugin::testMakePatch()
QCOMPARE(result, patchText); QCOMPARE(result, patchText);
bool ok; const std::optional<QList<FileData>> resultList = DiffUtils::readPatch(result);
QList<FileData> resultList = DiffUtils::readPatch(result, &ok); const bool ok = resultList.has_value();
QVERIFY(ok); QVERIFY(ok);
QCOMPARE(resultList.count(), 1); QCOMPARE(resultList->count(), 1);
for (int i = 0; i < resultList.count(); i++) { for (int i = 0; i < resultList->count(); i++) {
const FileData &resultFileData = resultList.at(i); const FileData &resultFileData = resultList->at(i);
QCOMPARE(resultFileData.fileInfo[LeftSide].fileName, fileName); QCOMPARE(resultFileData.fileInfo[LeftSide].fileName, fileName);
QCOMPARE(resultFileData.fileInfo[RightSide].fileName, fileName); QCOMPARE(resultFileData.fileInfo[RightSide].fileName, fileName);
QCOMPARE(resultFileData.chunks.count(), 1); QCOMPARE(resultFileData.chunks.count(), 1);
@@ -1335,14 +1334,14 @@ void DiffEditor::Internal::DiffEditorPlugin::testReadPatch()
QFETCH(QString, sourcePatch); QFETCH(QString, sourcePatch);
QFETCH(QList<FileData>, fileDataList); QFETCH(QList<FileData>, fileDataList);
bool ok; const std::optional<QList<FileData>> result = DiffUtils::readPatch(sourcePatch);
const QList<FileData> &result = DiffUtils::readPatch(sourcePatch, &ok); const bool ok = result.has_value();
QVERIFY(ok); QVERIFY(ok);
QCOMPARE(result.count(), fileDataList.count()); QCOMPARE(result->count(), fileDataList.count());
for (int i = 0; i < fileDataList.count(); i++) { for (int i = 0; i < fileDataList.count(); i++) {
const FileData &origFileData = fileDataList.at(i); const FileData &origFileData = fileDataList.at(i);
const FileData &resultFileData = result.at(i); const FileData &resultFileData = result->at(i);
QCOMPARE(resultFileData.fileInfo[LeftSide].fileName, origFileData.fileInfo[LeftSide].fileName); QCOMPARE(resultFileData.fileInfo[LeftSide].fileName, origFileData.fileInfo[LeftSide].fileName);
QCOMPARE(resultFileData.fileInfo[LeftSide].typeInfo, origFileData.fileInfo[LeftSide].typeInfo); QCOMPARE(resultFileData.fileInfo[LeftSide].typeInfo, origFileData.fileInfo[LeftSide].typeInfo);
QCOMPARE(resultFileData.fileInfo[RightSide].fileName, origFileData.fileInfo[RightSide].fileName); QCOMPARE(resultFileData.fileInfo[RightSide].fileName, origFileData.fileInfo[RightSide].fileName);

View File

@@ -6,7 +6,8 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/differ.h> #include <utils/differ.h>
#include <QFutureInterfaceBase> #include <QFuture>
#include <QPromise>
#include <QRegularExpression> #include <QRegularExpression>
#include <QStringList> #include <QStringList>
#include <QTextStream> #include <QTextStream>
@@ -892,7 +893,7 @@ static FileData readDiffHeaderAndChunks(QStringView headerAndChunks, bool *ok)
} }
static QList<FileData> readDiffPatch(QStringView patch, bool *ok, QFutureInterfaceBase *jobController) static void readDiffPatch(QPromise<QList<FileData>> &promise, QStringView patch)
{ {
const QRegularExpression diffRegExp("(?:\\n|^)" // new line of the beginning of a patch const QRegularExpression diffRegExp("(?:\\n|^)" // new line of the beginning of a patch
"(" // either "(" // either
@@ -911,23 +912,20 @@ static QList<FileData> readDiffPatch(QStringView patch, bool *ok, QFutureInterfa
")"); // end of or ")"); // end of or
bool readOk = false; bool readOk = false;
QList<FileData> fileDataList; QList<FileData> fileDataList;
QRegularExpressionMatch diffMatch = diffRegExp.match(patch); QRegularExpressionMatch diffMatch = diffRegExp.match(patch);
if (diffMatch.hasMatch()) { if (diffMatch.hasMatch()) {
readOk = true; readOk = true;
int lastPos = -1; int lastPos = -1;
do { do {
if (jobController && jobController->isCanceled()) if (promise.isCanceled())
return {}; return;
int pos = diffMatch.capturedStart(); int pos = diffMatch.capturedStart();
if (lastPos >= 0) { if (lastPos >= 0) {
QStringView headerAndChunks = patch.mid(lastPos, pos - lastPos); QStringView headerAndChunks = patch.mid(lastPos, pos - lastPos);
const FileData fileData = readDiffHeaderAndChunks(headerAndChunks, const FileData fileData = readDiffHeaderAndChunks(headerAndChunks, &readOk);
&readOk);
if (!readOk) if (!readOk)
break; break;
@@ -942,21 +940,15 @@ static QList<FileData> readDiffPatch(QStringView patch, bool *ok, QFutureInterfa
if (readOk) { if (readOk) {
QStringView headerAndChunks = patch.mid(lastPos, patch.size() - lastPos - 1); QStringView headerAndChunks = patch.mid(lastPos, patch.size() - lastPos - 1);
const FileData fileData = readDiffHeaderAndChunks(headerAndChunks, const FileData fileData = readDiffHeaderAndChunks(headerAndChunks, &readOk);
&readOk);
if (readOk) if (readOk)
fileDataList.append(fileData); fileDataList.append(fileData);
} }
} }
if (ok)
*ok = readOk;
if (!readOk) if (!readOk)
return {}; return;
promise.addResult(fileDataList);
return fileDataList;
} }
// The git diff patch format (ChangeFile, NewFile, DeleteFile) // The git diff patch format (ChangeFile, NewFile, DeleteFile)
@@ -1203,7 +1195,7 @@ static bool detectFileData(QStringView patch, FileData *fileData, QStringView *r
return detectIndexAndBinary(*remainingPatch, fileData, remainingPatch); return detectIndexAndBinary(*remainingPatch, fileData, remainingPatch);
} }
static QList<FileData> readGitPatch(QStringView patch, bool *ok, QFutureInterfaceBase *jobController) static void readGitPatch(QPromise<QList<FileData>> &promise, QStringView patch)
{ {
int position = -1; int position = -1;
@@ -1221,13 +1213,12 @@ static QList<FileData> readGitPatch(QStringView patch, bool *ok, QFutureInterfac
}; };
const QChar newLine('\n'); const QChar newLine('\n');
bool readOk = true;
QVector<PatchInfo> patches; QVector<PatchInfo> patches;
const int count = startingPositions.size(); const int count = startingPositions.size();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
if (jobController && jobController->isCanceled()) if (promise.isCanceled())
return {}; return;
const int diffStart = startingPositions.at(i); const int diffStart = startingPositions.at(i);
const int diffEnd = (i < count - 1) const int diffEnd = (i < count - 1)
@@ -1242,32 +1233,21 @@ static QList<FileData> readGitPatch(QStringView patch, bool *ok, QFutureInterfac
FileData fileData; FileData fileData;
QStringView remainingFileDiff; QStringView remainingFileDiff;
readOk = detectFileData(fileDiff, &fileData, &remainingFileDiff); if (!detectFileData(fileDiff, &fileData, &remainingFileDiff))
return;
if (!readOk)
break;
patches.append(PatchInfo { remainingFileDiff, fileData }); patches.append(PatchInfo { remainingFileDiff, fileData });
} }
if (!readOk) { promise.setProgressRange(0, patches.size());
if (ok)
*ok = readOk;
return {};
}
if (jobController)
jobController->setProgressRange(0, patches.size());
QList<FileData> fileDataList; QList<FileData> fileDataList;
readOk = false; bool readOk = false;
int i = 0; int i = 0;
for (const auto &patchInfo : std::as_const(patches)) { for (const auto &patchInfo : std::as_const(patches)) {
if (jobController) { if (promise.isCanceled())
if (jobController->isCanceled()) return;
return {}; promise.setProgressValue(i++);
jobController->setProgressValue(i++);
}
FileData fileData = patchInfo.fileData; FileData fileData = patchInfo.fileData;
if (!patchInfo.patch.isEmpty() || fileData.fileOperation == FileData::ChangeFile) if (!patchInfo.patch.isEmpty() || fileData.fileOperation == FileData::ChangeFile)
@@ -1276,31 +1256,27 @@ static QList<FileData> readGitPatch(QStringView patch, bool *ok, QFutureInterfac
readOk = true; readOk = true;
if (!readOk) if (!readOk)
break; return;
fileDataList.append(fileData); fileDataList.append(fileData);
} }
promise.addResult(fileDataList);
if (ok)
*ok = readOk;
if (!readOk)
return {};
return fileDataList;
} }
QList<FileData> DiffUtils::readPatch(const QString &patch, bool *ok, std::optional<QList<FileData>> DiffUtils::readPatch(const QString &patch)
QFutureInterfaceBase *jobController)
{ {
bool readOk = false; QPromise<QList<FileData>> promise;
promise.start();
readPatchWithPromise(promise, patch);
if (promise.future().resultCount() == 0)
return {};
return promise.future().result();
}
QList<FileData> fileDataList; void DiffUtils::readPatchWithPromise(QPromise<QList<FileData>> &promise, const QString &patch)
{
if (jobController) { promise.setProgressRange(0, 1);
jobController->setProgressRange(0, 1); promise.setProgressValue(0);
jobController->setProgressValue(0);
}
QStringView croppedPatch = QStringView(patch); QStringView croppedPatch = QStringView(patch);
// Crop e.g. "-- \n2.10.2.windows.1\n\n" at end of file // Crop e.g. "-- \n2.10.2.windows.1\n\n" at end of file
const QRegularExpression formatPatchEndingRegExp("(\\n-- \\n\\S*\\n\\n$)"); const QRegularExpression formatPatchEndingRegExp("(\\n-- \\n\\S*\\n\\n$)");
@@ -1308,14 +1284,9 @@ QList<FileData> DiffUtils::readPatch(const QString &patch, bool *ok,
if (match.hasMatch()) if (match.hasMatch())
croppedPatch = croppedPatch.left(match.capturedStart() + 1); croppedPatch = croppedPatch.left(match.capturedStart() + 1);
fileDataList = readGitPatch(croppedPatch, &readOk, jobController); readGitPatch(promise, croppedPatch);
if (!readOk) if (promise.future().resultCount() == 0)
fileDataList = readDiffPatch(croppedPatch, &readOk, jobController); readDiffPatch(promise, croppedPatch);
if (ok)
*ok = readOk;
return fileDataList;
} }
} // namespace DiffEditor } // namespace DiffEditor

View File

@@ -14,7 +14,8 @@
#include <array> #include <array>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QFutureInterfaceBase; template <class T>
class QPromise;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Utils { class Diff; } namespace Utils { class Diff; }
@@ -142,9 +143,8 @@ public:
const QString &rightFileName, const QString &rightFileName,
bool lastChunk = false); bool lastChunk = false);
static QString makePatch(const QList<FileData> &fileDataList); static QString makePatch(const QList<FileData> &fileDataList);
static QList<FileData> readPatch(const QString &patch, static std::optional<QList<FileData>> readPatch(const QString &patch);
bool *ok = nullptr, static void readPatchWithPromise(QPromise<QList<FileData>> &promise, const QString &patch);
QFutureInterfaceBase *jobController = nullptr);
}; };
} // namespace DiffEditor } // namespace DiffEditor

View File

@@ -8,14 +8,8 @@
#include "diffeditorplugin.h" #include "diffeditorplugin.h"
#include "diffeditortr.h" #include "diffeditortr.h"
#include <QMenu>
#include <QPainter>
#include <QScrollBar>
#include <QTextBlock>
#include <QVBoxLayout>
#include <coreplugin/icore.h>
#include <coreplugin/find/highlightscrollbarcontroller.h> #include <coreplugin/find/highlightscrollbarcontroller.h>
#include <coreplugin/icore.h>
#include <coreplugin/minisplitter.h> #include <coreplugin/minisplitter.h>
#include <coreplugin/progressmanager/progressmanager.h> #include <coreplugin/progressmanager/progressmanager.h>
@@ -29,6 +23,11 @@
#include <utils/mathutils.h> #include <utils/mathutils.h>
#include <utils/tooltip/tooltip.h> #include <utils/tooltip/tooltip.h>
#include <QMenu>
#include <QPainter>
#include <QScrollBar>
#include <QVBoxLayout>
using namespace Core; using namespace Core;
using namespace TextEditor; using namespace TextEditor;
using namespace Utils; using namespace Utils;
@@ -245,7 +244,7 @@ QString SideDiffEditorWidget::plainTextFromSelection(const QTextCursor &cursor)
return TextDocument::convertToPlainText(text); return TextDocument::convertToPlainText(text);
} }
SideBySideDiffOutput SideDiffData::diffOutput(QFutureInterface<void> &fi, int progressMin, SideBySideDiffOutput SideDiffData::diffOutput(QFutureInterfaceBase &fi, int progressMin,
int progressMax, const DiffEditorInput &input) int progressMax, const DiffEditorInput &input)
{ {
SideBySideDiffOutput output; SideBySideDiffOutput output;
@@ -914,19 +913,15 @@ void SideBySideDiffEditorWidget::showDiff()
const DiffEditorInput input(&m_controller); const DiffEditorInput input(&m_controller);
auto getDocument = [input](QFutureInterface<ShowResults> &futureInterface) { auto getDocument = [input](QPromise<ShowResults> &promise) {
auto cleanup = qScopeGuard([&futureInterface] {
if (futureInterface.isCanceled())
futureInterface.reportCanceled();
});
const int firstPartMax = 20; // diffOutput is about 4 times quicker than filling document const int firstPartMax = 20; // diffOutput is about 4 times quicker than filling document
const int leftPartMax = 60; const int leftPartMax = 60;
const int rightPartMax = 100; const int rightPartMax = 100;
futureInterface.setProgressRange(0, rightPartMax); promise.setProgressRange(0, rightPartMax);
futureInterface.setProgressValue(0); promise.setProgressValue(0);
QFutureInterface<void> fi = futureInterface; QFutureInterfaceBase fi = QFutureInterfaceBase::get(promise.future());
const SideBySideDiffOutput output = SideDiffData::diffOutput(fi, 0, firstPartMax, input); const SideBySideDiffOutput output = SideDiffData::diffOutput(fi, 0, firstPartMax, input);
if (futureInterface.isCanceled()) if (promise.isCanceled())
return; return;
const ShowResult leftResult{TextDocumentPtr(new TextDocument("DiffEditor.SideDiffEditor")), const ShowResult leftResult{TextDocumentPtr(new TextDocument("DiffEditor.SideDiffEditor")),
@@ -935,7 +930,7 @@ void SideBySideDiffEditorWidget::showDiff()
output.side[RightSide].diffData, output.side[RightSide].selections}; output.side[RightSide].diffData, output.side[RightSide].selections};
const ShowResults result{leftResult, rightResult}; const ShowResults result{leftResult, rightResult};
auto propagateDocument = [&output, &fi](DiffSide side, const ShowResult &result, auto propagateDocument = [&output, &promise](DiffSide side, const ShowResult &result,
int progressMin, int progressMax) { int progressMin, int progressMax) {
// No need to store the change history // No need to store the change history
result.textDocument->document()->setUndoRedoEnabled(false); result.textDocument->document()->setUndoRedoEnabled(false);
@@ -952,8 +947,9 @@ void SideBySideDiffEditorWidget::showDiff()
const QString package = output.side[side].diffText.mid(currentPos, packageSize); const QString package = output.side[side].diffText.mid(currentPos, packageSize);
cursor.insertText(package); cursor.insertText(package);
currentPos += package.size(); currentPos += package.size();
fi.setProgressValue(MathUtils::interpolateLinear(currentPos, 0, diffSize, progressMin, progressMax)); promise.setProgressValue(MathUtils::interpolateLinear(currentPos, 0, diffSize,
if (fi.isCanceled()) progressMin, progressMax));
if (promise.isCanceled())
return; return;
} }
@@ -968,16 +964,16 @@ void SideBySideDiffEditorWidget::showDiff()
}; };
propagateDocument(LeftSide, leftResult, firstPartMax, leftPartMax); propagateDocument(LeftSide, leftResult, firstPartMax, leftPartMax);
if (fi.isCanceled()) if (promise.isCanceled())
return; return;
propagateDocument(RightSide, rightResult, leftPartMax, rightPartMax); propagateDocument(RightSide, rightResult, leftPartMax, rightPartMax);
if (fi.isCanceled()) if (promise.isCanceled())
return; return;
futureInterface.reportResult(result); promise.addResult(result);
}; };
m_asyncTask->setAsyncCallData(getDocument); m_asyncTask->setConcurrentCallData(getDocument);
m_asyncTask->start(); m_asyncTask->start();
ProgressManager::addTask(m_asyncTask->future(), Tr::tr("Rendering diff"), "DiffEditor"); ProgressManager::addTask(m_asyncTask->future(), Tr::tr("Rendering diff"), "DiffEditor");
} }

View File

@@ -7,7 +7,6 @@
#include "diffeditorwidgetcontroller.h" #include "diffeditorwidgetcontroller.h"
#include "selectabletexteditorwidget.h" // TODO: we need DiffSelections here only #include "selectabletexteditorwidget.h" // TODO: we need DiffSelections here only
#include <QFutureInterface>
#include <QWidget> #include <QWidget>
namespace Core { class IContext; } namespace Core { class IContext; }
@@ -23,6 +22,7 @@ class AsyncTask;
} }
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QFutureInterfaceBase;
class QMenu; class QMenu;
class QSplitter; class QSplitter;
QT_END_NAMESPACE QT_END_NAMESPACE
@@ -40,7 +40,7 @@ class SideBySideDiffOutput;
class SideDiffData class SideDiffData
{ {
public: public:
static SideBySideDiffOutput diffOutput(QFutureInterface<void> &fi, int progressMin, static SideBySideDiffOutput diffOutput(QFutureInterfaceBase &fi, int progressMin,
int progressMax, const DiffEditorInput &input); int progressMax, const DiffEditorInput &input);
DiffChunkInfo m_chunkInfo; DiffChunkInfo m_chunkInfo;

View File

@@ -8,23 +8,20 @@
#include "diffeditorplugin.h" #include "diffeditorplugin.h"
#include "diffeditortr.h" #include "diffeditortr.h"
#include <QMenu>
#include <QPainter>
#include <QScrollBar>
#include <QTextBlock>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h> #include <coreplugin/progressmanager/progressmanager.h>
#include <texteditor/fontsettings.h> #include <texteditor/fontsettings.h>
#include <texteditor/textdocument.h> #include <texteditor/textdocument.h>
#include <texteditor/textdocumentlayout.h>
#include <texteditor/texteditorsettings.h> #include <texteditor/texteditorsettings.h>
#include <utils/asynctask.h> #include <utils/asynctask.h>
#include <utils/mathutils.h> #include <utils/mathutils.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/tooltip/tooltip.h>
#include <QMenu>
#include <QScrollBar>
#include <QTextBlock>
using namespace Core; using namespace Core;
using namespace TextEditor; using namespace TextEditor;
@@ -48,10 +45,10 @@ UnifiedDiffEditorWidget::UnifiedDiffEditorWidget(QWidget *parent)
connect(this, &QPlainTextEdit::cursorPositionChanged, connect(this, &QPlainTextEdit::cursorPositionChanged,
this, &UnifiedDiffEditorWidget::slotCursorPositionChangedInEditor); this, &UnifiedDiffEditorWidget::slotCursorPositionChangedInEditor);
auto context = new Core::IContext(this); auto context = new IContext(this);
context->setWidget(this); context->setWidget(this);
context->setContext(Core::Context(Constants::UNIFIED_VIEW_ID)); context->setContext(Context(Constants::UNIFIED_VIEW_ID));
Core::ICore::addContextObject(context); ICore::addContextObject(context);
} }
UnifiedDiffEditorWidget::~UnifiedDiffEditorWidget() = default; UnifiedDiffEditorWidget::~UnifiedDiffEditorWidget() = default;
@@ -391,7 +388,7 @@ QString UnifiedDiffData::setChunk(const DiffEditorInput &input, const ChunkData
return diffText; return diffText;
} }
UnifiedDiffOutput UnifiedDiffData::diffOutput(QFutureInterface<void> &fi, int progressMin, UnifiedDiffOutput UnifiedDiffData::diffOutput(QFutureInterfaceBase &fi, int progressMin,
int progressMax, const DiffEditorInput &input) int progressMax, const DiffEditorInput &input)
{ {
UnifiedDiffOutput output; UnifiedDiffOutput output;
@@ -481,18 +478,14 @@ void UnifiedDiffEditorWidget::showDiff()
const DiffEditorInput input(&m_controller); const DiffEditorInput input(&m_controller);
auto getDocument = [input](QFutureInterface<ShowResult> &futureInterface) { auto getDocument = [input](QPromise<ShowResult> &promise) {
auto cleanup = qScopeGuard([&futureInterface] {
if (futureInterface.isCanceled())
futureInterface.reportCanceled();
});
const int progressMax = 100; const int progressMax = 100;
const int firstPartMax = 20; // diffOutput is about 4 times quicker than filling document const int firstPartMax = 20; // diffOutput is about 4 times quicker than filling document
futureInterface.setProgressRange(0, progressMax); promise.setProgressRange(0, progressMax);
futureInterface.setProgressValue(0); promise.setProgressValue(0);
QFutureInterface<void> fi = futureInterface; QFutureInterfaceBase fi = QFutureInterfaceBase::get(promise.future());
const UnifiedDiffOutput output = UnifiedDiffData::diffOutput(fi, 0, firstPartMax, input); const UnifiedDiffOutput output = UnifiedDiffData::diffOutput(fi, 0, firstPartMax, input);
if (futureInterface.isCanceled()) if (promise.isCanceled())
return; return;
const ShowResult result = {TextDocumentPtr(new TextDocument("DiffEditor.UnifiedDiffEditor")), const ShowResult result = {TextDocumentPtr(new TextDocument("DiffEditor.UnifiedDiffEditor")),
@@ -512,8 +505,9 @@ void UnifiedDiffEditorWidget::showDiff()
const QString package = output.diffText.mid(currentPos, packageSize); const QString package = output.diffText.mid(currentPos, packageSize);
cursor.insertText(package); cursor.insertText(package);
currentPos += package.size(); currentPos += package.size();
fi.setProgressValue(MathUtils::interpolateLinear(currentPos, 0, diffSize, firstPartMax, progressMax)); promise.setProgressValue(MathUtils::interpolateLinear(currentPos, 0, diffSize,
if (futureInterface.isCanceled()) firstPartMax, progressMax));
if (promise.isCanceled())
return; return;
} }
@@ -525,10 +519,10 @@ void UnifiedDiffEditorWidget::showDiff()
// to caller's thread. We push it to no thread (make object to have no thread affinity), // to caller's thread. We push it to no thread (make object to have no thread affinity),
// and later, in the caller's thread, we pull it back to the caller's thread. // and later, in the caller's thread, we pull it back to the caller's thread.
result.textDocument->moveToThread(nullptr); result.textDocument->moveToThread(nullptr);
futureInterface.reportResult(result); promise.addResult(result);
}; };
m_asyncTask->setAsyncCallData(getDocument); m_asyncTask->setConcurrentCallData(getDocument);
m_asyncTask->start(); m_asyncTask->start();
ProgressManager::addTask(m_asyncTask->future(), Tr::tr("Rendering diff"), "DiffEditor"); ProgressManager::addTask(m_asyncTask->future(), Tr::tr("Rendering diff"), "DiffEditor");
} }

View File

@@ -6,8 +6,6 @@
#include "diffeditorwidgetcontroller.h" #include "diffeditorwidgetcontroller.h"
#include "selectabletexteditorwidget.h" #include "selectabletexteditorwidget.h"
#include <QFutureInterface>
namespace Core { class IContext; } namespace Core { class IContext; }
namespace TextEditor { class FontSettings; } namespace TextEditor { class FontSettings; }
@@ -17,6 +15,10 @@ template <typename R>
class AsyncTask; class AsyncTask;
} }
QT_BEGIN_NAMESPACE
class QFutureInterfaceBase;
QT_END_NAMESPACE
namespace DiffEditor { namespace DiffEditor {
class ChunkData; class ChunkData;
@@ -31,7 +33,7 @@ class UnifiedDiffOutput;
class UnifiedDiffData class UnifiedDiffData
{ {
public: public:
static UnifiedDiffOutput diffOutput(QFutureInterface<void> &fi, int progressMin, int progressMax, static UnifiedDiffOutput diffOutput(QFutureInterfaceBase &fi, int progressMin, int progressMax,
const DiffEditorInput &input); const DiffEditorInput &input);
DiffChunkInfo m_chunkInfo; DiffChunkInfo m_chunkInfo;

View File

@@ -15,15 +15,6 @@ using namespace Utils;
namespace VcsBase { namespace VcsBase {
static void readPatch(QFutureInterface<QList<FileData>> &futureInterface, const QString &patch)
{
bool ok;
const QList<FileData> &fileDataList = DiffUtils::readPatch(patch, &ok, &futureInterface);
futureInterface.reportResult(fileDataList);
}
/////////////////////
class VcsBaseDiffEditorControllerPrivate class VcsBaseDiffEditorControllerPrivate
{ {
public: public:
@@ -61,11 +52,11 @@ Tasking::TaskItem VcsBaseDiffEditorController::postProcessTask()
QTC_ASSERT(storage, qWarning("Using postProcessTask() requires putting inputStorage() " QTC_ASSERT(storage, qWarning("Using postProcessTask() requires putting inputStorage() "
"into task tree's root group.")); "into task tree's root group."));
const QString inputData = storage ? *storage : QString(); const QString inputData = storage ? *storage : QString();
async.setAsyncCallData(readPatch, inputData); async.setConcurrentCallData(&DiffUtils::readPatchWithPromise, inputData);
async.setFutureSynchronizer(Internal::VcsPlugin::futureSynchronizer()); async.setFutureSynchronizer(Internal::VcsPlugin::futureSynchronizer());
}; };
const auto onDiffProcessorDone = [this](const AsyncTask<QList<FileData>> &async) { const auto onDiffProcessorDone = [this](const AsyncTask<QList<FileData>> &async) {
setDiffFiles(async.result()); setDiffFiles(async.isResultAvailable() ? async.result() : QList<FileData>());
}; };
const auto onDiffProcessorError = [this](const AsyncTask<QList<FileData>> &) { const auto onDiffProcessorError = [this](const AsyncTask<QList<FileData>> &) {
setDiffFiles({}); setDiffFiles({});