diff --git a/src/libs/qmljs/parser/cmd.sed b/src/libs/qmljs/parser/cmd.sed index fa2ef28f2f5313918877d98281deb2237bb937ab..740da4e3d1acb77deb7d27d619d3db9935b6de58 100644 --- a/src/libs/qmljs/parser/cmd.sed +++ b/src/libs/qmljs/parser/cmd.sed @@ -1,3 +1,11 @@ s/qdeclarative/qml/g s/QDECLARATIVE/QML/g s/QDeclarative/Qml/g + +# adjust pri file +s/ \$\$PWD\/qmljsglobal_p.h/ $$PWD\/qmljsglobal_p.h \\\ + $$PWD\/qmldirparser_p.h \\\ + $$PWD\/qmlerror.h/ +s/ \$\$PWD\/qmljsparser.cpp/ $$PWD\/qmljsparser.cpp \\\ + $$PWD\/qmldirparser.cpp \\\ + $$PWD\/qmlerror.cpp/ diff --git a/src/libs/qmljs/parser/gen-parser.sh b/src/libs/qmljs/parser/gen-parser.sh index 1925432977a8dbe511e9331f45dd83e2ab2c2686..5b999e27f158cb2b18c9c9d8e1f227733d61ba27 100755 --- a/src/libs/qmljs/parser/gen-parser.sh +++ b/src/libs/qmljs/parser/gen-parser.sh @@ -10,3 +10,5 @@ for i in $QTDIR/src/declarative/qml/qdeclarative{error.{h,cpp},dirparser{_p.h,.c sed -f $me/cmd.sed $i > $me/$(echo $(basename $i) | sed s/qdeclarative/qml/) done +# export QmlDirParser +perl -p -0777 -i -e 's/QT_BEGIN_NAMESPACE\n\nclass QmlError;\n\nclass QmlDirParser/#include "qmljsglobal_p.h"\n\nQT_BEGIN_NAMESPACE\n\nclass QmlError;\n\nclass QML_PARSER_EXPORT QmlDirParser/' qmldirparser_p.h diff --git a/src/libs/qmljs/parser/qmldirparser_p.h b/src/libs/qmljs/parser/qmldirparser_p.h index c58c03fb8c068b2b9ae958760297dffd3ceb0146..8ab6095c3825116a28abe9cdbf07d102b3f86de3 100644 --- a/src/libs/qmljs/parser/qmldirparser_p.h +++ b/src/libs/qmljs/parser/qmldirparser_p.h @@ -56,11 +56,13 @@ #include <QtCore/QUrl> #include <QtCore/QHash> +#include "qmljsglobal_p.h" + QT_BEGIN_NAMESPACE class QmlError; -class QmlDirParser +class QML_PARSER_EXPORT QmlDirParser { Q_DISABLE_COPY(QmlDirParser) diff --git a/src/libs/qmljs/qmljsdocument.cpp b/src/libs/qmljs/qmljsdocument.cpp index 68693c4772d9b9d96919907070fea914090a852e..6b4f3ed96ba7d7c9b84549da5dc3c4d7d440f67b 100644 --- a/src/libs/qmljs/qmljsdocument.cpp +++ b/src/libs/qmljs/qmljsdocument.cpp @@ -202,6 +202,22 @@ Bind *Document::bind() const return _bind; } +LibraryInfo::LibraryInfo() + : _valid(false) +{ +} + +LibraryInfo::LibraryInfo(const QmlDirParser &parser) + : _valid(true) + , _components(parser.components()) + , _plugins(parser.plugins()) +{ +} + +LibraryInfo::~LibraryInfo() +{ +} + Snapshot::Snapshot() { } @@ -216,6 +232,11 @@ void Snapshot::insert(const Document::Ptr &document) _documents.insert(document->fileName(), document); } +void Snapshot::insertLibraryInfo(const QString &path, const LibraryInfo &info) +{ + _libraries.insert(path, info); +} + Document::Ptr Snapshot::documentFromSource(const QString &code, const QString &fileName) const { diff --git a/src/libs/qmljs/qmljsdocument.h b/src/libs/qmljs/qmljsdocument.h index 126f364e6203ad66259f214957f8c6933bac0f41..fd3742e8b86db3339b4b531b2a12ebb4c41b8c7d 100644 --- a/src/libs/qmljs/qmljsdocument.h +++ b/src/libs/qmljs/qmljsdocument.h @@ -35,6 +35,7 @@ #include <QtCore/QSharedPointer> #include <QtCore/QString> +#include "parser/qmldirparser_p.h" #include "parser/qmljsengine_p.h" #include "qmljs_global.h" @@ -102,10 +103,32 @@ private: friend class Snapshot; }; +class QMLJS_EXPORT LibraryInfo +{ + bool _valid; + QList<QmlDirParser::Component> _components; + QList<QmlDirParser::Plugin> _plugins; + +public: + LibraryInfo(); + LibraryInfo(const QmlDirParser &parser); + ~LibraryInfo(); + + QList<QmlDirParser::Component> components() const + { return _components; } + + QList<QmlDirParser::Plugin> plugins() const + { return _plugins; } + + bool isValid() const + { return _valid; } +}; + class QMLJS_EXPORT Snapshot { typedef QMap<QString, Document::Ptr> _Base; QMap<QString, Document::Ptr> _documents; + QMap<QString, LibraryInfo> _libraries; public: Snapshot(); @@ -118,10 +141,14 @@ public: const_iterator end() const { return _documents.end(); } void insert(const Document::Ptr &document); + void insertLibraryInfo(const QString &path, const LibraryInfo &info); Document::Ptr document(const QString &fileName) const { return _documents.value(fileName); } + LibraryInfo libraryInfo(const QString &path) const + { return _libraries.value(path); } + Document::Ptr documentFromSource(const QString &code, const QString &fileName) const; diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp index f8b184b9c5c55d0e96e6cb40cee148643908c60e..24d417baa87886238828b3fd008b19c3f0564014 100644 --- a/src/libs/qmljs/qmljslink.cpp +++ b/src/libs/qmljs/qmljslink.cpp @@ -1,7 +1,6 @@ #include "qmljslink.h" #include "parser/qmljsast_p.h" -#include "parser/qmldirparser_p.h" #include "qmljsdocument.h" #include "qmljsbind.h" #include "qmljsscopebuilder.h" @@ -289,18 +288,13 @@ void Link::importNonFile(Interpreter::ObjectValue *typeEnv, Document::Ptr doc, A QDir dir(importPath); if (!dir.cd(package)) continue; - if (!dir.exists("qmldir")) - continue; - QFile qmldirFile(dir.filePath("qmldir")); - qmldirFile.open(QFile::ReadOnly); - QString qmldirData = QString::fromUtf8(qmldirFile.readAll()); - QmlDirParser qmldirParser; - qmldirParser.setSource(qmldirData); - qmldirParser.parse(); + const LibraryInfo libraryInfo = _snapshot.libraryInfo(dir.path()); + if (!libraryInfo.isValid()) + continue; QSet<QString> importedTypes; - foreach (const QmlDirParser::Component &component, qmldirParser.components()) { + foreach (const QmlDirParser::Component &component, libraryInfo.components()) { if (importedTypes.contains(component.typeName)) continue; diff --git a/src/plugins/qmljseditor/qmljsmodelmanager.cpp b/src/plugins/qmljseditor/qmljsmodelmanager.cpp index e765b5fa3770204221d04c14204a78e73b938abf..52a781efdd83d2a9f28b8320c5a8f6e5d1971bf6 100644 --- a/src/plugins/qmljseditor/qmljsmodelmanager.cpp +++ b/src/plugins/qmljseditor/qmljsmodelmanager.cpp @@ -36,6 +36,7 @@ #include <coreplugin/progressmanager/progressmanager.h> #include <coreplugin/mimedatabase.h> #include <qmljs/qmljsinterpreter.h> +#include <qmljs/parser/qmldirparser_p.h> #include <texteditor/itexteditor.h> #include <QDir> @@ -62,9 +63,12 @@ ModelManager::ModelManager(QObject *parent): m_synchronizer.setCancelOnWait(true); qRegisterMetaType<QmlJS::Document::Ptr>("QmlJS::Document::Ptr"); + qRegisterMetaType<QmlJS::LibraryInfo>("QmlJS::LibraryInfo"); connect(this, SIGNAL(documentUpdated(QmlJS::Document::Ptr)), this, SLOT(onDocumentUpdated(QmlJS::Document::Ptr))); + connect(this, SIGNAL(libraryInfoUpdated(QString,QmlJS::LibraryInfo)), + this, SLOT(onLibraryInfoUpdated(QString,QmlJS::LibraryInfo))); loadQmlTypeDescriptions(); @@ -197,6 +201,16 @@ void ModelManager::onDocumentUpdated(Document::Ptr doc) _snapshot.insert(doc); } +void ModelManager::emitLibraryInfoUpdated(const QString &path, const LibraryInfo &info) +{ emit libraryInfoUpdated(path, info); } + +void ModelManager::onLibraryInfoUpdated(const QString &path, const LibraryInfo &info) +{ + QMutexLocker locker(&m_mutex); + + _snapshot.insertLibraryInfo(path, info); +} + void ModelManager::parse(QFutureInterface<void> &future, QMap<QString, WorkingCopy> workingCopy, QStringList files, @@ -270,13 +284,33 @@ void ModelManager::parseDirectories(QFutureInterface<void> &future, pattern << glob.pattern(); foreach (const QRegExp &glob, qmlSourceTy.globPatterns()) pattern << glob.pattern(); + pattern << QLatin1String("qmldir"); QStringList importedFiles; + QStringList qmldirFiles; foreach (const QString &path, directories) { QDirIterator fileIterator(path, pattern, QDir::Files, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks); - while (fileIterator.hasNext()) - importedFiles << fileIterator.next(); + while (fileIterator.hasNext()) { + fileIterator.next(); + if (fileIterator.fileName() == QLatin1String("qmldir")) + qmldirFiles << fileIterator.filePath(); + else + importedFiles << fileIterator.filePath(); + } + } + + foreach (const QString &qmldirFilePath, qmldirFiles) { + QFile qmldirFile(qmldirFilePath); + qmldirFile.open(QFile::ReadOnly); + QString qmldirData = QString::fromUtf8(qmldirFile.readAll()); + + QmlDirParser qmldirParser; + qmldirParser.setSource(qmldirData); + qmldirParser.parse(); + + modelManager->emitLibraryInfoUpdated(QFileInfo(qmldirFilePath).path(), + LibraryInfo(qmldirParser)); } parse(future, workingCopy, importedFiles, modelManager); diff --git a/src/plugins/qmljseditor/qmljsmodelmanager.h b/src/plugins/qmljseditor/qmljsmodelmanager.h index aafdc2a89f5ca0b0b58e54509305c5ff53e5d1d2..8ca17240196f19a9e86a89062fc9ca938f738bd7 100644 --- a/src/plugins/qmljseditor/qmljsmodelmanager.h +++ b/src/plugins/qmljseditor/qmljsmodelmanager.h @@ -58,6 +58,7 @@ public: virtual void updateSourceDirectories(const QStringList &directories); void emitDocumentUpdated(QmlJS::Document::Ptr doc); + void emitLibraryInfoUpdated(const QString &path, const QmlJS::LibraryInfo &info); virtual void setProjectImportPaths(const QStringList &importPaths); virtual QStringList importPaths() const; @@ -65,10 +66,12 @@ public: Q_SIGNALS: void projectPathChanged(const QString &projectPath); void aboutToRemoveFiles(const QStringList &files); + void libraryInfoUpdated(const QString &path, const QmlJS::LibraryInfo &info); private Q_SLOTS: // this should be executed in the GUI thread. void onDocumentUpdated(QmlJS::Document::Ptr doc); + void onLibraryInfoUpdated(const QString &path, const QmlJS::LibraryInfo &info); protected: struct WorkingCopy