forked from qt-creator/qt-creator
QmlJS: Move the exported-C++-type detection out of C++ code.
It now lives in qmljstools/qmljsfindexportedcpptypes, all in one place. Also ensures that the source code is available when a file is being scanned for QML exports. This will enable checking comments for annotations about the URI a plugin is usually imported as. Change-Id: I1da36d0678e0a8d34b171dbe0f6b5690d89eb18b Reviewed-on: http://codereview.qt.nokia.com/3392 Reviewed-by: Fawzi Mohamed <fawzi.mohamed@nokia.com>
This commit is contained in:
@@ -290,15 +290,11 @@ public:
|
||||
void operator()()
|
||||
{
|
||||
_doc->check(_mode);
|
||||
_doc->findExposedQmlTypes();
|
||||
_doc->releaseSource();
|
||||
_doc->releaseTranslationUnit();
|
||||
|
||||
if (_mode == Document::FastCheck)
|
||||
_doc->control()->squeeze();
|
||||
|
||||
if (_modelManager)
|
||||
_modelManager->emitDocumentUpdated(_doc); // ### TODO: compress
|
||||
|
||||
_doc->releaseSourceAndAST();
|
||||
}
|
||||
};
|
||||
} // end of anonymous namespace
|
||||
@@ -590,6 +586,7 @@ void CppPreprocessor::sourceNeeded(QString &fileName, IncludeType type, unsigned
|
||||
const QByteArray preprocessedCode = preprocess(fileName, contents);
|
||||
|
||||
doc->setSource(preprocessedCode);
|
||||
doc->keepSourceAndAST();
|
||||
doc->tokenize();
|
||||
|
||||
snapshot.insert(doc);
|
||||
@@ -1284,166 +1281,6 @@ 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::Ptr fmo, Class *klass,
|
||||
QHash<Class *, LanguageUtils::FakeMetaObject::Ptr> *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();
|
||||
const int revision = 0; // ### fixme
|
||||
FakeMetaProperty property(
|
||||
namePrinter(propDecl->name()),
|
||||
toQmlType(type),
|
||||
isList, isWritable, isPointer,
|
||||
revision);
|
||||
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::Ptr baseFmo = classes->value(baseClass);
|
||||
if (!baseFmo) {
|
||||
baseFmo = FakeMetaObject::Ptr(new FakeMetaObject);
|
||||
populate(baseFmo, baseClass, classes, typeOf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QList<LanguageUtils::FakeMetaObject::ConstPtr> CppModelManager::exportedQmlObjects(const Document::Ptr &doc) const
|
||||
{
|
||||
using namespace LanguageUtils;
|
||||
QList<FakeMetaObject::ConstPtr> exportedObjects;
|
||||
QHash<Class *, FakeMetaObject::Ptr> classes;
|
||||
|
||||
const QList<CPlusPlus::Document::ExportedQmlType> exported = doc->exportedQmlTypes();
|
||||
if (exported.isEmpty())
|
||||
return exportedObjects;
|
||||
|
||||
TypeOfExpression typeOf;
|
||||
const Snapshot currentSnapshot = snapshot();
|
||||
typeOf.init(doc, currentSnapshot);
|
||||
foreach (const Document::ExportedQmlType &exportedType, exported) {
|
||||
FakeMetaObject::Ptr 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;
|
||||
}
|
||||
|
||||
void CppModelManager::finishedRefreshingSourceFiles(const QStringList &files)
|
||||
{
|
||||
emit sourceFilesRefreshed(files);
|
||||
|
||||
Reference in New Issue
Block a user