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/htmldocextractor.h>
#include <QVersionNumber>
using namespace Core;
HelpItem::HelpItem() = default;
@@ -165,31 +167,66 @@ QString HelpItem::extractContent(bool extended) const
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 QStringList hostParts = host.split('.');
if (hostParts.size() == 4 && (host.startsWith("com.trolltech.")
|| host.startsWith("org.qt-project."))) {
bool ok = false;
// 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
const int version = hostParts.at(3).toInt(&ok);
if (ok) {
const QVersionNumber version = qtVersionHeuristic(hostParts.at(3));
if (!version.isNull()) {
QUrl urlWithoutVersion(url);
urlWithoutVersion.setHost(hostParts.mid(0, 3).join('.'));
return {urlWithoutVersion, version};
}
}
return {url, 0};
return {url, {}};
}
// sort primary by "url without version" and seconday by "version"
static bool helpUrlLessThan(const QUrl &a, const QUrl &b)
{
const std::pair<QUrl, int> va = extractVersion(a);
const std::pair<QUrl, int> vb = extractVersion(b);
const std::pair<QUrl, QVersionNumber> va = extractVersion(a);
const std::pair<QUrl, QVersionNumber> vb = extractVersion(b);
const QString sa = va.first.toString();
const QString sb = vb.first.toString();
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
// documentation, that we only return the Qt5 link even though the Qt5 and Qt4 URLs look
// different.
int highestVersion = -1;
QVersionNumber highestVersion;
HelpItem::Link bestLink;
for (const HelpItem::Link &link : links) {
const int version = extractVersion(link.second).second;
const QVersionNumber version = extractVersion(link.second).second;
if (version > highestVersion) {
highestVersion = version;
bestLink = link;