forked from qt-creator/qt-creator
QmlJS: Fix library-by-path imports.
Fixes the problem5426c3ac2cand7b25f438c6worked around. Reviewed-by: Erik Verbruggen (cherry picked from commite21311132b) Change-Id: I5426c3ac2cdf898ca1190a7746ba506ff24abc50xx Reviewed-on: http://codereview.qt.nokia.com/381 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -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)
|
|||||||
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
|
|||||||
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)
|
|||||||
// 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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 &
|
|||||||
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
|
|||||||
}
|
}
|
||||||
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:
|
|||||||
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:
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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;
|
||||||
|
|||||||
Reference in New Issue
Block a user