diff options
author | Marco Benelli <marco.benelli@theqtcompany.com> | 2016-04-29 16:25:17 +0200 |
---|---|---|
committer | Marco Benelli <marco.benelli@qt.io> | 2016-05-04 08:08:15 +0000 |
commit | 1556a707c32a0b101edc11e5e04c257f353ef718 (patch) | |
tree | 2715d04965f00d8ab37c7e2d6dadd18266fc6544 /src/libs/qmljs/qmljsutils.cpp | |
parent | b92ff237a9283b553bdd9c710417af6dd5cc2708 (diff) |
QmlJs: search for version in parent modules.
Modules used to be searched by name with optionally an attached
version. Now, if a module with version is not found, the version is
attached to the parent module.
Task-number: QTCREATORBUG-16145
Change-Id: Ie0f30d4df64d13b3ec4c5ee38e9ad9215ae56420
Reviewed-by: Thomas Hartmann <Thomas.Hartmann@theqtcompany.com>
Diffstat (limited to 'src/libs/qmljs/qmljsutils.cpp')
-rw-r--r-- | src/libs/qmljs/qmljsutils.cpp | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/libs/qmljs/qmljsutils.cpp b/src/libs/qmljs/qmljsutils.cpp index 8fbfaf39be9..98deff530ac 100644 --- a/src/libs/qmljs/qmljsutils.cpp +++ b/src/libs/qmljs/qmljsutils.cpp @@ -28,6 +28,8 @@ #include "parser/qmljsast_p.h" #include <QColor> +#include <QDir> +#include <QRegularExpression> using namespace QmlJS; using namespace QmlJS::AST; @@ -195,6 +197,67 @@ DiagnosticMessage QmlJS::errorMessage(const AST::SourceLocation &loc, const QStr return DiagnosticMessage(Severity::Error, loc, message); } +/*! + * \brief Permissive validation of a string representing a module version. + * \param version + * \return True if \p version is a valid version format (<digit(s)>.<digit(s)>) or if it is empty. + * False otherwise. + */ +bool QmlJS::maybeModuleVersion(const QString &version) { + QRegularExpression re(QLatin1String("^\\d+\\.\\d+$")); + return version.isEmpty() || re.match(version).hasMatch(); +} + +/*! + * \brief Get the path of a module + * \param name + * \param version + * \param importPaths + * + * Given the qualified \p name and \p version of a module, look for a valid path in \p importPaths. + * Most specific version are searched first, the version is searched also in parent modules. + * For example, given the \p name QtQml.Models and \p version 2.0, the following directories are + * searched in every element of \p importPath: + * + * - QtQml/Models.2.0 + * - QtQml.2.0/Models + * - QtQml/Models.2 + * - QtQml.2/Models + * - QtQml/Models + * + * \return The module paths if found, an empty string otherwise + * \see qmlimportscanner in qtdeclarative/tools + */ +QString QmlJS::modulePath(const QString &name, const QString &version, + const QStringList &importPaths) +{ + Q_ASSERT(maybeModuleVersion(version)); + + const QStringList parts = name.split(QLatin1Char('.'), QString::SkipEmptyParts); + auto mkpath = [] (const QStringList &xs) -> QString { return xs.join(QLatin1Char('/')); }; + + QString candidate; + + for (QString ver = version; ; ver.remove(QRegularExpression(QLatin1String("\\.?\\d+$")))) { + for (const QString &path: importPaths) { + if (ver.isEmpty()) { + candidate = QDir::cleanPath(QString::fromLatin1("%1/%2").arg(path, mkpath(parts))); + return QDir(candidate).exists() ? candidate : QString(); + } else { + 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)))); + if (QDir(candidate).exists()) + return candidate; + } + } + } + } +} + bool QmlJS::isValidBuiltinPropertyType(const QString &name) { return sharedData()->validBuiltinPropertyNames.contains(name); |