diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index 9714bbf11ac00659e26a64cd2d574c203a1ad792..7113e5db06a58d88b4964e95638d40d53aaae4d7 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -256,7 +256,8 @@ Document::Document(const QString &fileName) : _fileName(QDir::cleanPath(fileName)), _globalNamespace(0), _revision(0), - _editorRevision(0) + _editorRevision(0), + _checkMode(0) { _control = new Control(); @@ -569,6 +570,8 @@ void Document::check(CheckMode mode) { Q_ASSERT(!_globalNamespace); + _checkMode = mode; + if (! isParsed()) parse(); diff --git a/src/libs/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h index 3be9dbe6cb27860790cded13eff95c76a03c6d00..7e475912a2cf5ffce84f4dd81726dfff37a61c93 100644 --- a/src/libs/cplusplus/CppDocument.h +++ b/src/libs/cplusplus/CppDocument.h @@ -120,6 +120,7 @@ public: bool parse(ParseMode mode = ParseTranlationUnit); enum CheckMode { + Unchecked, FullCheck, FastCheck }; @@ -322,6 +323,9 @@ public: void keepSourceAndAST(); void releaseSourceAndAST(); + CheckMode checkMode() const + { return static_cast<CheckMode>(_checkMode); } + private: QString _fileName; Control *_control; @@ -338,6 +342,7 @@ private: QAtomicInt _keepSourceAndASTCount; unsigned _revision; unsigned _editorRevision; + quint8 _checkMode; friend class Snapshot; }; diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp index d43dbbe05c655464bf51f13793d200ae4c16f1ba..62cec1aaebec8b3317b63f17546174bbf13accf4 100644 --- a/src/libs/qmljs/qmljslink.cpp +++ b/src/libs/qmljs/qmljslink.cpp @@ -120,11 +120,29 @@ Link::Link(const Snapshot &snapshot, const QStringList &importPaths, const Libra d->diagnosticMessages = 0; d->allDiagnosticMessages = 0; - // populate engine with types from C++ ModelManagerInterface *modelManager = ModelManagerInterface::instance(); if (modelManager) { - foreach (const QList<FakeMetaObject::ConstPtr> &cppTypes, modelManager->cppQmlTypes()) { - d->valueOwner->cppQmlTypes().load(d->valueOwner, cppTypes); + ModelManagerInterface::CppDataHash cppDataHash = modelManager->cppData(); + + // populate engine with types from C++ + foreach (const ModelManagerInterface::CppData &cppData, cppDataHash) { + d->valueOwner->cppQmlTypes().load(d->valueOwner, cppData.exportedTypes); + } + + // populate global object with context properties from C++ + ObjectValue *global = d->valueOwner->globalObject(); + foreach (const ModelManagerInterface::CppData &cppData, cppDataHash) { + QMapIterator<QString, QString> it(cppData.contextProperties); + while (it.hasNext()) { + it.next(); + const Value *value = 0; + const QString cppTypeName = it.value(); + if (!cppTypeName.isEmpty()) + value = d->valueOwner->cppQmlTypes().typeByCppName(cppTypeName); + if (!value) + value = d->valueOwner->undefinedValue(); + global->setMember(it.key(), value); + } } } } diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h index 891350c68a79581e84a2b3e0db19dd82a0c25518..c848d8e6adcd72cd110b7781f558fb6ad3eb35cf 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.h +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h @@ -110,7 +110,14 @@ public: Table _elements; }; - typedef QHash<QString, QList<LanguageUtils::FakeMetaObject::ConstPtr> > CppQmlTypeHash; + class CppData + { + public: + QList<LanguageUtils::FakeMetaObject::ConstPtr> exportedTypes; + QMap<QString, QString> contextProperties; + }; + + typedef QHash<QString, CppData> CppDataHash; public: ModelManagerInterface(QObject *parent = 0); @@ -138,7 +145,7 @@ public: virtual void loadPluginTypes(const QString &libraryPath, const QString &importPath, const QString &importUri, const QString &importVersion) = 0; - virtual CppQmlTypeHash cppQmlTypes() const = 0; + virtual CppDataHash cppData() const = 0; virtual LibraryInfo builtins(const Document::Ptr &doc) const = 0; diff --git a/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp b/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp index 786e23d83acdffc8733dece413c450c19ca2c9a8..a35ac471bccca00819fc7cfd440300b5d05e10cc 100644 --- a/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp +++ b/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp @@ -64,10 +64,18 @@ public: QString typeExpression; }; +class ContextProperty { +public: + QString name; + QString expression; + unsigned line, column; +}; + class FindExportsVisitor : protected ASTVisitor { CPlusPlus::Document::Ptr _doc; QList<ExportedQmlType> _exportedTypes; + QList<ContextProperty> _contextProperties; CompoundStatementAST *_compound; ASTMatcher _matcher; ASTPatternBuilder _builder; @@ -81,11 +89,11 @@ public: , _compound(0) {} - QList<ExportedQmlType> operator()() + void operator()() { _exportedTypes.clear(); + _contextProperties.clear(); accept(translationUnit()->ast()); - return _exportedTypes; } QList<Document::DiagnosticMessage> messages() const @@ -93,6 +101,16 @@ public: return _messages; } + QList<ExportedQmlType> exportedTypes() const + { + return _exportedTypes; + } + + QList<ContextProperty> contextProperties() const + { + return _contextProperties; + } + protected: virtual bool visit(CompoundStatementAST *ast) { @@ -104,6 +122,14 @@ protected: } virtual bool visit(CallAST *ast) + { + if (checkForQmlRegisterType(ast)) + return false; + checkForSetContextProperty(ast); + return false; + } + + bool checkForQmlRegisterType(CallAST *ast) { IdExpressionAST *idExp = ast->base_expression->asIdExpression(); if (!idExp || !idExp->name) @@ -139,7 +165,7 @@ protected: // last argument must be a string literal const StringLiteral *nameLit = 0; - if (StringLiteralAST *nameAst = ast->expression_list->next->next->next->value->asStringLiteral()) + if (StringLiteralAST *nameAst = skipStringCall(ast->expression_list->next->next->next->value)->asStringLiteral()) nameLit = translationUnit()->stringLiteral(nameAst->literal_token); if (!nameLit) { unsigned line, column; @@ -155,7 +181,7 @@ protected: // if the first argument is a string literal, things are easy QString packageName; - if (StringLiteralAST *packageAst = ast->expression_list->value->asStringLiteral()) { + if (StringLiteralAST *packageAst = skipStringCall(ast->expression_list->value)->asStringLiteral()) { const StringLiteral *packageLit = translationUnit()->stringLiteral(packageAst->literal_token); packageName = QString::fromUtf8(packageLit->chars(), packageLit->size()); } @@ -242,7 +268,118 @@ protected: _exportedTypes += exportedType; - return false; + return true; + } + + static NameAST *callName(ExpressionAST *exp) + { + if (IdExpressionAST *idExp = exp->asIdExpression()) + return idExp->name; + if (MemberAccessAST *memberExp = exp->asMemberAccess()) + return memberExp->member_name; + return 0; + } + + static ExpressionAST *skipQVariant(ExpressionAST *ast, TranslationUnit *translationUnit) + { + CallAST *call = ast->asCall(); + if (!call) + return ast; + if (!call->expression_list + || !call->expression_list->value + || call->expression_list->next) + return ast; + + IdExpressionAST *idExp = call->base_expression->asIdExpression(); + if (!idExp || !idExp->name) + return ast; + + // QVariant(foo) -> foo + if (SimpleNameAST *simpleName = idExp->name->asSimpleName()) { + const Identifier *id = translationUnit->identifier(simpleName->identifier_token); + if (!id) + return ast; + if (QString::fromUtf8(id->chars(), id->size()) != QLatin1String("QVariant")) + return ast; + return call->expression_list->value; + } + // QVariant::fromValue(foo) -> foo + else if (QualifiedNameAST *q = idExp->name->asQualifiedName()) { + SimpleNameAST *simpleRhsName = q->unqualified_name->asSimpleName(); + if (!simpleRhsName + || !q->nested_name_specifier_list + || !q->nested_name_specifier_list->value + || q->nested_name_specifier_list->next) + return ast; + const Identifier *rhsId = translationUnit->identifier(simpleRhsName->identifier_token); + if (!rhsId) + return ast; + if (QString::fromUtf8(rhsId->chars(), rhsId->size()) != QLatin1String("fromValue")) + return ast; + NestedNameSpecifierAST *nested = q->nested_name_specifier_list->value; + SimpleNameAST *simpleLhsName = nested->class_or_namespace_name->asSimpleName(); + if (!simpleLhsName) + return ast; + const Identifier *lhsId = translationUnit->identifier(simpleLhsName->identifier_token); + if (!lhsId) + return ast; + if (QString::fromUtf8(lhsId->chars(), lhsId->size()) != QLatin1String("QVariant")) + return ast; + return call->expression_list->value; + } + + return ast; + } + + bool checkForSetContextProperty(CallAST *ast) + { + // check whether ast->base_expression has the 'setContextProperty' name + NameAST *callNameAst = callName(ast->base_expression); + if (!callNameAst) + return false; + SimpleNameAST *simpleNameAst = callNameAst->asSimpleName(); + if (!simpleNameAst || !simpleNameAst->identifier_token) + return false; + const Identifier *nameIdentifier = translationUnit()->identifier(simpleNameAst->identifier_token); + if (!nameIdentifier) + return false; + const QString callName = QString::fromUtf8(nameIdentifier->chars(), nameIdentifier->size()); + if (callName != QLatin1String("setContextProperty")) + return false; + + // must have two arguments + if (!ast->expression_list + || !ast->expression_list->value || !ast->expression_list->next + || !ast->expression_list->next->value || ast->expression_list->next->next) + return false; + + // first argument must be a string literal + const StringLiteral *nameLit = 0; + if (StringLiteralAST *nameAst = skipStringCall(ast->expression_list->value)->asStringLiteral()) + nameLit = translationUnit()->stringLiteral(nameAst->literal_token); + if (!nameLit) { + unsigned line, column; + translationUnit()->getTokenStartPosition(ast->expression_list->value->firstToken(), &line, &column); + _messages += Document::DiagnosticMessage( + Document::DiagnosticMessage::Warning, + _doc->fileName(), + line, column, + FindExportedCppTypes::tr( + "must be a string literal to be available in qml editor")); + return false; + } + + ContextProperty contextProperty; + contextProperty.name = QString::fromUtf8(nameLit->chars(), nameLit->size()); + contextProperty.expression = stringOf(skipQVariant(ast->expression_list->next->value, translationUnit())); + // we want to do lookup later, so also store the line and column of the target scope + translationUnit()->getTokenStartPosition(ast->firstToken(), + &contextProperty.line, + &contextProperty.column); + + _contextProperties += contextProperty; + + return true; } private: @@ -265,8 +402,8 @@ private: ExpressionAST *skipStringCall(ExpressionAST *exp) { - if (!exp) - return 0; + if (!exp || !exp->asCall()) + return exp; IdExpressionAST *callName = _builder.IdExpression(); CallAST *call = _builder.Call(callName); @@ -381,15 +518,26 @@ static Class *lookupClass(const QString &expression, Scope *scope, TypeOfExpress return 0; } -static void populate(LanguageUtils::FakeMetaObject::Ptr fmo, Class *klass, - QHash<Class *, LanguageUtils::FakeMetaObject::Ptr> *classes, - TypeOfExpression &typeOf) +static LanguageUtils::FakeMetaObject::Ptr buildFakeMetaObject( + Class *klass, + QHash<Class *, LanguageUtils::FakeMetaObject::Ptr> *fakeMetaObjects, + TypeOfExpression &typeOf) { using namespace LanguageUtils; + if (FakeMetaObject::Ptr fmo = fakeMetaObjects->value(klass)) + return fmo; + + FakeMetaObject::Ptr fmo(new FakeMetaObject); + if (!klass) + return fmo; + fakeMetaObjects->insert(klass, fmo); + Overview namePrinter; - classes->insert(klass, fmo); + fmo->setClassName(namePrinter(klass->name())); + // add the no-package export, so the cpp name can be used in properties + fmo->addExport(fmo->className(), QmlJS::CppQmlTypes::cppPackage, ComponentVersion()); for (unsigned i = 0; i < klass->memberCount(); ++i) { Symbol *member = klass->memberAt(i); @@ -454,56 +602,74 @@ static void populate(LanguageUtils::FakeMetaObject::Ptr fmo, Class *klass, if (klass->baseClassCount() > 0) { BaseClass *base = klass->baseClassAt(0); if (!base->name()) - return; + return fmo; const QString baseClassName = namePrinter(base->name()); fmo->setSuperclassName(baseClassName); Class *baseClass = lookupClass(baseClassName, klass, typeOf); if (!baseClass) - return; + return fmo; - FakeMetaObject::Ptr baseFmo = classes->value(baseClass); - if (!baseFmo) { - baseFmo = FakeMetaObject::Ptr(new FakeMetaObject); - populate(baseFmo, baseClass, classes, typeOf); - } + buildFakeMetaObject(baseClass, fakeMetaObjects, typeOf); } + + return fmo; } -QList<LanguageUtils::FakeMetaObject::ConstPtr> exportedQmlObjects( - const Document::Ptr &doc, - const Snapshot &snapshot, - const QList<ExportedQmlType> &exportedTypes) +static void buildExportedQmlObjects( + TypeOfExpression &typeOf, + const QList<ExportedQmlType> &cppExports, + QHash<Class *, LanguageUtils::FakeMetaObject::Ptr> *fakeMetaObjects) { using namespace LanguageUtils; - QList<FakeMetaObject::ConstPtr> exportedObjects; - QHash<Class *, FakeMetaObject::Ptr> classes; - if (exportedTypes.isEmpty()) - return exportedObjects; + if (cppExports.isEmpty()) + return; - TypeOfExpression typeOf; - typeOf.init(doc, snapshot); - foreach (const ExportedQmlType &exportedType, exportedTypes) { - FakeMetaObject::Ptr fmo(new FakeMetaObject); + foreach (const ExportedQmlType &exportedType, cppExports) { + Class *klass = lookupClass(exportedType.typeExpression, exportedType.scope, typeOf); + // accepts a null klass + FakeMetaObject::Ptr fmo = buildFakeMetaObject(klass, fakeMetaObjects, typeOf); fmo->addExport(exportedType.typeName, exportedType.packageName, exportedType.version); - exportedObjects += fmo; + } +} - Class *klass = lookupClass(exportedType.typeExpression, exportedType.scope, typeOf); - if (!klass) - continue; +static void buildContextProperties( + const Document::Ptr &doc, + TypeOfExpression &typeOf, + const QList<ContextProperty> &contextPropertyDescriptions, + QHash<Class *, LanguageUtils::FakeMetaObject::Ptr> *fakeMetaObjects, + QMap<QString, QString> *contextProperties) +{ + using namespace LanguageUtils; - // add the no-package export, so the cpp name can be used in properties - Overview overview; - fmo->addExport(overview(klass->name()), QmlJS::CppQmlTypes::cppPackage, ComponentVersion()); + foreach (const ContextProperty &property, contextPropertyDescriptions) { + Scope *scope = doc->scopeAt(property.line, property.column); + QList<LookupItem> results = typeOf(property.expression, scope); + QString typeName; + if (!results.isEmpty()) { + LookupItem result = results.first(); + FullySpecifiedType simpleType = stripPointerAndReference(result.type()); + if (NamedType *namedType = simpleType.type()->asNamedType()) { + Scope *typeScope = result.scope(); + if (!typeScope) + typeScope = scope; // incorrect but may be an ok fallback + ClassOrNamespace *binding = typeOf.context().lookupType(namedType->name(), typeScope); + if (binding && !binding->symbols().isEmpty()) { + Class *klass = binding->symbols().first()->asClass(); + if (klass) { + FakeMetaObject::Ptr fmo = buildFakeMetaObject(klass, fakeMetaObjects, typeOf); + typeName = fmo->className(); + } + } + } + } - populate(fmo, klass, &classes, typeOf); + contextProperties->insert(property.name, typeName); } - - return exportedObjects; } } // anonymous namespace @@ -513,26 +679,65 @@ FindExportedCppTypes::FindExportedCppTypes(const CPlusPlus::Snapshot &snapshot) { } -QList<LanguageUtils::FakeMetaObject::ConstPtr> FindExportedCppTypes::operator()(const CPlusPlus::Document::Ptr &document) +void FindExportedCppTypes::operator()(const CPlusPlus::Document::Ptr &document) { - QList<LanguageUtils::FakeMetaObject::ConstPtr> noResults; + m_contextProperties.clear(); + m_exportedTypes.clear(); + // this check only guards against some input errors, if document's source and AST has not // been guarded properly the source and AST may still become empty/null while this function is running if (document->source().isEmpty() || !document->translationUnit()->ast()) - return noResults; + return; FindExportsVisitor finder(document); - QList<ExportedQmlType> exports = finder(); + finder(); if (CppModelManagerInterface *cppModelManager = CppModelManagerInterface::instance()) { cppModelManager->setExtraDiagnostics( document->fileName(), CppModelManagerInterface::ExportedQmlTypesDiagnostic, finder.messages()); } - if (exports.isEmpty()) - return noResults; - return exportedQmlObjects(document, m_snapshot, exports); + // if nothing was found, done + const QList<ContextProperty> contextPropertyDescriptions = finder.contextProperties(); + const QList<ExportedQmlType> exports = finder.exportedTypes(); + if (exports.isEmpty() && contextPropertyDescriptions.isEmpty()) + return; + + // context properties need lookup inside function scope, and thus require a full check + Document::Ptr localDoc = document; + if (document->checkMode() != Document::FullCheck && !contextPropertyDescriptions.isEmpty()) { + localDoc = m_snapshot.documentFromSource(document->source(), document->fileName()); + localDoc->check(); + } + + // create a single type of expression (and bindings) for the document + TypeOfExpression typeOf; + typeOf.init(localDoc, m_snapshot); + QHash<Class *, LanguageUtils::FakeMetaObject::Ptr> fakeMetaObjects; + + // generate the exports from qmlRegisterType + buildExportedQmlObjects(typeOf, exports, &fakeMetaObjects); + + // add the types from the context properties and create a name->cppname map + // also expose types where necessary + buildContextProperties(localDoc, typeOf, contextPropertyDescriptions, + &fakeMetaObjects, &m_contextProperties); + + // convert to list of FakeMetaObject::ConstPtr + m_exportedTypes.reserve(fakeMetaObjects.size()); + foreach (const LanguageUtils::FakeMetaObject::Ptr &fmo, fakeMetaObjects) + m_exportedTypes += fmo; +} + +QList<LanguageUtils::FakeMetaObject::ConstPtr> FindExportedCppTypes::exportedTypes() const +{ + return m_exportedTypes; +} + +QMap<QString, QString> FindExportedCppTypes::contextProperties() const +{ + return m_contextProperties; } bool FindExportedCppTypes::maybeExportsTypes(const Document::Ptr &document) @@ -540,9 +745,14 @@ bool FindExportedCppTypes::maybeExportsTypes(const Document::Ptr &document) if (!document->control()) return false; const QByteArray qmlRegisterTypeToken("qmlRegisterType"); + const QByteArray setContextPropertyToken("setContextProperty"); if (document->control()->findIdentifier( qmlRegisterTypeToken.constData(), qmlRegisterTypeToken.size())) { return true; } + if (document->control()->findIdentifier( + setContextPropertyToken.constData(), setContextPropertyToken.size())) { + return true; + } return false; } diff --git a/src/plugins/qmljstools/qmljsfindexportedcpptypes.h b/src/plugins/qmljstools/qmljsfindexportedcpptypes.h index 2814441ceed627cc19d347ebc4608a7247968c4b..a2033914d316ca3b3c9da0ca5b6c6e220480160b 100644 --- a/src/plugins/qmljstools/qmljsfindexportedcpptypes.h +++ b/src/plugins/qmljstools/qmljsfindexportedcpptypes.h @@ -37,6 +37,7 @@ #include <languageutils/fakemetaobject.h> #include <QtCore/QCoreApplication> +#include <QtCore/QMap> namespace QmlJSTools { @@ -47,12 +48,17 @@ public: FindExportedCppTypes(const CPlusPlus::Snapshot &snapshot); // document must have a valid source and ast for the duration of the call - QList<LanguageUtils::FakeMetaObject::ConstPtr> operator()(const CPlusPlus::Document::Ptr &document); + void operator()(const CPlusPlus::Document::Ptr &document); + + QList<LanguageUtils::FakeMetaObject::ConstPtr> exportedTypes() const; + QMap<QString, QString> contextProperties() const; static bool maybeExportsTypes(const CPlusPlus::Document::Ptr &document); private: CPlusPlus::Snapshot m_snapshot; + QList<LanguageUtils::FakeMetaObject::ConstPtr> m_exportedTypes; + QMap<QString, QString> m_contextProperties; }; } // namespace QmlJSTools diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp index f06a49c11284fc9bb4a47c324f83ab1f62654740..054776c18429bbf3e26e2133c113e4ed1e91cdb3 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.cpp +++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp @@ -717,7 +717,8 @@ void ModelManager::updateCppQmlTypes(ModelManager *qmlModelManager, CPlusPlus::CppModelManagerInterface *cppModelManager, QMap<QString, QPair<CPlusPlus::Document::Ptr, bool> > documents) { - CppQmlTypeHash newCppTypes = qmlModelManager->cppQmlTypes(); + CppDataHash newData = qmlModelManager->cppData(); + CPlusPlus::Snapshot snapshot = cppModelManager->snapshot(); FindExportedCppTypes finder(snapshot); @@ -727,28 +728,33 @@ void ModelManager::updateCppQmlTypes(ModelManager *qmlModelManager, const bool scan = pair.second; const QString fileName = doc->fileName(); if (!scan) { - newCppTypes.remove(fileName); + newData.remove(fileName); continue; } - QList<LanguageUtils::FakeMetaObject::ConstPtr> exported = finder(doc); + finder(doc); - if (!exported.isEmpty()) - newCppTypes[fileName] = exported; - else - newCppTypes.remove(fileName); + QList<LanguageUtils::FakeMetaObject::ConstPtr> exported = finder.exportedTypes(); + QMap<QString, QString> contextProperties = finder.contextProperties(); + if (exported.isEmpty() && contextProperties.isEmpty()) { + newData.remove(fileName); + } else { + CppData &data = newData[fileName]; + data.exportedTypes = exported; + data.contextProperties = contextProperties; + } doc->releaseSourceAndAST(); } - QMutexLocker locker(&qmlModelManager->m_cppTypesMutex); - qmlModelManager->m_cppTypes = newCppTypes; + QMutexLocker locker(&qmlModelManager->m_cppDataMutex); + qmlModelManager->m_cppDataHash = newData; } -ModelManagerInterface::CppQmlTypeHash ModelManager::cppQmlTypes() const +ModelManager::CppDataHash ModelManager::cppData() const { - QMutexLocker locker(&m_cppTypesMutex); - return m_cppTypes; + QMutexLocker locker(&m_cppDataMutex); + return m_cppDataHash; } LibraryInfo ModelManager::builtins(const Document::Ptr &doc) const diff --git a/src/plugins/qmljstools/qmljsmodelmanager.h b/src/plugins/qmljstools/qmljsmodelmanager.h index fd00825a889e42a2163475fa514ee87a3b86879d..4fd79063b99b51a1b5c7dbb2bd401c795d721a9b 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.h +++ b/src/plugins/qmljstools/qmljsmodelmanager.h @@ -91,7 +91,7 @@ public: virtual void loadPluginTypes(const QString &libraryPath, const QString &importPath, const QString &importUri, const QString &importVersion); - virtual CppQmlTypeHash cppQmlTypes() const; + virtual CppDataHash cppData() const; virtual QmlJS::LibraryInfo builtins(const QmlJS::Document::Ptr &doc) const; @@ -140,8 +140,9 @@ private: QTimer *m_updateCppQmlTypesTimer; QMap<QString, QPair<CPlusPlus::Document::Ptr, bool> > m_queuedCppDocuments; - CppQmlTypeHash m_cppTypes; - mutable QMutex m_cppTypesMutex; + + CppDataHash m_cppDataHash; + mutable QMutex m_cppDataMutex; // project integration QMap<ProjectExplorer::Project *, ProjectInfo> m_projects;