| 258 | } |
| 259 | |
| 260 | void ProjectFileDataProvider::projectOpened(IProject* project) |
| 261 | { |
| 262 | connect(project, &IProject::fileAddedToSet, |
| 263 | this, &ProjectFileDataProvider::fileAddedToSet); |
| 264 | connect(project, &IProject::fileRemovedFromSet, |
| 265 | this, &ProjectFileDataProvider::fileRemovedFromSet); |
| 266 | |
| 267 | // Collect the opened project's files. |
| 268 | const auto oldSize = m_projectFiles.size(); |
| 269 | KDevelop::forEachFile(project->projectItem(), [this](ProjectFileItem* fileItem) { |
| 270 | // TODO Qt6: benchmark the following alternatives: |
| 271 | // 1) emplace_back in place of push_back here; |
| 272 | // 2) std::vector instead of QVector m_projectFiles, i.e. revert fdb3126371bb13b778ce48f538d4836b92a384f1. |
| 273 | m_projectFiles.push_back(ProjectFile{fileItem}); |
| 274 | }); |
| 275 | const auto justAddedBegin = m_projectFiles.begin() + oldSize; |
| 276 | |
| 277 | // Sort the opened project's files. |
| 278 | // Sorting stability is not useful here, but timsort vastly outperforms all |
| 279 | // std and boost sorting algorithms (boost::sort::flat_stable_sort is the |
| 280 | // second best) on the files of large real-life projects, because |
| 281 | // KDevelop::forEachFile() collects files in an almost sorted order. |
| 282 | gfx::timsort(justAddedBegin, m_projectFiles.end()); |
| 283 | |
| 284 | // Merge the sorted ranges of files belonging to previously opened projects |
| 285 | // and to the just opened project. |
| 286 | // Since the file sets from different projects usually don't overlap or overlap |
| 287 | // very little, timmerge is the perfect merge algorithm. Furthermore, the |
| 288 | // comparison of ProjectFile objects is expensive and cache-unfriendly. This |
| 289 | // aspect lets timmerge outperform std::inplace_merge even more here. This same |
| 290 | // aspect also helps timsort outperform other sorting algorithms. |
| 291 | gfx::timmerge(m_projectFiles.begin(), justAddedBegin, m_projectFiles.end()); |
| 292 | |
| 293 | // Remove duplicates across all open projects. Usually different projects have no |
| 294 | // common files. But since a file can belong to multiple targets within one project, |
| 295 | // a single call to KDevelop::forEachFile() often produces many duplicates. |
| 296 | const auto equalFiles = [](const ProjectFile& a, const ProjectFile& b) { |
| 297 | return a.indexedPath == b.indexedPath; |
| 298 | }; |
| 299 | m_projectFiles.erase(std::unique(m_projectFiles.begin(), m_projectFiles.end(), equalFiles), |
| 300 | m_projectFiles.end()); |
| 301 | } |
| 302 | |
| 303 | void ProjectFileDataProvider::fileAddedToSet(ProjectFileItem* fileItem) |
| 304 | { |
nothing calls this directly
no test coverage detected