forked from qt-creator/qt-creator
ExtraCompiler: Expose TaskItem for compile task
This is an intermediate state before employing one common TaskTree inside CppProjectUpdater. Use multiple one-task TaskTrees for now. Refactor ExtraCompiler so that there is only one pure virtual method to be implemented (taskItem()) instead of two (2 run() overloads). Use TaskTree inside ExtraCompiler for running the compilation process. Change-Id: I6884934508e043594589d117f6d3f0aed94b84c2 Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/runextensions.h>
|
#include <utils/runextensions.h>
|
||||||
|
#include <utils/tasktree.h>
|
||||||
|
|
||||||
#include <QFutureInterface>
|
#include <QFutureInterface>
|
||||||
|
|
||||||
@@ -68,33 +69,29 @@ void CppProjectUpdater::update(const ProjectUpdateInfo &projectUpdateInfo,
|
|||||||
|
|
||||||
// extra compilers
|
// extra compilers
|
||||||
for (QPointer<ExtraCompiler> compiler : std::as_const(m_extraCompilers)) {
|
for (QPointer<ExtraCompiler> compiler : std::as_const(m_extraCompilers)) {
|
||||||
if (compiler->isDirty()) {
|
if (!compiler->isDirty())
|
||||||
QPointer<QFutureWatcher<void>> watcher = new QFutureWatcher<void>;
|
continue;
|
||||||
// queued connection to delay after the extra compiler updated its result contents,
|
|
||||||
// which is also done in the main thread when compiler->run() finished
|
const auto destroyTaskTree = [this](TaskTree *taskTree) {
|
||||||
connect(watcher, &QFutureWatcherBase::finished,
|
m_extraCompilerTasks.remove(taskTree);
|
||||||
this, [this, watcher] {
|
taskTree->deleteLater();
|
||||||
// In very unlikely case the CppProjectUpdater::cancel() could have been
|
};
|
||||||
// invoked after posting the finished() signal and before this handler
|
TaskTree *taskTree = new TaskTree({compiler->compileFileItem()});
|
||||||
// gets called. In this case the watcher is already deleted.
|
connect(taskTree, &TaskTree::done, this, [this, taskTree, destroyTaskTree] {
|
||||||
if (!watcher)
|
destroyTaskTree(taskTree);
|
||||||
return;
|
m_projectUpdateFutureInterface->setProgressValue(
|
||||||
m_projectUpdateFutureInterface->setProgressValue(
|
m_projectUpdateFutureInterface->progressValue() + 1);
|
||||||
m_projectUpdateFutureInterface->progressValue() + 1);
|
checkForExtraCompilersFinished();
|
||||||
m_extraCompilersFutureWatchers.remove(watcher);
|
});
|
||||||
watcher->deleteLater();
|
connect(taskTree, &TaskTree::errorOccurred, this, [taskTree, destroyTaskTree] {
|
||||||
if (!watcher->isCanceled())
|
destroyTaskTree(taskTree);
|
||||||
checkForExtraCompilersFinished();
|
});
|
||||||
},
|
m_extraCompilerTasks.insert(taskTree);
|
||||||
Qt::QueuedConnection);
|
taskTree->start();
|
||||||
m_extraCompilersFutureWatchers += watcher;
|
|
||||||
watcher->setFuture(QFuture<void>(compiler->run()));
|
|
||||||
m_futureSynchronizer.addFuture(watcher->future());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_projectUpdateFutureInterface.reset(new QFutureInterface<void>);
|
m_projectUpdateFutureInterface.reset(new QFutureInterface<void>);
|
||||||
m_projectUpdateFutureInterface->setProgressRange(0, m_extraCompilersFutureWatchers.size()
|
m_projectUpdateFutureInterface->setProgressRange(0, m_extraCompilerTasks.size()
|
||||||
+ 1 /*generateFuture*/);
|
+ 1 /*generateFuture*/);
|
||||||
m_projectUpdateFutureInterface->setProgressValue(0);
|
m_projectUpdateFutureInterface->setProgressValue(0);
|
||||||
m_projectUpdateFutureInterface->reportStarted();
|
m_projectUpdateFutureInterface->reportStarted();
|
||||||
@@ -109,8 +106,8 @@ void CppProjectUpdater::cancel()
|
|||||||
m_projectUpdateFutureInterface->reportFinished();
|
m_projectUpdateFutureInterface->reportFinished();
|
||||||
m_generateFutureWatcher.setFuture({});
|
m_generateFutureWatcher.setFuture({});
|
||||||
m_isProjectInfoGenerated = false;
|
m_isProjectInfoGenerated = false;
|
||||||
qDeleteAll(m_extraCompilersFutureWatchers);
|
qDeleteAll(m_extraCompilerTasks);
|
||||||
m_extraCompilersFutureWatchers.clear();
|
m_extraCompilerTasks.clear();
|
||||||
m_extraCompilers.clear();
|
m_extraCompilers.clear();
|
||||||
m_futureSynchronizer.cancelAllFutures();
|
m_futureSynchronizer.cancelAllFutures();
|
||||||
}
|
}
|
||||||
@@ -128,7 +125,7 @@ void CppProjectUpdater::onProjectInfoGenerated()
|
|||||||
|
|
||||||
void CppProjectUpdater::checkForExtraCompilersFinished()
|
void CppProjectUpdater::checkForExtraCompilersFinished()
|
||||||
{
|
{
|
||||||
if (!m_extraCompilersFutureWatchers.isEmpty() || !m_isProjectInfoGenerated)
|
if (!m_extraCompilerTasks.isEmpty() || !m_isProjectInfoGenerated)
|
||||||
return; // still need to wait
|
return; // still need to wait
|
||||||
|
|
||||||
m_projectUpdateFutureInterface->reportFinished();
|
m_projectUpdateFutureInterface->reportFinished();
|
||||||
|
@@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
#include <QFutureWatcher>
|
#include <QFutureWatcher>
|
||||||
|
|
||||||
|
namespace Utils { class TaskTree; }
|
||||||
|
|
||||||
namespace CppEditor {
|
namespace CppEditor {
|
||||||
class ProjectInfo;
|
class ProjectInfo;
|
||||||
|
|
||||||
@@ -53,7 +55,7 @@ private:
|
|||||||
|
|
||||||
QFutureWatcher<ProjectInfo::ConstPtr> m_generateFutureWatcher;
|
QFutureWatcher<ProjectInfo::ConstPtr> m_generateFutureWatcher;
|
||||||
bool m_isProjectInfoGenerated = false;
|
bool m_isProjectInfoGenerated = false;
|
||||||
QSet<QFutureWatcher<void> *> m_extraCompilersFutureWatchers;
|
QSet<Utils::TaskTree *> m_extraCompilerTasks;
|
||||||
std::unique_ptr<QFutureInterface<void>> m_projectUpdateFutureInterface;
|
std::unique_ptr<QFutureInterface<void>> m_projectUpdateFutureInterface;
|
||||||
Utils::FutureSynchronizer m_futureSynchronizer;
|
Utils::FutureSynchronizer m_futureSynchronizer;
|
||||||
};
|
};
|
||||||
|
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "extracompiler.h"
|
#include "extracompiler.h"
|
||||||
|
|
||||||
#include "buildconfiguration.h"
|
|
||||||
#include "buildmanager.h"
|
#include "buildmanager.h"
|
||||||
#include "kitinformation.h"
|
#include "kitinformation.h"
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
@@ -13,18 +12,14 @@
|
|||||||
#include <coreplugin/idocument.h>
|
#include <coreplugin/idocument.h>
|
||||||
#include <texteditor/texteditor.h>
|
#include <texteditor/texteditor.h>
|
||||||
#include <texteditor/texteditorsettings.h>
|
#include <texteditor/texteditorsettings.h>
|
||||||
#include <texteditor/texteditorconstants.h>
|
|
||||||
#include <texteditor/fontsettings.h>
|
#include <texteditor/fontsettings.h>
|
||||||
|
|
||||||
|
#include <utils/asynctask.h>
|
||||||
#include <utils/expected.h>
|
#include <utils/expected.h>
|
||||||
#include <utils/qtcassert.h>
|
|
||||||
#include <utils/qtcprocess.h>
|
#include <utils/qtcprocess.h>
|
||||||
#include <utils/runextensions.h>
|
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QFutureInterface>
|
#include <QFutureInterface>
|
||||||
#include <QFutureWatcher>
|
|
||||||
#include <QTextBlock>
|
|
||||||
#include <QThreadPool>
|
#include <QThreadPool>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
@@ -50,6 +45,9 @@ public:
|
|||||||
|
|
||||||
QTimer timer;
|
QTimer timer;
|
||||||
void updateIssues();
|
void updateIssues();
|
||||||
|
|
||||||
|
FutureSynchronizer m_futureSynchronizer;
|
||||||
|
std::unique_ptr<TaskTree> m_taskTree;
|
||||||
};
|
};
|
||||||
|
|
||||||
ExtraCompiler::ExtraCompiler(const Project *project, const FilePath &source,
|
ExtraCompiler::ExtraCompiler(const Project *project, const FilePath &source,
|
||||||
@@ -65,7 +63,7 @@ ExtraCompiler::ExtraCompiler(const Project *project, const FilePath &source,
|
|||||||
connect(&d->timer, &QTimer::timeout, this, [this] {
|
connect(&d->timer, &QTimer::timeout, this, [this] {
|
||||||
if (d->dirty && d->lastEditor) {
|
if (d->dirty && d->lastEditor) {
|
||||||
d->dirty = false;
|
d->dirty = false;
|
||||||
run(d->lastEditor->document()->contents());
|
compileContent(d->lastEditor->document()->contents());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -128,7 +126,7 @@ FilePaths ExtraCompiler::targets() const
|
|||||||
return d->contents.keys();
|
return d->contents.keys();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtraCompiler::forEachTarget(std::function<void (const FilePath &)> func)
|
void ExtraCompiler::forEachTarget(std::function<void (const FilePath &)> func) const
|
||||||
{
|
{
|
||||||
for (auto it = d->contents.constBegin(), end = d->contents.constEnd(); it != end; ++it)
|
for (auto it = d->contents.constBegin(), end = d->contents.constEnd(); it != end; ++it)
|
||||||
func(it.key());
|
func(it.key());
|
||||||
@@ -144,6 +142,42 @@ QThreadPool *ExtraCompiler::extraCompilerThreadPool()
|
|||||||
return s_extraCompilerThreadPool();
|
return s_extraCompilerThreadPool();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tasking::TaskItem ExtraCompiler::compileFileItem()
|
||||||
|
{
|
||||||
|
return taskItemImpl(fromFileProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtraCompiler::compileFile()
|
||||||
|
{
|
||||||
|
compileImpl(fromFileProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtraCompiler::compileContent(const QByteArray &content)
|
||||||
|
{
|
||||||
|
compileImpl([content] { return content; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtraCompiler::compileImpl(const ContentProvider &provider)
|
||||||
|
{
|
||||||
|
const auto finalize = [=] {
|
||||||
|
d->m_taskTree.release()->deleteLater();
|
||||||
|
};
|
||||||
|
d->m_taskTree.reset(new TaskTree({taskItemImpl(provider)}));
|
||||||
|
connect(d->m_taskTree.get(), &TaskTree::done, this, finalize);
|
||||||
|
connect(d->m_taskTree.get(), &TaskTree::errorOccurred, this, finalize);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtraCompiler::ContentProvider ExtraCompiler::fromFileProvider() const
|
||||||
|
{
|
||||||
|
const auto provider = [fileName = source()] {
|
||||||
|
QFile file(fileName.toString());
|
||||||
|
if (!file.open(QFile::ReadOnly | QFile::Text))
|
||||||
|
return QByteArray();
|
||||||
|
return file.readAll();
|
||||||
|
};
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
bool ExtraCompiler::isDirty() const
|
bool ExtraCompiler::isDirty() const
|
||||||
{
|
{
|
||||||
return d->dirty;
|
return d->dirty;
|
||||||
@@ -186,7 +220,7 @@ void ExtraCompiler::onEditorChanged(Core::IEditor *editor)
|
|||||||
|
|
||||||
if (d->dirty) {
|
if (d->dirty) {
|
||||||
d->dirty = false;
|
d->dirty = false;
|
||||||
run(doc->contents());
|
compileContent(doc->contents());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,7 +254,7 @@ void ExtraCompiler::onEditorAboutToClose(Core::IEditor *editor)
|
|||||||
this, &ExtraCompiler::setDirty);
|
this, &ExtraCompiler::setDirty);
|
||||||
if (d->dirty) {
|
if (d->dirty) {
|
||||||
d->dirty = false;
|
d->dirty = false;
|
||||||
run(doc->contents());
|
compileContent(doc->contents());
|
||||||
}
|
}
|
||||||
d->lastEditor = nullptr;
|
d->lastEditor = nullptr;
|
||||||
}
|
}
|
||||||
@@ -276,6 +310,11 @@ void ExtraCompilerPrivate::updateIssues()
|
|||||||
widget->setExtraSelections(TextEditor::TextEditorWidget::CodeWarningsSelection, selections);
|
widget->setExtraSelections(TextEditor::TextEditorWidget::CodeWarningsSelection, selections);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Utils::FutureSynchronizer *ExtraCompiler::futureSynchronizer() const
|
||||||
|
{
|
||||||
|
return &d->m_futureSynchronizer;
|
||||||
|
}
|
||||||
|
|
||||||
void ExtraCompiler::setContent(const FilePath &file, const QByteArray &contents)
|
void ExtraCompiler::setContent(const FilePath &file, const QByteArray &contents)
|
||||||
{
|
{
|
||||||
auto it = d->contents.find(file);
|
auto it = d->contents.find(file);
|
||||||
@@ -308,30 +347,25 @@ ProcessExtraCompiler::ProcessExtraCompiler(const Project *project, const FilePat
|
|||||||
ExtraCompiler(project, source, targets, parent)
|
ExtraCompiler(project, source, targets, parent)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
ProcessExtraCompiler::~ProcessExtraCompiler()
|
Tasking::TaskItem ProcessExtraCompiler::taskItemImpl(const ContentProvider &provider)
|
||||||
{
|
{
|
||||||
if (!m_watcher)
|
const auto setupTask = [=](AsyncTask<FileNameToContentsHash> &async) {
|
||||||
return;
|
async.setThreadPool(extraCompilerThreadPool());
|
||||||
m_watcher->cancel();
|
async.setAsyncCallData(&ProcessExtraCompiler::runInThread, this, command(),
|
||||||
m_watcher->waitForFinished();
|
workingDirectory(), arguments(), provider, buildEnvironment());
|
||||||
}
|
async.setFutureSynchronizer(futureSynchronizer());
|
||||||
|
|
||||||
void ProcessExtraCompiler::run(const QByteArray &sourceContents)
|
|
||||||
{
|
|
||||||
ContentProvider contents = [sourceContents]() { return sourceContents; };
|
|
||||||
runImpl(contents);
|
|
||||||
}
|
|
||||||
|
|
||||||
QFuture<FileNameToContentsHash> ProcessExtraCompiler::run()
|
|
||||||
{
|
|
||||||
const FilePath fileName = source();
|
|
||||||
ContentProvider contents = [fileName]() {
|
|
||||||
QFile file(fileName.toString());
|
|
||||||
if (!file.open(QFile::ReadOnly | QFile::Text))
|
|
||||||
return QByteArray();
|
|
||||||
return file.readAll();
|
|
||||||
};
|
};
|
||||||
return runImpl(contents);
|
const auto taskDone = [=](const AsyncTask<FileNameToContentsHash> &async) {
|
||||||
|
if (async.results().size() == 0)
|
||||||
|
return;
|
||||||
|
const FileNameToContentsHash data = async.result();
|
||||||
|
if (data.isEmpty())
|
||||||
|
return; // There was some kind of error...
|
||||||
|
for (auto it = data.constBegin(), end = data.constEnd(); it != end; ++it)
|
||||||
|
setContent(it.key(), it.value());
|
||||||
|
updateCompileTime();
|
||||||
|
};
|
||||||
|
return Tasking::Async<FileNameToContentsHash>(setupTask, taskDone);
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath ProcessExtraCompiler::workingDirectory() const
|
FilePath ProcessExtraCompiler::workingDirectory() const
|
||||||
@@ -356,27 +390,10 @@ Tasks ProcessExtraCompiler::parseIssues(const QByteArray &stdErr)
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QFuture<FileNameToContentsHash> ProcessExtraCompiler::runImpl(const ContentProvider &provider)
|
void ProcessExtraCompiler::runInThread(QFutureInterface<FileNameToContentsHash> &futureInterface,
|
||||||
{
|
const FilePath &cmd, const FilePath &workDir,
|
||||||
if (m_watcher)
|
const QStringList &args, const ContentProvider &provider,
|
||||||
delete m_watcher;
|
const Environment &env)
|
||||||
|
|
||||||
m_watcher = new QFutureWatcher<FileNameToContentsHash>();
|
|
||||||
connect(m_watcher, &QFutureWatcher<FileNameToContentsHash>::finished,
|
|
||||||
this, &ProcessExtraCompiler::cleanUp);
|
|
||||||
|
|
||||||
m_watcher->setFuture(runAsync(extraCompilerThreadPool(),
|
|
||||||
&ProcessExtraCompiler::runInThread, this,
|
|
||||||
command(), workingDirectory(), arguments(), provider,
|
|
||||||
buildEnvironment()));
|
|
||||||
return m_watcher->future();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProcessExtraCompiler::runInThread(
|
|
||||||
QFutureInterface<FileNameToContentsHash> &futureInterface,
|
|
||||||
const FilePath &cmd, const FilePath &workDir,
|
|
||||||
const QStringList &args, const ContentProvider &provider,
|
|
||||||
const Environment &env)
|
|
||||||
{
|
{
|
||||||
if (cmd.isEmpty() || !cmd.toFileInfo().isExecutable())
|
if (cmd.isEmpty() || !cmd.toFileInfo().isExecutable())
|
||||||
return;
|
return;
|
||||||
@@ -396,9 +413,10 @@ void ProcessExtraCompiler::runInThread(
|
|||||||
if (!process.waitForStarted())
|
if (!process.waitForStarted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (!futureInterface.isCanceled())
|
while (!futureInterface.isCanceled()) {
|
||||||
if (process.waitForFinished(200))
|
if (process.waitForFinished(200))
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (futureInterface.isCanceled())
|
if (futureInterface.isCanceled())
|
||||||
return;
|
return;
|
||||||
@@ -406,23 +424,4 @@ void ProcessExtraCompiler::runInThread(
|
|||||||
futureInterface.reportResult(handleProcessFinished(&process));
|
futureInterface.reportResult(handleProcessFinished(&process));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessExtraCompiler::cleanUp()
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_watcher, return);
|
|
||||||
auto future = m_watcher->future();
|
|
||||||
delete m_watcher;
|
|
||||||
m_watcher = nullptr;
|
|
||||||
if (!future.resultCount())
|
|
||||||
return;
|
|
||||||
const FileNameToContentsHash data = future.result();
|
|
||||||
|
|
||||||
if (data.isEmpty())
|
|
||||||
return; // There was some kind of error...
|
|
||||||
|
|
||||||
for (auto it = data.constBegin(), end = data.constEnd(); it != end; ++it)
|
|
||||||
setContent(it.key(), it.value());
|
|
||||||
|
|
||||||
updateCompileTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
@@ -8,8 +8,10 @@
|
|||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
#include <coreplugin/editormanager/ieditor.h>
|
#include <coreplugin/editormanager/ieditor.h>
|
||||||
#include <utils/fileutils.h>
|
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
|
#include <utils/filepath.h>
|
||||||
|
#include <utils/tasktree.h>
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
@@ -18,15 +20,16 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QThreadPool);
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class QFutureInterface;
|
class QFutureInterface;
|
||||||
template <typename T>
|
class QThreadPool;
|
||||||
class QFutureWatcher;
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Utils { class QtcProcess; }
|
namespace Utils {
|
||||||
|
class FutureSynchronizer;
|
||||||
|
class QtcProcess;
|
||||||
|
}
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
@@ -48,9 +51,10 @@ public:
|
|||||||
QByteArray content(const Utils::FilePath &file) const;
|
QByteArray content(const Utils::FilePath &file) const;
|
||||||
|
|
||||||
Utils::FilePaths targets() const;
|
Utils::FilePaths targets() const;
|
||||||
void forEachTarget(std::function<void(const Utils::FilePath &)> func);
|
void forEachTarget(std::function<void(const Utils::FilePath &)> func) const;
|
||||||
|
|
||||||
virtual QFuture<FileNameToContentsHash> run() = 0;
|
Utils::Tasking::TaskItem compileFileItem();
|
||||||
|
void compileFile();
|
||||||
bool isDirty() const;
|
bool isDirty() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
@@ -58,18 +62,23 @@ signals:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
static QThreadPool *extraCompilerThreadPool();
|
static QThreadPool *extraCompilerThreadPool();
|
||||||
|
|
||||||
|
Utils::FutureSynchronizer *futureSynchronizer() const;
|
||||||
void setContent(const Utils::FilePath &file, const QByteArray &content);
|
void setContent(const Utils::FilePath &file, const QByteArray &content);
|
||||||
void updateCompileTime();
|
void updateCompileTime();
|
||||||
Utils::Environment buildEnvironment() const;
|
Utils::Environment buildEnvironment() const;
|
||||||
void setCompileIssues(const Tasks &issues);
|
void setCompileIssues(const Tasks &issues);
|
||||||
|
using ContentProvider = std::function<QByteArray()>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onTargetsBuilt(Project *project);
|
void onTargetsBuilt(Project *project);
|
||||||
void onEditorChanged(Core::IEditor *editor);
|
void onEditorChanged(Core::IEditor *editor);
|
||||||
void onEditorAboutToClose(Core::IEditor *editor);
|
void onEditorAboutToClose(Core::IEditor *editor);
|
||||||
void setDirty();
|
void setDirty();
|
||||||
// This method may not block!
|
ContentProvider fromFileProvider() const;
|
||||||
virtual void run(const QByteArray &sourceContent) = 0;
|
void compileContent(const QByteArray &content);
|
||||||
|
void compileImpl(const ContentProvider &provider);
|
||||||
|
virtual Utils::Tasking::TaskItem taskItemImpl(const ContentProvider &provider) = 0;
|
||||||
|
|
||||||
const std::unique_ptr<ExtraCompilerPrivate> d;
|
const std::unique_ptr<ExtraCompilerPrivate> d;
|
||||||
};
|
};
|
||||||
@@ -81,17 +90,8 @@ public:
|
|||||||
|
|
||||||
ProcessExtraCompiler(const Project *project, const Utils::FilePath &source,
|
ProcessExtraCompiler(const Project *project, const Utils::FilePath &source,
|
||||||
const Utils::FilePaths &targets, QObject *parent = nullptr);
|
const Utils::FilePaths &targets, QObject *parent = nullptr);
|
||||||
~ProcessExtraCompiler() override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// This will run a process in a thread, if
|
|
||||||
// * command() does not return an empty file name
|
|
||||||
// * command() is exectuable
|
|
||||||
// * prepareToRun returns true
|
|
||||||
// * The process is not yet running
|
|
||||||
void run(const QByteArray &sourceContents) override;
|
|
||||||
QFuture<FileNameToContentsHash> run() override;
|
|
||||||
|
|
||||||
// Information about the process to run:
|
// Information about the process to run:
|
||||||
virtual Utils::FilePath workingDirectory() const;
|
virtual Utils::FilePath workingDirectory() const;
|
||||||
virtual Utils::FilePath command() const = 0;
|
virtual Utils::FilePath command() const = 0;
|
||||||
@@ -104,15 +104,11 @@ protected:
|
|||||||
virtual Tasks parseIssues(const QByteArray &stdErr);
|
virtual Tasks parseIssues(const QByteArray &stdErr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using ContentProvider = std::function<QByteArray()>;
|
Utils::Tasking::TaskItem taskItemImpl(const ContentProvider &provider) final;
|
||||||
QFuture<FileNameToContentsHash> runImpl(const ContentProvider &sourceContents);
|
|
||||||
void runInThread(QFutureInterface<FileNameToContentsHash> &futureInterface,
|
void runInThread(QFutureInterface<FileNameToContentsHash> &futureInterface,
|
||||||
const Utils::FilePath &cmd, const Utils::FilePath &workDir,
|
const Utils::FilePath &cmd, const Utils::FilePath &workDir,
|
||||||
const QStringList &args, const ContentProvider &provider,
|
const QStringList &args, const ContentProvider &provider,
|
||||||
const Utils::Environment &env);
|
const Utils::Environment &env);
|
||||||
void cleanUp();
|
|
||||||
|
|
||||||
QFutureWatcher<FileNameToContentsHash> *m_watcher = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PROJECTEXPLORER_EXPORT ExtraCompilerFactory : public QObject
|
class PROJECTEXPLORER_EXPORT ExtraCompilerFactory : public QObject
|
||||||
@@ -127,8 +123,7 @@ public:
|
|||||||
|
|
||||||
virtual ExtraCompiler *create(const Project *project,
|
virtual ExtraCompiler *create(const Project *project,
|
||||||
const Utils::FilePath &source,
|
const Utils::FilePath &source,
|
||||||
const Utils::FilePaths &targets)
|
const Utils::FilePaths &targets) = 0;
|
||||||
= 0;
|
|
||||||
|
|
||||||
static QList<ExtraCompilerFactory *> extraCompilerFactories();
|
static QList<ExtraCompilerFactory *> extraCompilerFactories();
|
||||||
};
|
};
|
||||||
|
@@ -249,7 +249,7 @@ void PyLSClient::updateExtraCompilers(ProjectExplorer::Project *project,
|
|||||||
updateExtraCompilerContents(extraCompiler, file);
|
updateExtraCompilerContents(extraCompiler, file);
|
||||||
});
|
});
|
||||||
if (extraCompiler->isDirty())
|
if (extraCompiler->isDirty())
|
||||||
static_cast<ExtraCompiler *>(extraCompiler)->run();
|
extraCompiler->compileFile();
|
||||||
} else {
|
} else {
|
||||||
m_extraCompilers[project] << oldCompilers.takeAt(index);
|
m_extraCompilers[project] << oldCompilers.takeAt(index);
|
||||||
}
|
}
|
||||||
|
@@ -175,7 +175,7 @@ QbsBuildSystem::QbsBuildSystem(QbsBuildConfiguration *bc)
|
|||||||
CppEditor::GeneratedCodeModelSupport::update(m_extraCompilers);
|
CppEditor::GeneratedCodeModelSupport::update(m_extraCompilers);
|
||||||
for (ExtraCompiler *compiler : m_extraCompilers) {
|
for (ExtraCompiler *compiler : m_extraCompilers) {
|
||||||
if (compiler->isDirty())
|
if (compiler->isDirty())
|
||||||
compiler->run();
|
compiler->compileFile();
|
||||||
}
|
}
|
||||||
m_sourcesForGeneratedFiles.clear();
|
m_sourcesForGeneratedFiles.clear();
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user