aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qmlcompiler/qqmljsresourcefilemapper.cpp157
-rw-r--r--src/qmlcompiler/qqmljsresourcefilemapper_p.h39
-rw-r--r--tools/qmlcachegen/qmlcachegen.cpp8
-rw-r--r--tools/qmlimportscanner/main.cpp6
4 files changed, 178 insertions, 32 deletions
diff --git a/src/qmlcompiler/qqmljsresourcefilemapper.cpp b/src/qmlcompiler/qqmljsresourcefilemapper.cpp
index a31aeb29e5..ee05482b11 100644
--- a/src/qmlcompiler/qqmljsresourcefilemapper.cpp
+++ b/src/qmlcompiler/qqmljsresourcefilemapper.cpp
@@ -34,6 +34,42 @@
QT_BEGIN_NAMESPACE
+QQmlJSResourceFileMapper::Filter QQmlJSResourceFileMapper::allQmlJSFilter() {
+ return Filter {
+ QString(),
+ QStringList { QStringLiteral("qml"), QStringLiteral("js"), QStringLiteral("mjs") },
+ Directory | Recurse
+ };
+}
+
+QQmlJSResourceFileMapper::Filter QQmlJSResourceFileMapper::localFileFilter(const QString &file)
+{
+ return Filter {
+ QFileInfo(file).canonicalFilePath(),
+ QStringList(),
+ File
+ };
+}
+
+QQmlJSResourceFileMapper::Filter QQmlJSResourceFileMapper::resourceFileFilter(const QString &file)
+{
+ return Filter {
+ file,
+ QStringList(),
+ Resource
+ };
+}
+
+QQmlJSResourceFileMapper::Filter QQmlJSResourceFileMapper::resourceQmlDirectoryFilter(
+ const QString &directory)
+{
+ return Filter {
+ directory,
+ QStringList { QStringLiteral("qml") },
+ Directory | Resource
+ };
+}
+
QQmlJSResourceFileMapper::QQmlJSResourceFileMapper(const QStringList &resourceFiles)
{
for (const QString &fileName: resourceFiles) {
@@ -49,32 +85,111 @@ bool QQmlJSResourceFileMapper::isEmpty() const
return qrcPathToFileSystemPath.isEmpty();
}
-QStringList QQmlJSResourceFileMapper::resourcePaths(const QString &fileName)
+bool QQmlJSResourceFileMapper::isFile(const QString &resourcePath) const
{
- const QString absPath = QDir::cleanPath(QDir::current().absoluteFilePath(fileName));
- QStringList resourcePaths;
- for (auto it = qrcPathToFileSystemPath.cbegin(), end = qrcPathToFileSystemPath.cend(); it != end; ++it) {
- if (QFileInfo(it.value()) == QFileInfo(absPath))
- resourcePaths.append(it.key());
+ for (const auto &entry : qrcPathToFileSystemPath) {
+ if (entry.resourcePath == resourcePath)
+ return true;
}
- return resourcePaths;
+ return false;
}
-QStringList QQmlJSResourceFileMapper::qmlCompilerFiles(FileOutput fo) const
+static bool hasSuffix(const QString &qrcPath, const QStringList &suffixes)
{
- QStringList files;
- for (auto it = qrcPathToFileSystemPath.constBegin(), end = qrcPathToFileSystemPath.constEnd();
- it != end; ++it) {
- const QString &qrcPath = it.key();
- const QString suffix = QFileInfo(qrcPath).suffix();
- if (suffix != QStringLiteral("qml") && suffix != QStringLiteral("js") && suffix != QStringLiteral("mjs"))
- continue;
- if (fo == FileOutput::AbsoluteFilePath)
- files << it.value();
- else
- files << qrcPath;
+ if (suffixes.isEmpty())
+ return true;
+ const QString suffix = QFileInfo(qrcPath).suffix();
+ return suffixes.contains(suffix);
+}
+
+template<typename HandleMatch>
+void doFilter(const QList<QQmlJSResourceFileMapper::Entry> &qrcPathToFileSystemPath,
+ const QQmlJSResourceFileMapper::Filter &filter,
+ const HandleMatch &handler)
+{
+ if (filter.flags & QQmlJSResourceFileMapper::Directory) {
+ const QString terminatedDirectory = filter.path.endsWith(u'/')
+ ? filter.path : (filter.path + u'/');
+
+ for (auto it = qrcPathToFileSystemPath.constBegin(),
+ end = qrcPathToFileSystemPath.constEnd(); it != end; ++it) {
+
+ const QString candidate = (filter.flags & QQmlJSResourceFileMapper::Resource)
+ ? it->resourcePath
+ : it->filePath;
+
+ if (!candidate.startsWith(terminatedDirectory))
+ continue;
+
+ if (!hasSuffix(candidate, filter.suffixes))
+ continue;
+
+ if ((filter.flags & QQmlJSResourceFileMapper::Recurse)
+ // Crude. But shall we really allow slashes in QRC file names?
+ || !candidate.mid(terminatedDirectory.length()).contains(u'/')) {
+ if (handler(*it))
+ return;
+ }
+ }
+ return;
+ }
+
+ if (!hasSuffix(filter.path, filter.suffixes))
+ return;
+
+ for (auto it = qrcPathToFileSystemPath.constBegin(),
+ end = qrcPathToFileSystemPath.constEnd(); it != end; ++it) {
+ if (filter.flags & QQmlJSResourceFileMapper::Resource) {
+ if (it->resourcePath == filter.path && handler(*it))
+ return;
+ } else if (it->filePath == filter.path && handler(*it)) {
+ return;
+ }
}
- return files;
+}
+
+QList<QQmlJSResourceFileMapper::Entry> QQmlJSResourceFileMapper::filter(
+ const QQmlJSResourceFileMapper::Filter &filter) const
+{
+ QList<Entry> result;
+ doFilter(qrcPathToFileSystemPath, filter, [&](const Entry &entry) {
+ result.append(entry);
+ return false;
+ });
+ return result;
+}
+
+QStringList QQmlJSResourceFileMapper::filePaths(
+ const QQmlJSResourceFileMapper::Filter &filter) const
+{
+ QStringList result;
+ doFilter(qrcPathToFileSystemPath, filter, [&](const Entry &entry) {
+ result.append(entry.filePath);
+ return false;
+ });
+ return result;
+}
+
+QStringList QQmlJSResourceFileMapper::resourcePaths(
+ const QQmlJSResourceFileMapper::Filter &filter) const
+{
+ QStringList result;
+ doFilter(qrcPathToFileSystemPath, filter, [&](const Entry &entry) {
+ result.append(entry.resourcePath);
+ return false;
+ });
+ return result;
+}
+
+QQmlJSResourceFileMapper::Entry QQmlJSResourceFileMapper::entry(
+ const QQmlJSResourceFileMapper::Filter &filter) const
+{
+ Entry result;
+ doFilter(qrcPathToFileSystemPath, filter, [&](const Entry &entry) {
+ result = entry;
+ return true;
+ });
+ return result;
}
void QQmlJSResourceFileMapper::populateFromQrcFile(QFile &file)
@@ -162,7 +277,7 @@ void QQmlJSResourceFileMapper::populateFromQrcFile(QFile &file)
const QString qrcPath = prefix + currentFileName;
if (QFile::exists(fsPath))
- qrcPathToFileSystemPath.insert(qrcPath, fsPath);
+ qrcPathToFileSystemPath.append({qrcPath, fsPath});
continue;
}
diff --git a/src/qmlcompiler/qqmljsresourcefilemapper_p.h b/src/qmlcompiler/qqmljsresourcefilemapper_p.h
index 2946075387..6be1503556 100644
--- a/src/qmlcompiler/qqmljsresourcefilemapper_p.h
+++ b/src/qmlcompiler/qqmljsresourcefilemapper_p.h
@@ -46,23 +46,50 @@ QT_BEGIN_NAMESPACE
struct QQmlJSResourceFileMapper
{
- enum class FileOutput {
- RelativeFilePath,
- AbsoluteFilePath
+ struct Entry
+ {
+ QString resourcePath;
+ QString filePath;
+ bool isValid() const { return !resourcePath.isEmpty() && !filePath.isEmpty(); }
};
+
+ enum FilterMode {
+ File = 0x0, // Default is local (non-directory) file, without recursion
+ Directory = 0x1, // Directory, either local or resource
+ Resource = 0x2, // Resource path, either to file or directory
+ Recurse = 0x4, // Recurse into subdirectories if Directory
+ };
+ Q_DECLARE_FLAGS(FilterFlags, FilterMode);
+
+ struct Filter {
+ QString path;
+ QStringList suffixes;
+ FilterFlags flags;
+ };
+
+ static Filter allQmlJSFilter();
+ static Filter localFileFilter(const QString &file);
+ static Filter resourceFileFilter(const QString &file);
+ static Filter resourceQmlDirectoryFilter(const QString &directory);
+
QQmlJSResourceFileMapper(const QStringList &resourceFiles);
bool isEmpty() const;
+ bool isFile(const QString &resourcePath) const;
- QStringList resourcePaths(const QString &fileName);
- QStringList qmlCompilerFiles(FileOutput fo = FileOutput::RelativeFilePath) const;
+ QList<Entry> filter(const Filter &filter) const;
+ QStringList filePaths(const Filter &filter) const;
+ QStringList resourcePaths(const Filter &filter) const;
+ Entry entry(const Filter &filter) const;
private:
void populateFromQrcFile(QFile &file);
- QHash<QString, QString> qrcPathToFileSystemPath;
+ QList<Entry> qrcPathToFileSystemPath;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlJSResourceFileMapper::FilterFlags);
+
QT_END_NAMESPACE
#endif // QMLJSRESOURCEFILEMAPPER_P_H
diff --git a/tools/qmlcachegen/qmlcachegen.cpp b/tools/qmlcachegen/qmlcachegen.cpp
index a011442528..285e6c02ea 100644
--- a/tools/qmlcachegen/qmlcachegen.cpp
+++ b/tools/qmlcachegen/qmlcachegen.cpp
@@ -167,8 +167,9 @@ int main(int argc, char **argv)
QQmlJSResourceFileMapper mapper(sources);
QQmlJSCompileError error;
- if (!qQmlJSGenerateLoader(mapper.qmlCompilerFiles(), outputFileName,
- parser.values(resourceFileMappingOption), &error.message)) {
+ if (!qQmlJSGenerateLoader(
+ mapper.resourcePaths(QQmlJSResourceFileMapper::allQmlJSFilter()),
+ outputFileName, parser.values(resourceFileMappingOption), &error.message)) {
error.augment(QLatin1String("Error generating loader stub: ")).print();
return EXIT_FAILURE;
}
@@ -194,7 +195,8 @@ int main(int argc, char **argv)
// If the user didn't specify the resource path corresponding to the file on disk being
// compiled, try to determine it from the resource file, if one was supplied.
if (inputResourcePath.isEmpty()) {
- const QStringList resourcePaths = fileMapper.resourcePaths(inputFile);
+ const QStringList resourcePaths = fileMapper.resourcePaths(
+ QQmlJSResourceFileMapper::localFileFilter(inputFile));
if (resourcePaths.isEmpty()) {
fprintf(stderr, "No resource path for file: %s\n", qPrintable(inputFile));
return EXIT_FAILURE;
diff --git a/tools/qmlimportscanner/main.cpp b/tools/qmlimportscanner/main.cpp
index 9313dee634..ea17df921f 100644
--- a/tools/qmlimportscanner/main.cpp
+++ b/tools/qmlimportscanner/main.cpp
@@ -631,8 +631,10 @@ int main(int argc, char *argv[])
}
}
- if (!qrcFiles.isEmpty())
- scanFiles << QQmlJSResourceFileMapper(qrcFiles).qmlCompilerFiles(QQmlJSResourceFileMapper::FileOutput::AbsoluteFilePath);
+ if (!qrcFiles.isEmpty()) {
+ scanFiles << QQmlJSResourceFileMapper(qrcFiles).filePaths(
+ QQmlJSResourceFileMapper::allQmlJSFilter());
+ }
g_qmlImportPaths = qmlImportPaths;