aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmlcompiler/qqmljsutils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qmlcompiler/qqmljsutils.cpp')
-rw-r--r--src/qmlcompiler/qqmljsutils.cpp93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/qmlcompiler/qqmljsutils.cpp b/src/qmlcompiler/qqmljsutils.cpp
index fcf56d4b96..f40d4932ca 100644
--- a/src/qmlcompiler/qqmljsutils.cpp
+++ b/src/qmlcompiler/qqmljsutils.cpp
@@ -280,5 +280,98 @@ QStringList QQmlJSUtils::resourceFilesFromBuildFolders(const QStringList &buildF
return result;
}
+enum FilterType {
+ LocalFileFilter,
+ ResourceFileFilter
+};
+
+/*!
+\internal
+Obtain a QML module qrc entry from its qmldir entry.
+
+Contains a heuristic for QML modules without nested-qml-module-with-prefer-feature
+that tries to find a parent directory that contains a qmldir entry in the qrc.
+*/
+static QQmlJSResourceFileMapper::Entry
+qmlModuleEntryFromBuildPath(const QQmlJSResourceFileMapper *mapper,
+ const QString &pathInBuildFolder, FilterType type)
+{
+ const QString cleanPath = QDir::cleanPath(pathInBuildFolder);
+ QStringView directoryPath = cleanPath;
+
+ while (!directoryPath.isEmpty()) {
+ const qsizetype lastSlashIndex = directoryPath.lastIndexOf(u'/');
+ if (lastSlashIndex == -1)
+ return {};
+
+ directoryPath.truncate(lastSlashIndex);
+ const QString qmldirPath = u"%1/qmldir"_s.arg(directoryPath);
+ const QQmlJSResourceFileMapper::Filter qmldirFilter = type == LocalFileFilter
+ ? QQmlJSResourceFileMapper::localFileFilter(qmldirPath)
+ : QQmlJSResourceFileMapper::resourceFileFilter(qmldirPath);
+
+ QQmlJSResourceFileMapper::Entry result = mapper->entry(qmldirFilter);
+ if (result.isValid()) {
+ result.resourcePath.chop(std::char_traits<char>::length("/qmldir"));
+ result.filePath.chop(std::char_traits<char>::length("/qmldir"));
+ return result;
+ }
+ }
+ return {};
+}
+
+/*!
+\internal
+Obtains the source folder path from a build folder QML file path via the passed \c mapper.
+
+This works on proper QML modules when using the nested-qml-module-with-prefer-feature
+from 6.8 and uses a heuristic when the qmldir with the prefer entry is missing.
+*/
+QString QQmlJSUtils::qmlSourcePathFromBuildPath(const QQmlJSResourceFileMapper *mapper,
+ const QString &pathInBuildFolder)
+{
+ if (!mapper)
+ return pathInBuildFolder;
+
+ const auto qmlModuleEntry =
+ qmlModuleEntryFromBuildPath(mapper, pathInBuildFolder, LocalFileFilter);
+ if (!qmlModuleEntry.isValid())
+ return pathInBuildFolder;
+ const QString qrcPath = qmlModuleEntry.resourcePath
+ + QStringView(pathInBuildFolder).sliced(qmlModuleEntry.filePath.size());
+
+ const auto entry = mapper->entry(QQmlJSResourceFileMapper::resourceFileFilter(qrcPath));
+ return entry.isValid()? entry.filePath : pathInBuildFolder;
+}
+
+/*!
+\internal
+Obtains the source folder path from a build folder QML file path via the passed \c mapper, see also
+\l QQmlJSUtils::qmlSourcePathFromBuildPath.
+*/
+QString QQmlJSUtils::qmlBuildPathFromSourcePath(const QQmlJSResourceFileMapper *mapper,
+ const QString &pathInSourceFolder)
+{
+ if (!mapper)
+ return pathInSourceFolder;
+
+ const QString qrcPath =
+ mapper->entry(QQmlJSResourceFileMapper::localFileFilter(pathInSourceFolder))
+ .resourcePath;
+
+ if (qrcPath.isEmpty())
+ return pathInSourceFolder;
+
+ const auto moduleBuildEntry =
+ qmlModuleEntryFromBuildPath(mapper, qrcPath, ResourceFileFilter);
+
+ if (!moduleBuildEntry.isValid())
+ return pathInSourceFolder;
+
+ const auto qrcFolderPath = qrcPath.first(qrcPath.lastIndexOf(u'/')); // drop the filename
+
+ return moduleBuildEntry.filePath + qrcFolderPath.sliced(moduleBuildEntry.resourcePath.size())
+ + pathInSourceFolder.sliced(pathInSourceFolder.lastIndexOf(u'/'));
+}
QT_END_NAMESPACE