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 63 Lines • ▼ Show 20 Line(s) | |||||
107 | { | 109 | { | ||
108 | parseLock()->lockForWrite(); | 110 | parseLock()->lockForWrite(); | ||
109 | // By locking the parse-mutexes, we make sure that parse jobs get a chance to finish in a good state | 111 | // By locking the parse-mutexes, we make sure that parse jobs get a chance to finish in a good state | ||
110 | parseLock()->unlock(); | 112 | parseLock()->unlock(); | ||
111 | } | 113 | } | ||
112 | 114 | | |||
113 | bool CMakeManager::hasBuildInfo(ProjectBaseItem* item) const | 115 | bool CMakeManager::hasBuildInfo(ProjectBaseItem* item) const | ||
114 | { | 116 | { | ||
115 | return m_projects[item->project()].jsonData.files.contains(item->path()); | 117 | return m_projects[item->project()].compilationData.files.contains(item->path()); | ||
116 | } | 118 | } | ||
117 | 119 | | |||
118 | Path CMakeManager::buildDirectory(KDevelop::ProjectBaseItem *item) const | 120 | Path CMakeManager::buildDirectory(KDevelop::ProjectBaseItem *item) const | ||
119 | { | 121 | { | ||
120 | // CMakeFolderItem *fi=dynamic_cast<CMakeFolderItem*>(item); | 122 | // CMakeFolderItem *fi=dynamic_cast<CMakeFolderItem*>(item); | ||
121 | // Path ret; | 123 | // Path ret; | ||
122 | // ProjectBaseItem* parent = fi ? fi->formerParent() : item->parent(); | 124 | // ProjectBaseItem* parent = fi ? fi->formerParent() : item->parent(); | ||
123 | // if (parent) | 125 | // if (parent) | ||
Show All 9 Lines | |||||
133 | 135 | | |||
134 | KDevelop::ProjectFolderItem* CMakeManager::import( KDevelop::IProject *project ) | 136 | KDevelop::ProjectFolderItem* CMakeManager::import( KDevelop::IProject *project ) | ||
135 | { | 137 | { | ||
136 | CMake::checkForNeedingConfigure(project); | 138 | CMake::checkForNeedingConfigure(project); | ||
137 | 139 | | |||
138 | return AbstractFileManagerPlugin::import(project); | 140 | return AbstractFileManagerPlugin::import(project); | ||
139 | } | 141 | } | ||
140 | 142 | | |||
141 | KJob* CMakeManager::createImportJob(ProjectFolderItem* item) | 143 | 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? | |||||
142 | { | 144 | { | ||
143 | auto project = item->project(); | 145 | Q_OBJECT | ||
146 | public: | ||||
147 | ChooseCMakeInterfaceJob(IProject* project, CMakeManager* manager) | ||||
148 | : ExecuteCompositeJob(manager, {}) | ||||
149 | , project(project) | ||||
150 | , manager(manager) | ||||
151 | { | ||||
152 | } | ||||
153 | | ||||
154 | void start() override { | ||||
155 | server = new CMakeServer(project); | ||||
156 | connect(server, &CMakeServer::connected, this, &ChooseCMakeInterfaceJob::successfulConnection); | ||||
157 | connect(server, &CMakeServer::disconnected, this, &ChooseCMakeInterfaceJob::failedConnection); | ||||
Somewhy is not working:
zhigalin: Somewhy is not working:
> kdevelop.projectmanagers.cmake: cmake server socket error… | |||||
158 | } | ||||
159 | | ||||
160 | private: | ||||
161 | void successfulConnection() { | ||||
162 | auto job = new CMakeServerImportJob(project, server, this); | ||||
163 | connect(job, &CMakeServerImportJob::result, this, [this, job](){ | ||||
164 | if (job->error() == 0) { | ||||
165 | manager->integrateData(job->projectData(), job->project()); | ||||
166 | } | ||||
167 | }); | ||||
168 | addSubjob(job); | ||||
169 | ExecuteCompositeJob::start(); | ||||
170 | } | ||||
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… | |||||
171 | | ||||
172 | void failedConnection() { | ||||
173 | Q_ASSERT(!server->isServerAvailable()); | ||||
144 | 174 | | |||
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… | |||||
145 | QList<KJob*> jobs; | 175 | delete server; | ||
176 | // parse the JSON file | ||||
177 | CMakeImportJsonJob* job = new CMakeImportJsonJob(project, this); | ||||
146 | 178 | | |||
147 | // create the JSON file if it doesn't exist | 179 | // create the JSON file if it doesn't exist | ||
148 | auto commandsFile = CMake::commandsFile(project); | 180 | auto commandsFile = CMake::commandsFile(project); | ||
149 | if (!QFileInfo::exists(commandsFile.toLocalFile())) { | 181 | if (!QFileInfo::exists(commandsFile.toLocalFile())) { | ||
150 | qCDebug(CMAKE) << "couldn't find commands file:" << commandsFile << "- now trying to reconfigure"; | 182 | qCDebug(CMAKE) << "couldn't find commands file:" << commandsFile << "- now trying to reconfigure"; | ||
151 | jobs << builder()->configure(project); | 183 | addSubjob(manager->builder()->configure(project)); | ||
152 | } | 184 | } | ||
153 | 185 | | |||
154 | // parse the JSON file | 186 | connect(job, &CMakeImportJsonJob::result, this, [this, job](){ | ||
155 | CMakeImportJob* job = new CMakeImportJob(project, this); | 187 | if (job->error() == 0) { | ||
156 | connect(job, &CMakeImportJob::result, this, &CMakeManager::importFinished); | 188 | manager->integrateData(job->projectData(), job->project()); | ||
arrowd: Why comment this? | |||||
157 | jobs << job; | 189 | } | ||
190 | }); | ||||
191 | addSubjob(job); | ||||
192 | ExecuteCompositeJob::start(); | ||||
193 | } | ||||
194 | | ||||
195 | QPointer<CMakeServer> server = nullptr; | ||||
mwolff: these shouldn't be QPointer, or? | |||||
196 | QPointer<IProject> project = nullptr; | ||||
197 | QPointer<CMakeManager> manager; | ||||
198 | }; | ||||
158 | 199 | | |||
159 | // generate the file system listing | 200 | KJob* CMakeManager::createImportJob(ProjectFolderItem* item) | ||
160 | jobs << KDevelop::AbstractFileManagerPlugin::createImportJob(item); | 201 | { | ||
202 | auto project = item->project(); | ||||
203 | | ||||
204 | auto job = new ChooseCMakeInterfaceJob(project, this); | ||||
205 | connect(job, &CMakeImportJsonJob::result, this, [this, job, project](){ | ||||
206 | if (job->error() != 0) { | ||||
207 | qCWarning(CMAKE) << "couldn't load json successfully" << project->name(); | ||||
208 | m_projects.remove(project); | ||||
209 | } | ||||
210 | }); | ||||
211 | | ||||
212 | const QList<KJob*> jobs = { | ||||
213 | job, | ||||
214 | KDevelop::AbstractFileManagerPlugin::createImportJob(item) // generate the file system listing | ||||
215 | }; | ||||
161 | 216 | | |||
162 | Q_ASSERT(!jobs.contains(nullptr)); | 217 | Q_ASSERT(!jobs.contains(nullptr)); | ||
163 | ExecuteCompositeJob* composite = new ExecuteCompositeJob(this, jobs); | 218 | ExecuteCompositeJob* composite = new ExecuteCompositeJob(this, jobs); | ||
164 | // even if the cmake call failed, we want to load the project so that the project can be worked on | 219 | // even if the cmake call failed, we want to load the project so that the project can be worked on | ||
165 | composite->setAbortOnError(false); | 220 | composite->setAbortOnError(false); | ||
166 | return composite; | 221 | return composite; | ||
167 | } | 222 | } | ||
168 | 223 | | |||
Show All 9 Lines | 230 | { | |||
178 | { | 233 | { | ||
179 | ret+=p->projectItem()->targetList(); | 234 | ret+=p->projectItem()->targetList(); | ||
180 | } | 235 | } | ||
181 | return ret; | 236 | return ret; | ||
182 | } | 237 | } | ||
183 | 238 | | |||
184 | CMakeFile CMakeManager::fileInformation(KDevelop::ProjectBaseItem* item) const | 239 | CMakeFile CMakeManager::fileInformation(KDevelop::ProjectBaseItem* item) const | ||
185 | { | 240 | { | ||
186 | const CMakeJsonData & data = m_projects[item->project()].jsonData; | 241 | const auto & data = m_projects[item->project()].compilationData; | ||
187 | QHash<KDevelop::Path, CMakeFile>::const_iterator it = data.files.constFind(item->path()); | 242 | QHash<KDevelop::Path, CMakeFile>::const_iterator it = data.files.constFind(item->path()); | ||
188 | 243 | | |||
189 | if (it == data.files.constEnd()) { | 244 | if (it == data.files.constEnd()) { | ||
190 | // if the item path contains a symlink, then we will not find it in the lookup table | 245 | // if the item path contains a symlink, then we will not find it in the lookup table | ||
191 | // as that only only stores canonicalized paths. Thus, we fallback to | 246 | // as that only only stores canonicalized paths. Thus, we fallback to | ||
192 | // to the canonicalized path and see if that brings up any matches | 247 | // to the canonicalized path and see if that brings up any matches | ||
193 | const auto canonicalized = Path(QFileInfo(item->path().toLocalFile()).canonicalFilePath()); | 248 | const auto canonicalized = Path(QFileInfo(item->path().toLocalFile()).canonicalFilePath()); | ||
194 | it = data.files.constFind(canonicalized); | 249 | it = data.files.constFind(canonicalized); | ||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Line(s) | 335 | ) | |||
281 | new CMakeTargetItem(folder, name); | 336 | new CMakeTargetItem(folder, name); | ||
282 | } | 337 | } | ||
283 | 338 | | |||
284 | foreach (ProjectFolderItem* children, folder->folderList()) { | 339 | foreach (ProjectFolderItem* children, folder->folderList()) { | ||
285 | populateTargets(children, targets); | 340 | populateTargets(children, targets); | ||
286 | } | 341 | } | ||
287 | } | 342 | } | ||
288 | 343 | | |||
289 | void CMakeManager::importFinished(KJob* j) | 344 | void CMakeManager::integrateData(const CMakeProjectData &data, KDevelop::IProject* project) | ||
290 | { | 345 | { | ||
291 | CMakeImportJob* job = qobject_cast<CMakeImportJob*>(j); | | |||
292 | Q_ASSERT(job); | | |||
293 | | ||||
294 | auto project = job->project(); | | |||
295 | if (job->error() != 0) { | | |||
296 | qCDebug(CMAKE) << "Import failed for project" << project->name() << job->errorText(); | | |||
297 | m_projects.remove(project); | | |||
298 | } | | |||
299 | | ||||
300 | qCDebug(CMAKE) << "Successfully imported project" << project->name(); | | |||
301 | | ||||
302 | CMakeProjectData data; | | |||
303 | data.watcher->addPath(CMake::commandsFile(project).toLocalFile()); | | |||
304 | data.watcher->addPath(CMake::targetDirectoriesFile(project).toLocalFile()); | | |||
305 | data.jsonData = job->jsonData(); | | |||
306 | data.targets = job->targets(); | | |||
307 | connect(data.watcher.data(), &QFileSystemWatcher::fileChanged, this, &CMakeManager::dirtyFile); | 346 | connect(data.watcher.data(), &QFileSystemWatcher::fileChanged, this, &CMakeManager::dirtyFile); | ||
308 | connect(data.watcher.data(), &QFileSystemWatcher::directoryChanged, this, &CMakeManager::dirtyFile); | 347 | connect(data.watcher.data(), &QFileSystemWatcher::directoryChanged, this, &CMakeManager::dirtyFile); | ||
309 | m_projects[job->project()] = data; | 348 | m_projects[project] = data; | ||
310 | | ||||
311 | populateTargets(job->project()->projectItem(), job->targets()); | | |||
312 | 349 | | |||
313 | CTestUtils::createTestSuites(job->testSuites(), project); | 350 | populateTargets(project->projectItem(), data.targets); | ||
351 | CTestUtils::createTestSuites(data.m_testSuites, project); | ||||
314 | } | 352 | } | ||
315 | 353 | | |||
316 | // void CMakeManager::deletedWatchedDirectory(IProject* p, const QUrl &dir) | 354 | // void CMakeManager::deletedWatchedDirectory(IProject* p, const QUrl &dir) | ||
317 | // { | 355 | // { | ||
318 | // if(p->folder().equals(dir, QUrl::CompareWithoutTrailingSlash)) { | 356 | // if(p->folder().equals(dir, QUrl::CompareWithoutTrailingSlash)) { | ||
319 | // ICore::self()->projectController()->closeProject(p); | 357 | // ICore::self()->projectController()->closeProject(p); | ||
320 | // } else { | 358 | // } else { | ||
321 | // if(dir.fileName()=="CMakeLists.txt") { | 359 | // 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?