aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/qmljs/qmljsutils.cpp
diff options
context:
space:
mode:
authorMarco Benelli <marco.benelli@theqtcompany.com>2016-04-29 16:25:17 +0200
committerMarco Benelli <marco.benelli@qt.io>2016-05-04 08:08:15 +0000
commit1556a707c32a0b101edc11e5e04c257f353ef718 (patch)
tree2715d04965f00d8ab37c7e2d6dadd18266fc6544 /src/libs/qmljs/qmljsutils.cpp
parentb92ff237a9283b553bdd9c710417af6dd5cc2708 (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.cpp63
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);