Commit 918a1653 authored by Christian Kamm's avatar Christian Kamm Committed by hjk

QmlJS: Fix library-by-path imports.

Fixes the problem 5426c3ac and
7b25f438 worked around.

Reviewed-by: Erik Verbruggen
(cherry picked from commit e2131113)
Change-Id: I5426c3acxx
Reviewed-on: http://codereview.qt.nokia.com/381Reviewed-by: default avatarQt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: default avatarhjk <qthjk@ovi.com>
parent 8b95ca89
...@@ -2029,12 +2029,15 @@ template <typename T> ...@@ -2029,12 +2029,15 @@ template <typename T>
QList<QmlObjectValue *> CppQmlTypes::load(Engine *engine, const T &objects) QList<QmlObjectValue *> CppQmlTypes::load(Engine *engine, const T &objects)
{ {
// load // load
QList<QmlObjectValue *> loadedObjects;
QList<QmlObjectValue *> newObjects; QList<QmlObjectValue *> newObjects;
foreach (FakeMetaObject::ConstPtr metaObject, objects) { foreach (FakeMetaObject::ConstPtr metaObject, objects) {
foreach (const FakeMetaObject::Export &exp, metaObject->exports()) { foreach (const FakeMetaObject::Export &exp, metaObject->exports()) {
QmlObjectValue *newObject = makeObject(engine, metaObject, exp); bool wasCreated;
if (newObject) QmlObjectValue *loadedObject = getOrCreate(engine, metaObject, exp, &wasCreated);
newObjects += newObject; loadedObjects += loadedObject;
if (wasCreated)
newObjects += loadedObject;
} }
} }
...@@ -2043,7 +2046,7 @@ QList<QmlObjectValue *> CppQmlTypes::load(Engine *engine, const T &objects) ...@@ -2043,7 +2046,7 @@ QList<QmlObjectValue *> CppQmlTypes::load(Engine *engine, const T &objects)
setPrototypes(object); setPrototypes(object);
} }
return newObjects; return loadedObjects;
} }
// explicitly instantiate load for list and hash // explicitly instantiate load for list and hash
template QList<QmlObjectValue *> CppQmlTypes::load< QList<FakeMetaObject::ConstPtr> >(Engine *, const QList<FakeMetaObject::ConstPtr> &); 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 ...@@ -2101,19 +2104,26 @@ QmlObjectValue *CppQmlTypes::typeByQualifiedName(const QString &package, const Q
return typeByQualifiedName(qualifiedName(package, type, version)); return typeByQualifiedName(qualifiedName(package, type, version));
} }
QmlObjectValue *CppQmlTypes::makeObject( QmlObjectValue *CppQmlTypes::getOrCreate(
Engine *engine, Engine *engine,
FakeMetaObject::ConstPtr metaObject, FakeMetaObject::ConstPtr metaObject,
const LanguageUtils::FakeMetaObject::Export &exp) const LanguageUtils::FakeMetaObject::Export &exp,
bool *wasCreated)
{ {
// make sure we're not loading duplicate objects // make sure we're not loading duplicate objects
if (_typesByFullyQualifiedName.contains(exp.packageNameVersion)) if (QmlObjectValue *existing = _typesByFullyQualifiedName.value(exp.packageNameVersion)) {
return 0; if (wasCreated)
*wasCreated = false;
return existing;
}
QmlObjectValue *objectValue = new QmlObjectValue( QmlObjectValue *objectValue = new QmlObjectValue(
metaObject, exp.type, exp.package, exp.version, engine); metaObject, exp.type, exp.package, exp.version, engine);
_typesByPackage[exp.package].append(objectValue); _typesByPackage[exp.package].append(objectValue);
_typesByFullyQualifiedName[exp.packageNameVersion] = objectValue; _typesByFullyQualifiedName[exp.packageNameVersion] = objectValue;
if (wasCreated)
*wasCreated = true;
return objectValue; return objectValue;
} }
...@@ -2141,7 +2151,7 @@ void CppQmlTypes::setPrototypes(QmlObjectValue *object) ...@@ -2141,7 +2151,7 @@ void CppQmlTypes::setPrototypes(QmlObjectValue *object)
// needs to create Positioner (Qt) and Positioner (QtQuick) // needs to create Positioner (Qt) and Positioner (QtQuick)
QmlObjectValue *v = object; QmlObjectValue *v = object;
while (!v->prototype() && !fmo->superclassName().isEmpty()) { while (!v->prototype() && !fmo->superclassName().isEmpty()) {
QmlObjectValue *superValue = getOrCreate(targetPackage, fmo->superclassName()); QmlObjectValue *superValue = getOrCreateForPackage(targetPackage, fmo->superclassName());
if (!superValue) if (!superValue)
return; return;
v->setPrototype(superValue); v->setPrototype(superValue);
...@@ -2150,7 +2160,7 @@ void CppQmlTypes::setPrototypes(QmlObjectValue *object) ...@@ -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 // first get the cpp object value
QmlObjectValue *cppObject = typeByCppName(cppName); QmlObjectValue *cppObject = typeByCppName(cppName);
...@@ -2164,10 +2174,9 @@ QmlObjectValue *CppQmlTypes::getOrCreate(const QString &package, const QString & ...@@ -2164,10 +2174,9 @@ QmlObjectValue *CppQmlTypes::getOrCreate(const QString &package, const QString &
FakeMetaObject::Export exp = metaObject->exportInPackage(package); FakeMetaObject::Export exp = metaObject->exportInPackage(package);
QmlObjectValue *object = 0; QmlObjectValue *object = 0;
if (exp.isValid()) { if (exp.isValid()) {
object = typeByQualifiedName(exp.packageNameVersion); object = getOrCreate(cppObject->engine(), metaObject, exp);
if (!object)
object = makeObject(cppObject->engine(), metaObject, exp);
} else { } else {
// make a convenience object that does not get added to _typesByPackage
const QString qname = qualifiedName(package, cppName, ComponentVersion()); const QString qname = qualifiedName(package, cppName, ComponentVersion());
object = typeByQualifiedName(qname); object = typeByQualifiedName(qname);
if (!object) { if (!object) {
...@@ -3443,3 +3452,59 @@ ImportInfo TypeEnvironment::importInfo(const QString &name, const Context *conte ...@@ -3443,3 +3452,59 @@ ImportInfo TypeEnvironment::importInfo(const QString &name, const Context *conte
} }
return ImportInfo(); 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: ...@@ -633,11 +633,12 @@ public:
LanguageUtils::ComponentVersion version) const; LanguageUtils::ComponentVersion version) const;
private: private:
QmlObjectValue *makeObject(Engine *engine,
LanguageUtils::FakeMetaObject::ConstPtr metaObject,
const LanguageUtils::FakeMetaObject::Export &exp);
void setPrototypes(QmlObjectValue *object); 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; QHash<QString, QList<QmlObjectValue *> > _typesByPackage;
...@@ -1036,6 +1037,10 @@ public: ...@@ -1036,6 +1037,10 @@ public:
void addImport(const ObjectValue *import, const ImportInfo &info); void addImport(const ObjectValue *import, const ImportInfo &info);
ImportInfo importInfo(const QString &name, const Context *context) const; ImportInfo importInfo(const QString &name, const Context *context) const;
#ifdef QT_DEBUG
void dump() const;
#endif
}; };
} } // namespace QmlJS::Interpreter } } // namespace QmlJS::Interpreter
......
...@@ -181,27 +181,6 @@ void Link::populateImportedTypes(TypeEnvironment *typeEnv, Document::Ptr doc) ...@@ -181,27 +181,6 @@ void Link::populateImportedTypes(TypeEnvironment *typeEnv, Document::Ptr doc)
foreach (const ImportInfo &info, doc->bind()->imports()) { foreach (const ImportInfo &info, doc->bind()->imports()) {
ObjectValue *import = d->importCache.value(ImportCacheKey(info)); 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) { if (!import) {
switch (info.type()) { switch (info.type()) {
case ImportInfo::FileImport: case ImportInfo::FileImport:
......
...@@ -274,7 +274,6 @@ void PluginDumper::dump(const Plugin &plugin) ...@@ -274,7 +274,6 @@ void PluginDumper::dump(const Plugin &plugin)
connect(process, SIGNAL(finished(int)), SLOT(qmlPluginTypeDumpDone(int))); connect(process, SIGNAL(finished(int)), SLOT(qmlPluginTypeDumpDone(int)));
connect(process, SIGNAL(error(QProcess::ProcessError)), SLOT(qmlPluginTypeDumpError(QProcess::ProcessError))); connect(process, SIGNAL(error(QProcess::ProcessError)), SLOT(qmlPluginTypeDumpError(QProcess::ProcessError)));
QStringList args; QStringList args;
args << QLatin1String("--notrelocatable");
if (plugin.importUri.isEmpty()) { if (plugin.importUri.isEmpty()) {
args << QLatin1String("--path"); args << QLatin1String("--path");
args << plugin.importPath; 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