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:
Christian Kamm
2011-08-23 12:02:29 +02:00
parent c105ae47c1
commit 27d0830698
11 changed files with 616 additions and 450 deletions

View File

@@ -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);