1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "cppprojectupdater.h"
#include "cppeditortr.h"
#include "cppmodelmanager.h"
#include "cppprojectinfogenerator.h"
#include "generatedcodemodelsupport.h"
#include <coreplugin/progressmanager/taskprogress.h>
#include <projectexplorer/extracompiler.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectupdater.h>
#include <projectexplorer/rawprojectpart.h>
#include <solutions/tasking/tasktreerunner.h>
#include <utils/algorithm.h>
#include <utils/async.h>
#include <utils/futuresynchronizer.h>
#include <utils/qtcassert.h>
using namespace ProjectExplorer;
using namespace Tasking;
using namespace Utils;
namespace CppEditor::Internal {
class CppProjectUpdater final : public ProjectUpdater
{
public:
void update(const ProjectUpdateInfo &projectUpdateInfo,
const QList<ExtraCompiler *> &extraCompilers) final;
void cancel() final;
private:
FutureSynchronizer m_futureSynchronizer;
SingleTaskTreeRunner m_taskTreeRunner;
};
void CppProjectUpdater::update(const ProjectUpdateInfo &projectUpdateInfo,
const QList<ExtraCompiler *> &extraCompilers)
{
// Stop previous update.
cancel();
const QList<QPointer<ExtraCompiler>> compilers =
Utils::transform(extraCompilers, [](ExtraCompiler *compiler) {
return QPointer<ExtraCompiler>(compiler);
});
// Run the project info generator in a worker thread and continue if that one is finished.
const auto infoGenerator = [projectUpdateInfo](QPromise<ProjectInfo::ConstPtr> &promise) {
ProjectUpdateInfo fullProjectUpdateInfo = projectUpdateInfo;
if (fullProjectUpdateInfo.rppGenerator)
fullProjectUpdateInfo.rawProjectParts = fullProjectUpdateInfo.rppGenerator();
Internal::ProjectInfoGenerator generator(fullProjectUpdateInfo);
promise.addResult(generator.generate(promise));
};
struct UpdateStorage {
ProjectInfo::ConstPtr projectInfo = nullptr;
};
const Storage<UpdateStorage> storage;
const auto onInfoGeneratorSetup = [this, infoGenerator](Async<ProjectInfo::ConstPtr> &async) {
async.setConcurrentCallData(infoGenerator);
async.setFutureSynchronizer(&m_futureSynchronizer);
};
const auto onInfoGeneratorDone = [storage](const Async<ProjectInfo::ConstPtr> &async) {
if (async.isResultAvailable())
storage->projectInfo = async.result();
};
GroupItems tasks{parallel};
tasks.append(AsyncTask<ProjectInfo::ConstPtr>(onInfoGeneratorSetup, onInfoGeneratorDone,
CallDone::OnSuccess));
for (QPointer<ExtraCompiler> compiler : compilers) {
if (compiler && compiler->isDirty())
tasks.append(compiler->compileFileItem());
}
const auto onDone = [this, storage, compilers] {
QList<ExtraCompiler *> extraCompilers;
QSet<FilePath> compilerFiles;
for (const QPointer<ExtraCompiler> &compiler : compilers) {
if (compiler) {
extraCompilers += compiler.data();
compilerFiles += Utils::toSet(compiler->targets());
}
}
GeneratedCodeModelSupport::update(extraCompilers);
auto updateFuture = CppModelManager::updateProjectInfo(storage->projectInfo, compilerFiles);
m_futureSynchronizer.addFuture(updateFuture);
};
const Group recipe {
storage,
Group(tasks),
onGroupDone(onDone, CallDone::OnSuccess)
};
m_taskTreeRunner.start(recipe, [](TaskTree &taskTree) {
auto progress = new Core::TaskProgress(&taskTree);
progress->setDisplayName(Tr::tr("Preparing C++ Code Model"));
});
}
void CppProjectUpdater::cancel()
{
m_taskTreeRunner.reset();
m_futureSynchronizer.cancelAllFutures();
}
class CppProjectUpdaterFactory final : public ProjectUpdaterFactory
{
public:
CppProjectUpdaterFactory()
{
setLanguage(Constants::CXX_LANGUAGE_ID);
setCreator([] { return new CppProjectUpdater; });
}
};
void setupCppProjectUpdater()
{
static CppProjectUpdaterFactory theCppProjectUpdaterFactory;
}
} // CppEditor::Internal
|