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()
|
||||
{
|
||||
_source.clear();
|
||||
|
@@ -125,6 +125,8 @@ public:
|
||||
|
||||
void check(CheckMode mode = FullCheck);
|
||||
|
||||
void findExposedQmlTypes();
|
||||
|
||||
void releaseSource();
|
||||
void releaseTranslationUnit();
|
||||
|
||||
@@ -318,6 +320,19 @@ public:
|
||||
const MacroUse *findMacroUseAt(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:
|
||||
QString _fileName;
|
||||
Control *_control;
|
||||
@@ -329,6 +344,7 @@ private:
|
||||
QList<Block> _skippedBlocks;
|
||||
QList<MacroUse> _macroUses;
|
||||
QList<UndefinedMacroUse> _undefinedMacroUses;
|
||||
QList<ExportedQmlType> _exportedQmlTypes;
|
||||
QByteArray _source;
|
||||
QDateTime _lastModified;
|
||||
unsigned _revision;
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#define CPPMODELMANAGERINTERFACE_H
|
||||
|
||||
#include <cplusplus/CppDocument.h>
|
||||
#include <languageutils/fakemetaobject.h>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QPointer>
|
||||
@@ -146,6 +147,8 @@ public:
|
||||
|
||||
virtual void findMacroUsages(const CPlusPlus::Macro ¯o) = 0;
|
||||
|
||||
virtual QList<LanguageUtils::FakeMetaObject *> exportedQmlObjects() const = 0;
|
||||
|
||||
Q_SIGNALS:
|
||||
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::cppObjects;
|
||||
|
||||
QStringList CppQmlTypesLoader::load(const QFileInfoList &xmlFiles)
|
||||
{
|
||||
@@ -2440,6 +2441,7 @@ Engine::Engine()
|
||||
initializePrototypes();
|
||||
|
||||
_cppQmlTypes.load(this, CppQmlTypesLoader::builtinObjects);
|
||||
_cppQmlTypes.load(this, CppQmlTypesLoader::cppObjects);
|
||||
|
||||
// the 'Qt' object is dumped even though it is not exported
|
||||
// it contains useful information, in particular on enums - add the
|
||||
|
@@ -593,6 +593,7 @@ public:
|
||||
/** \return an empty list when successful, error messages otherwise. */
|
||||
static QStringList load(const QFileInfoList &xmlFiles);
|
||||
static QList<const LanguageUtils::FakeMetaObject *> builtinObjects;
|
||||
static QList<const LanguageUtils::FakeMetaObject *> cppObjects;
|
||||
|
||||
// parses the xml string and fills the newObjects map
|
||||
static QString parseQmlTypeXml(const QByteArray &xml,
|
||||
|
@@ -162,9 +162,26 @@ void Link::populateImportedTypes(TypeEnvironment *typeEnv, Document::Ptr doc)
|
||||
{
|
||||
Q_D(Link);
|
||||
|
||||
if (! (doc->qmlProgram() && doc->qmlProgram()->imports))
|
||||
if (! doc->qmlProgram())
|
||||
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:
|
||||
// qml files in the same directory are available without explicit imports
|
||||
ImportInfo implcitImportInfo(ImportInfo::ImplicitDirectoryImport, doc->path());
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -131,6 +131,8 @@ public:
|
||||
|
||||
virtual void findMacroUsages(const CPlusPlus::Macro ¯o);
|
||||
|
||||
virtual QList<LanguageUtils::FakeMetaObject *> exportedQmlObjects() const;
|
||||
|
||||
void setHeaderSuffixes(const QStringList &suffixes)
|
||||
{ m_headerSuffixes = suffixes; }
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
||||
|
@@ -89,6 +89,7 @@ bool QmlJSToolsPlugin::initialize(const QStringList &arguments, QString *error)
|
||||
|
||||
void QmlJSToolsPlugin::extensionsInitialized()
|
||||
{
|
||||
m_modelManager->delayedInitialization();
|
||||
}
|
||||
|
||||
ExtensionSystem::IPlugin::ShutdownFlag QmlJSToolsPlugin::aboutToShutdown()
|
||||
|
Reference in New Issue
Block a user