Implement heuristics for parsing version number

Similar solution exists in QtHelp module:
QString QHelpDBReader::qtVersionHeuristic() const

Fixes: QTCREATORBUG-26292
Change-Id: I9037785920e25428db0fa7f03f737c5ef66c4ac3
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Jarek Kobus
2021-09-20 17:45:08 +02:00
parent 04bb1ee5da
commit 128c7dfbef

View File

@@ -29,6 +29,8 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/htmldocextractor.h> #include <utils/htmldocextractor.h>
#include <QVersionNumber>
using namespace Core; using namespace Core;
HelpItem::HelpItem() = default; HelpItem::HelpItem() = default;
@@ -165,31 +167,66 @@ QString HelpItem::extractContent(bool extended) const
return contents; return contents;
} }
static std::pair<QUrl, int> extractVersion(const QUrl &url) // The following is only correct under the specific current conditions, and it will
// always be quite some guessing as long as the version information does not
// include separators for major vs minor vs patch version.
static QVersionNumber qtVersionHeuristic(const QString &digits)
{
if (digits.count() > 6 || digits.count() < 3)
return {}; // suspicious version number
for (const QChar &digit : digits)
if (!digit.isDigit())
return {}; // we should have only digits
// When we have 3 digits, we split it like: ABC -> A.B.C
// When we have 4 digits, we split it like: ABCD -> A.BC.D
// When we have 5 digits, we split it like: ABCDE -> A.BC.DE
// When we have 6 digits, we split it like: ABCDEF -> AB.CD.EF
switch (digits.count()) {
case 3:
return QVersionNumber(digits.mid(0, 1).toInt(),
digits.mid(1, 1).toInt(),
digits.mid(2, 1).toInt());
case 4:
return QVersionNumber(digits.mid(0, 1).toInt(),
digits.mid(1, 2).toInt(),
digits.mid(3, 1).toInt());
case 5:
return QVersionNumber(digits.mid(0, 1).toInt(),
digits.mid(1, 2).toInt(),
digits.mid(3, 2).toInt());
case 6:
return QVersionNumber(digits.mid(0, 2).toInt(),
digits.mid(2, 2).toInt(),
digits.mid(4, 2).toInt());
default:
break;
}
return {};
}
static std::pair<QUrl, QVersionNumber> extractVersion(const QUrl &url)
{ {
const QString host = url.host(); const QString host = url.host();
const QStringList hostParts = host.split('.'); const QStringList hostParts = host.split('.');
if (hostParts.size() == 4 && (host.startsWith("com.trolltech.") if (hostParts.size() == 4 && (host.startsWith("com.trolltech.")
|| host.startsWith("org.qt-project."))) { || host.startsWith("org.qt-project."))) {
bool ok = false; const QVersionNumber version = qtVersionHeuristic(hostParts.at(3));
// the following is only correct under the specific current conditions, and it will if (!version.isNull()) {
// always be quite some guessing as long as the version information does not
// include separators for major vs minor vs patch version
const int version = hostParts.at(3).toInt(&ok);
if (ok) {
QUrl urlWithoutVersion(url); QUrl urlWithoutVersion(url);
urlWithoutVersion.setHost(hostParts.mid(0, 3).join('.')); urlWithoutVersion.setHost(hostParts.mid(0, 3).join('.'));
return {urlWithoutVersion, version}; return {urlWithoutVersion, version};
} }
} }
return {url, 0}; return {url, {}};
} }
// sort primary by "url without version" and seconday by "version" // sort primary by "url without version" and seconday by "version"
static bool helpUrlLessThan(const QUrl &a, const QUrl &b) static bool helpUrlLessThan(const QUrl &a, const QUrl &b)
{ {
const std::pair<QUrl, int> va = extractVersion(a); const std::pair<QUrl, QVersionNumber> va = extractVersion(a);
const std::pair<QUrl, int> vb = extractVersion(b); const std::pair<QUrl, QVersionNumber> vb = extractVersion(b);
const QString sa = va.first.toString(); const QString sa = va.first.toString();
const QString sb = vb.first.toString(); const QString sb = vb.first.toString();
if (sa == sb) if (sa == sb)
@@ -260,10 +297,10 @@ static const HelpItem::Links getBestLink(const HelpItem::Links &links)
// This is to ensure that if we succeeded with an ID lookup, and we have e.g. Qt5 and Qt4 // This is to ensure that if we succeeded with an ID lookup, and we have e.g. Qt5 and Qt4
// documentation, that we only return the Qt5 link even though the Qt5 and Qt4 URLs look // documentation, that we only return the Qt5 link even though the Qt5 and Qt4 URLs look
// different. // different.
int highestVersion = -1; QVersionNumber highestVersion;
HelpItem::Link bestLink; HelpItem::Link bestLink;
for (const HelpItem::Link &link : links) { for (const HelpItem::Link &link : links) {
const int version = extractVersion(link.second).second; const QVersionNumber version = extractVersion(link.second).second;
if (version > highestVersion) { if (version > highestVersion) {
highestVersion = version; highestVersion = version;
bestLink = link; bestLink = link;