FileInProjectFinder: Proper lookup of qrc URLs

Parse the project's qrc files to map a qrc URL to the actual file in the
project, rather than employing a heuristic.

Fixes: QTCREATORBUG-20207
Change-Id: I4fc9e11c20a36e9d477bb3dc43a787d81e067886
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Christian Kandeler
2019-02-07 17:41:20 +01:00
parent dc2e8472e3
commit 55b0cc7814
2 changed files with 54 additions and 0 deletions

View File

@@ -24,8 +24,11 @@
****************************************************************************/ ****************************************************************************/
#include "fileinprojectfinder.h" #include "fileinprojectfinder.h"
#include "algorithm.h"
#include "fileutils.h" #include "fileutils.h"
#include "hostosinfo.h" #include "hostosinfo.h"
#include "qrcparser.h"
#include "qtcassert.h" #include "qtcassert.h"
#include <QDebug> #include <QDebug>
@@ -102,6 +105,7 @@ void FileInProjectFinder::setProjectFiles(const FileNameList &projectFiles)
m_projectFiles = projectFiles; m_projectFiles = projectFiles;
m_cache.clear(); m_cache.clear();
m_qrcUrlFinder.setProjectFiles(projectFiles);
} }
void FileInProjectFinder::setSysroot(const FileName &sysroot) void FileInProjectFinder::setSysroot(const FileName &sysroot)
@@ -140,6 +144,13 @@ QString FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const
{ {
qCDebug(finderLog) << "FileInProjectFinder: trying to find file" << fileUrl.toString() << "..."; qCDebug(finderLog) << "FileInProjectFinder: trying to find file" << fileUrl.toString() << "...";
if (fileUrl.scheme() == "qrc" || fileUrl.toString().startsWith(':')) {
const QString result = m_qrcUrlFinder.find(fileUrl);
if (success)
*success = !result.isEmpty();
return result;
}
QString originalPath = fileUrl.toLocalFile(); QString originalPath = fileUrl.toLocalFile();
if (originalPath.isEmpty()) // e.g. qrc:// if (originalPath.isEmpty()) // e.g. qrc://
originalPath = fileUrl.path(); originalPath = fileUrl.path();
@@ -421,4 +432,34 @@ FileInProjectFinder::PathMappingNode::~PathMappingNode()
qDeleteAll(children); qDeleteAll(children);
} }
QString FileInProjectFinder::QrcUrlFinder::find(const QUrl &fileUrl) const
{
QString result;
const auto fileIt = m_fileCache.constFind(fileUrl);
if (fileIt != m_fileCache.cend())
return fileIt.value();
for (const FileName &f : m_allQrcFiles) {
QrcParser::Ptr &qrcParser = m_parserCache[f];
if (!qrcParser)
qrcParser = QrcParser::parseQrcFile(f.toString(), QString());
if (!qrcParser->isValid())
continue;
QStringList hits;
qrcParser->collectFilesAtPath(QrcParser::normalizedQrcFilePath(fileUrl.toString()), &hits);
if (!hits.empty()) {
result = hits.first();
break;
}
}
m_fileCache.insert(fileUrl, result);
return result;
}
void FileInProjectFinder::QrcUrlFinder::setProjectFiles(const FileNameList &projectFiles)
{
m_allQrcFiles = filtered(projectFiles, [](const FileName &f) { return f.endsWith(".qrc"); });
m_fileCache.clear();
m_parserCache.clear();
}
} // namespace Utils } // namespace Utils

View File

@@ -29,11 +29,13 @@
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <QHash> #include <QHash>
#include <QSharedPointer>
#include <QStringList> #include <QStringList>
QT_FORWARD_DECLARE_CLASS(QUrl) QT_FORWARD_DECLARE_CLASS(QUrl)
namespace Utils { namespace Utils {
class QrcParser;
class QTCREATOR_UTILS_EXPORT FileInProjectFinder class QTCREATOR_UTILS_EXPORT FileInProjectFinder
{ {
@@ -73,6 +75,16 @@ private:
int matchLength = 0; int matchLength = 0;
}; };
class QrcUrlFinder {
public:
QString find(const QUrl &fileUrl) const;
void setProjectFiles(const FileNameList &projectFiles);
private:
FileNameList m_allQrcFiles;
mutable QHash<QUrl, QString> m_fileCache;
mutable QHash<FileName, QSharedPointer<QrcParser>> m_parserCache;
};
CacheEntry findInSearchPaths(const QString &filePath, FileHandler fileHandler, CacheEntry findInSearchPaths(const QString &filePath, FileHandler fileHandler,
DirectoryHandler directoryHandler) const; DirectoryHandler directoryHandler) const;
static CacheEntry findInSearchPath(const QString &searchPath, const QString &filePath, static CacheEntry findInSearchPath(const QString &searchPath, const QString &filePath,
@@ -93,6 +105,7 @@ private:
PathMappingNode m_pathMapRoot; PathMappingNode m_pathMapRoot;
mutable QHash<QString, CacheEntry> m_cache; mutable QHash<QString, CacheEntry> m_cache;
QrcUrlFinder m_qrcUrlFinder;
}; };
} // namespace Utils } // namespace Utils