diff options
author | Tarja Sundqvist <tarja.sundqvist@qt.io> | 2024-01-22 22:38:27 +0200 |
---|---|---|
committer | Tarja Sundqvist <tarja.sundqvist@qt.io> | 2024-02-20 10:05:13 +0000 |
commit | 302ab20d46280e11042f3896460c55d8b8146e41 (patch) | |
tree | 3cef87d6ca24d2e37a3dc8c4af4506e510903a78 /src/qml/qml/qqmlimport.cpp | |
parent | 02277e3753613d9e19bbb36367c7d2b1d13d7545 (diff) | |
parent | a7df6331b29e44ed364fcd7297c4e1bc6ce2167c (diff) |
Merge remote-tracking branch 'origin/tqtc/lts-6.2.8' into tqtc/lts-6.2-opensource
Conflicts solved in a file:
dependencies.yaml
Change-Id: Ib4083daa41a689b937d2aeb522e93e3aab0be1c4
Diffstat (limited to 'src/qml/qml/qqmlimport.cpp')
-rw-r--r-- | src/qml/qml/qqmlimport.cpp | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index e35df5b907..d04d6751cd 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -1169,6 +1169,26 @@ QString QQmlImportsPrivate::resolvedUri(const QString &dir_arg, QQmlImportDataba return stableRelativePath; } +/* removes all file selector occurrences in path + firstPlus is the position of the initial '+' in the path + which we always have as we check for '+' to decide whether + we need to do some work at all +*/ +static QString pathWithoutFileSelectors(QString path, // we want a copy of path + qsizetype firstPlus) +{ + do { + Q_ASSERT(path.at(firstPlus) == u'+'); + const auto eos = path.size(); + qsizetype terminatingSlashPos = firstPlus + 1; + while (terminatingSlashPos != eos && path.at(terminatingSlashPos) != u'/') + ++terminatingSlashPos; + path.remove(firstPlus, terminatingSlashPos - firstPlus + 1); + firstPlus = path.indexOf(u'+', firstPlus); + } while (firstPlus != -1); + return path; +} + /*! \internal @@ -1215,10 +1235,42 @@ QTypeRevision QQmlImportsPrivate::matchingQmldirVersion( typedef QQmlDirComponents::const_iterator ConstIterator; const QQmlDirComponents &components = qmldir.components(); + QMultiHash<QString, ConstIterator> baseFileName2ConflictingComponents; + ConstIterator cend = components.constEnd(); for (ConstIterator cit = components.constBegin(); cit != cend; ++cit) { for (ConstIterator cit2 = components.constBegin(); cit2 != cit; ++cit2) { if (cit2->typeName == cit->typeName && cit2->version == cit->version) { + // ugly heuristic to deal with file selectors + const auto comp2PotentialFileSelectorPos = cit2->fileName.indexOf(u'+'); + const bool comp2MightHaveFileSelector = comp2PotentialFileSelectorPos != -1; + /* If we detect conflicting paths, we check if they agree when we remove anything looking like a + file selector. + We need to create copies of the filenames, otherwise QString::replace would modify the + existing file-names + */ + QString compFileName1 = cit->fileName; + QString compFileName2 = cit2->fileName; + if (auto fileSelectorPos1 = compFileName1.indexOf(u'+'); fileSelectorPos1 != -1) { + // existing entry was file selector entry, fix it up + // it could also be the case that _both_ are using file selectors + QString baseName = comp2MightHaveFileSelector ? pathWithoutFileSelectors(compFileName2, + comp2PotentialFileSelectorPos) + : compFileName2; + if (pathWithoutFileSelectors(compFileName1, fileSelectorPos1) == baseName) { + baseFileName2ConflictingComponents.insert(baseName, cit); + baseFileName2ConflictingComponents.insert(baseName, cit2); + continue; + } + // fall through to error case + } else if (comp2MightHaveFileSelector) { + // new entry contains file selector (and we now that cit did not) + if (pathWithoutFileSelectors(compFileName2, comp2PotentialFileSelectorPos) == compFileName1) { + baseFileName2ConflictingComponents.insert(compFileName1, cit2); + continue; + } + // fall through to error case + } // This entry clashes with a predecessor QQmlError error; error.setDescription(QQmlImportDatabase::tr("\"%1\" version %2.%3 is defined more than once in module \"%4\"") @@ -1232,6 +1284,14 @@ QTypeRevision QQmlImportsPrivate::matchingQmldirVersion( addVersion(cit->version); } + // ensure that all components point to the actual base URL, and let the file selectors resolve them correctly during URL resolution + for (auto keyIt = baseFileName2ConflictingComponents.keyBegin(); keyIt != baseFileName2ConflictingComponents.keyEnd(); ++keyIt) { + const QString& baseFileName = *keyIt; + const auto conflictingComponents = baseFileName2ConflictingComponents.values(baseFileName); + for (ConstIterator component: conflictingComponents) + component->fileName = baseFileName; + } + typedef QList<QQmlDirParser::Script>::const_iterator SConstIterator; const QQmlDirScripts &scripts = qmldir.scripts(); |