summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authorChristian Kamm <christian.d.kamm@nokia.com>2010-12-03 10:13:15 +0100
committerChristian Kamm <christian.d.kamm@nokia.com>2011-01-04 15:58:22 +0100
commit0194da7300d3fd76594e337c785566c4498e12f4 (patch)
treea27481b214c038f7fc5f140b233d767e5ab1363c /src/plugins
parent16542241c91d6a4296bfbd18077de4eff1f43c8b (diff)
downloadqt-creator-0194da7300d3fd76594e337c785566c4498e12f4.tar.gz
Qml-C++: Find C++ qmlRegisterType calls and populate QML code model.
Reviewed-by: Erik Verbruggen
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/cpptools/cppmodelmanager.cpp162
-rw-r--r--src/plugins/cpptools/cppmodelmanager.h2
-rw-r--r--src/plugins/qmljstools/qmljsmodelmanager.cpp30
-rw-r--r--src/plugins/qmljstools/qmljsmodelmanager.h8
-rw-r--r--src/plugins/qmljstools/qmljstools_dependencies.pri1
-rw-r--r--src/plugins/qmljstools/qmljstoolsplugin.cpp1
6 files changed, 203 insertions, 1 deletions
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp
index efe8175dcb..19d3530346 100644
--- a/src/plugins/cpptools/cppmodelmanager.cpp
+++ b/src/plugins/cpptools/cppmodelmanager.cpp
@@ -77,6 +77,7 @@
#include <Token.h>
#include <Parser.h>
#include <Control.h>
+#include <CoreTypes.h>
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
@@ -290,6 +291,8 @@ public:
void operator()()
{
_doc->check(_mode);
+ _doc->findExposedQmlTypes();
+ _doc->releaseSource();
_doc->releaseTranslationUnit();
if (_mode == Document::FastCheck)
@@ -589,7 +592,6 @@ void CppPreprocessor::sourceNeeded(QString &fileName, IncludeType type, unsigned
doc->setSource(preprocessedCode);
doc->tokenize();
- doc->releaseSource();
snapshot.insert(doc);
m_todo.remove(fileName);
@@ -601,6 +603,7 @@ void CppPreprocessor::sourceNeeded(QString &fileName, IncludeType type, unsigned
(void) switchDocument(previousDoc);
#else
+ doc->releaseSource();
Document::CheckMode mode = Document::FastCheck;
mode = Document::FullCheck;
doc->parse();
@@ -1418,5 +1421,162 @@ void CppModelManager::GC()
protectSnapshot.unlock();
}
+static FullySpecifiedType stripPointerAndReference(const FullySpecifiedType &type)
+{
+ Type *t = type.type();
+ while (t) {
+ if (PointerType *ptr = t->asPointerType())
+ t = ptr->elementType().type();
+ else if (ReferenceType *ref = t->asReferenceType())
+ t = ref->elementType().type();
+ else
+ break;
+ }
+ return FullySpecifiedType(t);
+}
+
+static QString toQmlType(const FullySpecifiedType &type)
+{
+ Overview overview;
+ QString result = overview(stripPointerAndReference(type));
+ if (result == QLatin1String("QString"))
+ result = QLatin1String("string");
+ return result;
+}
+
+static Class *lookupClass(const QString &expression, Scope *scope, TypeOfExpression &typeOf)
+{
+ QList<LookupItem> results = typeOf(expression, scope);
+ Class *klass = 0;
+ foreach (const LookupItem &item, results) {
+ if (item.declaration()) {
+ klass = item.declaration()->asClass();
+ if (klass)
+ return klass;
+ }
+ }
+ return 0;
+}
+
+static void populate(LanguageUtils::FakeMetaObject *fmo, Class *klass,
+ QHash<Class *, LanguageUtils::FakeMetaObject *> *classes,
+ TypeOfExpression &typeOf)
+{
+ using namespace LanguageUtils;
+
+ Overview namePrinter;
+
+ classes->insert(klass, fmo);
+
+ for (unsigned i = 0; i < klass->memberCount(); ++i) {
+ Symbol *member = klass->memberAt(i);
+ if (!member->name())
+ continue;
+ if (Function *func = member->type()->asFunctionType()) {
+ if (!func->isSlot() && !func->isInvokable() && !func->isSignal())
+ continue;
+ FakeMetaMethod method(namePrinter(func->name()), toQmlType(func->returnType()));
+ if (func->isSignal())
+ method.setMethodType(FakeMetaMethod::Signal);
+ else
+ method.setMethodType(FakeMetaMethod::Slot);
+ for (unsigned a = 0; a < func->argumentCount(); ++a) {
+ Symbol *arg = func->argumentAt(a);
+ QString name(CppModelManager::tr("unnamed"));
+ if (arg->name())
+ name = namePrinter(arg->name());
+ method.addParameter(name, toQmlType(arg->type()));
+ }
+ fmo->addMethod(method);
+ }
+ if (QtPropertyDeclaration *propDecl = member->asQtPropertyDeclaration()) {
+ const FullySpecifiedType &type = propDecl->type();
+ const bool isList = false; // ### fixme
+ const bool isWritable = propDecl->flags() & QtPropertyDeclaration::WriteFunction;
+ const bool isPointer = type.type() && type.type()->isPointerType();
+ FakeMetaProperty property(
+ namePrinter(propDecl->name()),
+ toQmlType(type),
+ isList, isWritable, isPointer);
+ fmo->addProperty(property);
+ }
+ if (QtEnum *qtEnum = member->asQtEnum()) {
+ // find the matching enum
+ Enum *e = 0;
+ QList<LookupItem> result = typeOf(namePrinter(qtEnum->name()), klass);
+ foreach (const LookupItem &item, result) {
+ if (item.declaration()) {
+ e = item.declaration()->asEnum();
+ if (e)
+ break;
+ }
+ }
+ if (!e)
+ continue;
+
+ FakeMetaEnum metaEnum(namePrinter(e->name()));
+ for (unsigned j = 0; j < e->memberCount(); ++j) {
+ Symbol *enumMember = e->memberAt(j);
+ if (!enumMember->name())
+ continue;
+ metaEnum.addKey(namePrinter(enumMember->name()), 0);
+ }
+ fmo->addEnum(metaEnum);
+ }
+ }
+
+ // only single inheritance is supported
+ if (klass->baseClassCount() > 0) {
+ BaseClass *base = klass->baseClassAt(0);
+ if (!base->name())
+ return;
+
+ const QString baseClassName = namePrinter(base->name());
+ fmo->setSuperclassName(baseClassName);
+
+ Class *baseClass = lookupClass(baseClassName, klass, typeOf);
+ if (!baseClass)
+ return;
+
+ FakeMetaObject *baseFmo = classes->value(baseClass);
+ if (!baseFmo) {
+ baseFmo = new FakeMetaObject;
+ populate(baseFmo, baseClass, classes, typeOf);
+ }
+ fmo->setSuperclass(baseFmo);
+ }
+}
+
+QList<LanguageUtils::FakeMetaObject *> CppModelManager::exportedQmlObjects() const
+{
+ using namespace LanguageUtils;
+ QList<FakeMetaObject *> exportedObjects;
+ QHash<Class *, FakeMetaObject *> classes;
+
+ const Snapshot currentSnapshot = snapshot();
+ foreach (Document::Ptr doc, currentSnapshot) {
+ TypeOfExpression typeOf;
+ typeOf.init(doc, currentSnapshot);
+ foreach (const Document::ExportedQmlType &exportedType, doc->exportedQmlTypes()) {
+ FakeMetaObject *fmo = new FakeMetaObject;
+ fmo->addExport(exportedType.typeName, exportedType.packageName,
+ ComponentVersion(exportedType.majorVersion, exportedType.minorVersion));
+ exportedObjects += fmo;
+
+ Class *klass = lookupClass(exportedType.typeExpression, exportedType.scope, typeOf);
+ if (!klass)
+ continue;
+
+ // add the no-package export, so the cpp name can be used in properties
+ Overview overview;
+ fmo->addExport(overview(klass->name()), QString(), ComponentVersion());
+
+ populate(fmo, klass, &classes, typeOf);
+ }
+ }
+
+ return exportedObjects;
+}
+
#endif
diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h
index 865421a16e..bd0bef0962 100644
--- a/src/plugins/cpptools/cppmodelmanager.h
+++ b/src/plugins/cpptools/cppmodelmanager.h
@@ -131,6 +131,8 @@ public:
virtual void findMacroUsages(const CPlusPlus::Macro &macro);
+ virtual QList<LanguageUtils::FakeMetaObject *> exportedQmlObjects() const;
+
void setHeaderSuffixes(const QStringList &suffixes)
{ m_headerSuffixes = suffixes; }
diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp
index 69f43c5579..0477f9ed01 100644
--- a/src/plugins/qmljstools/qmljsmodelmanager.cpp
+++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp
@@ -39,6 +39,7 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/mimedatabase.h>
+#include <cplusplus/ModelManagerInterface.h>
#include <qmljs/qmljsinterpreter.h>
#include <qmljs/qmljsbind.h>
#include <qmljs/parser/qmldirparser_p.h>
@@ -56,6 +57,7 @@
#include <qtconcurrent/runextensions.h>
#include <QTextStream>
#include <QCoreApplication>
+#include <QTimer>
#include <QDebug>
@@ -72,6 +74,11 @@ ModelManager::ModelManager(QObject *parent):
{
m_synchronizer.setCancelOnWait(true);
+ m_updateCppQmlTypesTimer = new QTimer(this);
+ m_updateCppQmlTypesTimer->setInterval(1000);
+ m_updateCppQmlTypesTimer->setSingleShot(true);
+ connect(m_updateCppQmlTypesTimer, SIGNAL(timeout()), SLOT(updateCppQmlTypes()));
+
qRegisterMetaType<QmlJS::Document::Ptr>("QmlJS::Document::Ptr");
qRegisterMetaType<QmlJS::LibraryInfo>("QmlJS::LibraryInfo");
@@ -81,6 +88,16 @@ ModelManager::ModelManager(QObject *parent):
updateImportPaths();
}
+void ModelManager::delayedInitialization()
+{
+ CPlusPlus::CppModelManagerInterface *cppModelManager =
+ CPlusPlus::CppModelManagerInterface::instance();
+ if (cppModelManager) {
+ connect(cppModelManager, SIGNAL(documentUpdated(CPlusPlus::Document::Ptr)),
+ m_updateCppQmlTypesTimer, SLOT(start()));
+ }
+}
+
void ModelManager::loadQmlTypeDescriptions()
{
if (Core::ICore::instance()) {
@@ -537,3 +554,16 @@ void ModelManager::loadPluginTypes(const QString &libraryPath, const QString &im
{
m_pluginDumper->loadPluginTypes(libraryPath, importPath, importUri);
}
+
+void ModelManager::updateCppQmlTypes()
+{
+ CPlusPlus::CppModelManagerInterface *cppModelManager =
+ CPlusPlus::CppModelManagerInterface::instance();
+ if (!cppModelManager)
+ return;
+
+ QList<const LanguageUtils::FakeMetaObject *> constFMOs;
+ foreach (LanguageUtils::FakeMetaObject *fmo, cppModelManager->exportedQmlObjects())
+ constFMOs.append(fmo);
+ Interpreter::CppQmlTypesLoader::cppObjects = constFMOs;
+}
diff --git a/src/plugins/qmljstools/qmljsmodelmanager.h b/src/plugins/qmljstools/qmljsmodelmanager.h
index a80f18cdca..1a0b4c2833 100644
--- a/src/plugins/qmljstools/qmljsmodelmanager.h
+++ b/src/plugins/qmljstools/qmljsmodelmanager.h
@@ -44,6 +44,8 @@
#include <QMutex>
#include <QProcess>
+QT_FORWARD_DECLARE_CLASS(QTimer)
+
namespace Core {
class ICore;
class MimeType;
@@ -61,6 +63,8 @@ class QMLJSTOOLS_EXPORT ModelManager: public QmlJS::ModelManagerInterface
public:
ModelManager(QObject *parent = 0);
+ void delayedInitialization();
+
virtual WorkingCopy workingCopy() const;
virtual QmlJS::Snapshot snapshot() const;
@@ -99,6 +103,9 @@ protected:
void updateImportPaths();
+private slots:
+ void updateCppQmlTypes();
+
private:
static bool matchesMimeType(const Core::MimeType &fileMimeType, const Core::MimeType &knownMimeType);
@@ -109,6 +116,7 @@ private:
QStringList m_defaultImportPaths;
QFutureSynchronizer<void> m_synchronizer;
+ QTimer *m_updateCppQmlTypesTimer;
// project integration
QMap<ProjectExplorer::Project *, ProjectInfo> m_projects;
diff --git a/src/plugins/qmljstools/qmljstools_dependencies.pri b/src/plugins/qmljstools/qmljstools_dependencies.pri
index d63c784082..c94524e75c 100644
--- a/src/plugins/qmljstools/qmljstools_dependencies.pri
+++ b/src/plugins/qmljstools/qmljstools_dependencies.pri
@@ -1,4 +1,5 @@
include($$IDE_SOURCE_TREE/src/libs/languageutils/languageutils.pri)
+include($$IDE_SOURCE_TREE/src/libs/cplusplus/cplusplus.pri)
include($$IDE_SOURCE_TREE/src/libs/qmljs/qmljs.pri)
include($$IDE_SOURCE_TREE/src/plugins/projectexplorer/projectexplorer.pri)
include($$IDE_SOURCE_TREE/src/plugins/texteditor/texteditor.pri)
diff --git a/src/plugins/qmljstools/qmljstoolsplugin.cpp b/src/plugins/qmljstools/qmljstoolsplugin.cpp
index c1f0e91e6b..3a456eed75 100644
--- a/src/plugins/qmljstools/qmljstoolsplugin.cpp
+++ b/src/plugins/qmljstools/qmljstoolsplugin.cpp
@@ -89,6 +89,7 @@ bool QmlJSToolsPlugin::initialize(const QStringList &arguments, QString *error)
void QmlJSToolsPlugin::extensionsInitialized()
{
+ m_modelManager->delayedInitialization();
}
ExtensionSystem::IPlugin::ShutdownFlag QmlJSToolsPlugin::aboutToShutdown()