forked from qt-creator/qt-creator
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>
This commit is contained in:
committed by
Marco Benelli
parent
b92ff237a9
commit
1556a707c3
@@ -377,38 +377,8 @@ Import LinkPrivate::importNonFile(Document::Ptr doc, const ImportInfo &importInf
|
|||||||
const QString packageName = importInfo.name();
|
const QString packageName = importInfo.name();
|
||||||
const ComponentVersion version = importInfo.version();
|
const ComponentVersion version = importInfo.version();
|
||||||
|
|
||||||
bool importFound = false;
|
QString libraryPath = modulePath(packageName, version.toString(), importPaths);
|
||||||
|
bool importFound = importLibrary(doc, libraryPath, &import);
|
||||||
const QString &packagePath = importInfo.path();
|
|
||||||
// check the filesystem with full version
|
|
||||||
foreach (const QString &importPath, importPaths) {
|
|
||||||
QString libraryPath = QString::fromLatin1("%1/%2.%3").arg(importPath, packagePath, version.toString());
|
|
||||||
if (importLibrary(doc, libraryPath, &import, importPath)) {
|
|
||||||
importFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!importFound) {
|
|
||||||
// check the filesystem with major version
|
|
||||||
foreach (const QString &importPath, importPaths) {
|
|
||||||
QString libraryPath = QString::fromLatin1("%1/%2.%3").arg(importPath, packagePath,
|
|
||||||
QString::number(version.majorVersion()));
|
|
||||||
if (importLibrary(doc, libraryPath, &import, importPath)) {
|
|
||||||
importFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!importFound) {
|
|
||||||
// check the filesystem with no version
|
|
||||||
foreach (const QString &importPath, importPaths) {
|
|
||||||
QString libraryPath = QString::fromLatin1("%1/%2").arg(importPath, packagePath);
|
|
||||||
if (importLibrary(doc, libraryPath, &import, importPath)) {
|
|
||||||
importFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there are cpp-based types for this package, use them too
|
// if there are cpp-based types for this package, use them too
|
||||||
if (valueOwner->cppQmlTypes().hasModule(packageName)) {
|
if (valueOwner->cppQmlTypes().hasModule(packageName)) {
|
||||||
|
@@ -28,6 +28,8 @@
|
|||||||
#include "parser/qmljsast_p.h"
|
#include "parser/qmljsast_p.h"
|
||||||
|
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
using namespace QmlJS;
|
using namespace QmlJS;
|
||||||
using namespace QmlJS::AST;
|
using namespace QmlJS::AST;
|
||||||
@@ -195,6 +197,67 @@ DiagnosticMessage QmlJS::errorMessage(const AST::SourceLocation &loc, const QStr
|
|||||||
return DiagnosticMessage(Severity::Error, loc, message);
|
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)
|
bool QmlJS::isValidBuiltinPropertyType(const QString &name)
|
||||||
{
|
{
|
||||||
return sharedData()->validBuiltinPropertyNames.contains(name);
|
return sharedData()->validBuiltinPropertyNames.contains(name);
|
||||||
|
@@ -54,6 +54,11 @@ QMLJS_EXPORT bool isValidBuiltinPropertyType(const QString &name);
|
|||||||
QMLJS_EXPORT DiagnosticMessage errorMessage(const AST::SourceLocation &loc,
|
QMLJS_EXPORT DiagnosticMessage errorMessage(const AST::SourceLocation &loc,
|
||||||
const QString &message);
|
const QString &message);
|
||||||
|
|
||||||
|
QMLJS_EXPORT bool maybeModuleVersion(const QString &version);
|
||||||
|
|
||||||
|
QMLJS_EXPORT QString modulePath(const QString &moduleImportName, const QString &version,
|
||||||
|
const QStringList &importPaths);
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
AST::SourceLocation locationFromRange(const T *node)
|
AST::SourceLocation locationFromRange(const T *node)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user