forked from qt-creator/qt-creator
QmlJS: Fix issues with getting modulePaths
This patch - improves performance by removing the usage of QRegularExpression for trivial string operations (this is called 3000 times after configuring Qt Creator) - fixes handling of version number like "2.-1" which are the result of imports with only a major version number like "import QtQuick 2" Task-number: QTCREATORBUG-25899 Fixes: QTCREATORBUG-26178 Fixes: QTCREATORBUG-26216 Change-Id: Ic792909513f4fe25ac72043645f297ee41890375 Reviewed-by: Fawzi Mohamed <fawzi.mohamed@qt.io> Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
This commit is contained in:
@@ -213,6 +213,29 @@ bool QmlJS::maybeModuleVersion(const QString &version) {
|
||||
return version.isEmpty() || version == undefinedVersion || re.match(version).hasMatch();
|
||||
}
|
||||
|
||||
const QStringList QmlJS::splitVersion(const QString &version)
|
||||
{
|
||||
// Successively removing minor and major version numbers.
|
||||
QStringList result;
|
||||
int versionEnd = version.length();
|
||||
while (versionEnd > 0) {
|
||||
result.append(version.left(versionEnd));
|
||||
// remove numbers and then potential . at the end
|
||||
const int oldVersionEnd = versionEnd;
|
||||
while (versionEnd > 0 && version.at(versionEnd - 1).isDigit())
|
||||
--versionEnd;
|
||||
// handle e.g. -1, because an import "QtQuick 2" results in version "2.-1"
|
||||
if (versionEnd > 0 && version.at(versionEnd - 1) == '-')
|
||||
--versionEnd;
|
||||
if (versionEnd > 0 && version.at(versionEnd - 1) == '.')
|
||||
--versionEnd;
|
||||
// bail out if we didn't proceed because version string contains invalid characters
|
||||
if (versionEnd == oldVersionEnd)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Get the path of a module
|
||||
* \param name
|
||||
@@ -242,24 +265,19 @@ QStringList QmlJS::modulePaths(const QString &name, const QString &version,
|
||||
|
||||
const QString sanitizedVersion = version == undefinedVersion ? QString() : version;
|
||||
const QStringList parts = name.split('.', Qt::SkipEmptyParts);
|
||||
auto mkpath = [] (const QStringList &xs) -> QString { return xs.join(QLatin1Char('/')); };
|
||||
|
||||
// Regular expression for building candidates by successively removing minor and major
|
||||
// version numbers. It does not match the undefined version, so it has to be applied to the
|
||||
// sanitized version.
|
||||
const QRegularExpression re("\\.?\\d+$");
|
||||
auto mkpath = [](const QStringList &xs) -> QString { return xs.join(QLatin1Char('/')); };
|
||||
|
||||
QStringList result;
|
||||
QString candidate;
|
||||
|
||||
for (QString ver = sanitizedVersion; !ver.isEmpty(); ver.remove(re)) {
|
||||
for (const QString &path: importPaths) {
|
||||
for (const QString &versionPart : splitVersion(sanitizedVersion)) {
|
||||
for (const QString &path : importPaths) {
|
||||
for (int i = parts.count() - 1; i >= 0; --i) {
|
||||
candidate = QDir::cleanPath(
|
||||
QString::fromLatin1("%1/%2.%3/%4").arg(path,
|
||||
mkpath(parts.mid(0, i + 1)),
|
||||
ver,
|
||||
mkpath(parts.mid(i + 1))));
|
||||
candidate = QDir::cleanPath(QString::fromLatin1("%1/%2.%3/%4")
|
||||
.arg(path,
|
||||
mkpath(parts.mid(0, i + 1)),
|
||||
versionPart,
|
||||
mkpath(parts.mid(i + 1))));
|
||||
if (QDir(candidate).exists())
|
||||
result << candidate;
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ QMLJS_EXPORT DiagnosticMessage errorMessage(const SourceLocation &loc,
|
||||
|
||||
QMLJS_EXPORT bool maybeModuleVersion(const QString &version);
|
||||
|
||||
QMLJS_EXPORT const QStringList splitVersion(const QString &version);
|
||||
QMLJS_EXPORT QStringList modulePaths(const QString &moduleImportName, const QString &version,
|
||||
const QStringList &importPaths);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ add_subdirectory(persistenttrie)
|
||||
add_subdirectory(qmldesigner)
|
||||
add_subdirectory(qmleditor)
|
||||
add_subdirectory(qmljssimplereader)
|
||||
add_subdirectory(qmljsutils)
|
||||
add_subdirectory(qmlprojectmanager)
|
||||
add_subdirectory(qrcparser)
|
||||
add_subdirectory(reformatter)
|
||||
|
||||
5
tests/auto/qml/qmljsutils/CMakeLists.txt
Normal file
5
tests/auto/qml/qmljsutils/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
add_qtc_test(tst_qmljstools
|
||||
DEPENDS QmlJS
|
||||
DEFINES
|
||||
SOURCES tst_qmljsutils.cpp
|
||||
)
|
||||
62
tests/auto/qml/qmljsutils/tst_qmljsutils.cpp
Normal file
62
tests/auto/qml/qmljsutils/tst_qmljsutils.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtTest>
|
||||
#include <QDebug>
|
||||
|
||||
#include <qmljs/qmljsutils.h>
|
||||
|
||||
class tst_QmlJSUtils: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void moduleVersionNumbers_data();
|
||||
void moduleVersionNumbers();
|
||||
};
|
||||
|
||||
void tst_QmlJSUtils::moduleVersionNumbers_data()
|
||||
{
|
||||
QTest::addColumn<QString>("version");
|
||||
QTest::addColumn<QStringList>("result");
|
||||
|
||||
QTest::newRow("empty") << "" << QStringList();
|
||||
QTest::newRow("full") << "2.15" << QStringList{"2.15", "2"};
|
||||
QTest::newRow("single") << "2" << QStringList{"2"};
|
||||
// result if "import QtQuick 2":
|
||||
QTest::newRow("major") << "2.-1" << QStringList{"2.-1", "2"};
|
||||
QTest::newRow("broken") << "2.+3" << QStringList{"2.+3", "2.+"};
|
||||
}
|
||||
|
||||
void tst_QmlJSUtils::moduleVersionNumbers()
|
||||
{
|
||||
QFETCH(QString, version);
|
||||
QFETCH(QStringList, result);
|
||||
QCOMPARE(QmlJS::splitVersion(version), result);
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(tst_QmlJSUtils)
|
||||
|
||||
#include "tst_qmljsutils.moc"
|
||||
Reference in New Issue
Block a user