From 8f79503ed21bfab3bc54a0891008628398c6ca6e Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Tue, 5 Jan 2021 19:16:54 +0100 Subject: [PATCH] qmljs: avoid quadratic explosion Change-Id: Icb184fd5c54a5398ed91b926841f7945dc8a81ec Reviewed-by: Thomas Hartmann --- src/libs/qmljs/qmljsdocument.cpp | 10 ++++---- src/libs/qmljs/qmljsimportdependencies.cpp | 17 ++---------- src/libs/qmljs/qmljsimportdependencies.h | 30 ++++++++++++++++++++-- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/src/libs/qmljs/qmljsdocument.cpp b/src/libs/qmljs/qmljsdocument.cpp index ce8b7ba7fe8..df30dcb75ae 100644 --- a/src/libs/qmljs/qmljsdocument.cpp +++ b/src/libs/qmljs/qmljsdocument.cpp @@ -479,8 +479,8 @@ void Snapshot::insert(const Document::Ptr &document, bool allowInvalid) CoreImport cImport; cImport.importId = document->importId(); cImport.language = document->language(); - cImport.possibleExports << Export(ImportKey(ImportType::File, fileName), - QString(), true, QFileInfo(fileName).baseName()); + cImport.addPossibleExport(Export(ImportKey(ImportType::File, fileName), + {}, true, QFileInfo(fileName).baseName())); cImport.fingerprint = document->fingerprint(); _dependencies.addCoreImport(cImport); } @@ -526,13 +526,13 @@ void Snapshot::insertLibraryInfo(const QString &path, const LibraryInfo &info) break; ImportKey iKey(ImportType::Library, QStringList(myPath.mid(iPath)).join(QLatin1Char('.')), importKey.majorVersion, importKey.minorVersion); - cImport.possibleExports.append(Export(iKey, (iPath == 1) ? QLatin1String("/") : + cImport.addPossibleExport(Export(iKey, (iPath == 1) ? QLatin1String("/") : QStringList(myPath.mid(0, iPath)).join(QLatin1Char('/')), true)); } } else { QString requiredPath = QStringList(splitPath.mid(0, splitPath.size() - importKey.splitPath.size())) .join(QLatin1String("/")); - cImport.possibleExports << Export(importKey, requiredPath, true); + cImport.addPossibleExport(Export(importKey, requiredPath, true)); } } if (cImport.possibleExports.isEmpty() && splitPath.size() > 0) { @@ -567,7 +567,7 @@ void Snapshot::insertLibraryInfo(const QString &path, const LibraryInfo &info) break; ImportKey iKey(ImportType::Library, QStringList(splitPath.mid(iPath)).join(QLatin1Char('.')), majorVersion, minorVersion); - cImport.possibleExports.append(Export(iKey, (iPath == 1) ? QLatin1String("/") : + cImport.addPossibleExport(Export(iKey, (iPath == 1) ? QLatin1String("/") : QStringList(splitPath.mid(0, iPath)).join(QLatin1Char('/')), true)); } } diff --git a/src/libs/qmljs/qmljsimportdependencies.cpp b/src/libs/qmljs/qmljsimportdependencies.cpp index 26b1e82526c..e6b919eaec3 100644 --- a/src/libs/qmljs/qmljsimportdependencies.cpp +++ b/src/libs/qmljs/qmljsimportdependencies.cpp @@ -520,19 +520,6 @@ bool Export::visibleInVContext(const ViewerContext &vContext) const return pathRequired.isEmpty() || vContext.paths.contains(pathRequired); } -bool operator ==(const Export &i1, const Export &i2) -{ - return i1.exportName == i2.exportName - && i1.pathRequired == i2.pathRequired - && i1.intrinsic == i2.intrinsic - && i1.typeName == i2.typeName; -} - -bool operator !=(const Export &i1, const Export &i2) -{ - return !(i1 == i2); -} - CoreImport::CoreImport() : language(Dialect::Qml) { } CoreImport::CoreImport(const QString &importId, const QList &possibleExports, @@ -810,13 +797,13 @@ void ImportDependencies::addExport(const QString &importId, const ImportKey &imp if (!m_coreImports.contains(importId)) { CoreImport newImport(importId); newImport.language = Dialect::AnyLanguage; - newImport.possibleExports.append(Export(importKey, requiredPath, false, typeName)); + newImport.addPossibleExport(Export(importKey, requiredPath, false, typeName)); m_coreImports.insert(newImport.importId, newImport); m_importCache[importKey].append(importId); return; } CoreImport &importValue = m_coreImports[importId]; - importValue.possibleExports.append(Export(importKey, requiredPath, false, typeName)); + importValue.addPossibleExport(Export(importKey, requiredPath, false, typeName)); m_importCache[importKey].append(importId); qCDebug(importsLog) << "added export "<< importKey.toString() << " for id " < &possibleExports = QList(), Dialect language = Dialect::Qml, const QByteArray &fingerprint = QByteArray()); + template + void addPossibleExport(E &&e) + { + auto found = std::lower_bound(possibleExports.begin(), possibleExports.end(), e); + if (found == possibleExports.end() || e != *found) + possibleExports.insert(found, std::forward(e)); + } + QString importId; QList possibleExports; Dialect language;