forked from qt-creator/qt-creator
FileInProjectFinder: Search DeploymentData for paths
The deployment data is the most reliable information we can get regarding where a file from the host ended up on the target. Therefore it is searched first. Since the "directories" found this way may not actually exist on the host, we return the list of entries rather than the actual path for those. Files from different host directories can be deployed to the same target directory, after all. Using the list of entries, a client can reconstruct children of the directory by appending an entry to the base path and searching again. Change-Id: Ia0f72872a4ff6313f1ae8b0f441b67f55be5a456 Reviewed-by: Vikas Pachdha <vikas.pachdha@qt.io>
This commit is contained in:
@@ -39,11 +39,18 @@ enum { debug = false };
|
|||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
static bool checkPath(const QString &candidate, FileInProjectFinder::FindMode findMode)
|
static bool checkPath(const QString &candidate, FileInProjectFinder::FileHandler fileHandler,
|
||||||
|
FileInProjectFinder::DirectoryHandler directoryHandler)
|
||||||
{
|
{
|
||||||
const QFileInfo candidateInfo(candidate);
|
const QFileInfo candidateInfo(candidate);
|
||||||
return (candidateInfo.isFile() && (findMode & FileInProjectFinder::FindFile))
|
if (fileHandler && candidateInfo.isFile()) {
|
||||||
|| (candidateInfo.isDir() && (findMode & FileInProjectFinder::FindDirectory));
|
fileHandler(candidate);
|
||||||
|
return true;
|
||||||
|
} else if (directoryHandler && candidateInfo.isDir()) {
|
||||||
|
directoryHandler(QDir(candidate).entryList());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -115,6 +122,20 @@ void FileInProjectFinder::setSysroot(const QString &sysroot)
|
|||||||
m_cache.clear();
|
m_cache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileInProjectFinder::addMappedPath(const QString &localFilePath, const QString &remoteFilePath)
|
||||||
|
{
|
||||||
|
const QStringList segments = remoteFilePath.split('/', QString::SkipEmptyParts);
|
||||||
|
|
||||||
|
PathMappingNode *node = &m_pathMapRoot;
|
||||||
|
for (const QString &segment : segments) {
|
||||||
|
auto it = node->children.find(segment);
|
||||||
|
if (it == node->children.end())
|
||||||
|
it = node->children.insert(segment, new PathMappingNode);
|
||||||
|
node = *it;
|
||||||
|
}
|
||||||
|
node->localPath = localFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the best match for the given file URL in the project directory.
|
Returns the best match for the given file URL in the project directory.
|
||||||
|
|
||||||
@@ -133,30 +154,57 @@ QString FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const
|
|||||||
if (originalPath.isEmpty()) // e.g. qrc://
|
if (originalPath.isEmpty()) // e.g. qrc://
|
||||||
originalPath = fileUrl.path();
|
originalPath = fileUrl.path();
|
||||||
|
|
||||||
return findFileOrDirectory(originalPath, FindFile, success);
|
QString result;
|
||||||
|
bool found = findFileOrDirectory(originalPath, [&](const QString &fileName) {
|
||||||
|
result = fileName;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
*success = found;
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FileInProjectFinder::handleSuccess(const QString &originalPath, const QString &found,
|
bool FileInProjectFinder::handleSuccess(const QString &originalPath, const QString &found,
|
||||||
bool *success, const char *where, bool doCache) const
|
const char *where) const
|
||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
qDebug() << "FileInProjectFinder: found" << found << where;
|
qDebug() << "FileInProjectFinder: found" << found << where;
|
||||||
if (doCache)
|
|
||||||
m_cache.insert(originalPath, found);
|
m_cache.insert(originalPath, found);
|
||||||
if (success)
|
return true;
|
||||||
*success = true;
|
|
||||||
return found;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FindMode findMode,
|
bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileHandler fileHandler,
|
||||||
bool *success) const
|
DirectoryHandler directoryHandler) const
|
||||||
{
|
{
|
||||||
if (originalPath.isEmpty()) {
|
if (originalPath.isEmpty()) {
|
||||||
if (debug)
|
if (debug)
|
||||||
qDebug() << "FileInProjectFinder: malformed original path, returning";
|
qDebug() << "FileInProjectFinder: malformed original path, returning";
|
||||||
if (success)
|
return false;
|
||||||
*success = false;
|
}
|
||||||
return originalPath;
|
|
||||||
|
const auto segments = originalPath.splitRef('/', QString::SkipEmptyParts);
|
||||||
|
const PathMappingNode *node = &m_pathMapRoot;
|
||||||
|
for (const auto &segment : segments) {
|
||||||
|
auto it = node->children.find(segment.toString());
|
||||||
|
if (it == node->children.end()) {
|
||||||
|
node = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
node = *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node) {
|
||||||
|
if (!node->localPath.isEmpty()) {
|
||||||
|
if (checkPath(node->localPath, fileHandler, directoryHandler))
|
||||||
|
return handleSuccess(originalPath, node->localPath, "in deployment data");
|
||||||
|
} else if (directoryHandler) {
|
||||||
|
directoryHandler(node->children.keys());
|
||||||
|
if (debug)
|
||||||
|
qDebug() << "FileInProjectFinder: found virtual directory" << originalPath
|
||||||
|
<< "in deployment data";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = m_cache.find(originalPath);
|
auto it = m_cache.find(originalPath);
|
||||||
@@ -165,11 +213,14 @@ QString FileInProjectFinder::findFileOrDirectory(const QString &originalPath, Fi
|
|||||||
qDebug() << "FileInProjectFinder: checking cache ...";
|
qDebug() << "FileInProjectFinder: checking cache ...";
|
||||||
// check if cached path is still there
|
// check if cached path is still there
|
||||||
const QString &candidate = it.value();
|
const QString &candidate = it.value();
|
||||||
if (checkPath(candidate, findMode))
|
if (checkPath(candidate, fileHandler, directoryHandler)) {
|
||||||
return handleSuccess(originalPath, candidate, success, "in the cache", false);
|
if (debug)
|
||||||
else
|
qDebug() << "FileInProjectFinder: found" << candidate << "in the cache";
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
m_cache.erase(it);
|
m_cache.erase(it);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_projectDir.isEmpty()) {
|
if (!m_projectDir.isEmpty()) {
|
||||||
if (debug)
|
if (debug)
|
||||||
@@ -188,8 +239,8 @@ QString FileInProjectFinder::findFileOrDirectory(const QString &originalPath, Fi
|
|||||||
prefixToIgnore = originalPath.indexOf(appResourcePath) + appResourcePath.length();
|
prefixToIgnore = originalPath.indexOf(appResourcePath) + appResourcePath.length();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (prefixToIgnore == -1 && checkPath(originalPath, findMode))
|
if (prefixToIgnore == -1 && checkPath(originalPath, fileHandler, directoryHandler))
|
||||||
return handleSuccess(originalPath, originalPath, success, "in project directory");
|
return handleSuccess(originalPath, originalPath, "in project directory");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
@@ -209,8 +260,8 @@ QString FileInProjectFinder::findFileOrDirectory(const QString &originalPath, Fi
|
|||||||
QString candidate = originalPath;
|
QString candidate = originalPath;
|
||||||
candidate.remove(0, prefixToIgnore);
|
candidate.remove(0, prefixToIgnore);
|
||||||
candidate.prepend(m_projectDir);
|
candidate.prepend(m_projectDir);
|
||||||
if (checkPath(candidate, findMode))
|
if (checkPath(candidate, fileHandler, directoryHandler))
|
||||||
return handleSuccess(originalPath, candidate, success, "in project directory");
|
return handleSuccess(originalPath, candidate, "in project directory");
|
||||||
prefixToIgnore = originalPath.indexOf(separator, prefixToIgnore + 1);
|
prefixToIgnore = originalPath.indexOf(separator, prefixToIgnore + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,18 +272,17 @@ QString FileInProjectFinder::findFileOrDirectory(const QString &originalPath, Fi
|
|||||||
|
|
||||||
QStringList matches;
|
QStringList matches;
|
||||||
const QString lastSegment = FileName::fromString(originalPath).fileName();
|
const QString lastSegment = FileName::fromString(originalPath).fileName();
|
||||||
if (findMode & FindFile)
|
if (fileHandler)
|
||||||
matches.append(filesWithSameFileName(lastSegment));
|
matches.append(filesWithSameFileName(lastSegment));
|
||||||
if (findMode & FindDirectory)
|
if (directoryHandler)
|
||||||
matches.append(pathSegmentsWithSameName(lastSegment));
|
matches.append(pathSegmentsWithSameName(lastSegment));
|
||||||
const QString matchedFilePath = bestMatch(matches, originalPath);
|
const QString matchedFilePath = bestMatch(matches, originalPath);
|
||||||
if (!matchedFilePath.isEmpty())
|
if (!matchedFilePath.isEmpty() && checkPath(matchedFilePath, fileHandler, directoryHandler))
|
||||||
return handleSuccess(originalPath, matchedFilePath, success, "when matching project files");
|
return handleSuccess(originalPath, matchedFilePath, "when matching project files");
|
||||||
|
|
||||||
bool foundinSearchPaths = false;
|
QString foundPath = findInSearchPaths(originalPath, fileHandler, directoryHandler);
|
||||||
const QString foundPath = findInSearchPaths(originalPath, findMode, &foundinSearchPaths);
|
if (!foundPath.isEmpty())
|
||||||
if (foundinSearchPaths)
|
return handleSuccess(originalPath, foundPath, "in search path");
|
||||||
return handleSuccess(originalPath, foundPath, success, "in search path");
|
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
qDebug() << "FileInProjectFinder: checking absolute path in sysroot ...";
|
qDebug() << "FileInProjectFinder: checking absolute path in sysroot ...";
|
||||||
@@ -240,25 +290,22 @@ QString FileInProjectFinder::findFileOrDirectory(const QString &originalPath, Fi
|
|||||||
// check if absolute path is found in sysroot
|
// check if absolute path is found in sysroot
|
||||||
if (!m_sysroot.isEmpty()) {
|
if (!m_sysroot.isEmpty()) {
|
||||||
const QString sysrootPath = m_sysroot + originalPath;
|
const QString sysrootPath = m_sysroot + originalPath;
|
||||||
if (checkPath(sysrootPath, findMode))
|
if (checkPath(sysrootPath, fileHandler, directoryHandler))
|
||||||
return handleSuccess(originalPath, sysrootPath, success, "in sysroot");
|
return handleSuccess(originalPath, sysrootPath, "in sysroot");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success)
|
|
||||||
*success = false;
|
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
qDebug() << "FileInProjectFinder: couldn't find file!";
|
qDebug() << "FileInProjectFinder: couldn't find file!";
|
||||||
return originalPath;
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FileInProjectFinder::findInSearchPaths(const QString &filePath, FindMode findMode,
|
QString FileInProjectFinder::findInSearchPaths(const QString &filePath, FileHandler fileHandler,
|
||||||
bool *success) const
|
DirectoryHandler directoryHandler) const
|
||||||
{
|
{
|
||||||
*success = false;
|
|
||||||
for (const QString &dirPath : m_searchDirectories) {
|
for (const QString &dirPath : m_searchDirectories) {
|
||||||
const QString found = findInSearchPath(dirPath, filePath, findMode, success);
|
const QString found = findInSearchPath(dirPath, filePath, fileHandler, directoryHandler);
|
||||||
if (*success)
|
if (!found.isEmpty())
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
return QString();
|
return QString();
|
||||||
@@ -274,7 +321,8 @@ static QString chopFirstDir(const QString &dirPath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString FileInProjectFinder::findInSearchPath(const QString &searchPath, const QString &filePath,
|
QString FileInProjectFinder::findInSearchPath(const QString &searchPath, const QString &filePath,
|
||||||
FindMode findMode, bool *success)
|
FileHandler fileHandler,
|
||||||
|
DirectoryHandler directoryHandler)
|
||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
qDebug() << "FileInProjectFinder: checking search path" << searchPath;
|
qDebug() << "FileInProjectFinder: checking search path" << searchPath;
|
||||||
@@ -285,14 +333,14 @@ QString FileInProjectFinder::findInSearchPath(const QString &searchPath, const Q
|
|||||||
const QString candidate = searchPath + QLatin1Char('/') + s;
|
const QString candidate = searchPath + QLatin1Char('/') + s;
|
||||||
if (debug)
|
if (debug)
|
||||||
qDebug() << "FileInProjectFinder: trying" << candidate;
|
qDebug() << "FileInProjectFinder: trying" << candidate;
|
||||||
if (checkPath(candidate, findMode)) {
|
|
||||||
*success = true;
|
if (checkPath(candidate, fileHandler, directoryHandler))
|
||||||
return candidate;
|
return candidate;
|
||||||
}
|
|
||||||
QString next = chopFirstDir(s);
|
QString next = chopFirstDir(s);
|
||||||
if (next.isEmpty()) {
|
if (next.isEmpty()) {
|
||||||
if ((findMode & FindDirectory) && QFileInfo(searchPath).fileName() == s) {
|
if (directoryHandler && QFileInfo(searchPath).fileName() == s) {
|
||||||
*success = true;
|
directoryHandler(QDir(searchPath).entryList());
|
||||||
return searchPath;
|
return searchPath;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -300,7 +348,6 @@ QString FileInProjectFinder::findInSearchPath(const QString &searchPath, const Q
|
|||||||
s = next;
|
s = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
*success = false;
|
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,5 +418,9 @@ void FileInProjectFinder::setAdditionalSearchDirectories(const QStringList &sear
|
|||||||
m_searchDirectories = searchDirectories;
|
m_searchDirectories = searchDirectories;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileInProjectFinder::PathMappingNode::~PathMappingNode()
|
||||||
|
{
|
||||||
|
qDeleteAll(children);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
@@ -38,11 +38,9 @@ namespace Utils {
|
|||||||
class QTCREATOR_UTILS_EXPORT FileInProjectFinder
|
class QTCREATOR_UTILS_EXPORT FileInProjectFinder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum FindMode {
|
|
||||||
FindFile = 0x1,
|
using FileHandler = std::function<void(const QString &)>;
|
||||||
FindDirectory = 0x2,
|
using DirectoryHandler = std::function<void(const QStringList &)>;
|
||||||
FindEither = FindFile | FindDirectory
|
|
||||||
};
|
|
||||||
|
|
||||||
FileInProjectFinder();
|
FileInProjectFinder();
|
||||||
|
|
||||||
@@ -52,22 +50,31 @@ public:
|
|||||||
void setProjectFiles(const FileNameList &projectFiles);
|
void setProjectFiles(const FileNameList &projectFiles);
|
||||||
void setSysroot(const QString &sysroot);
|
void setSysroot(const QString &sysroot);
|
||||||
|
|
||||||
|
void addMappedPath(const QString &localFilePath, const QString &remoteFilePath);
|
||||||
|
|
||||||
QString findFile(const QUrl &fileUrl, bool *success = nullptr) const;
|
QString findFile(const QUrl &fileUrl, bool *success = nullptr) const;
|
||||||
QString findFileOrDirectory(const QString &originalPath, FindMode findMode,
|
bool findFileOrDirectory(const QString &originalPath, FileHandler fileHandler = nullptr,
|
||||||
bool *success) const;
|
DirectoryHandler directoryHandler = nullptr) const;
|
||||||
|
|
||||||
QStringList searchDirectories() const;
|
QStringList searchDirectories() const;
|
||||||
void setAdditionalSearchDirectories(const QStringList &searchDirectories);
|
void setAdditionalSearchDirectories(const QStringList &searchDirectories);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString findInSearchPaths(const QString &filePath, FindMode findMode, bool *success) const;
|
struct PathMappingNode
|
||||||
|
{
|
||||||
|
~PathMappingNode();
|
||||||
|
QString localPath;
|
||||||
|
QHash<QString, PathMappingNode *> children;
|
||||||
|
};
|
||||||
|
|
||||||
|
QString findInSearchPaths(const QString &filePath, FileHandler fileHandler,
|
||||||
|
DirectoryHandler directoryHandler) const;
|
||||||
static QString findInSearchPath(const QString &searchPath, const QString &filePath,
|
static QString findInSearchPath(const QString &searchPath, const QString &filePath,
|
||||||
FindMode findMode, bool *success);
|
FileHandler fileHandler, DirectoryHandler directoryHandler);
|
||||||
QStringList filesWithSameFileName(const QString &fileName) const;
|
QStringList filesWithSameFileName(const QString &fileName) const;
|
||||||
QStringList pathSegmentsWithSameName(const QString &path) const;
|
QStringList pathSegmentsWithSameName(const QString &path) const;
|
||||||
|
|
||||||
QString handleSuccess(const QString &originalPath, const QString &found, bool *success,
|
bool handleSuccess(const QString &originalPath, const QString &found, const char *where) const;
|
||||||
const char *where, bool doCache = true) const;
|
|
||||||
|
|
||||||
static int rankFilePath(const QString &candidatePath, const QString &filePathToFind);
|
static int rankFilePath(const QString &candidatePath, const QString &filePathToFind);
|
||||||
static QString bestMatch(const QStringList &filePaths, const QString &filePathToFind);
|
static QString bestMatch(const QStringList &filePaths, const QString &filePathToFind);
|
||||||
@@ -76,6 +83,8 @@ private:
|
|||||||
QString m_sysroot;
|
QString m_sysroot;
|
||||||
FileNameList m_projectFiles;
|
FileNameList m_projectFiles;
|
||||||
QStringList m_searchDirectories;
|
QStringList m_searchDirectories;
|
||||||
|
PathMappingNode m_pathMapRoot;
|
||||||
|
|
||||||
mutable QHash<QString,QString> m_cache;
|
mutable QHash<QString,QString> m_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -33,6 +33,8 @@
|
|||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/progressmanager/progressmanager.h>
|
#include <coreplugin/progressmanager/progressmanager.h>
|
||||||
#include <proparser/qmakevfs.h>
|
#include <proparser/qmakevfs.h>
|
||||||
|
#include <projectexplorer/deployablefile.h>
|
||||||
|
#include <projectexplorer/deploymentdata.h>
|
||||||
#include <projectexplorer/toolchainmanager.h>
|
#include <projectexplorer/toolchainmanager.h>
|
||||||
#include <projectexplorer/toolchain.h>
|
#include <projectexplorer/toolchain.h>
|
||||||
#include <projectexplorer/projectexplorer.h>
|
#include <projectexplorer/projectexplorer.h>
|
||||||
@@ -1358,6 +1360,11 @@ void BaseQtVersion::populateQmlFileFinder(FileInProjectFinder *finder, const Tar
|
|||||||
QStringList additionalSearchDirectories = qtVersion
|
QStringList additionalSearchDirectories = qtVersion
|
||||||
? QStringList(qtVersion->qmlPath().toString()) : QStringList();
|
? QStringList(qtVersion->qmlPath().toString()) : QStringList();
|
||||||
|
|
||||||
|
if (target) {
|
||||||
|
for (const ProjectExplorer::DeployableFile &file : target->deploymentData().allFiles())
|
||||||
|
finder->addMappedPath(file.localFilePath().toString(), file.remoteFilePath());
|
||||||
|
}
|
||||||
|
|
||||||
// Finally, do populate m_projectFinder
|
// Finally, do populate m_projectFinder
|
||||||
finder->setProjectDirectory(projectDirectory);
|
finder->setProjectDirectory(projectDirectory);
|
||||||
finder->setProjectFiles(sourceFiles);
|
finder->setProjectFiles(sourceFiles);
|
||||||
|
Reference in New Issue
Block a user