forked from qt-creator/qt-creator
QmlJS: Allow for QML modules with version subdirectories.
That means import Foo 2.1 can resolve to /path/Foo.2.1 or /path/Foo.2 or /path/Foo Task-number: QTCREATORBUG-4607 Change-Id: Ie1efc5be2ca2ed3ccc130e8a662f94aed11bec1a Reviewed-on: http://codereview.qt.nokia.com/194 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
This commit is contained in:
@@ -34,9 +34,12 @@
|
||||
|
||||
#include <QtCore/QString>
|
||||
|
||||
#include <limits>
|
||||
|
||||
using namespace LanguageUtils;
|
||||
|
||||
const int ComponentVersion::NoVersion = -1;
|
||||
const int ComponentVersion::MaxVersion = std::numeric_limits<int>::max();
|
||||
|
||||
ComponentVersion::ComponentVersion()
|
||||
: _major(NoVersion), _minor(NoVersion)
|
||||
|
@@ -44,6 +44,7 @@ class LANGUAGEUTILS_EXPORT ComponentVersion
|
||||
|
||||
public:
|
||||
static const int NoVersion;
|
||||
static const int MaxVersion;
|
||||
|
||||
ComponentVersion();
|
||||
ComponentVersion(int major, int minor);
|
||||
|
@@ -363,14 +363,14 @@ void Document::extractPragmas(QString *source)
|
||||
}
|
||||
}
|
||||
|
||||
LibraryInfo::LibraryInfo()
|
||||
: _valid(false)
|
||||
LibraryInfo::LibraryInfo(Status status)
|
||||
: _status(status)
|
||||
, _dumpStatus(NoTypeInfo)
|
||||
{
|
||||
}
|
||||
|
||||
LibraryInfo::LibraryInfo(const QmlDirParser &parser)
|
||||
: _valid(true)
|
||||
: _status(Found)
|
||||
, _components(parser.components())
|
||||
, _plugins(parser.plugins())
|
||||
, _dumpStatus(NoTypeInfo)
|
||||
|
@@ -132,8 +132,14 @@ public:
|
||||
TypeInfoFileError
|
||||
};
|
||||
|
||||
enum Status {
|
||||
NotScanned,
|
||||
NotFound,
|
||||
Found
|
||||
};
|
||||
|
||||
private:
|
||||
bool _valid;
|
||||
Status _status;
|
||||
QList<QmlDirParser::Component> _components;
|
||||
QList<QmlDirParser::Plugin> _plugins;
|
||||
typedef QList<LanguageUtils::FakeMetaObject::ConstPtr> FakeMetaObjectList;
|
||||
@@ -143,8 +149,8 @@ private:
|
||||
QString _dumpError;
|
||||
|
||||
public:
|
||||
LibraryInfo();
|
||||
LibraryInfo(const QmlDirParser &parser);
|
||||
explicit LibraryInfo(Status status = NotScanned);
|
||||
explicit LibraryInfo(const QmlDirParser &parser);
|
||||
~LibraryInfo();
|
||||
|
||||
QList<QmlDirParser::Component> components() const
|
||||
@@ -160,7 +166,10 @@ public:
|
||||
{ _metaObjects = objects; }
|
||||
|
||||
bool isValid() const
|
||||
{ return _valid; }
|
||||
{ return _status == Found; }
|
||||
|
||||
bool wasScanned() const
|
||||
{ return _status != NotScanned; }
|
||||
|
||||
PluginTypeInfoStatus pluginTypeInfoStatus() const
|
||||
{ return _dumpStatus; }
|
||||
|
@@ -42,8 +42,6 @@
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <limits>
|
||||
|
||||
using namespace LanguageUtils;
|
||||
using namespace QmlJS;
|
||||
using namespace QmlJS::Interpreter;
|
||||
@@ -278,18 +276,36 @@ Import Link::importNonFile(Document::Ptr doc, const ImportInfo &importInfo)
|
||||
|
||||
bool importFound = false;
|
||||
|
||||
// check the filesystem
|
||||
const QString &packagePath = importInfo.name();
|
||||
// check the filesystem with full version
|
||||
foreach (const QString &importPath, d->importPaths) {
|
||||
QString libraryPath = importPath;
|
||||
libraryPath += QDir::separator();
|
||||
libraryPath += packagePath;
|
||||
|
||||
QString libraryPath = QString("%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, d->importPaths) {
|
||||
QString libraryPath = QString("%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, d->importPaths) {
|
||||
QString libraryPath = QString("%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 (engine()->cppQmlTypes().hasPackage(packageName)) {
|
||||
@@ -417,8 +433,7 @@ void Link::loadQmldirComponents(Interpreter::ObjectValue *import, ComponentVersi
|
||||
|
||||
// if the version isn't valid, import the latest
|
||||
if (!version.isValid()) {
|
||||
const int maxVersion = std::numeric_limits<int>::max();
|
||||
version = ComponentVersion(maxVersion, maxVersion);
|
||||
version = ComponentVersion(ComponentVersion::MaxVersion, ComponentVersion::MaxVersion);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -287,6 +287,8 @@ void ModelManager::updateLibraryInfo(const QString &path, const LibraryInfo &inf
|
||||
QMutexLocker locker(&m_mutex);
|
||||
_snapshot.insertLibraryInfo(path, info);
|
||||
}
|
||||
// only emit if we got new useful information
|
||||
if (info.isValid())
|
||||
emit libraryInfoUpdated(path, info);
|
||||
}
|
||||
|
||||
@@ -358,15 +360,22 @@ static bool findNewQmlLibraryInPath(const QString &path,
|
||||
QSet<QString> *newLibraries)
|
||||
{
|
||||
// if we know there is a library, done
|
||||
if (snapshot.libraryInfo(path).isValid())
|
||||
const LibraryInfo &existingInfo = snapshot.libraryInfo(path);
|
||||
if (existingInfo.isValid())
|
||||
return true;
|
||||
if (newLibraries->contains(path))
|
||||
return true;
|
||||
// if we looked at the path before, done
|
||||
if (existingInfo.wasScanned())
|
||||
return false;
|
||||
|
||||
const QDir dir(path);
|
||||
QFile qmldirFile(dir.filePath(QLatin1String("qmldir")));
|
||||
if (!qmldirFile.exists())
|
||||
if (!qmldirFile.exists()) {
|
||||
LibraryInfo libraryInfo(LibraryInfo::NotFound);
|
||||
modelManager->updateLibraryInfo(path, libraryInfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// QTCREATORBUG-3402 - be case sensitive even here?
|
||||
@@ -382,8 +391,7 @@ static bool findNewQmlLibraryInPath(const QString &path,
|
||||
|
||||
const QString libraryPath = QFileInfo(qmldirFile).absolutePath();
|
||||
newLibraries->insert(libraryPath);
|
||||
modelManager->updateLibraryInfo(libraryPath,
|
||||
LibraryInfo(qmldirParser));
|
||||
modelManager->updateLibraryInfo(libraryPath, LibraryInfo(qmldirParser));
|
||||
|
||||
// scan the qml files in the library
|
||||
foreach (const QmlDirParser::Component &component, qmldirParser.components()) {
|
||||
@@ -400,30 +408,62 @@ static bool findNewQmlLibraryInPath(const QString &path,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void findNewQmlLibrary(
|
||||
const QString &path,
|
||||
const LanguageUtils::ComponentVersion &version,
|
||||
const Snapshot &snapshot,
|
||||
ModelManager *modelManager,
|
||||
QStringList *importedFiles,
|
||||
QSet<QString> *scannedPaths,
|
||||
QSet<QString> *newLibraries)
|
||||
{
|
||||
QString libraryPath = QString("%1.%2.%3").arg(
|
||||
path,
|
||||
QString::number(version.majorVersion()),
|
||||
QString::number(version.minorVersion()));
|
||||
findNewQmlLibraryInPath(
|
||||
libraryPath, snapshot, modelManager,
|
||||
importedFiles, scannedPaths, newLibraries);
|
||||
|
||||
libraryPath = QString("%1.%2").arg(
|
||||
path,
|
||||
QString::number(version.majorVersion()));
|
||||
findNewQmlLibraryInPath(
|
||||
libraryPath, snapshot, modelManager,
|
||||
importedFiles, scannedPaths, newLibraries);
|
||||
|
||||
findNewQmlLibraryInPath(
|
||||
path, snapshot, modelManager,
|
||||
importedFiles, scannedPaths, newLibraries);
|
||||
}
|
||||
|
||||
static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snapshot,
|
||||
ModelManager *modelManager,
|
||||
QStringList *importedFiles, QSet<QString> *scannedPaths, QSet<QString> *newLibraries)
|
||||
{
|
||||
// scan library imports
|
||||
// scan current dir
|
||||
findNewQmlLibraryInPath(doc->path(), snapshot, modelManager,
|
||||
importedFiles, scannedPaths, newLibraries);
|
||||
|
||||
// scan dir and lib imports
|
||||
const QStringList importPaths = modelManager->importPaths();
|
||||
foreach (const Interpreter::ImportInfo &import, doc->bind()->imports()) {
|
||||
if (import.type() == Interpreter::ImportInfo::LibraryImport) {
|
||||
foreach (const QString &importPath, importPaths) {
|
||||
const QString targetPath = QDir(importPath).filePath(import.name());
|
||||
|
||||
if (findNewQmlLibraryInPath(targetPath, snapshot, modelManager,
|
||||
importedFiles, scannedPaths, newLibraries))
|
||||
break;
|
||||
}
|
||||
} else if (import.type() == Interpreter::ImportInfo::DirectoryImport) {
|
||||
if (import.type() == Interpreter::ImportInfo::DirectoryImport) {
|
||||
const QString targetPath = import.name();
|
||||
findNewQmlLibraryInPath(targetPath, snapshot, modelManager,
|
||||
importedFiles, scannedPaths, newLibraries);
|
||||
}
|
||||
}
|
||||
|
||||
findNewQmlLibraryInPath(doc->path(), snapshot, modelManager,
|
||||
if (import.type() == Interpreter::ImportInfo::LibraryImport) {
|
||||
if (!import.version().isValid())
|
||||
continue;
|
||||
foreach (const QString &importPath, importPaths) {
|
||||
const QString targetPath = QDir(importPath).filePath(import.name());
|
||||
findNewQmlLibrary(targetPath, import.version(), snapshot, modelManager,
|
||||
importedFiles, scannedPaths, newLibraries);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool suffixMatches(const QString &fileName, const Core::MimeType &mimeType)
|
||||
@@ -453,8 +493,6 @@ void ModelManager::parse(QFutureInterface<void> &future,
|
||||
int progressRange = files.size();
|
||||
future.setProgressRange(0, progressRange);
|
||||
|
||||
Snapshot snapshot = modelManager->_snapshot;
|
||||
|
||||
// paths we have scanned for files and added to the files list
|
||||
QSet<QString> scannedPaths;
|
||||
// libraries we've found while scanning imports
|
||||
@@ -501,6 +539,10 @@ void ModelManager::parse(QFutureInterface<void> &future,
|
||||
doc->setSource(contents);
|
||||
doc->parse();
|
||||
|
||||
// update snapshot. requires synchronization, but significantly reduces amount of file
|
||||
// system queries for library imports because queries are cached in libraryInfo
|
||||
const Snapshot snapshot = modelManager->snapshot();
|
||||
|
||||
// get list of referenced files not yet in snapshot or in directories already scanned
|
||||
QStringList importedFiles;
|
||||
findNewImplicitImports(doc, snapshot, &importedFiles, &scannedPaths);
|
||||
|
Reference in New Issue
Block a user