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
|
||||
|
||||
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;
|
||||
}
|
||||
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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue