forked from qt-creator/qt-creator
Qml-C++: Find C++ qmlRegisterType calls and populate QML code model.
Reviewed-by: Erik Verbruggen
This commit is contained in:
@@ -585,6 +585,122 @@ void Document::check(CheckMode mode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FindExposedQmlTypes : protected ASTVisitor
|
||||||
|
{
|
||||||
|
Document *_doc;
|
||||||
|
QList<Document::ExportedQmlType> _exportedTypes;
|
||||||
|
public:
|
||||||
|
FindExposedQmlTypes(Document *doc)
|
||||||
|
: ASTVisitor(doc->translationUnit())
|
||||||
|
, _doc(doc)
|
||||||
|
{}
|
||||||
|
|
||||||
|
QList<Document::ExportedQmlType> operator()()
|
||||||
|
{
|
||||||
|
_exportedTypes.clear();
|
||||||
|
accept(translationUnit()->ast());
|
||||||
|
return _exportedTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool visit(CallAST *ast)
|
||||||
|
{
|
||||||
|
IdExpressionAST *idExp = ast->base_expression->asIdExpression();
|
||||||
|
if (!idExp || !idExp->name)
|
||||||
|
return false;
|
||||||
|
TemplateIdAST *templateId = idExp->name->asTemplateId();
|
||||||
|
if (!templateId || !templateId->identifier_token)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// check the name
|
||||||
|
const Identifier *templateIdentifier = translationUnit()->identifier(templateId->identifier_token);
|
||||||
|
if (!templateIdentifier)
|
||||||
|
return false;
|
||||||
|
const QString callName = QString::fromUtf8(templateIdentifier->chars());
|
||||||
|
if (callName != QLatin1String("qmlRegisterType"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// must have a single typeid template argument
|
||||||
|
if (!templateId->template_argument_list || !templateId->template_argument_list->value
|
||||||
|
|| templateId->template_argument_list->next)
|
||||||
|
return false;
|
||||||
|
TypeIdAST *typeId = templateId->template_argument_list->value->asTypeId();
|
||||||
|
if (!typeId)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// must have four arguments
|
||||||
|
if (!ast->expression_list
|
||||||
|
|| !ast->expression_list->value || !ast->expression_list->next
|
||||||
|
|| !ast->expression_list->next->value || !ast->expression_list->next->next
|
||||||
|
|| !ast->expression_list->next->next->value || !ast->expression_list->next->next->next
|
||||||
|
|| !ast->expression_list->next->next->next->value
|
||||||
|
|| ast->expression_list->next->next->next->next)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// first and last arguments must be string literals
|
||||||
|
const StringLiteral *packageLit = 0;
|
||||||
|
const StringLiteral *nameLit = 0;
|
||||||
|
if (StringLiteralAST *packageAst = ast->expression_list->value->asStringLiteral())
|
||||||
|
packageLit = translationUnit()->stringLiteral(packageAst->literal_token);
|
||||||
|
if (StringLiteralAST *nameAst = ast->expression_list->next->next->next->value->asStringLiteral())
|
||||||
|
nameLit = translationUnit()->stringLiteral(nameAst->literal_token);
|
||||||
|
if (!nameLit) {
|
||||||
|
translationUnit()->warning(ast->expression_list->next->next->next->value->firstToken(),
|
||||||
|
"The type will only be available in Qt Creator's QML editors when the type name is a string literal");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// second and third argument must be integer literals
|
||||||
|
const NumericLiteral *majorLit = 0;
|
||||||
|
const NumericLiteral *minorLit = 0;
|
||||||
|
if (NumericLiteralAST *majorAst = ast->expression_list->next->value->asNumericLiteral())
|
||||||
|
majorLit = translationUnit()->numericLiteral(majorAst->literal_token);
|
||||||
|
if (NumericLiteralAST *minorAst = ast->expression_list->next->next->value->asNumericLiteral())
|
||||||
|
minorLit = translationUnit()->numericLiteral(minorAst->literal_token);
|
||||||
|
|
||||||
|
// build the descriptor
|
||||||
|
Document::ExportedQmlType exportedType;
|
||||||
|
exportedType.typeName = QString::fromUtf8(nameLit->chars(), nameLit->size());
|
||||||
|
if (packageLit && majorLit && minorLit && majorLit->isInt() && minorLit->isInt()) {
|
||||||
|
exportedType.packageName = QString::fromUtf8(packageLit->chars(), packageLit->size());
|
||||||
|
exportedType.majorVersion = QString::fromUtf8(majorLit->chars(), majorLit->size()).toInt();
|
||||||
|
exportedType.minorVersion = QString::fromUtf8(minorLit->chars(), minorLit->size()).toInt();
|
||||||
|
} else {
|
||||||
|
translationUnit()->warning(ast->base_expression->firstToken(),
|
||||||
|
"The package will only be available in Qt Creator's QML editors when the package name is a string literal and\n"
|
||||||
|
"the versions are integer literals. The type will be available globally.");
|
||||||
|
exportedType.packageName = QLatin1String("<default>");
|
||||||
|
}
|
||||||
|
|
||||||
|
// we want to do lookup later, so also store the surrounding scope
|
||||||
|
unsigned line, column;
|
||||||
|
translationUnit()->getTokenStartPosition(ast->firstToken(), &line, &column);
|
||||||
|
exportedType.scope = _doc->scopeAt(line, column);
|
||||||
|
|
||||||
|
// and the expression
|
||||||
|
const Token begin = translationUnit()->tokenAt(typeId->firstToken());
|
||||||
|
const Token last = translationUnit()->tokenAt(typeId->lastToken() - 1);
|
||||||
|
exportedType.typeExpression = _doc->source().mid(begin.begin(), last.end() - begin.begin());
|
||||||
|
|
||||||
|
_exportedTypes += exportedType;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void Document::findExposedQmlTypes()
|
||||||
|
{
|
||||||
|
if (! _translationUnit->ast())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QByteArray token("qmlRegisterType");
|
||||||
|
if (! _translationUnit->control()->findIdentifier(token.constData(), token.size()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
FindExposedQmlTypes finder(this);
|
||||||
|
_exportedQmlTypes = finder();
|
||||||
|
}
|
||||||
|
|
||||||
void Document::releaseSource()
|
void Document::releaseSource()
|
||||||
{
|
{
|
||||||
_source.clear();
|
_source.clear();
|
||||||
|
@@ -125,6 +125,8 @@ public:
|
|||||||
|
|
||||||
void check(CheckMode mode = FullCheck);
|
void check(CheckMode mode = FullCheck);
|
||||||
|
|
||||||
|
void findExposedQmlTypes();
|
||||||
|
|
||||||
void releaseSource();
|
void releaseSource();
|
||||||
void releaseTranslationUnit();
|
void releaseTranslationUnit();
|
||||||
|
|
||||||
@@ -318,6 +320,19 @@ public:
|
|||||||
const MacroUse *findMacroUseAt(unsigned offset) const;
|
const MacroUse *findMacroUseAt(unsigned offset) const;
|
||||||
const UndefinedMacroUse *findUndefinedMacroUseAt(unsigned offset) const;
|
const UndefinedMacroUse *findUndefinedMacroUseAt(unsigned offset) const;
|
||||||
|
|
||||||
|
class ExportedQmlType {
|
||||||
|
public:
|
||||||
|
QString packageName;
|
||||||
|
QString typeName;
|
||||||
|
int majorVersion;
|
||||||
|
int minorVersion;
|
||||||
|
Scope *scope;
|
||||||
|
QString typeExpression;
|
||||||
|
};
|
||||||
|
|
||||||
|
QList<ExportedQmlType> exportedQmlTypes() const
|
||||||
|
{ return _exportedQmlTypes; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString _fileName;
|
QString _fileName;
|
||||||
Control *_control;
|
Control *_control;
|
||||||
@@ -329,6 +344,7 @@ private:
|
|||||||
QList<Block> _skippedBlocks;
|
QList<Block> _skippedBlocks;
|
||||||
QList<MacroUse> _macroUses;
|
QList<MacroUse> _macroUses;
|
||||||
QList<UndefinedMacroUse> _undefinedMacroUses;
|
QList<UndefinedMacroUse> _undefinedMacroUses;
|
||||||
|
QList<ExportedQmlType> _exportedQmlTypes;
|
||||||
QByteArray _source;
|
QByteArray _source;
|
||||||
QDateTime _lastModified;
|
QDateTime _lastModified;
|
||||||
unsigned _revision;
|
unsigned _revision;
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
#define CPPMODELMANAGERINTERFACE_H
|
#define CPPMODELMANAGERINTERFACE_H
|
||||||
|
|
||||||
#include <cplusplus/CppDocument.h>
|
#include <cplusplus/CppDocument.h>
|
||||||
|
#include <languageutils/fakemetaobject.h>
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QtCore/QHash>
|
#include <QtCore/QHash>
|
||||||
#include <QtCore/QPointer>
|
#include <QtCore/QPointer>
|
||||||
@@ -146,6 +147,8 @@ public:
|
|||||||
|
|
||||||
virtual void findMacroUsages(const CPlusPlus::Macro ¯o) = 0;
|
virtual void findMacroUsages(const CPlusPlus::Macro ¯o) = 0;
|
||||||
|
|
||||||
|
virtual QList<LanguageUtils::FakeMetaObject *> exportedQmlObjects() const = 0;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void documentUpdated(CPlusPlus::Document::Ptr doc);
|
void documentUpdated(CPlusPlus::Document::Ptr doc);
|
||||||
|
|
||||||
|
@@ -1947,6 +1947,7 @@ const Value *Function::invoke(const Activation *activation) const
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
QList<const FakeMetaObject *> CppQmlTypesLoader::builtinObjects;
|
QList<const FakeMetaObject *> CppQmlTypesLoader::builtinObjects;
|
||||||
|
QList<const FakeMetaObject *> CppQmlTypesLoader::cppObjects;
|
||||||
|
|
||||||
QStringList CppQmlTypesLoader::load(const QFileInfoList &xmlFiles)
|
QStringList CppQmlTypesLoader::load(const QFileInfoList &xmlFiles)
|
||||||
{
|
{
|
||||||
@@ -2440,6 +2441,7 @@ Engine::Engine()
|
|||||||
initializePrototypes();
|
initializePrototypes();
|
||||||
|
|
||||||
_cppQmlTypes.load(this, CppQmlTypesLoader::builtinObjects);
|
_cppQmlTypes.load(this, CppQmlTypesLoader::builtinObjects);
|
||||||
|
_cppQmlTypes.load(this, CppQmlTypesLoader::cppObjects);
|
||||||
|
|
||||||
// the 'Qt' object is dumped even though it is not exported
|
// the 'Qt' object is dumped even though it is not exported
|
||||||
// it contains useful information, in particular on enums - add the
|
// it contains useful information, in particular on enums - add the
|
||||||
|
@@ -593,6 +593,7 @@ public:
|
|||||||
/** \return an empty list when successful, error messages otherwise. */
|
/** \return an empty list when successful, error messages otherwise. */
|
||||||
static QStringList load(const QFileInfoList &xmlFiles);
|
static QStringList load(const QFileInfoList &xmlFiles);
|
||||||
static QList<const LanguageUtils::FakeMetaObject *> builtinObjects;
|
static QList<const LanguageUtils::FakeMetaObject *> builtinObjects;
|
||||||
|
static QList<const LanguageUtils::FakeMetaObject *> cppObjects;
|
||||||
|
|
||||||
// parses the xml string and fills the newObjects map
|
// parses the xml string and fills the newObjects map
|
||||||
static QString parseQmlTypeXml(const QByteArray &xml,
|
static QString parseQmlTypeXml(const QByteArray &xml,
|
||||||
|
@@ -162,9 +162,26 @@ void Link::populateImportedTypes(TypeEnvironment *typeEnv, Document::Ptr doc)
|
|||||||
{
|
{
|
||||||
Q_D(Link);
|
Q_D(Link);
|
||||||
|
|
||||||
if (! (doc->qmlProgram() && doc->qmlProgram()->imports))
|
if (! doc->qmlProgram())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// implicit imports: the <default> package is always available
|
||||||
|
const QLatin1String defaultPackage("<default>");
|
||||||
|
if (engine()->cppQmlTypes().hasPackage(defaultPackage)) {
|
||||||
|
ImportInfo info(ImportInfo::LibraryImport, defaultPackage);
|
||||||
|
ObjectValue *import = d->importCache.value(ImportCacheKey(info));
|
||||||
|
if (!import) {
|
||||||
|
import = new ObjectValue(engine());
|
||||||
|
foreach (QmlObjectValue *object,
|
||||||
|
engine()->cppQmlTypes().typesForImport(defaultPackage, ComponentVersion())) {
|
||||||
|
import->setProperty(object->className(), object);
|
||||||
|
}
|
||||||
|
d->importCache.insert(ImportCacheKey(info), import);
|
||||||
|
}
|
||||||
|
typeEnv->addImport(import, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// implicit imports:
|
// implicit imports:
|
||||||
// qml files in the same directory are available without explicit imports
|
// qml files in the same directory are available without explicit imports
|
||||||
ImportInfo implcitImportInfo(ImportInfo::ImplicitDirectoryImport, doc->path());
|
ImportInfo implcitImportInfo(ImportInfo::ImplicitDirectoryImport, doc->path());
|
||||||
|
@@ -77,6 +77,7 @@
|
|||||||
#include <Token.h>
|
#include <Token.h>
|
||||||
#include <Parser.h>
|
#include <Parser.h>
|
||||||
#include <Control.h>
|
#include <Control.h>
|
||||||
|
#include <CoreTypes.h>
|
||||||
|
|
||||||
#include <QtCore/QCoreApplication>
|
#include <QtCore/QCoreApplication>
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
@@ -290,6 +291,8 @@ public:
|
|||||||
void operator()()
|
void operator()()
|
||||||
{
|
{
|
||||||
_doc->check(_mode);
|
_doc->check(_mode);
|
||||||
|
_doc->findExposedQmlTypes();
|
||||||
|
_doc->releaseSource();
|
||||||
_doc->releaseTranslationUnit();
|
_doc->releaseTranslationUnit();
|
||||||
|
|
||||||
if (_mode == Document::FastCheck)
|
if (_mode == Document::FastCheck)
|
||||||
@@ -589,7 +592,6 @@ void CppPreprocessor::sourceNeeded(QString &fileName, IncludeType type, unsigned
|
|||||||
|
|
||||||
doc->setSource(preprocessedCode);
|
doc->setSource(preprocessedCode);
|
||||||
doc->tokenize();
|
doc->tokenize();
|
||||||
doc->releaseSource();
|
|
||||||
|
|
||||||
snapshot.insert(doc);
|
snapshot.insert(doc);
|
||||||
m_todo.remove(fileName);
|
m_todo.remove(fileName);
|
||||||
@@ -601,6 +603,7 @@ void CppPreprocessor::sourceNeeded(QString &fileName, IncludeType type, unsigned
|
|||||||
|
|
||||||
(void) switchDocument(previousDoc);
|
(void) switchDocument(previousDoc);
|
||||||
#else
|
#else
|
||||||
|
doc->releaseSource();
|
||||||
Document::CheckMode mode = Document::FastCheck;
|
Document::CheckMode mode = Document::FastCheck;
|
||||||
mode = Document::FullCheck;
|
mode = Document::FullCheck;
|
||||||
doc->parse();
|
doc->parse();
|
||||||
@@ -1418,5 +1421,162 @@ void CppModelManager::GC()
|
|||||||
protectSnapshot.unlock();
|
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
|
#endif
|
||||||
|
|
||||||
|
@@ -131,6 +131,8 @@ public:
|
|||||||
|
|
||||||
virtual void findMacroUsages(const CPlusPlus::Macro ¯o);
|
virtual void findMacroUsages(const CPlusPlus::Macro ¯o);
|
||||||
|
|
||||||
|
virtual QList<LanguageUtils::FakeMetaObject *> exportedQmlObjects() const;
|
||||||
|
|
||||||
void setHeaderSuffixes(const QStringList &suffixes)
|
void setHeaderSuffixes(const QStringList &suffixes)
|
||||||
{ m_headerSuffixes = suffixes; }
|
{ m_headerSuffixes = suffixes; }
|
||||||
|
|
||||||
|
@@ -39,6 +39,7 @@
|
|||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
#include <coreplugin/progressmanager/progressmanager.h>
|
#include <coreplugin/progressmanager/progressmanager.h>
|
||||||
#include <coreplugin/mimedatabase.h>
|
#include <coreplugin/mimedatabase.h>
|
||||||
|
#include <cplusplus/ModelManagerInterface.h>
|
||||||
#include <qmljs/qmljsinterpreter.h>
|
#include <qmljs/qmljsinterpreter.h>
|
||||||
#include <qmljs/qmljsbind.h>
|
#include <qmljs/qmljsbind.h>
|
||||||
#include <qmljs/parser/qmldirparser_p.h>
|
#include <qmljs/parser/qmldirparser_p.h>
|
||||||
@@ -56,6 +57,7 @@
|
|||||||
#include <qtconcurrent/runextensions.h>
|
#include <qtconcurrent/runextensions.h>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
@@ -72,6 +74,11 @@ ModelManager::ModelManager(QObject *parent):
|
|||||||
{
|
{
|
||||||
m_synchronizer.setCancelOnWait(true);
|
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::Document::Ptr>("QmlJS::Document::Ptr");
|
||||||
qRegisterMetaType<QmlJS::LibraryInfo>("QmlJS::LibraryInfo");
|
qRegisterMetaType<QmlJS::LibraryInfo>("QmlJS::LibraryInfo");
|
||||||
|
|
||||||
@@ -81,6 +88,16 @@ ModelManager::ModelManager(QObject *parent):
|
|||||||
updateImportPaths();
|
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()
|
void ModelManager::loadQmlTypeDescriptions()
|
||||||
{
|
{
|
||||||
if (Core::ICore::instance()) {
|
if (Core::ICore::instance()) {
|
||||||
@@ -537,3 +554,16 @@ void ModelManager::loadPluginTypes(const QString &libraryPath, const QString &im
|
|||||||
{
|
{
|
||||||
m_pluginDumper->loadPluginTypes(libraryPath, importPath, importUri);
|
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;
|
||||||
|
}
|
||||||
|
@@ -44,6 +44,8 @@
|
|||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
|
||||||
|
QT_FORWARD_DECLARE_CLASS(QTimer)
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class ICore;
|
class ICore;
|
||||||
class MimeType;
|
class MimeType;
|
||||||
@@ -61,6 +63,8 @@ class QMLJSTOOLS_EXPORT ModelManager: public QmlJS::ModelManagerInterface
|
|||||||
public:
|
public:
|
||||||
ModelManager(QObject *parent = 0);
|
ModelManager(QObject *parent = 0);
|
||||||
|
|
||||||
|
void delayedInitialization();
|
||||||
|
|
||||||
virtual WorkingCopy workingCopy() const;
|
virtual WorkingCopy workingCopy() const;
|
||||||
virtual QmlJS::Snapshot snapshot() const;
|
virtual QmlJS::Snapshot snapshot() const;
|
||||||
|
|
||||||
@@ -99,6 +103,9 @@ protected:
|
|||||||
|
|
||||||
void updateImportPaths();
|
void updateImportPaths();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void updateCppQmlTypes();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool matchesMimeType(const Core::MimeType &fileMimeType, const Core::MimeType &knownMimeType);
|
static bool matchesMimeType(const Core::MimeType &fileMimeType, const Core::MimeType &knownMimeType);
|
||||||
|
|
||||||
@@ -109,6 +116,7 @@ private:
|
|||||||
QStringList m_defaultImportPaths;
|
QStringList m_defaultImportPaths;
|
||||||
|
|
||||||
QFutureSynchronizer<void> m_synchronizer;
|
QFutureSynchronizer<void> m_synchronizer;
|
||||||
|
QTimer *m_updateCppQmlTypesTimer;
|
||||||
|
|
||||||
// project integration
|
// project integration
|
||||||
QMap<ProjectExplorer::Project *, ProjectInfo> m_projects;
|
QMap<ProjectExplorer::Project *, ProjectInfo> m_projects;
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
include($$IDE_SOURCE_TREE/src/libs/languageutils/languageutils.pri)
|
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/libs/qmljs/qmljs.pri)
|
||||||
include($$IDE_SOURCE_TREE/src/plugins/projectexplorer/projectexplorer.pri)
|
include($$IDE_SOURCE_TREE/src/plugins/projectexplorer/projectexplorer.pri)
|
||||||
include($$IDE_SOURCE_TREE/src/plugins/texteditor/texteditor.pri)
|
include($$IDE_SOURCE_TREE/src/plugins/texteditor/texteditor.pri)
|
||||||
|
@@ -89,6 +89,7 @@ bool QmlJSToolsPlugin::initialize(const QStringList &arguments, QString *error)
|
|||||||
|
|
||||||
void QmlJSToolsPlugin::extensionsInitialized()
|
void QmlJSToolsPlugin::extensionsInitialized()
|
||||||
{
|
{
|
||||||
|
m_modelManager->delayedInitialization();
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtensionSystem::IPlugin::ShutdownFlag QmlJSToolsPlugin::aboutToShutdown()
|
ExtensionSystem::IPlugin::ShutdownFlag QmlJSToolsPlugin::aboutToShutdown()
|
||||||
|
Reference in New Issue
Block a user