Changeset View
Standalone View
projectmanagers/cmake/cmakemanager.cpp
Show All 27 Lines | |||||
28 | #include "debug.h" | 28 | #include "debug.h" | ||
29 | #include "settings/cmakepreferences.h" | 29 | #include "settings/cmakepreferences.h" | ||
30 | #include <projectmanagers/custommake/makefileresolver/makefileresolver.h> | 30 | #include <projectmanagers/custommake/makefileresolver/makefileresolver.h> | ||
31 | #include "cmakecodecompletionmodel.h" | 31 | #include "cmakecodecompletionmodel.h" | ||
32 | #include "cmakenavigationwidget.h" | 32 | #include "cmakenavigationwidget.h" | ||
33 | #include "icmakedocumentation.h" | 33 | #include "icmakedocumentation.h" | ||
34 | #include "cmakemodelitems.h" | 34 | #include "cmakemodelitems.h" | ||
35 | #include "testing/ctestutils.h" | 35 | #include "testing/ctestutils.h" | ||
36 | #include "cmakeserverimportjob.h" | ||||
37 | #include "cmakeserver.h" | ||||
36 | 38 | | |||
37 | #include <QDir> | 39 | #include <QDir> | ||
38 | #include <QReadWriteLock> | 40 | #include <QReadWriteLock> | ||
39 | #include <QThread> | 41 | #include <QThread> | ||
40 | #include <QFileSystemWatcher> | 42 | #include <QFileSystemWatcher> | ||
41 | #include <QTimer> | 43 | #include <QTimer> | ||
42 | #include <qjsondocument.h> | 44 | #include <qjsondocument.h> | ||
43 | 45 | | |||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Line(s) | |||||
106 | { | 108 | { | ||
107 | parseLock()->lockForWrite(); | 109 | parseLock()->lockForWrite(); | ||
108 | // By locking the parse-mutexes, we make sure that parse jobs get a chance to finish in a good state | 110 | // By locking the parse-mutexes, we make sure that parse jobs get a chance to finish in a good state | ||
109 | parseLock()->unlock(); | 111 | parseLock()->unlock(); | ||
110 | } | 112 | } | ||
111 | 113 | | |||
112 | bool CMakeManager::hasBuildInfo(ProjectBaseItem* item) const | 114 | bool CMakeManager::hasBuildInfo(ProjectBaseItem* item) const | ||
113 | { | 115 | { | ||
114 | return m_projects[item->project()].jsonData.files.contains(item->path()); | 116 | return m_projects[item->project()].compilationData.files.contains(item->path()); | ||
115 | } | 117 | } | ||
116 | 118 | | |||
117 | Path CMakeManager::buildDirectory(KDevelop::ProjectBaseItem *item) const | 119 | Path CMakeManager::buildDirectory(KDevelop::ProjectBaseItem *item) const | ||
118 | { | 120 | { | ||
119 | // CMakeFolderItem *fi=dynamic_cast<CMakeFolderItem*>(item); | 121 | // CMakeFolderItem *fi=dynamic_cast<CMakeFolderItem*>(item); | ||
120 | // Path ret; | 122 | // Path ret; | ||
121 | // ProjectBaseItem* parent = fi ? fi->formerParent() : item->parent(); | 123 | // ProjectBaseItem* parent = fi ? fi->formerParent() : item->parent(); | ||
122 | // if (parent) | 124 | // if (parent) | ||
Show All 9 Lines | |||||
132 | 134 | | |||
133 | KDevelop::ProjectFolderItem* CMakeManager::import( KDevelop::IProject *project ) | 135 | KDevelop::ProjectFolderItem* CMakeManager::import( KDevelop::IProject *project ) | ||
134 | { | 136 | { | ||
135 | CMake::checkForNeedingConfigure(project); | 137 | CMake::checkForNeedingConfigure(project); | ||
136 | 138 | | |||
137 | return AbstractFileManagerPlugin::import(project); | 139 | return AbstractFileManagerPlugin::import(project); | ||
138 | } | 140 | } | ||
139 | 141 | | |||
140 | KJob* CMakeManager::createImportJob(ProjectFolderItem* item) | 142 | class ChooseCMakeInterfaceJob : public ExecuteCompositeJob | ||
mwolff: for PODs, you don't need Q_GLOBAL_STATIC. simply make this a
namespace {
static bool… | |||||
mwolff: this is not used anywhere now? | |||||
141 | { | 143 | { | ||
142 | auto project = item->project(); | 144 | Q_OBJECT | ||
145 | public: | ||||
146 | ChooseCMakeInterfaceJob(IProject* project, CMakeManager* manager) | ||||
147 | : ExecuteCompositeJob(manager, {}) | ||||
148 | , project(project) | ||||
149 | , manager(manager) | ||||
150 | { | ||||
151 | } | ||||
152 | | ||||
153 | void start() override { | ||||
154 | server = new CMakeServer(project); | ||||
155 | connect(server, &CMakeServer::connected, this, &ChooseCMakeInterfaceJob::successfulConnection); | ||||
156 | connect(server, &CMakeServer::disconnected, this, &ChooseCMakeInterfaceJob::failedConnection); | ||||
Somewhy is not working:
zhigalin: Somewhy is not working:
> kdevelop.projectmanagers.cmake: cmake server socket error… | |||||
157 | } | ||||
158 | | ||||
159 | private: | ||||
160 | void successfulConnection() { | ||||
161 | auto job = new CMakeServerImportJob(project, server, this); | ||||
162 | connect(job, &CMakeServerImportJob::result, this, [this, job](){ | ||||
163 | if (job->error() == 0) { | ||||
164 | manager->integrateData(job->projectData(), job->project()); | ||||
165 | } | ||||
166 | }); | ||||
167 | addSubjob(job); | ||||
168 | ExecuteCompositeJob::start(); | ||||
169 | } | ||||
Who will delete the server when it is available? this looks like you are piling up servers until the CMakeManager is deleted at shutdown. You probably want to use a unique_ptr here and transfer ownership into the import job when the server is available mwolff: Who will delete the server when it is available? this looks like you are piling up servers… | |||||
170 | | ||||
171 | void failedConnection() { | ||||
172 | Q_ASSERT(!server->isServerAvailable()); | ||||
143 | 173 | | |||
make this a warning? also, do we want to show the user that? this can be serious and render the whole cmake support useless after all, right? mwolff: make this a warning? also, do we want to show the user that? this can be serious and render the… | |||||
warning, and see above? actually the whole code is duplicated - move this into a proper slot? or at least share the lambda body? mwolff: warning, and see above? actually the whole code is duplicated - move this into a proper slot? | |||||
As is we can't, they should inherit from the same class. I don't think it's a big deal at the moment... apol: As is we can't, they should inherit from the same class. I don't think it's a big deal at the… | |||||
144 | QList<KJob*> jobs; | 174 | delete server; | ||
175 | // parse the JSON file | ||||
176 | CMakeImportJsonJob* job = new CMakeImportJsonJob(project, this); | ||||
145 | 177 | | |||
146 | // create the JSON file if it doesn't exist | 178 | // create the JSON file if it doesn't exist | ||
147 | auto commandsFile = CMake::commandsFile(project); | 179 | auto commandsFile = CMake::commandsFile(project); | ||
148 | if (!QFileInfo::exists(commandsFile.toLocalFile())) { | 180 | if (!QFileInfo::exists(commandsFile.toLocalFile())) { | ||
149 | qCDebug(CMAKE) << "couldn't find commands file:" << commandsFile << "- now trying to reconfigure"; | 181 | qCDebug(CMAKE) << "couldn't find commands file:" << commandsFile << "- now trying to reconfigure"; | ||
150 | jobs << builder()->configure(project); | 182 | addSubjob(manager->builder()->configure(project)); | ||
151 | } | 183 | } | ||
152 | 184 | | |||
153 | // parse the JSON file | 185 | connect(job, &CMakeImportJsonJob::result, this, [this, job](){ | ||
154 | CMakeImportJob* job = new CMakeImportJob(project, this); | 186 | if (job->error() == 0) { | ||
155 | connect(job, &CMakeImportJob::result, this, &CMakeManager::importFinished); | 187 | manager->integrateData(job->projectData(), job->project()); | ||
arrowd: Why comment this? | |||||
156 | jobs << job; | 188 | } | ||
189 | }); | ||||
190 | addSubjob(job); | ||||
191 | ExecuteCompositeJob::start(); | ||||
192 | } | ||||
193 | | ||||
194 | CMakeServer* server = nullptr; | ||||
mwolff: these shouldn't be QPointer, or? | |||||
195 | IProject* const project; | ||||
196 | CMakeManager* const manager; | ||||
197 | }; | ||||
157 | 198 | | |||
158 | // generate the file system listing | 199 | KJob* CMakeManager::createImportJob(ProjectFolderItem* item) | ||
159 | jobs << KDevelop::AbstractFileManagerPlugin::createImportJob(item); | 200 | { | ||
201 | auto project = item->project(); | ||||
202 | | ||||
203 | auto job = new ChooseCMakeInterfaceJob(project, this); | ||||
204 | connect(job, &CMakeImportJsonJob::result, this, [this, job, project](){ | ||||
205 | if (job->error() != 0) { | ||||
206 | qCWarning(CMAKE) << "couldn't load json successfully" << project->name(); | ||||
207 | m_projects.remove(project); | ||||
208 | } | ||||
209 | }); | ||||
210 | | ||||
211 | const QList<KJob*> jobs = { | ||||
212 | job, | ||||
213 | KDevelop::AbstractFileManagerPlugin::createImportJob(item) // generate the file system listing | ||||
214 | }; | ||||
160 | 215 | | |||
161 | Q_ASSERT(!jobs.contains(nullptr)); | 216 | Q_ASSERT(!jobs.contains(nullptr)); | ||
162 | ExecuteCompositeJob* composite = new ExecuteCompositeJob(this, jobs); | 217 | ExecuteCompositeJob* composite = new ExecuteCompositeJob(this, jobs); | ||
163 | // even if the cmake call failed, we want to load the project so that the project can be worked on | 218 | // even if the cmake call failed, we want to load the project so that the project can be worked on | ||
164 | composite->setAbortOnError(false); | 219 | composite->setAbortOnError(false); | ||
165 | return composite; | 220 | return composite; | ||
166 | } | 221 | } | ||
167 | 222 | | |||
Show All 9 Lines | 229 | { | |||
177 | { | 232 | { | ||
178 | ret+=p->projectItem()->targetList(); | 233 | ret+=p->projectItem()->targetList(); | ||
179 | } | 234 | } | ||
180 | return ret; | 235 | return ret; | ||
181 | } | 236 | } | ||
182 | 237 | | |||
183 | CMakeFile CMakeManager::fileInformation(KDevelop::ProjectBaseItem* item) const | 238 | CMakeFile CMakeManager::fileInformation(KDevelop::ProjectBaseItem* item) const | ||
184 | { | 239 | { | ||
185 | const CMakeJsonData & data = m_projects[item->project()].jsonData; | 240 | const auto & data = m_projects[item->project()].compilationData; | ||
186 | QHash<KDevelop::Path, CMakeFile>::const_iterator it = data.files.constFind(item->path()); | 241 | QHash<KDevelop::Path, CMakeFile>::const_iterator it = data.files.constFind(item->path()); | ||
187 | 242 | | |||
188 | if (it == data.files.constEnd()) { | 243 | if (it == data.files.constEnd()) { | ||
189 | // if the item path contains a symlink, then we will not find it in the lookup table | 244 | // if the item path contains a symlink, then we will not find it in the lookup table | ||
190 | // as that only only stores canonicalized paths. Thus, we fallback to | 245 | // as that only only stores canonicalized paths. Thus, we fallback to | ||
191 | // to the canonicalized path and see if that brings up any matches | 246 | // to the canonicalized path and see if that brings up any matches | ||
192 | const auto canonicalized = Path(QFileInfo(item->path().toLocalFile()).canonicalFilePath()); | 247 | const auto canonicalized = Path(QFileInfo(item->path().toLocalFile()).canonicalFilePath()); | ||
193 | it = data.files.constFind(canonicalized); | 248 | it = data.files.constFind(canonicalized); | ||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Line(s) | 334 | ) | |||
280 | new CMakeTargetItem(folder, name); | 335 | new CMakeTargetItem(folder, name); | ||
281 | } | 336 | } | ||
282 | 337 | | |||
283 | foreach (ProjectFolderItem* children, folder->folderList()) { | 338 | foreach (ProjectFolderItem* children, folder->folderList()) { | ||
284 | populateTargets(children, targets); | 339 | populateTargets(children, targets); | ||
285 | } | 340 | } | ||
286 | } | 341 | } | ||
287 | 342 | | |||
288 | void CMakeManager::importFinished(KJob* j) | 343 | void CMakeManager::integrateData(const CMakeProjectData &data, KDevelop::IProject* project) | ||
289 | { | 344 | { | ||
290 | CMakeImportJob* job = qobject_cast<CMakeImportJob*>(j); | | |||
291 | Q_ASSERT(job); | | |||
292 | | ||||
293 | auto project = job->project(); | | |||
294 | if (job->error() != 0) { | | |||
295 | qCDebug(CMAKE) << "Import failed for project" << project->name() << job->errorText(); | | |||
296 | m_projects.remove(project); | | |||
297 | } | | |||
298 | | ||||
299 | qCDebug(CMAKE) << "Successfully imported project" << project->name(); | | |||
300 | | ||||
301 | CMakeProjectData data; | | |||
302 | data.watcher->addPath(CMake::commandsFile(project).toLocalFile()); | | |||
303 | data.watcher->addPath(CMake::targetDirectoriesFile(project).toLocalFile()); | | |||
304 | data.jsonData = job->jsonData(); | | |||
305 | data.targets = job->targets(); | | |||
306 | connect(data.watcher.data(), &QFileSystemWatcher::fileChanged, this, &CMakeManager::dirtyFile); | 345 | connect(data.watcher.data(), &QFileSystemWatcher::fileChanged, this, &CMakeManager::dirtyFile); | ||
307 | connect(data.watcher.data(), &QFileSystemWatcher::directoryChanged, this, &CMakeManager::dirtyFile); | 346 | connect(data.watcher.data(), &QFileSystemWatcher::directoryChanged, this, &CMakeManager::dirtyFile); | ||
308 | m_projects[job->project()] = data; | 347 | m_projects[project] = data; | ||
309 | | ||||
310 | populateTargets(job->project()->projectItem(), job->targets()); | | |||
311 | 348 | | |||
312 | CTestUtils::createTestSuites(job->testSuites(), project); | 349 | populateTargets(project->projectItem(), data.targets); | ||
350 | CTestUtils::createTestSuites(data.m_testSuites, project); | ||||
313 | } | 351 | } | ||
314 | 352 | | |||
315 | // void CMakeManager::deletedWatchedDirectory(IProject* p, const QUrl &dir) | 353 | // void CMakeManager::deletedWatchedDirectory(IProject* p, const QUrl &dir) | ||
316 | // { | 354 | // { | ||
317 | // if(p->folder().equals(dir, QUrl::CompareWithoutTrailingSlash)) { | 355 | // if(p->folder().equals(dir, QUrl::CompareWithoutTrailingSlash)) { | ||
318 | // ICore::self()->projectController()->closeProject(p); | 356 | // ICore::self()->projectController()->closeProject(p); | ||
319 | // } else { | 357 | // } else { | ||
320 | // if(dir.fileName()=="CMakeLists.txt") { | 358 | // if(dir.fileName()=="CMakeLists.txt") { | ||
▲ Show 20 Lines • Show All 561 Lines • Show Last 20 Lines |
for PODs, you don't need Q_GLOBAL_STATIC. simply make this a
namespace {
static bool s_serverSupported = false;
}
on a conceptual level - this depends on the cmake binary that can be selected for every project, no? So this should not be a static at all, but rather a per-project property?