CMake: Use Utils::FilePath in fileapi parser and reader

It still relies on local host execution in some places.

Change-Id: I36adfeb93ea26b285bbf6da2aee7e0fac64a7d94
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
This commit is contained in:
hjk
2021-06-08 14:42:59 +02:00
parent 18a9df8b4a
commit d254cf5845
4 changed files with 63 additions and 54 deletions

View File

@@ -91,11 +91,13 @@ static std::pair<QString, QString> nameValue(const QJsonObject &obj)
return std::make_pair(obj.value("name").toString(), obj.value("value").toString()); return std::make_pair(obj.value("name").toString(), obj.value("value").toString());
} }
static QJsonDocument readJsonFile(const QString &path) static QJsonDocument readJsonFile(const FilePath &filePath)
{ {
qCDebug(cmakeFileApi) << "readJsonFile:" << path; qCDebug(cmakeFileApi) << "readJsonFile:" << filePath;
QFile file(path); QTC_CHECK(!filePath.needsDevice());
QFile file(filePath.path());
file.open(QIODevice::ReadOnly | QIODevice::Text); file.open(QIODevice::ReadOnly | QIODevice::Text);
const QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); const QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
@@ -116,9 +118,9 @@ std::vector<int> indexList(const QJsonValue &v)
// Reply file: // Reply file:
static ReplyFileContents readReplyFile(const QFileInfo &fi, QString &errorMessage) static ReplyFileContents readReplyFile(const FilePath &filePath, QString &errorMessage)
{ {
const QJsonDocument document = readJsonFile(fi.filePath()); const QJsonDocument document = readJsonFile(filePath);
static const QString msg = QCoreApplication::translate("CMakeProjectManager::Internal", static const QString msg = QCoreApplication::translate("CMakeProjectManager::Internal",
"Invalid reply file created by CMake."); "Invalid reply file created by CMake.");
@@ -176,7 +178,7 @@ static ReplyFileContents readReplyFile(const QFileInfo &fi, QString &errorMessag
// Cache file: // Cache file:
static CMakeConfig readCacheFile(const QString &cacheFile, QString &errorMessage) static CMakeConfig readCacheFile(const FilePath &cacheFile, QString &errorMessage)
{ {
CMakeConfig result; CMakeConfig result;
@@ -222,7 +224,7 @@ static CMakeConfig readCacheFile(const QString &cacheFile, QString &errorMessage
// CMake Files: // CMake Files:
std::vector<CMakeFileInfo> readCMakeFilesFile(const QString &cmakeFilesFile, QString &errorMessage) static std::vector<CMakeFileInfo> readCMakeFilesFile(const FilePath &cmakeFilesFile, QString &errorMessage)
{ {
std::vector<CMakeFileInfo> result; std::vector<CMakeFileInfo> result;
@@ -492,7 +494,7 @@ static std::vector<Configuration> extractConfigurations(const QJsonArray &config
return result; return result;
} }
static std::vector<Configuration> readCodemodelFile(const QString &codemodelFile, static std::vector<Configuration> readCodemodelFile(const FilePath &codemodelFile,
QString &errorMessage) QString &errorMessage)
{ {
const QJsonDocument doc = readJsonFile(codemodelFile); const QJsonDocument doc = readJsonFile(codemodelFile);
@@ -509,7 +511,7 @@ static std::vector<Configuration> readCodemodelFile(const QString &codemodelFile
// TargetDetails: // TargetDetails:
std::vector<FileApiDetails::FragmentInfo> extractFragments(const QJsonObject &obj) static std::vector<FileApiDetails::FragmentInfo> extractFragments(const QJsonObject &obj)
{ {
const QJsonArray fragments = obj.value("commandFragments").toArray(); const QJsonArray fragments = obj.value("commandFragments").toArray();
return transform<std::vector>(fragments, [](const QJsonValue &v) { return transform<std::vector>(fragments, [](const QJsonValue &v) {
@@ -519,7 +521,7 @@ std::vector<FileApiDetails::FragmentInfo> extractFragments(const QJsonObject &ob
}); });
} }
TargetDetails extractTargetDetails(const QJsonObject &root, QString &errorMessage) static TargetDetails extractTargetDetails(const QJsonObject &root, QString &errorMessage)
{ {
TargetDetails t; TargetDetails t;
t.name = root.value("name").toString(); t.name = root.value("name").toString();
@@ -676,7 +678,7 @@ TargetDetails extractTargetDetails(const QJsonObject &root, QString &errorMessag
return t; return t;
} }
int validateBacktraceGraph(const TargetDetails &t) static int validateBacktraceGraph(const TargetDetails &t)
{ {
const int backtraceFilesCount = static_cast<int>(t.backtraceGraph.files.size()); const int backtraceFilesCount = static_cast<int>(t.backtraceGraph.files.size());
const int backtraceCommandsCount = static_cast<int>(t.backtraceGraph.commands.size()); const int backtraceCommandsCount = static_cast<int>(t.backtraceGraph.commands.size());
@@ -710,7 +712,7 @@ int validateBacktraceGraph(const TargetDetails &t)
return backtraceNodeCount; return backtraceNodeCount;
} }
bool validateTargetDetails(const TargetDetails &t) static bool validateTargetDetails(const TargetDetails &t)
{ {
// The part filled in by the codemodel file has already been covered! // The part filled in by the codemodel file has already been covered!
@@ -789,7 +791,7 @@ bool validateTargetDetails(const TargetDetails &t)
return true; return true;
} }
TargetDetails readTargetFile(const QString &targetFile, QString &errorMessage) static TargetDetails readTargetFile(const FilePath &targetFile, QString &errorMessage)
{ {
const QJsonDocument doc = readJsonFile(targetFile); const QJsonDocument doc = readJsonFile(targetFile);
const QJsonObject root = doc.object(); const QJsonObject root = doc.object();
@@ -807,13 +809,13 @@ TargetDetails readTargetFile(const QString &targetFile, QString &errorMessage)
// ReplyFileContents: // ReplyFileContents:
// -------------------------------------------------------------------- // --------------------------------------------------------------------
QString FileApiDetails::ReplyFileContents::jsonFile(const QString &kind, const QDir &replyDir) const FilePath FileApiDetails::ReplyFileContents::jsonFile(const QString &kind, const FilePath &replyDir) const
{ {
const auto ro = findOrDefault(replies, equal(&ReplyObject::kind, kind)); const auto ro = findOrDefault(replies, equal(&ReplyObject::kind, kind));
if (ro.file.isEmpty()) if (ro.file.isEmpty())
return QString(); return {};
else else
return replyDir.absoluteFilePath(ro.file); return (replyDir / ro.file).absoluteFilePath();
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
@@ -839,8 +841,9 @@ bool FileApiParser::setupCMakeFileApi(const FilePath &buildDirectory, Utils::Fil
QTC_ASSERT(queryDir.exists(), ); QTC_ASSERT(queryDir.exists(), );
bool failedBefore = false; bool failedBefore = false;
for (const QString &filePath : cmakeQueryFilePaths(buildDirectory)) { for (const FilePath &filePath : cmakeQueryFilePaths(buildDirectory)) {
QFile f(filePath); QTC_CHECK(!filePath.needsDevice());
QFile f(filePath.path());
if (!f.exists()) { if (!f.exists()) {
f.open(QFile::WriteOnly); f.open(QFile::WriteOnly);
f.close(); f.close();
@@ -871,12 +874,13 @@ static QStringList uniqueTargetFiles(const Configuration &config)
} }
FileApiData FileApiParser::parseData(QFutureInterface<std::shared_ptr<FileApiQtcData>> &fi, FileApiData FileApiParser::parseData(QFutureInterface<std::shared_ptr<FileApiQtcData>> &fi,
const QFileInfo &replyFileInfo, const FilePath &replyFilePath,
const QString &cmakeBuildType, const QString &cmakeBuildType,
QString &errorMessage) QString &errorMessage)
{ {
QTC_CHECK(errorMessage.isEmpty()); QTC_CHECK(errorMessage.isEmpty());
const QDir replyDir = replyFileInfo.dir(); QTC_CHECK(!replyFilePath.needsDevice());
const FilePath replyDir = replyFilePath.parentDir();
FileApiData result; FileApiData result;
@@ -888,7 +892,7 @@ FileApiData FileApiParser::parseData(QFutureInterface<std::shared_ptr<FileApiQtc
return false; return false;
}; };
result.replyFile = readReplyFile(replyFileInfo, errorMessage); result.replyFile = readReplyFile(replyFilePath, errorMessage);
if (cancelCheck()) if (cancelCheck())
return {}; return {};
result.cache = readCacheFile(result.replyFile.jsonFile("cache", replyDir), errorMessage); result.cache = readCacheFile(result.replyFile.jsonFile("cache", replyDir), errorMessage);
@@ -938,7 +942,7 @@ FileApiData FileApiParser::parseData(QFutureInterface<std::shared_ptr<FileApiQtc
if (cancelCheck()) if (cancelCheck())
return {}; return {};
QString targetErrorMessage; QString targetErrorMessage;
TargetDetails td = readTargetFile(replyDir.absoluteFilePath(targetFile), targetErrorMessage); TargetDetails td = readTargetFile((replyDir / targetFile).absoluteFilePath(), targetErrorMessage);
if (targetErrorMessage.isEmpty()) { if (targetErrorMessage.isEmpty()) {
result.targetDetails.emplace_back(std::move(td)); result.targetDetails.emplace_back(std::move(td));
} else { } else {
@@ -951,23 +955,27 @@ FileApiData FileApiParser::parseData(QFutureInterface<std::shared_ptr<FileApiQtc
return result; return result;
} }
QFileInfo FileApiParser::scanForCMakeReplyFile(const FilePath &buildDirectory) FilePath FileApiParser::scanForCMakeReplyFile(const FilePath &buildDirectory)
{ {
QDir replyDir(cmakeReplyDirectory(buildDirectory).toString()); QTC_CHECK(!buildDirectory.needsDevice());
QDir replyDir(cmakeReplyDirectory(buildDirectory).path());
if (!replyDir.exists()) if (!replyDir.exists())
return {}; return {};
const QFileInfoList fis = replyDir.entryInfoList(QStringList("index-*.json"), const QFileInfoList fis = replyDir.entryInfoList(QStringList("index-*.json"),
QDir::Files, QDir::Files,
QDir::Name); QDir::Name);
return fis.isEmpty() ? QFileInfo() : fis.last(); const QFileInfo fi = fis.isEmpty() ? QFileInfo() : fis.last();
return FilePath::fromFileInfo(fi);
} }
QStringList FileApiParser::cmakeQueryFilePaths(const Utils::FilePath &buildDirectory) FilePaths FileApiParser::cmakeQueryFilePaths(const FilePath &buildDirectory)
{ {
QDir queryDir(QDir::cleanPath(buildDirectory.pathAppended(CMAKE_RELATIVE_QUERY_PATH).toString())); QTC_CHECK(!buildDirectory.needsDevice());
return transform(CMAKE_QUERY_FILENAMES, QDir queryDir(QDir::cleanPath(buildDirectory.pathAppended(CMAKE_RELATIVE_QUERY_PATH).path()));
[&queryDir](const QString &name) { return queryDir.absoluteFilePath(name); }); return transform(CMAKE_QUERY_FILENAMES, [&queryDir](const QString &name) {
return FilePath::fromString(queryDir.absoluteFilePath(name));
});
} }
} // namespace Internal } // namespace Internal

View File

@@ -66,7 +66,7 @@ public:
QVector<ReplyObject> replies; QVector<ReplyObject> replies;
QString jsonFile(const QString &kind, const QDir &replyDir) const; Utils::FilePath jsonFile(const QString &kind, const Utils::FilePath &replyDir) const;
}; };
class CMakeFileInfo class CMakeFileInfo
@@ -251,16 +251,16 @@ class FileApiParser
Q_DECLARE_TR_FUNCTIONS(FileApiParser) Q_DECLARE_TR_FUNCTIONS(FileApiParser)
public: public:
static FileApiData parseData(QFutureInterface<std::shared_ptr<FileApiQtcData>> &fi, static FileApiData parseData(QFutureInterface<std::shared_ptr<FileApiQtcData>> &fi,
const QFileInfo &replyFileInfo, const Utils::FilePath &replyFilePath,
const QString &cmakeBuildType, const QString &cmakeBuildType,
QString &errorMessage); QString &errorMessage);
static bool setupCMakeFileApi(const Utils::FilePath &buildDirectory, static bool setupCMakeFileApi(const Utils::FilePath &buildDirectory,
Utils::FileSystemWatcher &watcher); Utils::FileSystemWatcher &watcher);
static QStringList cmakeQueryFilePaths(const Utils::FilePath &buildDirectory); static Utils::FilePaths cmakeQueryFilePaths(const Utils::FilePath &buildDirectory);
static QFileInfo scanForCMakeReplyFile(const Utils::FilePath &buildDirectory); static Utils::FilePath scanForCMakeReplyFile(const Utils::FilePath &buildDirectory);
}; };
} // namespace Internal } // namespace Internal

View File

@@ -116,7 +116,7 @@ void FileApiReader::parse(bool forceCMakeRun,
: QStringList()); : QStringList());
qCDebug(cmakeFileApiMode) << "Parameters request these CMake arguments:" << args; qCDebug(cmakeFileApiMode) << "Parameters request these CMake arguments:" << args;
const QFileInfo replyFi = FileApiParser::scanForCMakeReplyFile(m_parameters.workDirectory); const FilePath replyFile = FileApiParser::scanForCMakeReplyFile(m_parameters.workDirectory);
// Only need to update when one of the following conditions is met: // Only need to update when one of the following conditions is met:
// * The user forces the cmake run, // * The user forces the cmake run,
// * The user provided arguments, // * The user provided arguments,
@@ -125,17 +125,14 @@ void FileApiReader::parse(bool forceCMakeRun,
// for creator to run CMake as needed, // for creator to run CMake as needed,
// * A query file is newer than the reply file // * A query file is newer than the reply file
const bool hasArguments = !args.isEmpty(); const bool hasArguments = !args.isEmpty();
const bool replyFileMissing = !replyFi.exists(); const bool replyFileMissing = !replyFile.exists();
const bool cmakeFilesChanged = m_parameters.cmakeTool() && m_parameters.cmakeTool()->isAutoRun() const bool cmakeFilesChanged = m_parameters.cmakeTool() && m_parameters.cmakeTool()->isAutoRun()
&& anyOf(m_cmakeFiles, [&replyFi](const FilePath &f) { && anyOf(m_cmakeFiles, [&replyFile](const FilePath &f) {
return f.toFileInfo().lastModified() return f.lastModified() > replyFile.lastModified();
> replyFi.lastModified();
}); });
const bool queryFileChanged = anyOf(FileApiParser::cmakeQueryFilePaths( const bool queryFileChanged = anyOf(FileApiParser::cmakeQueryFilePaths(m_parameters.workDirectory),
m_parameters.workDirectory), [&replyFile](const FilePath &qf) {
[&replyFi](const QString &qf) { return qf.lastModified() > replyFile.lastModified();
return QFileInfo(qf).lastModified()
> replyFi.lastModified();
}); });
const bool mustUpdate = forceCMakeRun || hasArguments || replyFileMissing || cmakeFilesChanged const bool mustUpdate = forceCMakeRun || hasArguments || replyFileMissing || cmakeFilesChanged
@@ -156,7 +153,7 @@ void FileApiReader::parse(bool forceCMakeRun,
.arg(args.join("\", \"")); .arg(args.join("\", \""));
startCMakeState(args); startCMakeState(args);
} else { } else {
endState(replyFi); endState(replyFile);
} }
} }
@@ -245,7 +242,7 @@ void FileApiReader::startState()
emit configurationStarted(); emit configurationStarted();
} }
void FileApiReader::endState(const QFileInfo &replyFi) void FileApiReader::endState(const FilePath &replyFilePath)
{ {
qCDebug(cmakeFileApiMode) << "FileApiReader: END STATE."; qCDebug(cmakeFileApiMode) << "FileApiReader: END STATE.";
QTC_ASSERT(m_isParsing, return ); QTC_ASSERT(m_isParsing, return );
@@ -256,14 +253,15 @@ void FileApiReader::endState(const QFileInfo &replyFi)
const FilePath topCmakeFile = m_cmakeFiles.size() == 1 ? *m_cmakeFiles.begin() : FilePath{}; const FilePath topCmakeFile = m_cmakeFiles.size() == 1 ? *m_cmakeFiles.begin() : FilePath{};
const QString cmakeBuildType = m_parameters.cmakeBuildType == "Build" ? "" : m_parameters.cmakeBuildType; const QString cmakeBuildType = m_parameters.cmakeBuildType == "Build" ? "" : m_parameters.cmakeBuildType;
m_lastReplyTimestamp = replyFi.lastModified(); QTC_CHECK(!replyFilePath.needsDevice());
m_lastReplyTimestamp = replyFilePath.lastModified();
m_future = runAsync(ProjectExplorerPlugin::sharedThreadPool(), m_future = runAsync(ProjectExplorerPlugin::sharedThreadPool(),
[replyFi, sourceDirectory, buildDirectory, topCmakeFile, cmakeBuildType]( [replyFilePath, sourceDirectory, buildDirectory, topCmakeFile, cmakeBuildType](
QFutureInterface<std::shared_ptr<FileApiQtcData>> &fi) { QFutureInterface<std::shared_ptr<FileApiQtcData>> &fi) {
auto result = std::make_shared<FileApiQtcData>(); auto result = std::make_shared<FileApiQtcData>();
FileApiData data = FileApiParser::parseData(fi, FileApiData data = FileApiParser::parseData(fi,
replyFi, replyFilePath,
cmakeBuildType, cmakeBuildType,
result->errorMessage); result->errorMessage);
if (!result->errorMessage.isEmpty()) { if (!result->errorMessage.isEmpty()) {
@@ -336,7 +334,9 @@ void FileApiReader::makeBackupConfiguration(bool store)
void FileApiReader::writeConfigurationIntoBuildDirectory(const QStringList &configurationArguments) void FileApiReader::writeConfigurationIntoBuildDirectory(const QStringList &configurationArguments)
{ {
const FilePath buildDir = m_parameters.workDirectory; const FilePath buildDir = m_parameters.workDirectory;
QTC_ASSERT(buildDir.exists(), return ); QTC_ASSERT(buildDir.exists(), buildDir.ensureWritableDir());
if (!buildDir.exists())
buildDir.ensureWritableDir();
const FilePath settingsFile = buildDir.pathAppended("qtcsettings.cmake"); const FilePath settingsFile = buildDir.pathAppended("qtcsettings.cmake");
@@ -394,13 +394,14 @@ void FileApiReader::replyDirectoryHasChanged(const QString &directory) const
if (m_isParsing) if (m_isParsing)
return; // This has been triggered by ourselves, ignore. return; // This has been triggered by ourselves, ignore.
const QFileInfo fi = FileApiParser::scanForCMakeReplyFile(m_parameters.workDirectory); const FilePath reply = FileApiParser::scanForCMakeReplyFile(m_parameters.workDirectory);
const QString dir = fi.absolutePath(); const FilePath dir = reply.absolutePath();
if (dir.isEmpty()) if (dir.isEmpty())
return; // CMake started to fill the result dir, but has not written a result file yet return; // CMake started to fill the result dir, but has not written a result file yet
QTC_ASSERT(dir == directory, return); QTC_CHECK(!dir.needsDevice());
QTC_ASSERT(dir.path() == directory, return);
if (m_lastReplyTimestamp.isValid() && fi.lastModified() > m_lastReplyTimestamp) if (m_lastReplyTimestamp.isValid() && reply.lastModified() > m_lastReplyTimestamp)
emit dirty(); emit dirty();
} }

View File

@@ -86,7 +86,7 @@ signals:
private: private:
void startState(); void startState();
void endState(const QFileInfo &replyFi); void endState(const Utils::FilePath &replyFilePath);
void startCMakeState(const QStringList &configurationArguments); void startCMakeState(const QStringList &configurationArguments);
void cmakeFinishedState(); void cmakeFinishedState();