| 107 | } |
| 108 | |
| 109 | ReplyIndex findReplyIndexFile(const QString& buildDirectory) |
| 110 | { |
| 111 | const QFileInfo cmakeCacheInfo(buildDirectory + QLatin1String{"/CMakeCache.txt"}); |
| 112 | if (!cmakeCacheInfo.isFile()) { |
| 113 | // don't import data when no suitable CMakeCache file exists, which could happen |
| 114 | // because our prune job didn't use to delete the .cmake folder |
| 115 | qCDebug(CMAKE) << "no CMakeCache.txt found in" << cmakeCacheInfo.absolutePath(); |
| 116 | return {}; |
| 117 | } |
| 118 | |
| 119 | const QFileInfo queryInfo(queryDirPath(buildDirectory) + queryFileName()); |
| 120 | if (!queryInfo.isFile()) { |
| 121 | qCWarning(CMAKE) << "no API client query file found at" << queryInfo.absoluteFilePath(); |
| 122 | return {}; |
| 123 | } |
| 124 | |
| 125 | const auto isReplyOutdated = [&buildDirectory, &cmakeCacheInfo](const QDateTime& queryLastModified, |
| 126 | const QDateTime& replyLastModified) { |
| 127 | qCDebug(CMAKE) << PrintLastModified{"API client query file", queryLastModified} << "- within" << buildDirectory; |
| 128 | qCDebug(CMAKE) << PrintLastModified{"API reply index file", replyLastModified} << "- within" << buildDirectory; |
| 129 | if (replyLastModified < queryLastModified) { |
| 130 | qCDebug(CMAKE) << "API reply index file is out of date (last modified before the client query file)"; |
| 131 | return true; |
| 132 | } |
| 133 | |
| 134 | const auto cmakeCacheLastModified = cmakeCacheInfo.lastModified(); |
| 135 | qCDebug(CMAKE) << PrintLastModified{"CMakeCache.txt", cmakeCacheLastModified} << "- within" << buildDirectory; |
| 136 | // CMakeCache.txt can be modified during the CMake configure step - after KDevelop modifies the API |
| 137 | // client query file. The API reply index file is always modified during the CMake generate step. |
| 138 | if (replyLastModified < cmakeCacheLastModified) { |
| 139 | qCDebug(CMAKE) << "API reply index file is out of date (last modified before CMakeCache.txt)"; |
| 140 | return true; |
| 141 | } |
| 142 | |
| 143 | return false; |
| 144 | }; |
| 145 | |
| 146 | const auto replyDir = toReplyDir(buildDirectory); |
| 147 | const auto fileList = |
| 148 | replyDir.entryInfoList({QStringLiteral("index-*.json")}, QDir::Files, QDir::Name | QDir::Reversed); |
| 149 | for (const auto& entry : fileList) { |
| 150 | const auto object = parseFile(entry.absoluteFilePath()); |
| 151 | if (isKDevelopClientResponse(object)) { |
| 152 | ReplyIndex result{queryInfo.lastModified(), object}; |
| 153 | if (isReplyOutdated(result.queryLastModified, entry.lastModified())) { |
| 154 | result.markOutdated(); |
| 155 | } |
| 156 | return result; |
| 157 | } |
| 158 | } |
| 159 | qCWarning(CMAKE) << "no cmake-file-api reply index file found in" << replyDir.absolutePath(); |
| 160 | return {}; |
| 161 | } |
| 162 | |
| 163 | static CMakeTarget parseTarget(const QJsonObject& target, StringInterner& stringInterner, |
| 164 | PathInterner& sourcePathInterner, PathInterner& buildPathInterner, |