Commit e2131113 authored by Christian Kamm's avatar Christian Kamm

QmlJS: Fix library-by-path imports.

Fixes the problem 5426c3ac and
7b25f438 worked around.

Reviewed-by: Erik Verbruggen
parent e40a0ca9
......@@ -2029,12 +2029,15 @@ template <typename T>
QList<QmlObjectValue *> CppQmlTypes::load(Engine *engine, const T &objects)
{
// load
QList<QmlObjectValue *> loadedObjects;
QList<QmlObjectValue *> newObjects;
foreach (FakeMetaObject::ConstPtr metaObject, objects) {
foreach (const FakeMetaObject::Export &exp, metaObject->exports()) {
QmlObjectValue *newObject = makeObject(engine, metaObject, exp);
if (newObject)
newObjects += newObject;
bool wasCreated;
QmlObjectValue *loadedObject = getOrCreate(engine, metaObject, exp, &wasCreated);
loadedObjects += loadedObject;
if (wasCreated)
newObjects += loadedObject;
}
}
......@@ -2043,7 +2046,7 @@ QList<QmlObjectValue *> CppQmlTypes::load(Engine *engine, const T &objects)
setPrototypes(object);
}
return newObjects;
return loadedObjects;
}
// explicitly instantiate load for list and hash
template QList<QmlObjectValue *> CppQmlTypes::load< QList<FakeMetaObject::ConstPtr> >(Engine *, const QList<FakeMetaObject::ConstPtr> &);
......@@ -2101,19 +2104,26 @@ QmlObjectValue *CppQmlTypes::typeByQualifiedName(const QString &package, const Q
return typeByQualifiedName(qualifiedName(package, type, version));
}
QmlObjectValue *CppQmlTypes::makeObject(
QmlObjectValue *CppQmlTypes::getOrCreate(
Engine *engine,
FakeMetaObject::ConstPtr metaObject,
const LanguageUtils::FakeMetaObject::Export &exp)
const LanguageUtils::FakeMetaObject::Export &exp,
bool *wasCreated)
{
// make sure we're not loading duplicate objects
if (_typesByFullyQualifiedName.contains(exp.packageNameVersion))
return 0;
if (QmlObjectValue *existing = _typesByFullyQualifiedName.value(exp.packageNameVersion)) {
if (wasCreated)
*wasCreated = false;
return existing;
}
QmlObjectValue *objectValue = new QmlObjectValue(
metaObject, exp.type, exp.package, exp.version, engine);
_typesByPackage[exp.package].append(objectValue);
_typesByFullyQualifiedName[exp.packageNameVersion] = objectValue;
if (wasCreated)
*wasCreated = true;
return objectValue;
}
......@@ -2141,7 +2151,7 @@ void CppQmlTypes::setPrototypes(QmlObjectValue *object)
// needs to create Positioner (Qt) and Positioner (QtQuick)
QmlObjectValue *v = object;
while (!v->prototype() && !fmo->superclassName().isEmpty()) {
QmlObjectValue *superValue = getOrCreate(targetPackage, fmo->superclassName());
QmlObjectValue *superValue = getOrCreateForPackage(targetPackage, fmo->superclassName());
if (!superValue)
return;
v->setPrototype(superValue);
......@@ -2150,7 +2160,7 @@ void CppQmlTypes::setPrototypes(QmlObjectValue *object)
}
}
QmlObjectValue *CppQmlTypes::getOrCreate(const QString &package, const QString &cppName)
QmlObjectValue *CppQmlTypes::getOrCreateForPackage(const QString &package, const QString &cppName)
{
// first get the cpp object value
QmlObjectValue *cppObject = typeByCppName(cppName);
......@@ -2163,10 +2173,9 @@ QmlObjectValue *CppQmlTypes::getOrCreate(const QString &package, const QString &
FakeMetaObject::Export exp = metaObject->exportInPackage(package);
QmlObjectValue *object = 0;
if (exp.isValid()) {
object = typeByQualifiedName(exp.packageNameVersion);
if (!object)
object = makeObject(cppObject->engine(), metaObject, exp);
object = getOrCreate(cppObject->engine(), metaObject, exp);
} else {
// make a convenience object that does not get added to _typesByPackage
const QString qname = qualifiedName(package, cppName, ComponentVersion());
object = typeByQualifiedName(qname);
if (!object) {
......@@ -3442,3 +3451,59 @@ ImportInfo TypeEnvironment::importInfo(const QString &name, const Context *conte
}
return ImportInfo();
}
#ifdef QT_DEBUG
class MemberDumper: public MemberProcessor
{
public:
MemberDumper() {}
virtual bool processProperty(const QString &name, const Value *)
{
qDebug() << "property: " << name;
return true;
}
virtual bool processEnumerator(const QString &name, const Value *)
{
qDebug() << "enumerator: " << name;
return true;
}
virtual bool processSignal(const QString &name, const Value *)
{
qDebug() << "signal: " << name;
return true;
}
virtual bool processSlot(const QString &name, const Value *)
{
qDebug() << "slot: " << name;
return true;
}
virtual bool processGeneratedSlot(const QString &name, const Value *)
{
qDebug() << "generated slot: " << name;
return true;
}
};
void TypeEnvironment::dump() const
{
qDebug() << "Type environment contents, in search order:";
QListIterator<Import> it(_imports);
it.toBack();
while (it.hasPrevious()) {
const Import &i = it.previous();
const ObjectValue *import = i.object;
const ImportInfo &info = i.info;
qDebug() << " " << info.name() << " " << info.version().toString() << " as " << info.id() << " : " << import;
MemberDumper dumper;
import->processMembers(&dumper);
}
}
#endif
......@@ -633,11 +633,12 @@ public:
LanguageUtils::ComponentVersion version) const;
private:
QmlObjectValue *makeObject(Engine *engine,
LanguageUtils::FakeMetaObject::ConstPtr metaObject,
const LanguageUtils::FakeMetaObject::Export &exp);
void setPrototypes(QmlObjectValue *object);
QmlObjectValue *getOrCreate(const QString &package, const QString &cppName);
QmlObjectValue *getOrCreate(Engine *engine,
LanguageUtils::FakeMetaObject::ConstPtr metaObject,
const LanguageUtils::FakeMetaObject::Export &exp,
bool *wasCreated = 0);
QmlObjectValue *getOrCreateForPackage(const QString &package, const QString &cppName);
QHash<QString, QList<QmlObjectValue *> > _typesByPackage;
......@@ -1036,6 +1037,10 @@ public:
void addImport(const ObjectValue *import, const ImportInfo &info);
ImportInfo importInfo(const QString &name, const Context *context) const;
#ifdef QT_DEBUG
void dump() const;
#endif
};
} } // namespace QmlJS::Interpreter
......
......@@ -183,27 +183,6 @@ void Link::populateImportedTypes(TypeEnvironment *typeEnv, Document::Ptr doc)
foreach (const ImportInfo &info, doc->bind()->imports()) {
ObjectValue *import = d->importCache.value(ImportCacheKey(info));
//### Hack: if this document is in a library, and if there is an qmldir file in the same directory, and if the prefix is an import-path, the import means to import everything in this library.
if (info.ast() && info.ast()->fileName && info.ast()->fileName->asString() == QLatin1String(".")) {
const QString importInfoName(info.name());
if (QFileInfo(QDir(importInfoName), QLatin1String("qmldir")).exists()) {
foreach (const QString &importPath, d->importPaths) {
if (importInfoName.startsWith(importPath)) {
// Got it.
const QString cleanPath = QFileInfo(importInfoName).canonicalFilePath();
const QString forcedPackageName = cleanPath.mid(importPath.size() + 1).replace('/', '.').replace('\\', '.');
import = importNonFile(doc, info, forcedPackageName);
if (import)
d->importCache.insert(ImportCacheKey(info), import);
break;
}
}
}
}
//### End of hack.
if (!import) {
switch (info.type()) {
case ImportInfo::FileImport:
......
......@@ -281,7 +281,6 @@ void PluginDumper::dump(const Plugin &plugin)
connect(process, SIGNAL(finished(int)), SLOT(qmlPluginTypeDumpDone(int)));
connect(process, SIGNAL(error(QProcess::ProcessError)), SLOT(qmlPluginTypeDumpError(QProcess::ProcessError)));
QStringList args;
args << QLatin1String("--notrelocatable");
if (plugin.importUri.isEmpty()) {
args << QLatin1String("--path");
args << plugin.importPath;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment