diff options
| author | Christian Kamm <christian.d.kamm@nokia.com> | 2010-12-03 10:13:15 +0100 |
|---|---|---|
| committer | Christian Kamm <christian.d.kamm@nokia.com> | 2011-01-04 15:58:22 +0100 |
| commit | 0194da7300d3fd76594e337c785566c4498e12f4 (patch) | |
| tree | a27481b214c038f7fc5f140b233d767e5ab1363c /src/plugins/cpptools/cppmodelmanager.cpp | |
| parent | 16542241c91d6a4296bfbd18077de4eff1f43c8b (diff) | |
| download | qt-creator-0194da7300d3fd76594e337c785566c4498e12f4.tar.gz | |
Qml-C++: Find C++ qmlRegisterType calls and populate QML code model.
Reviewed-by: Erik Verbruggen
Diffstat (limited to 'src/plugins/cpptools/cppmodelmanager.cpp')
| -rw-r--r-- | src/plugins/cpptools/cppmodelmanager.cpp | 162 |
1 files changed, 161 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 |
