From 15fa9e7096d69b06ab56dfa99754fe5d5ff5c7ce Mon Sep 17 00:00:00 2001 From: Artem Sokolovskii Date: Thu, 22 Dec 2022 15:33:22 +0100 Subject: [PATCH] FileFinder: FilePathify Change-Id: I7a4bcb05f85058ddcaf0c69c01b0587116410d95 Reviewed-by: hjk --- src/libs/utils/fileinprojectfinder.cpp | 89 +++++++++---------- src/libs/utils/fileinprojectfinder.h | 14 +-- src/libs/utils/filepath.cpp | 9 ++ src/libs/utils/filepath.h | 1 + .../qmlpreviewconnectionmanager.cpp | 61 +++++++------ 5 files changed, 93 insertions(+), 81 deletions(-) diff --git a/src/libs/utils/fileinprojectfinder.cpp b/src/libs/utils/fileinprojectfinder.cpp index 407e9e6fc2e..9d0de16876c 100644 --- a/src/libs/utils/fileinprojectfinder.cpp +++ b/src/libs/utils/fileinprojectfinder.cpp @@ -24,16 +24,15 @@ static Q_LOGGING_CATEGORY(finderLog, "qtc.utils.fileinprojectfinder", QtWarningM namespace Utils { -static bool checkPath(const QString &candidate, int matchLength, +static bool checkPath(const FilePath &candidate, int matchLength, FileInProjectFinder::FileHandler fileHandler, FileInProjectFinder::DirectoryHandler directoryHandler) { - const QFileInfo candidateInfo(candidate); - if (fileHandler && candidateInfo.isFile()) { + if (fileHandler && candidate.isFile()) { fileHandler(candidate, matchLength); return true; - } else if (directoryHandler && candidateInfo.isDir()) { - directoryHandler(QDir(candidate).entryList(), matchLength); + } else if (directoryHandler && candidate.isDir()) { + directoryHandler(QDir(candidate.toFSPathString()).entryList(), matchLength); return true; } return false; @@ -131,16 +130,16 @@ FilePaths FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) cons } } - QString originalPath = fileUrl.toLocalFile(); + FilePath originalPath = FilePath::fromString(fileUrl.toLocalFile()); if (originalPath.isEmpty()) // e.g. qrc:// - originalPath = fileUrl.path(); + originalPath = FilePath::fromString(fileUrl.path()); FilePaths result; - bool found = findFileOrDirectory(originalPath, [&](const QString &fileName, int) { - result << FilePath::fromString(fileName); + bool found = findFileOrDirectory(originalPath, [&](const FilePath &fileName, int) { + result << fileName; }); if (!found) - result << FilePath::fromString(originalPath); + result << originalPath; if (success) *success = found; @@ -148,7 +147,7 @@ FilePaths FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) cons return result; } -bool FileInProjectFinder::handleSuccess(const QString &originalPath, const QStringList &found, +bool FileInProjectFinder::handleSuccess(const FilePath &originalPath, const FilePaths &found, int matchLength, const char *where) const { qCDebug(finderLog) << "FileInProjectFinder: found" << found << where; @@ -159,7 +158,7 @@ bool FileInProjectFinder::handleSuccess(const QString &originalPath, const QStri return true; } -bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileHandler fileHandler, +bool FileInProjectFinder::findFileOrDirectory(const FilePath &originalPath, FileHandler fileHandler, DirectoryHandler directoryHandler) const { if (originalPath.isEmpty()) { @@ -167,7 +166,7 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH return false; } - const auto segments = originalPath.split('/', Qt::SkipEmptyParts); + const auto segments = originalPath.toFSPathString().split('/', Qt::SkipEmptyParts); const PathMappingNode *node = &m_pathMapRoot; for (const auto &segment : segments) { auto it = node->children.find(segment); @@ -178,12 +177,11 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH node = *it; } - const int origLength = originalPath.length(); + const int origLength = originalPath.toFSPathString().length(); if (node) { if (!node->localPath.isEmpty()) { - const QString localPath = node->localPath.toString(); - if (checkPath(localPath, origLength, fileHandler, directoryHandler)) { - return handleSuccess(originalPath, QStringList(localPath), origLength, + if (checkPath(node->localPath, origLength, fileHandler, directoryHandler)) { + return handleSuccess(originalPath, {node->localPath}, origLength, "in mapped paths"); } } else if (directoryHandler) { @@ -217,21 +215,21 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH int prefixToIgnore = -1; const QChar separator = QLatin1Char('/'); - if (originalPath.startsWith(m_projectDir.toString() + separator)) { - if (HostOsInfo::isMacHost()) { + if (originalPath.startsWith(m_projectDir.toFSPathString() + separator)) { + if (originalPath.osType() == OsTypeMac) { // starting with the project path is not sufficient if the file was // copied in an insource build, e.g. into MyApp.app/Contents/Resources static const QString appResourcePath = QString::fromLatin1(".app/Contents/Resources"); if (originalPath.contains(appResourcePath)) { // the path is inside the project, but most probably as a resource of an insource build // so ignore that path - prefixToIgnore = originalPath.indexOf(appResourcePath) + appResourcePath.length(); + prefixToIgnore = originalPath.toFSPathString().indexOf(appResourcePath) + appResourcePath.length(); } } if (prefixToIgnore == -1 && checkPath(originalPath, origLength, fileHandler, directoryHandler)) { - return handleSuccess(originalPath, QStringList(originalPath), origLength, + return handleSuccess(originalPath, {originalPath}, origLength, "in project directory"); } } @@ -242,24 +240,22 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH // Strip directories one by one from the beginning of the path, // and see if the new relative path exists in the build directory. if (prefixToIgnore < 0) { - if (!QFileInfo(originalPath).isAbsolute() + if (!originalPath.isAbsolutePath() && !originalPath.startsWith(separator)) { prefixToIgnore = 0; } else { - prefixToIgnore = originalPath.indexOf(separator); + prefixToIgnore = originalPath.toFSPathString().indexOf(separator); } } while (prefixToIgnore != -1) { - QString candidate = originalPath; - candidate.remove(0, prefixToIgnore); - candidate.prepend(m_projectDir.toString()); + FilePath candidate = originalPath.resolvePath(m_projectDir); const int matchLength = origLength - prefixToIgnore; // FIXME: This might be a worse match than what we find later. if (checkPath(candidate, matchLength, fileHandler, directoryHandler)) { - return handleSuccess(originalPath, QStringList(candidate), matchLength, + return handleSuccess(originalPath, {candidate}, matchLength, "in project directory"); } - prefixToIgnore = originalPath.indexOf(separator, prefixToIgnore + 1); + prefixToIgnore = originalPath.toString().indexOf(separator, prefixToIgnore + 1); } } @@ -267,18 +263,19 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH qCDebug(finderLog) << "FileInProjectFinder: checking project files ..."; QStringList matches; - const QString lastSegment = FilePath::fromString(originalPath).fileName(); + const QString lastSegment = originalPath.fileName(); if (fileHandler) matches.append(filesWithSameFileName(lastSegment)); if (directoryHandler) matches.append(pathSegmentsWithSameName(lastSegment)); - const QStringList matchedFilePaths = bestMatches(matches, originalPath); + + const QStringList matchedFilePaths = bestMatches(matches, originalPath.toString()); if (!matchedFilePaths.empty()) { - const int matchLength = commonPostFixLength(matchedFilePaths.first(), originalPath); - QStringList hits; + const int matchLength = commonPostFixLength(matchedFilePaths.first(), originalPath.toString()); + FilePaths hits; for (const QString &matchedFilePath : matchedFilePaths) { - if (checkPath(matchedFilePath, matchLength, fileHandler, directoryHandler)) - hits << matchedFilePath; + if (checkPath(FilePath::fromString(matchedFilePath), matchLength, fileHandler, directoryHandler)) + hits.append(FilePath::fromString(matchedFilePath)); } if (!hits.empty()) return handleSuccess(originalPath, hits, matchLength, "when matching project files"); @@ -294,10 +291,9 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH // check if absolute path is found in sysroot if (!m_sysroot.isEmpty()) { - const FilePath sysrootPath = m_sysroot.pathAppended(originalPath); - if (checkPath(sysrootPath.toString(), origLength, fileHandler, directoryHandler)) { - return handleSuccess(originalPath, QStringList(sysrootPath.toString()), origLength, - "in sysroot"); + const FilePath sysrootPath = m_sysroot.pathAppended(originalPath.toString()); + if (checkPath(sysrootPath, origLength, fileHandler, directoryHandler)) { + return handleSuccess(originalPath, {sysrootPath}, origLength, "in sysroot"); } } @@ -307,10 +303,10 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH } FileInProjectFinder::CacheEntry FileInProjectFinder::findInSearchPaths( - const QString &filePath, FileHandler fileHandler, DirectoryHandler directoryHandler) const + const FilePath &filePath, FileHandler fileHandler, DirectoryHandler directoryHandler) const { for (const FilePath &dirPath : m_searchDirectories) { - const CacheEntry found = findInSearchPath(dirPath.toString(), filePath, + const CacheEntry found = findInSearchPath(dirPath, filePath, fileHandler, directoryHandler); if (!found.paths.isEmpty()) return found; @@ -329,15 +325,15 @@ static QString chopFirstDir(const QString &dirPath) } FileInProjectFinder::CacheEntry FileInProjectFinder::findInSearchPath( - const QString &searchPath, const QString &filePath, + const FilePath &searchPath, const FilePath &filePath, FileHandler fileHandler, DirectoryHandler directoryHandler) { qCDebug(finderLog) << "FileInProjectFinder: checking search path" << searchPath; - QString s = filePath; + QString s = filePath.toFSPathString(); while (!s.isEmpty()) { CacheEntry result; - result.paths << searchPath + '/' + s; + result.paths << searchPath / s; result.matchLength = s.length() + 1; qCDebug(finderLog) << "FileInProjectFinder: trying" << result.paths.first(); @@ -346,9 +342,10 @@ FileInProjectFinder::CacheEntry FileInProjectFinder::findInSearchPath( QString next = chopFirstDir(s); if (next.isEmpty()) { - if (directoryHandler && QFileInfo(searchPath).fileName() == s) { - result.paths = QStringList{searchPath}; - directoryHandler(QDir(searchPath).entryList(), result.matchLength); + if (directoryHandler && searchPath.fileName() == s) { + result.paths = {searchPath}; + directoryHandler(QDir(searchPath.toFSPathString()).entryList(), + result.matchLength); return result; } break; diff --git a/src/libs/utils/fileinprojectfinder.h b/src/libs/utils/fileinprojectfinder.h index 00fdb4f36d6..85d8205f030 100644 --- a/src/libs/utils/fileinprojectfinder.h +++ b/src/libs/utils/fileinprojectfinder.h @@ -19,7 +19,7 @@ class QTCREATOR_UTILS_EXPORT FileInProjectFinder { public: - using FileHandler = std::function; + using FileHandler = std::function; using DirectoryHandler = std::function; FileInProjectFinder(); @@ -34,7 +34,7 @@ public: void addMappedPath(const FilePath &localFilePath, const QString &remoteFilePath); FilePaths findFile(const QUrl &fileUrl, bool *success = nullptr) const; - bool findFileOrDirectory(const QString &originalPath, FileHandler fileHandler = nullptr, + bool findFileOrDirectory(const FilePath &originalPath, FileHandler fileHandler = nullptr, DirectoryHandler directoryHandler = nullptr) const; FilePaths searchDirectories() const; @@ -49,7 +49,7 @@ private: }; struct CacheEntry { - QStringList paths; + FilePaths paths; int matchLength = 0; }; @@ -63,14 +63,14 @@ private: mutable QHash> m_parserCache; }; - CacheEntry findInSearchPaths(const QString &filePath, FileHandler fileHandler, + CacheEntry findInSearchPaths(const FilePath &filePath, FileHandler fileHandler, DirectoryHandler directoryHandler) const; - static CacheEntry findInSearchPath(const QString &searchPath, const QString &filePath, + static CacheEntry findInSearchPath(const FilePath &searchPath, const FilePath &filePath, FileHandler fileHandler, DirectoryHandler directoryHandler); QStringList filesWithSameFileName(const QString &fileName) const; QStringList pathSegmentsWithSameName(const QString &path) const; - bool handleSuccess(const QString &originalPath, const QStringList &found, int confidence, + bool handleSuccess(const FilePath &originalPath, const FilePaths &found, int confidence, const char *where) const; static int commonPostFixLength(const QString &candidatePath, const QString &filePathToFind); @@ -82,7 +82,7 @@ private: FilePaths m_searchDirectories; PathMappingNode m_pathMapRoot; - mutable QHash m_cache; + mutable QHash m_cache; QrcUrlFinder m_qrcUrlFinder; }; diff --git a/src/libs/utils/filepath.cpp b/src/libs/utils/filepath.cpp index 7d63967e9f4..9260a3aa3d4 100644 --- a/src/libs/utils/filepath.cpp +++ b/src/libs/utils/filepath.cpp @@ -1038,6 +1038,15 @@ bool FilePath::endsWith(const QString &s) const return pathView().endsWith(s, caseSensitivity()); } +/*! +* \param s The string to check for contains. +* \returns whether FilePath contains \a s +*/ +bool FilePath::contains(const QString &s) const +{ + return pathView().contains(s, caseSensitivity()); +} + /*! * \brief Checks whether the FilePath starts with a drive letter. * Defaults to \c false if it is a non-Windows host or represents a path on device diff --git a/src/libs/utils/filepath.h b/src/libs/utils/filepath.h index 2897b278ec6..ef8762a15c5 100644 --- a/src/libs/utils/filepath.h +++ b/src/libs/utils/filepath.h @@ -94,6 +94,7 @@ public: [[nodiscard]] FilePath stringAppended(const QString &str) const; bool startsWith(const QString &s) const; bool endsWith(const QString &s) const; + bool contains(const QString &s) const; bool exists() const; diff --git a/src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp b/src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp index b6356147dd2..b081554b2d4 100644 --- a/src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp +++ b/src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp @@ -146,35 +146,40 @@ void QmlPreviewConnectionManager::createPreviewClient() connect(this, &QmlPreviewConnectionManager::zoom, m_qmlPreviewClient.data(), &QmlPreviewClient::zoom); - connect(m_qmlPreviewClient.data(), &QmlPreviewClient::pathRequested, - this, [this](const QString &path) { - const bool found = m_projectFileFinder.findFileOrDirectory( - path, [&](const QString &filename, int confidence) { - if (m_fileLoader && confidence == path.length()) { - bool success = false; - QByteArray contents = m_fileLoader(filename, &success); - if (success) { - if (!m_fileSystemWatcher.watchesFile(filename)) { - m_fileSystemWatcher.addFile(filename, - Utils::FileSystemWatcher::WatchModifiedDate); - } - m_qmlPreviewClient->announceFile(path, contents); - } else { - m_qmlPreviewClient->announceError(path); - } - } else { - m_qmlPreviewClient->announceError(path); - } - }, [&](const QStringList &entries, int confidence) { - if (confidence == path.length()) - m_qmlPreviewClient->announceDirectory(path, entries); - else - m_qmlPreviewClient->announceError(path); - }); + connect(m_qmlPreviewClient.data(), + &QmlPreviewClient::pathRequested, + this, + [this](const QString &path) { + const bool found = m_projectFileFinder.findFileOrDirectory( + Utils::FilePath::fromString(path), + [&](const Utils::FilePath &filename, int confidence) { + if (m_fileLoader && confidence == path.length()) { + bool success = false; + QByteArray contents = m_fileLoader(filename.toFSPathString(), &success); + if (success) { + if (!m_fileSystemWatcher.watchesFile(filename.toFSPathString())) { + m_fileSystemWatcher + .addFile(filename.toFSPathString(), + Utils::FileSystemWatcher::WatchModifiedDate); + } + m_qmlPreviewClient->announceFile(path, contents); + } else { + m_qmlPreviewClient->announceError(path); + } + } else { + m_qmlPreviewClient->announceError(path); + } + }, + [&](const QStringList &entries, int confidence) { + if (confidence == path.length()) + m_qmlPreviewClient->announceDirectory(path, entries); + else + m_qmlPreviewClient->announceError(path); + }); - if (!found) - m_qmlPreviewClient->announceError(path); - }); + if (!found) + m_qmlPreviewClient->announceError(path); + }); connect(m_qmlPreviewClient.data(), &QmlPreviewClient::errorReported,