qmljs: avoid quadratic explosion

Change-Id: Icb184fd5c54a5398ed91b926841f7945dc8a81ec
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Tim Jenssen
2021-01-05 19:16:54 +01:00
parent 7c1e210d2c
commit 8f79503ed2
3 changed files with 35 additions and 22 deletions

View File

@@ -479,8 +479,8 @@ void Snapshot::insert(const Document::Ptr &document, bool allowInvalid)
CoreImport cImport; CoreImport cImport;
cImport.importId = document->importId(); cImport.importId = document->importId();
cImport.language = document->language(); cImport.language = document->language();
cImport.possibleExports << Export(ImportKey(ImportType::File, fileName), cImport.addPossibleExport(Export(ImportKey(ImportType::File, fileName),
QString(), true, QFileInfo(fileName).baseName()); {}, true, QFileInfo(fileName).baseName()));
cImport.fingerprint = document->fingerprint(); cImport.fingerprint = document->fingerprint();
_dependencies.addCoreImport(cImport); _dependencies.addCoreImport(cImport);
} }
@@ -526,13 +526,13 @@ void Snapshot::insertLibraryInfo(const QString &path, const LibraryInfo &info)
break; break;
ImportKey iKey(ImportType::Library, QStringList(myPath.mid(iPath)).join(QLatin1Char('.')), ImportKey iKey(ImportType::Library, QStringList(myPath.mid(iPath)).join(QLatin1Char('.')),
importKey.majorVersion, importKey.minorVersion); 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)); QStringList(myPath.mid(0, iPath)).join(QLatin1Char('/')), true));
} }
} else { } else {
QString requiredPath = QStringList(splitPath.mid(0, splitPath.size() - importKey.splitPath.size())) QString requiredPath = QStringList(splitPath.mid(0, splitPath.size() - importKey.splitPath.size()))
.join(QLatin1String("/")); .join(QLatin1String("/"));
cImport.possibleExports << Export(importKey, requiredPath, true); cImport.addPossibleExport(Export(importKey, requiredPath, true));
} }
} }
if (cImport.possibleExports.isEmpty() && splitPath.size() > 0) { if (cImport.possibleExports.isEmpty() && splitPath.size() > 0) {
@@ -567,7 +567,7 @@ void Snapshot::insertLibraryInfo(const QString &path, const LibraryInfo &info)
break; break;
ImportKey iKey(ImportType::Library, QStringList(splitPath.mid(iPath)).join(QLatin1Char('.')), ImportKey iKey(ImportType::Library, QStringList(splitPath.mid(iPath)).join(QLatin1Char('.')),
majorVersion, minorVersion); 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)); QStringList(splitPath.mid(0, iPath)).join(QLatin1Char('/')), true));
} }
} }

View File

@@ -520,19 +520,6 @@ bool Export::visibleInVContext(const ViewerContext &vContext) const
return pathRequired.isEmpty() || vContext.paths.contains(pathRequired); 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() : language(Dialect::Qml) { }
CoreImport::CoreImport(const QString &importId, const QList<Export> &possibleExports, CoreImport::CoreImport(const QString &importId, const QList<Export> &possibleExports,
@@ -810,13 +797,13 @@ void ImportDependencies::addExport(const QString &importId, const ImportKey &imp
if (!m_coreImports.contains(importId)) { if (!m_coreImports.contains(importId)) {
CoreImport newImport(importId); CoreImport newImport(importId);
newImport.language = Dialect::AnyLanguage; 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_coreImports.insert(newImport.importId, newImport);
m_importCache[importKey].append(importId); m_importCache[importKey].append(importId);
return; return;
} }
CoreImport &importValue = m_coreImports[importId]; 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); m_importCache[importKey].append(importId);
qCDebug(importsLog) << "added export "<< importKey.toString() << " for id " <<importId qCDebug(importsLog) << "added export "<< importKey.toString() << " for id " <<importId
<< " (" << requiredPath << ")"; << " (" << requiredPath << ")";

View File

@@ -134,9 +134,27 @@ public:
QString typeName; QString typeName;
bool intrinsic; bool intrinsic;
bool visibleInVContext(const ViewerContext &vContext) const; bool visibleInVContext(const ViewerContext &vContext) const;
friend 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;
}
friend bool operator!=(const Export &i1, const Export &i2)
{
return !(i1 == i2);
}
friend bool operator<(const Export &i1, const Export &i2)
{
return std::tie(i1.intrinsic, i1.pathRequired, i1.typeName, i1.exportName)
< std::tie(i2.intrinsic, i2.pathRequired, i2.typeName, i2.exportName);
}
}; };
bool operator ==(const Export &i1, const Export &i2);
bool operator !=(const Export &i1, const Export &i2);
class QMLJS_EXPORT CoreImport class QMLJS_EXPORT CoreImport
{ {
@@ -144,6 +162,14 @@ public:
CoreImport(); CoreImport();
CoreImport(const QString &importId, const QList<Export> &possibleExports = QList<Export>(), CoreImport(const QString &importId, const QList<Export> &possibleExports = QList<Export>(),
Dialect language = Dialect::Qml, const QByteArray &fingerprint = QByteArray()); Dialect language = Dialect::Qml, const QByteArray &fingerprint = QByteArray());
template<typename E>
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>(e));
}
QString importId; QString importId;
QList<Export> possibleExports; QList<Export> possibleExports;
Dialect language; Dialect language;