Rework QQmlJSResourceFileMapper
We need more generic filtering capabilities so that it can, for example, retrieve all the .qml files in a directory, both as qrc paths and local file paths. Change-Id: I72a72abc6dd39adb41bcd035f7aa6777e50cb5a5 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
This commit is contained in:
parent
c603d30887
commit
74bf3c8c33
|
@ -34,6 +34,42 @@
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
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)
|
QQmlJSResourceFileMapper::QQmlJSResourceFileMapper(const QStringList &resourceFiles)
|
||||||
{
|
{
|
||||||
for (const QString &fileName: resourceFiles) {
|
for (const QString &fileName: resourceFiles) {
|
||||||
|
@ -49,32 +85,111 @@ bool QQmlJSResourceFileMapper::isEmpty() const
|
||||||
return qrcPathToFileSystemPath.isEmpty();
|
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));
|
for (const auto &entry : qrcPathToFileSystemPath) {
|
||||||
QStringList resourcePaths;
|
if (entry.resourcePath == resourcePath)
|
||||||
for (auto it = qrcPathToFileSystemPath.cbegin(), end = qrcPathToFileSystemPath.cend(); it != end; ++it) {
|
return true;
|
||||||
if (QFileInfo(it.value()) == QFileInfo(absPath))
|
|
||||||
resourcePaths.append(it.key());
|
|
||||||
}
|
}
|
||||||
return resourcePaths;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList QQmlJSResourceFileMapper::qmlCompilerFiles(FileOutput fo) const
|
static bool hasSuffix(const QString &qrcPath, const QStringList &suffixes)
|
||||||
{
|
{
|
||||||
QStringList files;
|
if (suffixes.isEmpty())
|
||||||
for (auto it = qrcPathToFileSystemPath.constBegin(), end = qrcPathToFileSystemPath.constEnd();
|
return true;
|
||||||
it != end; ++it) {
|
const QString suffix = QFileInfo(qrcPath).suffix();
|
||||||
const QString &qrcPath = it.key();
|
return suffixes.contains(suffix);
|
||||||
const QString suffix = QFileInfo(qrcPath).suffix();
|
}
|
||||||
if (suffix != QStringLiteral("qml") && suffix != QStringLiteral("js") && suffix != QStringLiteral("mjs"))
|
|
||||||
continue;
|
template<typename HandleMatch>
|
||||||
if (fo == FileOutput::AbsoluteFilePath)
|
void doFilter(const QList<QQmlJSResourceFileMapper::Entry> &qrcPathToFileSystemPath,
|
||||||
files << it.value();
|
const QQmlJSResourceFileMapper::Filter &filter,
|
||||||
else
|
const HandleMatch &handler)
|
||||||
files << qrcPath;
|
{
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
return files;
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
void QQmlJSResourceFileMapper::populateFromQrcFile(QFile &file)
|
||||||
|
@ -162,7 +277,7 @@ void QQmlJSResourceFileMapper::populateFromQrcFile(QFile &file)
|
||||||
|
|
||||||
const QString qrcPath = prefix + currentFileName;
|
const QString qrcPath = prefix + currentFileName;
|
||||||
if (QFile::exists(fsPath))
|
if (QFile::exists(fsPath))
|
||||||
qrcPathToFileSystemPath.insert(qrcPath, fsPath);
|
qrcPathToFileSystemPath.append({qrcPath, fsPath});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,23 +46,50 @@ QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
struct QQmlJSResourceFileMapper
|
struct QQmlJSResourceFileMapper
|
||||||
{
|
{
|
||||||
enum class FileOutput {
|
struct Entry
|
||||||
RelativeFilePath,
|
{
|
||||||
AbsoluteFilePath
|
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);
|
QQmlJSResourceFileMapper(const QStringList &resourceFiles);
|
||||||
|
|
||||||
bool isEmpty() const;
|
bool isEmpty() const;
|
||||||
|
bool isFile(const QString &resourcePath) const;
|
||||||
|
|
||||||
QStringList resourcePaths(const QString &fileName);
|
QList<Entry> filter(const Filter &filter) const;
|
||||||
QStringList qmlCompilerFiles(FileOutput fo = FileOutput::RelativeFilePath) const;
|
QStringList filePaths(const Filter &filter) const;
|
||||||
|
QStringList resourcePaths(const Filter &filter) const;
|
||||||
|
Entry entry(const Filter &filter) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void populateFromQrcFile(QFile &file);
|
void populateFromQrcFile(QFile &file);
|
||||||
|
|
||||||
QHash<QString, QString> qrcPathToFileSystemPath;
|
QList<Entry> qrcPathToFileSystemPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlJSResourceFileMapper::FilterFlags);
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QMLJSRESOURCEFILEMAPPER_P_H
|
#endif // QMLJSRESOURCEFILEMAPPER_P_H
|
||||||
|
|
|
@ -167,8 +167,9 @@ int main(int argc, char **argv)
|
||||||
QQmlJSResourceFileMapper mapper(sources);
|
QQmlJSResourceFileMapper mapper(sources);
|
||||||
|
|
||||||
QQmlJSCompileError error;
|
QQmlJSCompileError error;
|
||||||
if (!qQmlJSGenerateLoader(mapper.qmlCompilerFiles(), outputFileName,
|
if (!qQmlJSGenerateLoader(
|
||||||
parser.values(resourceFileMappingOption), &error.message)) {
|
mapper.resourcePaths(QQmlJSResourceFileMapper::allQmlJSFilter()),
|
||||||
|
outputFileName, parser.values(resourceFileMappingOption), &error.message)) {
|
||||||
error.augment(QLatin1String("Error generating loader stub: ")).print();
|
error.augment(QLatin1String("Error generating loader stub: ")).print();
|
||||||
return EXIT_FAILURE;
|
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
|
// 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.
|
// compiled, try to determine it from the resource file, if one was supplied.
|
||||||
if (inputResourcePath.isEmpty()) {
|
if (inputResourcePath.isEmpty()) {
|
||||||
const QStringList resourcePaths = fileMapper.resourcePaths(inputFile);
|
const QStringList resourcePaths = fileMapper.resourcePaths(
|
||||||
|
QQmlJSResourceFileMapper::localFileFilter(inputFile));
|
||||||
if (resourcePaths.isEmpty()) {
|
if (resourcePaths.isEmpty()) {
|
||||||
fprintf(stderr, "No resource path for file: %s\n", qPrintable(inputFile));
|
fprintf(stderr, "No resource path for file: %s\n", qPrintable(inputFile));
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
|
@ -631,8 +631,10 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!qrcFiles.isEmpty())
|
if (!qrcFiles.isEmpty()) {
|
||||||
scanFiles << QQmlJSResourceFileMapper(qrcFiles).qmlCompilerFiles(QQmlJSResourceFileMapper::FileOutput::AbsoluteFilePath);
|
scanFiles << QQmlJSResourceFileMapper(qrcFiles).filePaths(
|
||||||
|
QQmlJSResourceFileMapper::allQmlJSFilter());
|
||||||
|
}
|
||||||
|
|
||||||
g_qmlImportPaths = qmlImportPaths;
|
g_qmlImportPaths = qmlImportPaths;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue