forked from qt-creator/qt-creator
QmlJs: fix bug in resolving qml imports
The introduction of Controls.2 changed the way in which imports are resolved. This patch fix some leftovers of the old resolution scheme. Such leftovers caused false positives in import declaration to happen when resetting the QML/JS code model. The code has also been simplified a little, by the removal of duplicate code and of unused methods. Change-Id: I90bdf7ed47fdfea7cbd8259acd7a9a968f27301b Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -32,6 +32,7 @@
|
|||||||
#include "qmljstypedescriptionreader.h"
|
#include "qmljstypedescriptionreader.h"
|
||||||
#include "qmljsdialect.h"
|
#include "qmljsdialect.h"
|
||||||
#include "qmljsviewercontext.h"
|
#include "qmljsviewercontext.h"
|
||||||
|
#include "qmljsutils.h"
|
||||||
|
|
||||||
#include <cplusplus/cppmodelmanagerbase.h>
|
#include <cplusplus/cppmodelmanagerbase.h>
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
@@ -811,33 +812,11 @@ static bool findNewQmlLibraryInPath(const QString &path,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void findNewQmlLibrary(
|
static QString modulePath(const ImportInfo &import, const QStringList &paths)
|
||||||
const QString &path,
|
|
||||||
const LanguageUtils::ComponentVersion &version,
|
|
||||||
const Snapshot &snapshot,
|
|
||||||
ModelManagerInterface *modelManager,
|
|
||||||
QStringList *importedFiles,
|
|
||||||
QSet<QString> *scannedPaths,
|
|
||||||
QSet<QString> *newLibraries)
|
|
||||||
{
|
{
|
||||||
QString libraryPath = QString::fromLatin1("%1.%2.%3").arg(
|
if (!import.version().isValid())
|
||||||
path,
|
return QString();
|
||||||
QString::number(version.majorVersion()),
|
return modulePath(import.name(), import.version().toString(), paths);
|
||||||
QString::number(version.minorVersion()));
|
|
||||||
findNewQmlLibraryInPath(
|
|
||||||
libraryPath, snapshot, modelManager,
|
|
||||||
importedFiles, scannedPaths, newLibraries, false);
|
|
||||||
|
|
||||||
libraryPath = QString::fromLatin1("%1.%2").arg(
|
|
||||||
path,
|
|
||||||
QString::number(version.majorVersion()));
|
|
||||||
findNewQmlLibraryInPath(
|
|
||||||
libraryPath, snapshot, modelManager,
|
|
||||||
importedFiles, scannedPaths, newLibraries, false);
|
|
||||||
|
|
||||||
findNewQmlLibraryInPath(
|
|
||||||
path, snapshot, modelManager,
|
|
||||||
importedFiles, scannedPaths, newLibraries, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snapshot,
|
static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snapshot,
|
||||||
@@ -849,7 +828,7 @@ static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snap
|
|||||||
importedFiles, scannedPaths, newLibraries, false);
|
importedFiles, scannedPaths, newLibraries, false);
|
||||||
|
|
||||||
// scan dir and lib imports
|
// scan dir and lib imports
|
||||||
const PathsAndLanguages importPaths = modelManager->importPaths();
|
const QStringList importPaths = modelManager->importPathsNames();
|
||||||
foreach (const ImportInfo &import, doc->bind()->imports()) {
|
foreach (const ImportInfo &import, doc->bind()->imports()) {
|
||||||
if (import.type() == ImportType::Directory) {
|
if (import.type() == ImportType::Directory) {
|
||||||
const QString targetPath = import.path();
|
const QString targetPath = import.path();
|
||||||
@@ -858,13 +837,11 @@ static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snap
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (import.type() == ImportType::Library) {
|
if (import.type() == ImportType::Library) {
|
||||||
if (!import.version().isValid())
|
const QString libraryPath = modulePath(import, importPaths);
|
||||||
|
if (libraryPath.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
foreach (const PathAndLanguage &importPath, importPaths) {
|
findNewQmlLibraryInPath(libraryPath, snapshot, modelManager, importedFiles,
|
||||||
const QString targetPath = importPath.path().appendPath(import.path()).toString();
|
scannedPaths, newLibraries, false);
|
||||||
findNewQmlLibrary(targetPath, import.version(), snapshot, modelManager,
|
|
||||||
importedFiles, scannedPaths, newLibraries);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1071,10 +1048,14 @@ void ModelManagerInterface::importScan(QFutureInterface<void> &future,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PathsAndLanguages ModelManagerInterface::importPaths() const
|
QStringList ModelManagerInterface::importPathsNames() const
|
||||||
{
|
{
|
||||||
|
QStringList names;
|
||||||
QMutexLocker l(&m_mutex);
|
QMutexLocker l(&m_mutex);
|
||||||
return m_allImportPaths;
|
names.reserve(m_allImportPaths.size());
|
||||||
|
for (const PathAndLanguage &x: m_allImportPaths)
|
||||||
|
names << x.path().toString();
|
||||||
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlLanguageBundles ModelManagerInterface::activeBundles() const
|
QmlLanguageBundles ModelManagerInterface::activeBundles() const
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ public:
|
|||||||
QList<ProjectInfo> allProjectInfosForPath(const QString &path) const;
|
QList<ProjectInfo> allProjectInfosForPath(const QString &path) const;
|
||||||
bool isIdle() const ;
|
bool isIdle() const ;
|
||||||
|
|
||||||
PathsAndLanguages importPaths() const;
|
QStringList importPathsNames() const;
|
||||||
QmlJS::QmlLanguageBundles activeBundles() const;
|
QmlJS::QmlLanguageBundles activeBundles() const;
|
||||||
QmlJS::QmlLanguageBundles extendedBundles() const;
|
QmlJS::QmlLanguageBundles extendedBundles() const;
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "qmljsplugindumper.h"
|
#include "qmljsplugindumper.h"
|
||||||
#include "qmljsmodelmanagerinterface.h"
|
#include "qmljsmodelmanagerinterface.h"
|
||||||
|
#include "qmljsutils.h"
|
||||||
|
|
||||||
#include <qmljs/qmljsinterpreter.h>
|
#include <qmljs/qmljsinterpreter.h>
|
||||||
#include <qmljs/qmljsviewercontext.h>
|
#include <qmljs/qmljsviewercontext.h>
|
||||||
@@ -401,48 +402,35 @@ void PluginDumper::loadQmlTypeDescription(const QStringList &paths,
|
|||||||
/*!
|
/*!
|
||||||
* \brief Build the path of an existing qmltypes file from a module name.
|
* \brief Build the path of an existing qmltypes file from a module name.
|
||||||
* \param name
|
* \param name
|
||||||
* \return the module's qmltypes file path
|
* \return the module's qmltypes file path or an empty string if not found
|
||||||
*
|
*
|
||||||
* Look for \a name qmltypes file in model manager's import paths.
|
* Look for \a name qmltypes file in model manager's import paths.
|
||||||
* For each import path the following files are searched, in this order:
|
|
||||||
*
|
|
||||||
* - <name>.<major>.<minor>/plugins.qmltypes
|
|
||||||
* - <name>.<major>/plugins.qmltypes
|
|
||||||
* - <name>/plugins.qmltypes
|
|
||||||
*
|
|
||||||
* That means that a more qualified directory name has precedence over a
|
|
||||||
* less qualified one. Be aware that the import paths order has a stronger
|
|
||||||
* precedence, so a less qualified name could shadow a more qualified one if
|
|
||||||
* it resides in a different import path.
|
|
||||||
*
|
*
|
||||||
|
* \sa QmlJs::modulePath
|
||||||
* \sa LinkPrivate::importNonFile
|
* \sa LinkPrivate::importNonFile
|
||||||
*/
|
*/
|
||||||
QString PluginDumper::buildQmltypesPath(const QString &name) const
|
QString PluginDumper::buildQmltypesPath(const QString &name) const
|
||||||
{
|
{
|
||||||
QString qualifiedName;
|
QString qualifiedName;
|
||||||
QString majorVersion;
|
QString version;
|
||||||
QString minorVersion;
|
|
||||||
|
|
||||||
QRegularExpression import("^(?<name>[\\w|\\.]+)\\s+(?<major>\\d+)\\.(?<minor>\\d+)$");
|
QRegularExpression import("^(?<name>[\\w|\\.]+)\\s+(?<major>\\d+)\\.(?<minor>\\d+)$");
|
||||||
QRegularExpressionMatch m = import.match(name);
|
QRegularExpressionMatch m = import.match(name);
|
||||||
if (m.hasMatch()) {
|
if (m.hasMatch()) {
|
||||||
qualifiedName = m.captured("name");
|
qualifiedName = m.captured("name");
|
||||||
majorVersion = m.captured("major");
|
version = m.captured("major") + QLatin1Char('.') + m.captured("minor");
|
||||||
minorVersion = m.captured("minor");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const PathAndLanguage &p: m_modelManager->importPaths()) {
|
const QString path = modulePath(qualifiedName, version, m_modelManager->importPathsNames());
|
||||||
QString moduleName = qualifiedName.replace(QLatin1Char('.'), QLatin1Char('/'));
|
|
||||||
QString moduleNameMajor = moduleName + QLatin1Char('.') + majorVersion;
|
if (path.isEmpty())
|
||||||
QString moduleNameMajorMinor = moduleNameMajor + QLatin1Char('.') + minorVersion;
|
return QString();
|
||||||
|
|
||||||
|
const QString filename = path + QLatin1String("/plugins.qmltypes");
|
||||||
|
|
||||||
for (const auto n: QStringList{moduleNameMajorMinor, moduleNameMajor, moduleName}) {
|
|
||||||
QString filename(p.path().toString() + QLatin1Char('/') + n
|
|
||||||
+ QLatin1String("/plugins.qmltypes"));
|
|
||||||
if (QFile::exists(filename))
|
if (QFile::exists(filename))
|
||||||
return filename;
|
return filename;
|
||||||
}
|
|
||||||
}
|
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user