2010-01-21 15:54:19 +01:00
|
|
|
/**************************************************************************
|
|
|
|
**
|
|
|
|
** This file is part of Qt Creator
|
|
|
|
**
|
2011-01-11 16:28:15 +01:00
|
|
|
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
2010-01-21 15:54:19 +01:00
|
|
|
**
|
2011-04-13 08:42:33 +02:00
|
|
|
** Contact: Nokia Corporation (info@qt.nokia.com)
|
2010-01-21 15:54:19 +01:00
|
|
|
**
|
|
|
|
**
|
|
|
|
** GNU Lesser General Public License Usage
|
|
|
|
**
|
2011-04-13 08:42:33 +02:00
|
|
|
** This file may be used under the terms of the GNU Lesser General Public
|
|
|
|
** License version 2.1 as published by the Free Software Foundation and
|
|
|
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
|
|
** Please review the following information to ensure the GNU Lesser General
|
|
|
|
** Public License version 2.1 requirements will be met:
|
|
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
2010-01-21 15:54:19 +01:00
|
|
|
**
|
2010-12-17 16:01:08 +01:00
|
|
|
** In addition, as a special exception, Nokia gives you certain additional
|
2011-04-13 08:42:33 +02:00
|
|
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
2010-12-17 16:01:08 +01:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
**
|
2011-04-13 08:42:33 +02:00
|
|
|
** Other Usage
|
|
|
|
**
|
|
|
|
** Alternatively, this file may be used in accordance with the terms and
|
|
|
|
** conditions contained in a signed written agreement between you and Nokia.
|
|
|
|
**
|
2010-12-17 16:01:08 +01:00
|
|
|
** If you have questions regarding the use of this file, please contact
|
2011-05-06 15:05:37 +02:00
|
|
|
** Nokia at info@qt.nokia.com.
|
2010-01-21 15:54:19 +01:00
|
|
|
**
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
#include "qmljsinterpreter.h"
|
2010-02-15 11:52:39 +01:00
|
|
|
#include "qmljsevaluate.h"
|
2010-02-04 10:19:37 +01:00
|
|
|
#include "qmljslink.h"
|
2010-06-25 17:10:14 +02:00
|
|
|
#include "qmljsbind.h"
|
2010-04-22 15:59:21 +02:00
|
|
|
#include "qmljsscopebuilder.h"
|
2011-02-08 13:22:34 +01:00
|
|
|
#include "qmljstypedescriptionreader.h"
|
2011-05-04 11:12:45 +02:00
|
|
|
#include "qmljsscopeastpath.h"
|
2011-07-01 12:11:02 +02:00
|
|
|
#include "qmljsvalueowner.h"
|
2011-07-01 13:51:53 +02:00
|
|
|
#include "qmljscontext.h"
|
2010-02-03 14:31:03 +01:00
|
|
|
#include "parser/qmljsast_p.h"
|
2010-03-01 13:01:05 +01:00
|
|
|
|
2010-12-03 11:17:25 +01:00
|
|
|
#include <languageutils/fakemetaobject.h>
|
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
#include <QtCore/QFile>
|
2010-06-01 15:10:20 +02:00
|
|
|
#include <QtCore/QDir>
|
2010-03-01 13:01:05 +01:00
|
|
|
#include <QtCore/QString>
|
|
|
|
#include <QtCore/QStringList>
|
2010-01-24 19:31:38 +01:00
|
|
|
#include <QtCore/QMetaObject>
|
|
|
|
#include <QtCore/QMetaProperty>
|
2010-03-01 13:01:05 +01:00
|
|
|
#include <QtCore/QXmlStreamReader>
|
2010-06-01 15:10:20 +02:00
|
|
|
#include <QtCore/QProcess>
|
2010-01-21 15:54:19 +01:00
|
|
|
#include <QtCore/QDebug>
|
|
|
|
|
2010-12-03 11:17:25 +01:00
|
|
|
using namespace LanguageUtils;
|
2010-01-21 15:54:19 +01:00
|
|
|
using namespace QmlJS::Interpreter;
|
2010-02-03 14:31:03 +01:00
|
|
|
using namespace QmlJS::AST;
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-02-01 13:54:44 +01:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
class LookupMember: public MemberProcessor
|
|
|
|
{
|
|
|
|
QString _name;
|
|
|
|
const Value *_value;
|
|
|
|
|
|
|
|
bool process(const QString &name, const Value *value)
|
|
|
|
{
|
|
|
|
if (_value)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (name == _name) {
|
|
|
|
_value = value;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
LookupMember(const QString &name)
|
|
|
|
: _name(name), _value(0) {}
|
|
|
|
|
|
|
|
const Value *value() const { return _value; }
|
|
|
|
|
|
|
|
virtual bool processProperty(const QString &name, const Value *value)
|
|
|
|
{
|
|
|
|
return process(name, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool processEnumerator(const QString &name, const Value *value)
|
|
|
|
{
|
|
|
|
return process(name, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool processSignal(const QString &name, const Value *value)
|
|
|
|
{
|
|
|
|
return process(name, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool processSlot(const QString &name, const Value *value)
|
|
|
|
{
|
|
|
|
return process(name, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool processGeneratedSlot(const QString &name, const Value *value)
|
|
|
|
{
|
|
|
|
return process(name, value);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-01-26 10:50:30 +01:00
|
|
|
class MetaFunction: public FunctionValue
|
|
|
|
{
|
2010-03-01 13:01:05 +01:00
|
|
|
FakeMetaMethod _method;
|
2010-01-26 10:50:30 +01:00
|
|
|
|
|
|
|
public:
|
2011-07-01 12:11:02 +02:00
|
|
|
MetaFunction(const FakeMetaMethod &method, ValueOwner *valueOwner)
|
|
|
|
: FunctionValue(valueOwner), _method(method)
|
2010-01-26 10:50:30 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual const Value *returnValue() const
|
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
return valueOwner()->undefinedValue();
|
2010-01-26 10:50:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual int argumentCount() const
|
|
|
|
{
|
|
|
|
return _method.parameterNames().size();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual const Value *argument(int) const
|
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
return valueOwner()->undefinedValue();
|
2010-01-26 10:50:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual QString argumentName(int index) const
|
|
|
|
{
|
|
|
|
if (index < _method.parameterNames().size())
|
|
|
|
return _method.parameterNames().at(index);
|
|
|
|
|
|
|
|
return FunctionValue::argumentName(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool isVariadic() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual const Value *invoke(const Activation *) const
|
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
return valueOwner()->undefinedValue();
|
2010-01-26 10:50:30 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-02-01 13:54:44 +01:00
|
|
|
} // end of anonymous namespace
|
|
|
|
|
2011-01-04 17:04:44 +01:00
|
|
|
QmlObjectValue::QmlObjectValue(FakeMetaObject::ConstPtr metaObject, const QString &className,
|
2011-07-01 12:11:02 +02:00
|
|
|
const QString &packageName, const ComponentVersion version, ValueOwner *valueOwner)
|
|
|
|
: ObjectValue(valueOwner),
|
2011-02-10 17:03:52 +01:00
|
|
|
_attachedType(0),
|
2010-09-30 11:21:23 +02:00
|
|
|
_metaObject(metaObject),
|
2010-10-19 16:15:32 +02:00
|
|
|
_packageName(packageName),
|
|
|
|
_componentVersion(version)
|
2010-01-27 12:40:02 +01:00
|
|
|
{
|
2010-10-19 16:15:32 +02:00
|
|
|
setClassName(className);
|
2010-01-27 12:40:02 +01:00
|
|
|
}
|
2010-01-24 13:29:46 +01:00
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
QmlObjectValue::~QmlObjectValue()
|
|
|
|
{}
|
2010-01-24 13:29:46 +01:00
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
const Value *QmlObjectValue::findOrCreateSignature(int index, const FakeMetaMethod &method, QString *methodName) const
|
2010-02-01 13:54:44 +01:00
|
|
|
{
|
2010-03-01 13:01:05 +01:00
|
|
|
*methodName = method.methodName();
|
2010-02-01 13:54:44 +01:00
|
|
|
const Value *value = _metaSignature.value(index);
|
|
|
|
if (! value) {
|
2011-07-01 12:11:02 +02:00
|
|
|
value = new MetaFunction(method, valueOwner());
|
2010-02-01 13:54:44 +01:00
|
|
|
_metaSignature.insert(index, value);
|
2010-01-24 13:29:46 +01:00
|
|
|
}
|
2010-02-01 13:54:44 +01:00
|
|
|
return value;
|
2010-01-26 14:50:52 +01:00
|
|
|
}
|
2010-01-24 13:29:46 +01:00
|
|
|
|
2010-01-26 14:50:52 +01:00
|
|
|
void QmlObjectValue::processMembers(MemberProcessor *processor) const
|
|
|
|
{
|
2010-02-01 13:54:44 +01:00
|
|
|
// process the meta enums
|
2010-03-01 13:01:05 +01:00
|
|
|
for (int index = _metaObject->enumeratorOffset(); index < _metaObject->enumeratorCount(); ++index) {
|
|
|
|
FakeMetaEnum e = _metaObject->enumerator(index);
|
2010-01-28 15:50:58 +01:00
|
|
|
|
|
|
|
for (int i = 0; i < e.keyCount(); ++i) {
|
2011-07-01 12:11:02 +02:00
|
|
|
processor->processEnumerator(e.key(i), valueOwner()->numberValue());
|
2010-01-28 15:50:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-23 09:10:32 +02:00
|
|
|
// all explicitly defined signal names
|
|
|
|
QSet<QString> explicitSignals;
|
2010-01-26 10:10:11 +01:00
|
|
|
|
2010-02-01 13:54:44 +01:00
|
|
|
// process the meta methods
|
|
|
|
for (int index = 0; index < _metaObject->methodCount(); ++index) {
|
2011-06-23 13:32:00 +02:00
|
|
|
const FakeMetaMethod method = _metaObject->method(index);
|
|
|
|
if (_componentVersion.isValid() && _componentVersion.minorVersion() < method.revision())
|
|
|
|
continue;
|
|
|
|
|
2010-02-01 13:54:44 +01:00
|
|
|
QString methodName;
|
|
|
|
const Value *signature = findOrCreateSignature(index, method, &methodName);
|
2010-01-26 10:19:42 +01:00
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
if (method.methodType() == FakeMetaMethod::Slot && method.access() == FakeMetaMethod::Public) {
|
2010-02-01 13:54:44 +01:00
|
|
|
processor->processSlot(methodName, signature);
|
2010-01-26 10:19:42 +01:00
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (method.methodType() == FakeMetaMethod::Signal && method.access() != FakeMetaMethod::Private) {
|
2010-01-26 14:50:52 +01:00
|
|
|
// process the signal
|
2010-02-01 13:54:44 +01:00
|
|
|
processor->processSignal(methodName, signature);
|
2011-06-23 09:10:32 +02:00
|
|
|
explicitSignals.insert(methodName);
|
2010-01-26 10:19:42 +01:00
|
|
|
|
2011-06-23 09:10:32 +02:00
|
|
|
QString slotName = QLatin1String("on");
|
2010-01-26 14:50:52 +01:00
|
|
|
slotName += methodName.at(0).toUpper();
|
|
|
|
slotName += methodName.midRef(1);
|
2010-01-25 14:48:44 +01:00
|
|
|
|
2010-01-26 14:50:52 +01:00
|
|
|
// process the generated slot
|
2010-02-01 13:54:44 +01:00
|
|
|
processor->processGeneratedSlot(slotName, signature);
|
2010-01-26 14:50:52 +01:00
|
|
|
}
|
2010-01-24 13:29:46 +01:00
|
|
|
}
|
|
|
|
|
2011-06-23 09:10:32 +02:00
|
|
|
// process the meta properties
|
|
|
|
for (int index = 0; index < _metaObject->propertyCount(); ++index) {
|
2011-06-23 13:32:00 +02:00
|
|
|
const FakeMetaProperty prop = _metaObject->property(index);
|
|
|
|
if (_componentVersion.isValid() && _componentVersion.minorVersion() < prop.revision())
|
|
|
|
continue;
|
2011-06-23 09:10:32 +02:00
|
|
|
|
|
|
|
const QString propertyName = prop.name();
|
|
|
|
processor->processProperty(propertyName, propertyValue(prop));
|
|
|
|
|
|
|
|
// every property always has a onXyzChanged slot, even if the NOTIFY
|
|
|
|
// signal has a different name
|
|
|
|
QString signalName = propertyName;
|
|
|
|
signalName += QLatin1String("Changed");
|
|
|
|
if (!explicitSignals.contains(signalName)) {
|
|
|
|
QString slotName = QLatin1String("on");
|
|
|
|
slotName += signalName.at(0).toUpper();
|
|
|
|
slotName += signalName.midRef(1);
|
|
|
|
|
|
|
|
// process the generated slot
|
2011-07-01 12:11:02 +02:00
|
|
|
processor->processGeneratedSlot(slotName, valueOwner()->undefinedValue());
|
2011-06-23 09:10:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-21 14:56:16 +01:00
|
|
|
if (_attachedType)
|
|
|
|
_attachedType->processMembers(processor);
|
|
|
|
|
2010-01-26 14:50:52 +01:00
|
|
|
ObjectValue::processMembers(processor);
|
|
|
|
}
|
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
const Value *QmlObjectValue::propertyValue(const FakeMetaProperty &prop) const
|
2010-01-26 14:50:52 +01:00
|
|
|
{
|
2011-06-21 15:10:57 +02:00
|
|
|
QString typeName = prop.typeName();
|
2010-01-24 13:29:46 +01:00
|
|
|
|
2010-03-01 13:01:05 +01:00
|
|
|
// ### Verify type resolving.
|
2011-07-01 12:11:02 +02:00
|
|
|
QmlObjectValue *objectValue = valueOwner()->cppQmlTypes().typeByCppName(typeName);
|
2010-11-11 11:11:48 +01:00
|
|
|
if (objectValue) {
|
2011-02-10 14:53:57 +01:00
|
|
|
FakeMetaObject::Export exp = objectValue->metaObject()->exportInPackage(packageName());
|
|
|
|
if (exp.isValid())
|
2011-07-01 12:11:02 +02:00
|
|
|
objectValue = valueOwner()->cppQmlTypes().typeByQualifiedName(exp.packageNameVersion);
|
2010-03-01 13:01:05 +01:00
|
|
|
return objectValue;
|
2010-11-11 11:11:48 +01:00
|
|
|
}
|
2010-01-24 13:29:46 +01:00
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
const Value *value = valueOwner()->undefinedValue();
|
2010-03-01 13:01:05 +01:00
|
|
|
if (typeName == QLatin1String("QByteArray")
|
|
|
|
|| typeName == QLatin1String("string")
|
2010-11-11 16:04:55 +01:00
|
|
|
|| typeName == QLatin1String("QString")) {
|
2011-07-01 12:11:02 +02:00
|
|
|
value = valueOwner()->stringValue();
|
2010-11-11 16:04:55 +01:00
|
|
|
} else if (typeName == QLatin1String("QUrl")) {
|
2011-07-01 12:11:02 +02:00
|
|
|
value = valueOwner()->urlValue();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (typeName == QLatin1String("bool")) {
|
2011-07-01 12:11:02 +02:00
|
|
|
value = valueOwner()->booleanValue();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (typeName == QLatin1String("int")
|
2010-11-10 16:31:20 +01:00
|
|
|
|| typeName == QLatin1String("long")) {
|
2011-07-01 12:11:02 +02:00
|
|
|
value = valueOwner()->intValue();
|
2010-11-10 16:31:20 +01:00
|
|
|
} else if (typeName == QLatin1String("float")
|
|
|
|
|| typeName == QLatin1String("double")
|
|
|
|
|| typeName == QLatin1String("qreal")) {
|
2010-11-11 16:04:55 +01:00
|
|
|
// ### Review: more types here?
|
2011-07-01 12:11:02 +02:00
|
|
|
value = valueOwner()->realValue();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (typeName == QLatin1String("QFont")) {
|
2011-07-01 12:11:02 +02:00
|
|
|
value = valueOwner()->qmlFontObject();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (typeName == QLatin1String("QPoint")
|
|
|
|
|| typeName == QLatin1String("QPointF")
|
|
|
|
|| typeName == QLatin1String("QVector2D")) {
|
2011-07-01 12:11:02 +02:00
|
|
|
value = valueOwner()->qmlPointObject();
|
2010-04-15 11:36:12 +02:00
|
|
|
} else if (typeName == QLatin1String("QSize")
|
|
|
|
|| typeName == QLatin1String("QSizeF")) {
|
2011-07-01 12:11:02 +02:00
|
|
|
value = valueOwner()->qmlSizeObject();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (typeName == QLatin1String("QRect")
|
|
|
|
|| typeName == QLatin1String("QRectF")) {
|
2011-07-01 12:11:02 +02:00
|
|
|
value = valueOwner()->qmlRectObject();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (typeName == QLatin1String("QVector3D")) {
|
2011-07-01 12:11:02 +02:00
|
|
|
value = valueOwner()->qmlVector3DObject();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (typeName == QLatin1String("QColor")) {
|
2011-07-01 12:11:02 +02:00
|
|
|
value = valueOwner()->colorValue();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else if (typeName == QLatin1String("QDeclarativeAnchorLine")) {
|
2011-07-01 12:11:02 +02:00
|
|
|
value = valueOwner()->anchorLineValue();
|
2010-02-19 15:10:39 +01:00
|
|
|
}
|
|
|
|
|
2010-04-29 15:52:17 +02:00
|
|
|
// might be an enum
|
2011-06-21 15:10:57 +02:00
|
|
|
const QmlObjectValue *base = this;
|
|
|
|
const QStringList components = typeName.split(QLatin1String("::"));
|
|
|
|
if (components.size() == 2) {
|
2011-07-01 12:11:02 +02:00
|
|
|
base = valueOwner()->cppQmlTypes().typeByCppName(components.first());
|
2011-06-21 15:10:57 +02:00
|
|
|
typeName = components.last();
|
|
|
|
}
|
|
|
|
if (base) {
|
|
|
|
const FakeMetaEnum &metaEnum = base->getEnum(typeName);
|
|
|
|
if (metaEnum.isValid())
|
2011-07-01 12:11:02 +02:00
|
|
|
value = new QmlEnumValue(metaEnum, valueOwner());
|
2010-04-29 15:52:17 +02:00
|
|
|
}
|
|
|
|
|
2010-01-26 14:50:52 +01:00
|
|
|
return value;
|
|
|
|
}
|
2010-02-19 15:10:39 +01:00
|
|
|
|
2011-02-10 14:53:57 +01:00
|
|
|
const QmlObjectValue *QmlObjectValue::prototype() const
|
2010-11-11 11:11:48 +01:00
|
|
|
{
|
2011-02-10 14:53:57 +01:00
|
|
|
Q_ASSERT(!_prototype || dynamic_cast<const QmlObjectValue *>(_prototype));
|
|
|
|
return static_cast<const QmlObjectValue *>(_prototype);
|
2010-11-11 11:11:48 +01:00
|
|
|
}
|
|
|
|
|
2011-02-10 17:03:52 +01:00
|
|
|
const QmlObjectValue *QmlObjectValue::attachedType() const
|
|
|
|
{
|
|
|
|
return _attachedType;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QmlObjectValue::setAttachedType(QmlObjectValue *value)
|
|
|
|
{
|
|
|
|
_attachedType = value;
|
|
|
|
}
|
|
|
|
|
2011-02-10 14:53:57 +01:00
|
|
|
FakeMetaObject::ConstPtr QmlObjectValue::metaObject() const
|
2011-02-08 16:18:34 +01:00
|
|
|
{
|
2011-02-10 14:53:57 +01:00
|
|
|
return _metaObject;
|
2011-02-08 16:18:34 +01:00
|
|
|
}
|
|
|
|
|
2011-02-10 14:53:57 +01:00
|
|
|
QString QmlObjectValue::packageName() const
|
|
|
|
{ return _packageName; }
|
|
|
|
|
2010-12-03 11:17:25 +01:00
|
|
|
ComponentVersion QmlObjectValue::version() const
|
2010-10-19 16:15:32 +02:00
|
|
|
{ return _componentVersion; }
|
2010-03-01 13:01:05 +01:00
|
|
|
|
2010-03-31 14:18:57 +02:00
|
|
|
QString QmlObjectValue::defaultPropertyName() const
|
|
|
|
{ return _metaObject->defaultPropertyName(); }
|
|
|
|
|
2010-04-06 11:44:55 +02:00
|
|
|
QString QmlObjectValue::propertyType(const QString &propertyName) const
|
|
|
|
{
|
2011-02-10 14:53:57 +01:00
|
|
|
for (const QmlObjectValue *it = this; it; it = it->prototype()) {
|
|
|
|
FakeMetaObject::ConstPtr iter = it->_metaObject;
|
2010-11-10 16:38:41 +01:00
|
|
|
int propIdx = iter->propertyIndex(propertyName);
|
2010-04-06 11:44:55 +02:00
|
|
|
if (propIdx != -1) {
|
2010-11-10 16:38:41 +01:00
|
|
|
return iter->property(propIdx).typeName();
|
2010-04-06 11:44:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2010-11-10 16:38:41 +01:00
|
|
|
bool QmlObjectValue::isListProperty(const QString &propertyName) const
|
2010-04-06 12:56:53 +02:00
|
|
|
{
|
2011-02-10 14:53:57 +01:00
|
|
|
for (const QmlObjectValue *it = this; it; it = it->prototype()) {
|
|
|
|
FakeMetaObject::ConstPtr iter = it->_metaObject;
|
2010-11-10 16:38:41 +01:00
|
|
|
int propIdx = iter->propertyIndex(propertyName);
|
|
|
|
if (propIdx != -1) {
|
|
|
|
return iter->property(propIdx).isList();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2010-04-06 12:56:53 +02:00
|
|
|
}
|
|
|
|
|
2011-06-21 15:10:57 +02:00
|
|
|
FakeMetaEnum QmlObjectValue::getEnum(const QString &typeName) const
|
|
|
|
{
|
|
|
|
const int index = _metaObject->enumeratorIndex(typeName);
|
|
|
|
if (index == -1)
|
|
|
|
return FakeMetaEnum();
|
|
|
|
|
|
|
|
return _metaObject->enumerator(index);
|
|
|
|
}
|
|
|
|
|
2010-11-11 10:29:32 +01:00
|
|
|
bool QmlObjectValue::isWritable(const QString &propertyName) const
|
|
|
|
{
|
2011-02-10 14:53:57 +01:00
|
|
|
for (const QmlObjectValue *it = this; it; it = it->prototype()) {
|
|
|
|
FakeMetaObject::ConstPtr iter = it->_metaObject;
|
2010-11-11 10:29:32 +01:00
|
|
|
int propIdx = iter->propertyIndex(propertyName);
|
|
|
|
if (propIdx != -1) {
|
|
|
|
return iter->property(propIdx).isWritable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QmlObjectValue::isPointer(const QString &propertyName) const
|
|
|
|
{
|
2011-02-10 14:53:57 +01:00
|
|
|
for (const QmlObjectValue *it = this; it; it = it->prototype()) {
|
|
|
|
FakeMetaObject::ConstPtr iter = it->_metaObject;
|
2010-11-11 10:29:32 +01:00
|
|
|
int propIdx = iter->propertyIndex(propertyName);
|
|
|
|
if (propIdx != -1) {
|
|
|
|
return iter->property(propIdx).isPointer();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-11-11 10:46:19 +01:00
|
|
|
bool QmlObjectValue::hasLocalProperty(const QString &typeName) const
|
|
|
|
{
|
|
|
|
int idx = _metaObject->propertyIndex(typeName);
|
|
|
|
if (idx == -1)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QmlObjectValue::hasProperty(const QString &propertyName) const
|
|
|
|
{
|
2011-02-10 14:53:57 +01:00
|
|
|
for (const QmlObjectValue *it = this; it; it = it->prototype()) {
|
|
|
|
FakeMetaObject::ConstPtr iter = it->_metaObject;
|
2010-11-11 10:46:19 +01:00
|
|
|
int propIdx = iter->propertyIndex(propertyName);
|
|
|
|
if (propIdx != -1) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-06-07 17:33:44 +02:00
|
|
|
// Returns true if this object is in a package or if there is an object that
|
|
|
|
// has this one in its prototype chain and is itself in a package.
|
|
|
|
bool QmlObjectValue::hasChildInPackage() const
|
|
|
|
{
|
2011-06-22 17:18:06 +02:00
|
|
|
if (!packageName().isEmpty()
|
|
|
|
&& packageName() != CppQmlTypes::cppPackage)
|
2010-06-07 17:33:44 +02:00
|
|
|
return true;
|
2011-07-01 12:11:02 +02:00
|
|
|
QHashIterator<QString, QmlObjectValue *> it(valueOwner()->cppQmlTypes().types());
|
2010-06-01 15:10:20 +02:00
|
|
|
while (it.hasNext()) {
|
|
|
|
it.next();
|
2011-06-22 17:18:06 +02:00
|
|
|
FakeMetaObject::ConstPtr otherMeta = it.value()->_metaObject;
|
|
|
|
// if it has only a cpp-package export, it is not really exported
|
|
|
|
if (otherMeta->exports().size() <= 1)
|
2010-06-07 17:33:44 +02:00
|
|
|
continue;
|
2011-06-22 17:18:06 +02:00
|
|
|
for (const QmlObjectValue *other = it.value(); other; other = other->prototype()) {
|
|
|
|
if (other->metaObject() == _metaObject) // this object is a parent of other
|
2010-06-07 17:33:44 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-01-04 17:04:44 +01:00
|
|
|
bool QmlObjectValue::isDerivedFrom(FakeMetaObject::ConstPtr base) const
|
2010-02-19 15:10:39 +01:00
|
|
|
{
|
2011-02-10 14:53:57 +01:00
|
|
|
for (const QmlObjectValue *it = this; it; it = it->prototype()) {
|
|
|
|
FakeMetaObject::ConstPtr iter = it->_metaObject;
|
2010-02-19 15:10:39 +01:00
|
|
|
if (iter == base)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
QmlEnumValue::QmlEnumValue(const FakeMetaEnum &metaEnum, ValueOwner *valueOwner)
|
2010-04-29 15:52:17 +02:00
|
|
|
: NumberValue(),
|
|
|
|
_metaEnum(new FakeMetaEnum(metaEnum))
|
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
valueOwner->registerValue(this);
|
2010-04-29 15:52:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QmlEnumValue::~QmlEnumValue()
|
|
|
|
{
|
|
|
|
delete _metaEnum;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString QmlEnumValue::name() const
|
|
|
|
{
|
|
|
|
return _metaEnum->name();
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringList QmlEnumValue::keys() const
|
|
|
|
{
|
|
|
|
return _metaEnum->keys();
|
|
|
|
}
|
|
|
|
|
2010-01-21 15:54:19 +01:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ValueVisitor
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2010-01-24 11:10:01 +01:00
|
|
|
ValueVisitor::ValueVisitor()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ValueVisitor::~ValueVisitor()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ValueVisitor::visit(const NullValue *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ValueVisitor::visit(const UndefinedValue *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ValueVisitor::visit(const NumberValue *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ValueVisitor::visit(const BooleanValue *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ValueVisitor::visit(const StringValue *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ValueVisitor::visit(const ObjectValue *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ValueVisitor::visit(const FunctionValue *)
|
|
|
|
{
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-02-03 10:24:25 +01:00
|
|
|
void ValueVisitor::visit(const Reference *)
|
|
|
|
{
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-02-23 14:36:38 +01:00
|
|
|
void ValueVisitor::visit(const ColorValue *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-02-23 17:02:50 +01:00
|
|
|
void ValueVisitor::visit(const AnchorLineValue *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-01-21 15:54:19 +01:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Value
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2010-01-24 11:10:01 +01:00
|
|
|
Value::Value()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Value::~Value()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-02-08 12:50:10 +01:00
|
|
|
bool Value::getSourceLocation(QString *, int *, int *) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const NullValue *Value::asNullValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const UndefinedValue *Value::asUndefinedValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const NumberValue *Value::asNumberValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-11-10 16:31:20 +01:00
|
|
|
const IntValue *Value::asIntValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const RealValue *Value::asRealValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const BooleanValue *Value::asBooleanValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const StringValue *Value::asStringValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-11-11 16:04:55 +01:00
|
|
|
const UrlValue *Value::asUrlValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const ObjectValue *Value::asObjectValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const FunctionValue *Value::asFunctionValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-02-03 10:24:25 +01:00
|
|
|
const Reference *Value::asReference() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-02-23 14:36:38 +01:00
|
|
|
const ColorValue *Value::asColorValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-02-23 17:02:50 +01:00
|
|
|
const AnchorLineValue *Value::asAnchorLineValue() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-01-21 15:54:19 +01:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Values
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2010-01-24 11:10:01 +01:00
|
|
|
const NullValue *NullValue::asNullValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NullValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
const UndefinedValue *UndefinedValue::asUndefinedValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UndefinedValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const NumberValue *NumberValue::asNumberValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2010-11-10 16:31:20 +01:00
|
|
|
const RealValue *RealValue::asRealValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const IntValue *IntValue::asIntValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void NumberValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
const BooleanValue *BooleanValue::asBooleanValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BooleanValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
const StringValue *StringValue::asStringValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2010-11-11 16:04:55 +01:00
|
|
|
const UrlValue *UrlValue::asUrlValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void StringValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
2010-02-03 10:24:25 +01:00
|
|
|
|
2010-02-19 10:14:34 +01:00
|
|
|
ScopeChain::ScopeChain()
|
|
|
|
: globalScope(0)
|
|
|
|
, qmlTypes(0)
|
2011-05-27 10:43:06 +02:00
|
|
|
, jsImports(0)
|
2010-02-19 10:14:34 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-02-22 11:21:03 +01:00
|
|
|
ScopeChain::QmlComponentChain::QmlComponentChain()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ScopeChain::QmlComponentChain::~QmlComponentChain()
|
|
|
|
{
|
|
|
|
qDeleteAll(instantiatingComponents);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScopeChain::QmlComponentChain::clear()
|
|
|
|
{
|
|
|
|
qDeleteAll(instantiatingComponents);
|
|
|
|
instantiatingComponents.clear();
|
2010-06-25 17:10:14 +02:00
|
|
|
document = Document::Ptr(0);
|
2010-02-22 11:21:03 +01:00
|
|
|
}
|
|
|
|
|
2010-08-30 14:12:06 +02:00
|
|
|
void ScopeChain::QmlComponentChain::collect(QList<const ObjectValue *> *list) const
|
2010-02-19 10:14:34 +01:00
|
|
|
{
|
2010-08-30 14:12:06 +02:00
|
|
|
foreach (const QmlComponentChain *parent, instantiatingComponents)
|
|
|
|
parent->collect(list);
|
2010-02-19 10:14:34 +01:00
|
|
|
|
2010-06-25 17:10:14 +02:00
|
|
|
if (!document)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (ObjectValue *root = document->bind()->rootObjectValue())
|
|
|
|
list->append(root);
|
|
|
|
if (ObjectValue *ids = document->bind()->idEnvironment())
|
2010-02-19 10:14:34 +01:00
|
|
|
list->append(ids);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScopeChain::update()
|
|
|
|
{
|
2010-02-22 10:21:07 +01:00
|
|
|
_all.clear();
|
2010-02-19 10:14:34 +01:00
|
|
|
|
2010-02-22 10:21:07 +01:00
|
|
|
_all += globalScope;
|
2010-02-19 10:14:34 +01:00
|
|
|
|
2010-04-22 15:59:21 +02:00
|
|
|
// the root scope in js files doesn't see instantiating components
|
|
|
|
if (jsScopes.count() != 1 || !qmlScopeObjects.isEmpty()) {
|
2010-08-27 09:37:01 +02:00
|
|
|
if (qmlComponentScope) {
|
2010-08-30 14:12:06 +02:00
|
|
|
foreach (const QmlComponentChain *parent, qmlComponentScope->instantiatingComponents)
|
|
|
|
parent->collect(&_all);
|
2010-08-27 09:37:01 +02:00
|
|
|
}
|
2010-04-22 15:59:21 +02:00
|
|
|
}
|
2010-02-19 10:14:34 +01:00
|
|
|
|
2010-06-25 17:10:14 +02:00
|
|
|
ObjectValue *root = 0;
|
|
|
|
ObjectValue *ids = 0;
|
2010-08-27 09:37:01 +02:00
|
|
|
if (qmlComponentScope && qmlComponentScope->document) {
|
|
|
|
root = qmlComponentScope->document->bind()->rootObjectValue();
|
|
|
|
ids = qmlComponentScope->document->bind()->idEnvironment();
|
2010-06-25 17:10:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (root && !qmlScopeObjects.contains(root))
|
|
|
|
_all += root;
|
2010-02-22 10:21:07 +01:00
|
|
|
_all += qmlScopeObjects;
|
2010-06-25 17:10:14 +02:00
|
|
|
if (ids)
|
|
|
|
_all += ids;
|
2011-02-21 14:56:16 +01:00
|
|
|
if (qmlTypes)
|
|
|
|
_all += qmlTypes;
|
2011-05-27 10:43:06 +02:00
|
|
|
if (jsImports)
|
|
|
|
_all += jsImports;
|
2010-02-22 10:21:07 +01:00
|
|
|
_all += jsScopes;
|
|
|
|
}
|
|
|
|
|
|
|
|
QList<const ObjectValue *> ScopeChain::all() const
|
|
|
|
{
|
|
|
|
return _all;
|
2010-02-19 10:14:34 +01:00
|
|
|
}
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
Reference::Reference(ValueOwner *valueOwner)
|
|
|
|
: _valueOwner(valueOwner)
|
2010-02-03 10:24:25 +01:00
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
_valueOwner->registerValue(this);
|
2010-02-03 10:24:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Reference::~Reference()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
ValueOwner *Reference::valueOwner() const
|
2010-02-03 14:31:03 +01:00
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
return _valueOwner;
|
2010-02-03 14:31:03 +01:00
|
|
|
}
|
|
|
|
|
2010-02-03 10:24:25 +01:00
|
|
|
const Reference *Reference::asReference() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Reference::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const Value *Reference::value(const Context *) const
|
2010-02-03 14:31:03 +01:00
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
return _valueOwner->undefinedValue();
|
2010-02-03 14:31:03 +01:00
|
|
|
}
|
2010-02-03 10:24:25 +01:00
|
|
|
|
2010-02-23 14:36:38 +01:00
|
|
|
void ColorValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
const ColorValue *ColorValue::asColorValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2010-02-23 17:02:50 +01:00
|
|
|
void AnchorLineValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
const AnchorLineValue *AnchorLineValue::asAnchorLineValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2010-01-26 10:10:11 +01:00
|
|
|
MemberProcessor::MemberProcessor()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
MemberProcessor::~MemberProcessor()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemberProcessor::processProperty(const QString &, const Value *)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-01-28 15:50:58 +01:00
|
|
|
bool MemberProcessor::processEnumerator(const QString &, const Value *)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-01-26 10:10:11 +01:00
|
|
|
bool MemberProcessor::processSignal(const QString &, const Value *)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemberProcessor::processSlot(const QString &, const Value *)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-01-26 10:19:42 +01:00
|
|
|
bool MemberProcessor::processGeneratedSlot(const QString &, const Value *)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
ObjectValue::ObjectValue(ValueOwner *valueOwner)
|
|
|
|
: _valueOwner(valueOwner),
|
2010-02-03 10:59:52 +01:00
|
|
|
_prototype(0)
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
valueOwner->registerValue(this);
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjectValue::~ObjectValue()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
ValueOwner *ObjectValue::valueOwner() const
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
return _valueOwner;
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QString ObjectValue::className() const
|
|
|
|
{
|
|
|
|
return _className;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectValue::setClassName(const QString &className)
|
|
|
|
{
|
|
|
|
_className = className;
|
|
|
|
}
|
|
|
|
|
2011-05-20 13:19:16 +02:00
|
|
|
const Value *ObjectValue::prototype() const
|
|
|
|
{
|
|
|
|
return _prototype;
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const ObjectValue *ObjectValue::prototype(const Context *context) const
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
2010-02-03 15:39:57 +01:00
|
|
|
const ObjectValue *prototypeObject = value_cast<const ObjectValue *>(_prototype);
|
|
|
|
if (! prototypeObject) {
|
|
|
|
if (const Reference *prototypeReference = value_cast<const Reference *>(_prototype)) {
|
2010-06-08 15:36:06 +02:00
|
|
|
prototypeObject = value_cast<const ObjectValue *>(context->lookupReference(prototypeReference));
|
2010-02-03 15:39:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return prototypeObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectValue::setPrototype(const Value *prototype)
|
|
|
|
{
|
|
|
|
_prototype = prototype;
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
2011-05-24 11:50:10 +02:00
|
|
|
void ObjectValue::setMember(const QString &name, const Value *value)
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
|
|
|
_members[name] = value;
|
|
|
|
}
|
|
|
|
|
2011-05-24 11:50:10 +02:00
|
|
|
void ObjectValue::removeMember(const QString &name)
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
|
|
|
_members.remove(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
const ObjectValue *ObjectValue::asObjectValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
2010-02-03 15:39:57 +01:00
|
|
|
bool ObjectValue::checkPrototype(const ObjectValue *, QSet<const ObjectValue *> *) const
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-02-03 15:39:57 +01:00
|
|
|
#if 0
|
2010-01-21 15:54:19 +01:00
|
|
|
const int previousSize = processed->size();
|
|
|
|
processed->insert(this);
|
|
|
|
|
|
|
|
if (previousSize != processed->size()) {
|
|
|
|
if (this == proto)
|
|
|
|
return false;
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
if (prototype() && ! prototype()->checkPrototype(proto, processed))
|
2010-01-21 15:54:19 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2010-02-03 15:39:57 +01:00
|
|
|
#endif
|
2010-01-21 15:54:19 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void ObjectValue::processMembers(MemberProcessor *processor) const
|
|
|
|
{
|
|
|
|
QHashIterator<QString, const Value *> it(_members);
|
|
|
|
|
|
|
|
while (it.hasNext()) {
|
|
|
|
it.next();
|
|
|
|
|
2010-01-26 10:10:11 +01:00
|
|
|
if (! processor->processProperty(it.key(), it.value()))
|
2010-01-24 11:10:01 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-17 14:20:06 +01:00
|
|
|
const Value *ObjectValue::lookupMember(const QString &name, const Context *context,
|
|
|
|
const ObjectValue **foundInObject,
|
|
|
|
bool examinePrototypes) const
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
2010-11-17 14:20:06 +01:00
|
|
|
if (const Value *m = _members.value(name)) {
|
|
|
|
if (foundInObject)
|
|
|
|
*foundInObject = this;
|
2010-01-24 11:10:01 +01:00
|
|
|
return m;
|
2010-11-17 14:20:06 +01:00
|
|
|
} else {
|
2010-02-01 13:54:44 +01:00
|
|
|
LookupMember slowLookup(name);
|
|
|
|
processMembers(&slowLookup);
|
2010-11-17 14:20:06 +01:00
|
|
|
if (slowLookup.value()) {
|
|
|
|
if (foundInObject)
|
|
|
|
*foundInObject = this;
|
2010-02-01 13:54:44 +01:00
|
|
|
return slowLookup.value();
|
2010-11-17 14:20:06 +01:00
|
|
|
}
|
2010-02-01 13:54:44 +01:00
|
|
|
}
|
2010-01-24 11:10:01 +01:00
|
|
|
|
2010-04-06 11:44:55 +02:00
|
|
|
if (examinePrototypes) {
|
2010-11-12 14:53:00 +01:00
|
|
|
PrototypeIterator iter(this, context);
|
|
|
|
iter.next(); // skip this
|
|
|
|
while (iter.hasNext()) {
|
|
|
|
const ObjectValue *prototypeObject = iter.next();
|
2010-11-17 14:20:06 +01:00
|
|
|
if (const Value *m = prototypeObject->lookupMember(name, context, foundInObject, false))
|
2010-04-06 11:44:55 +02:00
|
|
|
return m;
|
|
|
|
}
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
2010-11-17 14:20:06 +01:00
|
|
|
if (foundInObject)
|
|
|
|
*foundInObject = 0;
|
2010-01-24 11:10:01 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-11-12 14:53:00 +01:00
|
|
|
PrototypeIterator::PrototypeIterator(const ObjectValue *start, const Context *context)
|
|
|
|
: m_current(0)
|
|
|
|
, m_next(start)
|
|
|
|
, m_context(context)
|
2011-05-25 11:48:47 +02:00
|
|
|
, m_error(NoError)
|
2010-11-12 14:53:00 +01:00
|
|
|
{
|
|
|
|
if (start)
|
|
|
|
m_prototypes.reserve(10);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PrototypeIterator::hasNext()
|
|
|
|
{
|
|
|
|
if (m_next)
|
|
|
|
return true;
|
|
|
|
if (!m_current)
|
|
|
|
return false;
|
2011-05-20 13:19:16 +02:00
|
|
|
const Value *proto = m_current->prototype();
|
|
|
|
if (!proto)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
m_next = value_cast<const ObjectValue *>(proto);
|
|
|
|
if (! m_next)
|
|
|
|
m_next = value_cast<const ObjectValue *>(m_context->lookupReference(proto));
|
|
|
|
if (!m_next) {
|
|
|
|
m_error = ReferenceResolutionError;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (m_prototypes.contains(m_next)) {
|
|
|
|
m_error = CycleError;
|
2010-11-12 14:53:00 +01:00
|
|
|
m_next = 0;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ObjectValue *PrototypeIterator::next()
|
|
|
|
{
|
|
|
|
if (hasNext()) {
|
|
|
|
m_current = m_next;
|
|
|
|
m_prototypes += m_next;
|
|
|
|
m_next = 0;
|
|
|
|
return m_current;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ObjectValue *PrototypeIterator::peekNext()
|
|
|
|
{
|
|
|
|
if (hasNext()) {
|
|
|
|
return m_next;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-05-20 13:19:16 +02:00
|
|
|
PrototypeIterator::Error PrototypeIterator::error() const
|
|
|
|
{
|
|
|
|
return m_error;
|
|
|
|
}
|
|
|
|
|
2010-11-12 14:53:00 +01:00
|
|
|
QList<const ObjectValue *> PrototypeIterator::all()
|
|
|
|
{
|
|
|
|
while (hasNext())
|
|
|
|
next();
|
|
|
|
return m_prototypes;
|
|
|
|
}
|
|
|
|
|
2010-02-03 15:39:57 +01:00
|
|
|
Activation::Activation(Context *parentContext)
|
2010-01-28 14:11:56 +01:00
|
|
|
: _thisObject(0),
|
2010-02-03 15:39:57 +01:00
|
|
|
_calledAsFunction(true),
|
|
|
|
_parentContext(parentContext)
|
2010-01-24 11:35:11 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Activation::~Activation()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-02-03 15:39:57 +01:00
|
|
|
Context *Activation::parentContext() const
|
|
|
|
{
|
|
|
|
return _parentContext;
|
|
|
|
}
|
|
|
|
|
|
|
|
Context *Activation::context() const
|
|
|
|
{
|
|
|
|
// ### FIXME: Real context for activations.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
bool Activation::calledAsConstructor() const
|
|
|
|
{
|
|
|
|
return ! _calledAsFunction;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Activation::setCalledAsConstructor(bool calledAsConstructor)
|
|
|
|
{
|
|
|
|
_calledAsFunction = ! calledAsConstructor;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Activation::calledAsFunction() const
|
|
|
|
{
|
|
|
|
return _calledAsFunction;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Activation::setCalledAsFunction(bool calledAsFunction)
|
|
|
|
{
|
|
|
|
_calledAsFunction = calledAsFunction;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectValue *Activation::thisObject() const
|
|
|
|
{
|
|
|
|
return _thisObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Activation::setThisObject(ObjectValue *thisObject)
|
|
|
|
{
|
|
|
|
_thisObject = thisObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
ValueList Activation::arguments() const
|
|
|
|
{
|
|
|
|
return _arguments;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Activation::setArguments(const ValueList &arguments)
|
|
|
|
{
|
|
|
|
_arguments = arguments;
|
|
|
|
}
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
FunctionValue::FunctionValue(ValueOwner *valueOwner)
|
|
|
|
: ObjectValue(valueOwner)
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
2011-07-04 09:24:24 +02:00
|
|
|
setMember(QLatin1String("length"), valueOwner->numberValue());
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
FunctionValue::~FunctionValue()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
const Value *FunctionValue::construct(const ValueList &actuals) const
|
|
|
|
{
|
2010-01-28 14:11:56 +01:00
|
|
|
Activation activation;
|
2010-01-24 11:35:11 +01:00
|
|
|
activation.setCalledAsConstructor(true);
|
2011-07-01 12:11:02 +02:00
|
|
|
activation.setThisObject(valueOwner()->newObject());
|
2010-01-24 11:35:11 +01:00
|
|
|
activation.setArguments(actuals);
|
|
|
|
return invoke(&activation);
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const Value *FunctionValue::call(const ValueList &actuals) const
|
|
|
|
{
|
2010-01-28 14:11:56 +01:00
|
|
|
Activation activation;
|
2010-01-24 11:35:11 +01:00
|
|
|
activation.setCalledAsFunction(true);
|
2011-07-01 12:11:02 +02:00
|
|
|
activation.setThisObject(valueOwner()->globalObject()); // ### FIXME: it should be `null'
|
2010-01-24 11:35:11 +01:00
|
|
|
activation.setArguments(actuals);
|
|
|
|
return invoke(&activation);
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const Value *FunctionValue::call(const ObjectValue *thisObject, const ValueList &actuals) const
|
|
|
|
{
|
2010-01-28 14:11:56 +01:00
|
|
|
Activation activation;
|
2010-01-24 11:35:11 +01:00
|
|
|
activation.setCalledAsFunction(true);
|
|
|
|
activation.setThisObject(const_cast<ObjectValue *>(thisObject)); // ### FIXME: remove the const_cast
|
|
|
|
activation.setArguments(actuals);
|
|
|
|
return invoke(&activation);
|
2010-01-24 11:10:01 +01:00
|
|
|
}
|
|
|
|
|
2010-01-26 10:50:30 +01:00
|
|
|
const Value *FunctionValue::returnValue() const
|
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
return valueOwner()->undefinedValue();
|
2010-01-26 10:50:30 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
int FunctionValue::argumentCount() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-01-26 10:50:30 +01:00
|
|
|
const Value *FunctionValue::argument(int) const
|
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
return valueOwner()->undefinedValue();
|
2010-01-26 10:50:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QString FunctionValue::argumentName(int index) const
|
|
|
|
{
|
2010-02-01 12:43:36 +01:00
|
|
|
return QString::fromLatin1("arg%1").arg(index + 1);
|
2010-01-26 10:50:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool FunctionValue::isVariadic() const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Value *FunctionValue::invoke(const Activation *activation) const
|
|
|
|
{
|
|
|
|
return activation->thisObject(); // ### FIXME: it should return undefined
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const FunctionValue *FunctionValue::asFunctionValue() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FunctionValue::accept(ValueVisitor *visitor) const
|
|
|
|
{
|
|
|
|
visitor->visit(this);
|
|
|
|
}
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
Function::Function(ValueOwner *valueOwner)
|
|
|
|
: FunctionValue(valueOwner), _returnValue(0)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
setClassName("Function");
|
2010-01-21 15:54:19 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
Function::~Function()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void Function::addArgument(const Value *argument)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
_arguments.push_back(argument);
|
2010-01-21 15:54:19 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *Function::returnValue() const
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
return _returnValue;
|
2010-01-21 15:54:19 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void Function::setReturnValue(const Value *returnValue)
|
|
|
|
{
|
|
|
|
_returnValue = returnValue;
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
int Function::argumentCount() const
|
|
|
|
{
|
|
|
|
return _arguments.size();
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *Function::argument(int index) const
|
|
|
|
{
|
|
|
|
return _arguments.at(index);
|
2010-01-21 15:54:19 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:35:11 +01:00
|
|
|
const Value *Function::invoke(const Activation *activation) const
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:35:11 +01:00
|
|
|
return activation->thisObject(); // ### FIXME it should return undefined
|
2010-01-21 15:54:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// typing environment
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2010-03-01 13:01:05 +01:00
|
|
|
|
2011-06-28 12:01:56 +02:00
|
|
|
CppQmlTypesLoader::BuiltinObjects CppQmlTypesLoader::defaultLibraryObjects;
|
|
|
|
CppQmlTypesLoader::BuiltinObjects CppQmlTypesLoader::defaultQtObjects;
|
2010-03-01 13:01:05 +01:00
|
|
|
|
2011-06-28 12:01:56 +02:00
|
|
|
CppQmlTypesLoader::BuiltinObjects CppQmlTypesLoader::loadQmlTypes(const QFileInfoList &qmlTypeFiles, QStringList *errors, QStringList *warnings)
|
2010-06-01 15:10:20 +02:00
|
|
|
{
|
2011-02-10 14:53:57 +01:00
|
|
|
QHash<QString, FakeMetaObject::ConstPtr> newObjects;
|
2010-03-01 13:01:05 +01:00
|
|
|
|
2011-02-08 13:22:34 +01:00
|
|
|
foreach (const QFileInfo &qmlTypeFile, qmlTypeFiles) {
|
2011-05-30 11:10:06 +02:00
|
|
|
QString error, warning;
|
2011-02-08 13:22:34 +01:00
|
|
|
QFile file(qmlTypeFile.absoluteFilePath());
|
2010-03-01 13:01:05 +01:00
|
|
|
if (file.open(QIODevice::ReadOnly)) {
|
2011-02-08 13:22:34 +01:00
|
|
|
QString contents = QString::fromUtf8(file.readAll());
|
2010-03-01 13:01:05 +01:00
|
|
|
file.close();
|
2011-02-08 13:22:34 +01:00
|
|
|
|
|
|
|
QmlJS::TypeDescriptionReader reader(contents);
|
2011-05-30 11:10:06 +02:00
|
|
|
if (!reader(&newObjects))
|
|
|
|
error = reader.errorMessage();
|
|
|
|
warning = reader.warningMessage();
|
2010-03-01 13:01:05 +01:00
|
|
|
} else {
|
2011-05-30 11:10:06 +02:00
|
|
|
error = file.errorString();
|
|
|
|
}
|
|
|
|
if (!error.isEmpty()) {
|
2011-05-30 12:56:24 +02:00
|
|
|
errors->append(TypeDescriptionReader::tr(
|
|
|
|
"Errors while loading qmltypes from %1:\n%2").arg(
|
|
|
|
qmlTypeFile.absoluteFilePath(), error));
|
2011-05-30 11:10:06 +02:00
|
|
|
}
|
|
|
|
if (!warning.isEmpty()) {
|
2011-05-30 12:56:24 +02:00
|
|
|
warnings->append(TypeDescriptionReader::tr(
|
|
|
|
"Warnings while loading qmltypes from %1:\n%2").arg(
|
|
|
|
qmlTypeFile.absoluteFilePath(), error));
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-28 12:01:56 +02:00
|
|
|
return newObjects;
|
2010-06-01 15:10:20 +02:00
|
|
|
}
|
|
|
|
|
2011-05-30 11:10:06 +02:00
|
|
|
void CppQmlTypesLoader::parseQmlTypeDescriptions(const QByteArray &xml,
|
2011-06-28 12:01:56 +02:00
|
|
|
BuiltinObjects *newObjects,
|
2011-05-30 11:10:06 +02:00
|
|
|
QString *errorMessage,
|
|
|
|
QString *warningMessage)
|
2010-06-01 15:10:20 +02:00
|
|
|
{
|
2011-05-30 11:10:06 +02:00
|
|
|
errorMessage->clear();
|
|
|
|
warningMessage->clear();
|
2011-02-08 13:22:34 +01:00
|
|
|
QmlJS::TypeDescriptionReader reader(QString::fromUtf8(xml));
|
2010-06-09 14:27:30 +02:00
|
|
|
if (!reader(newObjects)) {
|
2011-05-30 11:10:06 +02:00
|
|
|
if (reader.errorMessage().isEmpty()) {
|
|
|
|
*errorMessage = QLatin1String("unknown error");
|
|
|
|
} else {
|
|
|
|
*errorMessage = reader.errorMessage();
|
|
|
|
}
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
2011-05-30 11:10:06 +02:00
|
|
|
*warningMessage = reader.warningMessage();
|
2010-06-01 15:10:20 +02:00
|
|
|
}
|
2010-03-01 13:01:05 +01:00
|
|
|
|
2011-02-08 16:18:34 +01:00
|
|
|
const QLatin1String CppQmlTypes::defaultPackage("<default>");
|
|
|
|
const QLatin1String CppQmlTypes::cppPackage("<cpp>");
|
|
|
|
|
2011-02-08 13:22:34 +01:00
|
|
|
template <typename T>
|
2011-07-01 12:11:02 +02:00
|
|
|
QList<QmlObjectValue *> CppQmlTypes::load(ValueOwner *valueOwner, const T &objects)
|
2010-03-01 13:01:05 +01:00
|
|
|
{
|
2010-06-09 14:27:30 +02:00
|
|
|
// load
|
2011-04-20 10:46:04 +02:00
|
|
|
QList<QmlObjectValue *> loadedObjects;
|
2011-02-10 14:53:57 +01:00
|
|
|
QList<QmlObjectValue *> newObjects;
|
2011-01-04 17:04:44 +01:00
|
|
|
foreach (FakeMetaObject::ConstPtr metaObject, objects) {
|
2011-02-10 14:53:57 +01:00
|
|
|
foreach (const FakeMetaObject::Export &exp, metaObject->exports()) {
|
2011-04-20 10:46:04 +02:00
|
|
|
bool wasCreated;
|
2011-07-01 12:11:02 +02:00
|
|
|
QmlObjectValue *loadedObject = getOrCreate(valueOwner, metaObject, exp, &wasCreated);
|
2011-04-20 10:46:04 +02:00
|
|
|
loadedObjects += loadedObject;
|
|
|
|
if (wasCreated)
|
|
|
|
newObjects += loadedObject;
|
2011-02-10 14:53:57 +01:00
|
|
|
}
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
|
|
|
|
2010-10-19 16:15:32 +02:00
|
|
|
// set prototypes
|
2011-02-10 14:53:57 +01:00
|
|
|
foreach (QmlObjectValue *object, newObjects) {
|
|
|
|
setPrototypes(object);
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
2011-03-10 14:49:38 +01:00
|
|
|
|
2011-04-20 10:46:04 +02:00
|
|
|
return loadedObjects;
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
2011-02-08 13:22:34 +01:00
|
|
|
// explicitly instantiate load for list and hash
|
2011-07-01 12:11:02 +02:00
|
|
|
template QList<QmlObjectValue *> CppQmlTypes::load< QList<FakeMetaObject::ConstPtr> >(ValueOwner *, const QList<FakeMetaObject::ConstPtr> &);
|
|
|
|
template QList<QmlObjectValue *> CppQmlTypes::load< QHash<QString, FakeMetaObject::ConstPtr> >(ValueOwner *, const QHash<QString, FakeMetaObject::ConstPtr> &);
|
2010-03-01 13:01:05 +01:00
|
|
|
|
2010-12-03 11:17:25 +01:00
|
|
|
QList<QmlObjectValue *> CppQmlTypes::typesForImport(const QString &packageName, ComponentVersion version) const
|
2010-03-01 13:01:05 +01:00
|
|
|
{
|
|
|
|
QMap<QString, QmlObjectValue *> objectValuesByName;
|
|
|
|
|
2010-06-09 14:27:30 +02:00
|
|
|
foreach (QmlObjectValue *qmlObjectValue, _typesByPackage.value(packageName)) {
|
2010-06-01 15:36:52 +02:00
|
|
|
if (qmlObjectValue->version() <= version) {
|
2010-03-01 13:01:05 +01:00
|
|
|
// we got a candidate.
|
|
|
|
const QString typeName = qmlObjectValue->className();
|
|
|
|
QmlObjectValue *previousCandidate = objectValuesByName.value(typeName, 0);
|
|
|
|
if (previousCandidate) {
|
|
|
|
// check if our new candidate is newer than the one we found previously
|
2010-06-01 15:36:52 +02:00
|
|
|
if (previousCandidate->version() < qmlObjectValue->version()) {
|
2010-03-01 13:01:05 +01:00
|
|
|
// the new candidate has a higher version no. than the one we found previously, so replace it
|
|
|
|
objectValuesByName.insert(typeName, qmlObjectValue);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
objectValuesByName.insert(typeName, qmlObjectValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return objectValuesByName.values();
|
|
|
|
}
|
|
|
|
|
2011-02-08 16:18:34 +01:00
|
|
|
QmlObjectValue *CppQmlTypes::typeByCppName(const QString &cppName) const
|
2010-03-01 13:01:05 +01:00
|
|
|
{
|
2011-02-08 16:18:34 +01:00
|
|
|
return typeByQualifiedName(cppPackage, cppName, ComponentVersion());
|
2010-03-01 13:01:05 +01:00
|
|
|
}
|
|
|
|
|
2010-06-01 15:10:20 +02:00
|
|
|
bool CppQmlTypes::hasPackage(const QString &package) const
|
2010-03-16 16:34:33 +01:00
|
|
|
{
|
2010-06-09 14:27:30 +02:00
|
|
|
return _typesByPackage.contains(package);
|
2010-03-16 16:34:33 +01:00
|
|
|
}
|
|
|
|
|
2010-12-03 11:17:25 +01:00
|
|
|
QString CppQmlTypes::qualifiedName(const QString &package, const QString &type, ComponentVersion version)
|
2010-10-19 16:15:32 +02:00
|
|
|
{
|
2011-02-09 09:51:35 +01:00
|
|
|
return QString("%1/%2 %3").arg(
|
2010-10-19 16:15:32 +02:00
|
|
|
package, type,
|
2011-02-08 11:01:37 +01:00
|
|
|
version.toString());
|
|
|
|
|
2010-10-19 16:15:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QmlObjectValue *CppQmlTypes::typeByQualifiedName(const QString &name) const
|
|
|
|
{
|
|
|
|
return _typesByFullyQualifiedName.value(name);
|
|
|
|
}
|
|
|
|
|
2010-12-03 11:17:25 +01:00
|
|
|
QmlObjectValue *CppQmlTypes::typeByQualifiedName(const QString &package, const QString &type, ComponentVersion version) const
|
2010-10-19 16:15:32 +02:00
|
|
|
{
|
|
|
|
return typeByQualifiedName(qualifiedName(package, type, version));
|
|
|
|
}
|
|
|
|
|
2011-04-20 10:46:04 +02:00
|
|
|
QmlObjectValue *CppQmlTypes::getOrCreate(
|
2011-07-01 12:11:02 +02:00
|
|
|
ValueOwner *valueOwner,
|
2011-02-10 14:53:57 +01:00
|
|
|
FakeMetaObject::ConstPtr metaObject,
|
2011-04-20 10:46:04 +02:00
|
|
|
const LanguageUtils::FakeMetaObject::Export &exp,
|
|
|
|
bool *wasCreated)
|
2011-02-08 16:18:34 +01:00
|
|
|
{
|
|
|
|
// make sure we're not loading duplicate objects
|
2011-04-20 10:46:04 +02:00
|
|
|
if (QmlObjectValue *existing = _typesByFullyQualifiedName.value(exp.packageNameVersion)) {
|
|
|
|
if (wasCreated)
|
|
|
|
*wasCreated = false;
|
|
|
|
return existing;
|
|
|
|
}
|
2011-02-08 16:18:34 +01:00
|
|
|
|
|
|
|
QmlObjectValue *objectValue = new QmlObjectValue(
|
2011-07-01 12:11:02 +02:00
|
|
|
metaObject, exp.type, exp.package, exp.version, valueOwner);
|
2011-02-08 16:18:34 +01:00
|
|
|
_typesByPackage[exp.package].append(objectValue);
|
|
|
|
_typesByFullyQualifiedName[exp.packageNameVersion] = objectValue;
|
2011-04-20 10:46:04 +02:00
|
|
|
|
|
|
|
if (wasCreated)
|
|
|
|
*wasCreated = true;
|
2011-02-10 14:53:57 +01:00
|
|
|
return objectValue;
|
2011-02-08 16:18:34 +01:00
|
|
|
}
|
|
|
|
|
2011-02-10 14:53:57 +01:00
|
|
|
void CppQmlTypes::setPrototypes(QmlObjectValue *object)
|
2011-02-09 13:22:23 +01:00
|
|
|
{
|
2011-02-10 17:03:52 +01:00
|
|
|
if (!object)
|
2011-02-09 13:22:23 +01:00
|
|
|
return;
|
|
|
|
|
2011-02-10 17:03:52 +01:00
|
|
|
FakeMetaObject::ConstPtr fmo = object->metaObject();
|
|
|
|
|
|
|
|
// resolve attached type
|
2011-03-11 10:18:42 +01:00
|
|
|
// don't do it if the attached type name is the object itself (happens for QDeclarativeKeysAttached)
|
|
|
|
if (!fmo->attachedTypeName().isEmpty()
|
|
|
|
&& fmo->className() != fmo->attachedTypeName()) {
|
2011-02-10 17:03:52 +01:00
|
|
|
QmlObjectValue *attachedObject = typeByCppName(fmo->attachedTypeName());
|
2011-03-11 10:18:42 +01:00
|
|
|
if (attachedObject && attachedObject != object)
|
2011-02-10 17:03:52 +01:00
|
|
|
object->setAttachedType(attachedObject);
|
|
|
|
}
|
|
|
|
|
2011-02-10 14:53:57 +01:00
|
|
|
const QString targetPackage = object->packageName();
|
|
|
|
|
2011-02-09 13:22:23 +01:00
|
|
|
// set prototypes for whole chain, creating new QmlObjectValues if necessary
|
|
|
|
// for instance, if an type isn't exported in the package of the super type
|
|
|
|
// Example: QObject (Qt, QtQuick) -> Positioner (not exported) -> Column (Qt, QtQuick)
|
|
|
|
// needs to create Positioner (Qt) and Positioner (QtQuick)
|
2011-02-10 14:53:57 +01:00
|
|
|
QmlObjectValue *v = object;
|
|
|
|
while (!v->prototype() && !fmo->superclassName().isEmpty()) {
|
2011-04-20 10:46:04 +02:00
|
|
|
QmlObjectValue *superValue = getOrCreateForPackage(targetPackage, fmo->superclassName());
|
2011-02-10 14:53:57 +01:00
|
|
|
if (!superValue)
|
|
|
|
return;
|
2011-02-09 13:22:23 +01:00
|
|
|
v->setPrototype(superValue);
|
|
|
|
v = superValue;
|
2011-02-10 14:53:57 +01:00
|
|
|
fmo = v->metaObject();
|
2011-02-09 13:22:23 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-20 10:46:04 +02:00
|
|
|
QmlObjectValue *CppQmlTypes::getOrCreateForPackage(const QString &package, const QString &cppName)
|
2010-10-19 16:15:32 +02:00
|
|
|
{
|
2011-02-10 14:53:57 +01:00
|
|
|
// first get the cpp object value
|
|
|
|
QmlObjectValue *cppObject = typeByCppName(cppName);
|
|
|
|
if (!cppObject) {
|
2011-04-26 14:42:33 +02:00
|
|
|
// ### disabled for now, should be communicated to the user somehow.
|
|
|
|
//qWarning() << "QML type system: could not find '" << cppName << "'";
|
2011-02-10 14:53:57 +01:00
|
|
|
return 0;
|
2010-10-19 16:15:32 +02:00
|
|
|
}
|
|
|
|
|
2011-02-10 14:53:57 +01:00
|
|
|
FakeMetaObject::ConstPtr metaObject = cppObject->metaObject();
|
|
|
|
FakeMetaObject::Export exp = metaObject->exportInPackage(package);
|
|
|
|
QmlObjectValue *object = 0;
|
|
|
|
if (exp.isValid()) {
|
2011-07-01 12:11:02 +02:00
|
|
|
object = getOrCreate(cppObject->valueOwner(), metaObject, exp);
|
2010-10-19 16:15:32 +02:00
|
|
|
} else {
|
2011-04-20 10:46:04 +02:00
|
|
|
// make a convenience object that does not get added to _typesByPackage
|
2011-02-10 14:53:57 +01:00
|
|
|
const QString qname = qualifiedName(package, cppName, ComponentVersion());
|
|
|
|
object = typeByQualifiedName(qname);
|
|
|
|
if (!object) {
|
|
|
|
object = new QmlObjectValue(
|
2011-07-01 12:11:02 +02:00
|
|
|
metaObject, cppName, package, ComponentVersion(), cppObject->valueOwner());
|
2011-02-10 14:53:57 +01:00
|
|
|
_typesByFullyQualifiedName[qname] = object;
|
|
|
|
}
|
2010-10-19 16:15:32 +02:00
|
|
|
}
|
|
|
|
|
2011-02-10 14:53:57 +01:00
|
|
|
return object;
|
2010-10-19 16:15:32 +02:00
|
|
|
}
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
ConvertToNumber::ConvertToNumber(ValueOwner *valueOwner)
|
|
|
|
: _valueOwner(valueOwner), _result(0)
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *ConvertToNumber::operator()(const Value *value)
|
|
|
|
{
|
2010-01-21 15:54:19 +01:00
|
|
|
const Value *previousValue = switchResult(0);
|
|
|
|
|
|
|
|
if (value)
|
|
|
|
value->accept(this);
|
|
|
|
|
|
|
|
return switchResult(previousValue);
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *ConvertToNumber::switchResult(const Value *value)
|
|
|
|
{
|
2010-01-21 15:54:19 +01:00
|
|
|
const Value *previousResult = _result;
|
|
|
|
_result = value;
|
|
|
|
return previousResult;
|
|
|
|
}
|
|
|
|
|
2010-01-26 15:12:47 +01:00
|
|
|
void ConvertToNumber::visit(const NullValue *)
|
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
_result = _valueOwner->numberValue();
|
2010-01-26 15:12:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToNumber::visit(const UndefinedValue *)
|
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
_result = _valueOwner->numberValue();
|
2010-01-26 15:12:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToNumber::visit(const NumberValue *value)
|
|
|
|
{
|
|
|
|
_result = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToNumber::visit(const BooleanValue *)
|
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
_result = _valueOwner->numberValue();
|
2010-01-26 15:12:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToNumber::visit(const StringValue *)
|
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
_result = _valueOwner->numberValue();
|
2010-01-26 15:12:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToNumber::visit(const ObjectValue *object)
|
|
|
|
{
|
2010-02-03 15:39:57 +01:00
|
|
|
if (const FunctionValue *valueOfMember = value_cast<const FunctionValue *>(object->lookupMember("valueOf", 0))) {
|
2010-01-26 15:12:47 +01:00
|
|
|
_result = value_cast<const NumberValue *>(valueOfMember->call(object)); // ### invoke convert-to-number?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToNumber::visit(const FunctionValue *object)
|
|
|
|
{
|
2010-02-03 15:39:57 +01:00
|
|
|
if (const FunctionValue *valueOfMember = value_cast<const FunctionValue *>(object->lookupMember("valueOf", 0))) {
|
2010-01-26 15:12:47 +01:00
|
|
|
_result = value_cast<const NumberValue *>(valueOfMember->call(object)); // ### invoke convert-to-number?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
ConvertToString::ConvertToString(ValueOwner *valueOwner)
|
|
|
|
: _valueOwner(valueOwner), _result(0)
|
2010-01-24 11:10:01 +01:00
|
|
|
{
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *ConvertToString::operator()(const Value *value)
|
|
|
|
{
|
2010-01-21 15:54:19 +01:00
|
|
|
const Value *previousValue = switchResult(0);
|
|
|
|
|
|
|
|
if (value)
|
|
|
|
value->accept(this);
|
|
|
|
|
|
|
|
return switchResult(previousValue);
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *ConvertToString::switchResult(const Value *value)
|
|
|
|
{
|
2010-01-21 15:54:19 +01:00
|
|
|
const Value *previousResult = _result;
|
|
|
|
_result = value;
|
|
|
|
return previousResult;
|
|
|
|
}
|
|
|
|
|
2010-01-26 15:12:47 +01:00
|
|
|
void ConvertToString::visit(const NullValue *)
|
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
_result = _valueOwner->stringValue();
|
2010-01-26 15:12:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToString::visit(const UndefinedValue *)
|
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
_result = _valueOwner->stringValue();
|
2010-01-26 15:12:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToString::visit(const NumberValue *)
|
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
_result = _valueOwner->stringValue();
|
2010-01-26 15:12:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToString::visit(const BooleanValue *)
|
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
_result = _valueOwner->stringValue();
|
2010-01-26 15:12:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToString::visit(const StringValue *value)
|
|
|
|
{
|
|
|
|
_result = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToString::visit(const ObjectValue *object)
|
|
|
|
{
|
2010-02-03 15:39:57 +01:00
|
|
|
if (const FunctionValue *toStringMember = value_cast<const FunctionValue *>(object->lookupMember("toString", 0))) {
|
2010-01-26 15:12:47 +01:00
|
|
|
_result = value_cast<const StringValue *>(toStringMember->call(object)); // ### invoke convert-to-string?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToString::visit(const FunctionValue *object)
|
|
|
|
{
|
2010-02-03 15:39:57 +01:00
|
|
|
if (const FunctionValue *toStringMember = value_cast<const FunctionValue *>(object->lookupMember("toString", 0))) {
|
2010-01-26 15:12:47 +01:00
|
|
|
_result = value_cast<const StringValue *>(toStringMember->call(object)); // ### invoke convert-to-string?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
ConvertToObject::ConvertToObject(ValueOwner *valueOwner)
|
|
|
|
: _valueOwner(valueOwner), _result(0)
|
2010-01-22 14:42:15 +01:00
|
|
|
{
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *ConvertToObject::operator()(const Value *value)
|
|
|
|
{
|
2010-01-21 15:54:19 +01:00
|
|
|
const Value *previousValue = switchResult(0);
|
|
|
|
|
|
|
|
if (value)
|
|
|
|
value->accept(this);
|
|
|
|
|
|
|
|
return switchResult(previousValue);
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
const Value *ConvertToObject::switchResult(const Value *value)
|
|
|
|
{
|
2010-01-21 15:54:19 +01:00
|
|
|
const Value *previousResult = _result;
|
|
|
|
_result = value;
|
|
|
|
return previousResult;
|
|
|
|
}
|
|
|
|
|
2010-01-22 14:42:15 +01:00
|
|
|
void ConvertToObject::visit(const NullValue *value)
|
|
|
|
{
|
|
|
|
_result = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToObject::visit(const UndefinedValue *)
|
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
_result = _valueOwner->nullValue();
|
2010-01-22 14:42:15 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void ConvertToObject::visit(const NumberValue *value)
|
2010-01-22 14:42:15 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
ValueList actuals;
|
|
|
|
actuals.append(value);
|
2011-07-01 12:11:02 +02:00
|
|
|
_result = _valueOwner->numberCtor()->construct(actuals);
|
2010-01-22 14:42:15 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void ConvertToObject::visit(const BooleanValue *value)
|
2010-01-22 14:42:15 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
ValueList actuals;
|
|
|
|
actuals.append(value);
|
2011-07-01 12:11:02 +02:00
|
|
|
_result = _valueOwner->booleanCtor()->construct(actuals);
|
2010-01-22 14:42:15 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void ConvertToObject::visit(const StringValue *value)
|
2010-01-22 14:42:15 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
ValueList actuals;
|
|
|
|
actuals.append(value);
|
2011-07-01 12:11:02 +02:00
|
|
|
_result = _valueOwner->stringCtor()->construct(actuals);
|
2010-01-22 14:42:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToObject::visit(const ObjectValue *object)
|
|
|
|
{
|
|
|
|
_result = object;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertToObject::visit(const FunctionValue *object)
|
|
|
|
{
|
|
|
|
_result = object;
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
|
|
|
QString TypeId::operator()(const Value *value)
|
|
|
|
{
|
|
|
|
_result = QLatin1String("unknown");
|
|
|
|
|
|
|
|
if (value)
|
|
|
|
value->accept(this);
|
|
|
|
|
|
|
|
return _result;
|
|
|
|
}
|
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void TypeId::visit(const NullValue *)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
_result = QLatin1String("null");
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void TypeId::visit(const UndefinedValue *)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
_result = QLatin1String("undefined");
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void TypeId::visit(const NumberValue *)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
_result = QLatin1String("number");
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void TypeId::visit(const BooleanValue *)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
_result = QLatin1String("boolean");
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void TypeId::visit(const StringValue *)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
_result = QLatin1String("string");
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void TypeId::visit(const ObjectValue *object)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
_result = object->className();
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
if (_result.isEmpty())
|
|
|
|
_result = QLatin1String("object");
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
void TypeId::visit(const FunctionValue *object)
|
2010-01-21 15:54:19 +01:00
|
|
|
{
|
2010-01-24 11:10:01 +01:00
|
|
|
_result = object->className();
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-01-24 11:10:01 +01:00
|
|
|
if (_result.isEmpty())
|
|
|
|
_result = QLatin1String("Function");
|
|
|
|
}
|
2010-01-21 15:54:19 +01:00
|
|
|
|
2010-02-23 17:02:50 +01:00
|
|
|
void TypeId::visit(const ColorValue *)
|
|
|
|
{
|
|
|
|
_result = QLatin1String("string");
|
|
|
|
}
|
|
|
|
|
|
|
|
void TypeId::visit(const AnchorLineValue *)
|
|
|
|
{
|
|
|
|
_result = QLatin1String("AnchorLine");
|
|
|
|
}
|
|
|
|
|
2010-02-08 12:50:10 +01:00
|
|
|
ASTObjectValue::ASTObjectValue(UiQualifiedId *typeName,
|
|
|
|
UiObjectInitializer *initializer,
|
2010-02-09 12:27:52 +01:00
|
|
|
const QmlJS::Document *doc,
|
2011-07-01 12:11:02 +02:00
|
|
|
ValueOwner *valueOwner)
|
|
|
|
: ObjectValue(valueOwner), _typeName(typeName), _initializer(initializer), _doc(doc), _defaultPropertyRef(0)
|
2010-02-03 14:31:03 +01:00
|
|
|
{
|
|
|
|
if (_initializer) {
|
|
|
|
for (UiObjectMemberList *it = _initializer->members; it; it = it->next) {
|
|
|
|
UiObjectMember *member = it->member;
|
|
|
|
if (UiPublicMember *def = cast<UiPublicMember *>(member)) {
|
2010-02-17 08:44:17 +01:00
|
|
|
if (def->type == UiPublicMember::Property && def->name && def->memberType) {
|
2011-07-01 12:11:02 +02:00
|
|
|
ASTPropertyReference *ref = new ASTPropertyReference(def, _doc, valueOwner);
|
2010-02-08 12:50:10 +01:00
|
|
|
_properties.append(ref);
|
2010-05-31 12:21:12 +02:00
|
|
|
if (def->defaultToken.isValid())
|
|
|
|
_defaultPropertyRef = ref;
|
2010-02-17 08:44:17 +01:00
|
|
|
} else if (def->type == UiPublicMember::Signal && def->name) {
|
2011-07-01 12:11:02 +02:00
|
|
|
ASTSignalReference *ref = new ASTSignalReference(def, _doc, valueOwner);
|
2010-02-17 08:44:17 +01:00
|
|
|
_signals.append(ref);
|
2010-02-03 14:31:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-02-08 12:50:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ASTObjectValue::~ASTObjectValue()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ASTObjectValue::getSourceLocation(QString *fileName, int *line, int *column) const
|
|
|
|
{
|
|
|
|
*fileName = _doc->fileName();
|
|
|
|
*line = _typeName->identifierToken.startLine;
|
|
|
|
*column = _typeName->identifierToken.startColumn;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTObjectValue::processMembers(MemberProcessor *processor) const
|
|
|
|
{
|
2010-02-17 09:16:28 +01:00
|
|
|
foreach (ASTPropertyReference *ref, _properties) {
|
2010-02-08 12:50:10 +01:00
|
|
|
processor->processProperty(ref->ast()->name->asString(), ref);
|
2010-02-17 09:16:28 +01:00
|
|
|
// ### Should get a different value?
|
|
|
|
processor->processGeneratedSlot(ref->onChangedSlotName(), ref);
|
|
|
|
}
|
2010-02-17 08:44:17 +01:00
|
|
|
foreach (ASTSignalReference *ref, _signals) {
|
|
|
|
processor->processSignal(ref->ast()->name->asString(), ref);
|
2010-02-17 09:16:28 +01:00
|
|
|
// ### Should get a different value?
|
2010-02-17 08:44:17 +01:00
|
|
|
processor->processGeneratedSlot(ref->slotName(), ref);
|
|
|
|
}
|
2010-02-08 12:50:10 +01:00
|
|
|
|
2010-02-03 14:31:03 +01:00
|
|
|
ObjectValue::processMembers(processor);
|
|
|
|
}
|
|
|
|
|
2010-05-31 12:21:12 +02:00
|
|
|
QString ASTObjectValue::defaultPropertyName() const
|
|
|
|
{
|
|
|
|
if (_defaultPropertyRef) {
|
|
|
|
UiPublicMember *prop = _defaultPropertyRef->ast();
|
|
|
|
if (prop && prop->name)
|
|
|
|
return prop->name->asString();
|
|
|
|
}
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2010-12-01 11:11:37 +01:00
|
|
|
UiObjectInitializer *ASTObjectValue::initializer() const
|
|
|
|
{
|
|
|
|
return _initializer;
|
|
|
|
}
|
|
|
|
|
|
|
|
UiQualifiedId *ASTObjectValue::typeName() const
|
|
|
|
{
|
|
|
|
return _typeName;
|
|
|
|
}
|
|
|
|
|
|
|
|
const QmlJS::Document *ASTObjectValue::document() const
|
|
|
|
{
|
|
|
|
return _doc;
|
|
|
|
}
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
ASTVariableReference::ASTVariableReference(VariableDeclaration *ast, ValueOwner *valueOwner)
|
|
|
|
: Reference(valueOwner), _ast(ast)
|
2010-02-03 14:31:03 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTVariableReference::~ASTVariableReference()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const Value *ASTVariableReference::value(const Context *context) const
|
2010-02-03 14:31:03 +01:00
|
|
|
{
|
2010-02-15 11:52:39 +01:00
|
|
|
Evaluate check(context);
|
2010-02-03 14:31:03 +01:00
|
|
|
return check(_ast->expression);
|
|
|
|
}
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
ASTFunctionValue::ASTFunctionValue(FunctionExpression *ast, const QmlJS::Document *doc, ValueOwner *valueOwner)
|
|
|
|
: FunctionValue(valueOwner), _ast(ast), _doc(doc)
|
2010-02-03 14:31:03 +01:00
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
setPrototype(valueOwner->functionPrototype());
|
2010-02-03 14:31:03 +01:00
|
|
|
|
|
|
|
for (FormalParameterList *it = ast->formals; it; it = it->next)
|
|
|
|
_argumentNames.append(it->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTFunctionValue::~ASTFunctionValue()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-11-16 13:53:39 +01:00
|
|
|
FunctionExpression *ASTFunctionValue::ast() const
|
2010-02-03 14:31:03 +01:00
|
|
|
{
|
|
|
|
return _ast;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Value *ASTFunctionValue::returnValue() const
|
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
return valueOwner()->undefinedValue();
|
2010-02-03 14:31:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int ASTFunctionValue::argumentCount() const
|
|
|
|
{
|
|
|
|
return _argumentNames.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
const Value *ASTFunctionValue::argument(int) const
|
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
return valueOwner()->undefinedValue();
|
2010-02-03 14:31:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QString ASTFunctionValue::argumentName(int index) const
|
|
|
|
{
|
|
|
|
if (index < _argumentNames.size()) {
|
|
|
|
if (NameId *nameId = _argumentNames.at(index))
|
|
|
|
return nameId->asString();
|
|
|
|
}
|
|
|
|
|
|
|
|
return FunctionValue::argumentName(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ASTFunctionValue::isVariadic() const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2010-02-03 15:39:57 +01:00
|
|
|
|
2010-07-16 10:50:28 +02:00
|
|
|
bool ASTFunctionValue::getSourceLocation(QString *fileName, int *line, int *column) const
|
|
|
|
{
|
|
|
|
*fileName = _doc->fileName();
|
|
|
|
*line = _ast->identifierToken.startLine;
|
|
|
|
*column = _ast->identifierToken.startColumn;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-02-04 11:08:57 +01:00
|
|
|
QmlPrototypeReference::QmlPrototypeReference(UiQualifiedId *qmlTypeName, const QmlJS::Document *doc,
|
2011-07-01 12:11:02 +02:00
|
|
|
ValueOwner *valueOwner)
|
|
|
|
: Reference(valueOwner),
|
2010-02-04 09:44:43 +01:00
|
|
|
_qmlTypeName(qmlTypeName),
|
|
|
|
_doc(doc)
|
2010-02-03 15:39:57 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
QmlPrototypeReference::~QmlPrototypeReference()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
UiQualifiedId *QmlPrototypeReference::qmlTypeName() const
|
|
|
|
{
|
|
|
|
return _qmlTypeName;
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const Value *QmlPrototypeReference::value(const Context *context) const
|
2010-02-03 15:39:57 +01:00
|
|
|
{
|
2010-02-04 09:44:43 +01:00
|
|
|
return context->lookupType(_doc, _qmlTypeName);
|
2010-02-03 15:39:57 +01:00
|
|
|
}
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
ASTPropertyReference::ASTPropertyReference(UiPublicMember *ast, const QmlJS::Document *doc, ValueOwner *valueOwner)
|
|
|
|
: Reference(valueOwner), _ast(ast), _doc(doc)
|
2010-02-08 12:50:10 +01:00
|
|
|
{
|
2010-02-17 09:16:28 +01:00
|
|
|
const QString propertyName = ast->name->asString();
|
|
|
|
_onChangedSlotName = QLatin1String("on");
|
|
|
|
_onChangedSlotName += propertyName.at(0).toUpper();
|
|
|
|
_onChangedSlotName += propertyName.midRef(1);
|
|
|
|
_onChangedSlotName += QLatin1String("Changed");
|
2010-02-08 12:50:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ASTPropertyReference::~ASTPropertyReference()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ASTPropertyReference::getSourceLocation(QString *fileName, int *line, int *column) const
|
|
|
|
{
|
|
|
|
*fileName = _doc->fileName();
|
|
|
|
*line = _ast->identifierToken.startLine;
|
|
|
|
*column = _ast->identifierToken.startColumn;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const Value *ASTPropertyReference::value(const Context *context) const
|
2010-02-08 12:50:10 +01:00
|
|
|
{
|
2011-05-12 13:25:35 +02:00
|
|
|
if (_ast->statement
|
2011-05-04 11:12:45 +02:00
|
|
|
&& (!_ast->memberType || _ast->memberType->asString() == QLatin1String("variant")
|
|
|
|
|| _ast->memberType->asString() == QLatin1String("alias"))) {
|
|
|
|
|
|
|
|
// Adjust the context for the current location - expensive!
|
|
|
|
// ### Improve efficiency by caching the 'use chain' constructed in ScopeBuilder.
|
|
|
|
|
|
|
|
QmlJS::Document::Ptr doc = _doc->ptr();
|
|
|
|
Context localContext(*context);
|
|
|
|
QmlJS::ScopeBuilder builder(&localContext, doc);
|
2011-05-06 13:31:30 +02:00
|
|
|
builder.initializeRootScope();
|
2011-05-04 11:12:45 +02:00
|
|
|
|
2011-05-12 13:25:35 +02:00
|
|
|
int offset = _ast->statement->firstSourceLocation().begin();
|
2011-05-04 11:12:45 +02:00
|
|
|
builder.push(ScopeAstPath(doc)(offset));
|
|
|
|
|
|
|
|
Evaluate check(&localContext);
|
2011-05-12 13:25:35 +02:00
|
|
|
return check(_ast->statement);
|
2010-02-08 12:50:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (_ast->memberType)
|
2011-07-01 12:11:02 +02:00
|
|
|
return valueOwner()->defaultValueForBuiltinType(_ast->memberType->asString());
|
2010-02-08 12:50:10 +01:00
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
return valueOwner()->undefinedValue();
|
2010-02-08 12:50:10 +01:00
|
|
|
}
|
2010-02-17 08:44:17 +01:00
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
ASTSignalReference::ASTSignalReference(UiPublicMember *ast, const QmlJS::Document *doc, ValueOwner *valueOwner)
|
|
|
|
: Reference(valueOwner), _ast(ast), _doc(doc)
|
2010-02-17 08:44:17 +01:00
|
|
|
{
|
|
|
|
const QString signalName = ast->name->asString();
|
|
|
|
_slotName = QLatin1String("on");
|
|
|
|
_slotName += signalName.at(0).toUpper();
|
|
|
|
_slotName += signalName.midRef(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTSignalReference::~ASTSignalReference()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ASTSignalReference::getSourceLocation(QString *fileName, int *line, int *column) const
|
|
|
|
{
|
|
|
|
*fileName = _doc->fileName();
|
|
|
|
*line = _ast->identifierToken.startLine;
|
|
|
|
*column = _ast->identifierToken.startColumn;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-08-25 11:51:34 +02:00
|
|
|
const Value *ASTSignalReference::value(const Context *) const
|
2010-02-17 08:44:17 +01:00
|
|
|
{
|
2011-07-01 12:11:02 +02:00
|
|
|
return valueOwner()->undefinedValue();
|
2010-02-17 08:44:17 +01:00
|
|
|
}
|
2010-09-16 15:29:37 +02:00
|
|
|
|
|
|
|
ImportInfo::ImportInfo()
|
|
|
|
: _type(InvalidImport)
|
|
|
|
, _ast(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ImportInfo::ImportInfo(Type type, const QString &name,
|
2010-12-03 11:17:25 +01:00
|
|
|
ComponentVersion version, UiImport *ast)
|
2010-09-16 15:29:37 +02:00
|
|
|
: _type(type)
|
|
|
|
, _name(name)
|
|
|
|
, _version(version)
|
|
|
|
, _ast(ast)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ImportInfo::isValid() const
|
|
|
|
{
|
|
|
|
return _type != InvalidImport;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImportInfo::Type ImportInfo::type() const
|
|
|
|
{
|
|
|
|
return _type;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString ImportInfo::name() const
|
|
|
|
{
|
|
|
|
return _name;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString ImportInfo::id() const
|
|
|
|
{
|
|
|
|
if (_ast && _ast->importId)
|
|
|
|
return _ast->importId->asString();
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2010-12-03 11:17:25 +01:00
|
|
|
ComponentVersion ImportInfo::version() const
|
2010-09-16 15:29:37 +02:00
|
|
|
{
|
|
|
|
return _version;
|
|
|
|
}
|
|
|
|
|
|
|
|
UiImport *ImportInfo::ast() const
|
|
|
|
{
|
|
|
|
return _ast;
|
|
|
|
}
|
|
|
|
|
2011-05-27 10:43:06 +02:00
|
|
|
Import::Import()
|
2011-05-12 15:29:00 +02:00
|
|
|
: object(0)
|
|
|
|
{}
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
TypeScope::TypeScope(const Imports *imports, ValueOwner *valueOwner)
|
|
|
|
: ObjectValue(valueOwner)
|
2011-05-27 10:43:06 +02:00
|
|
|
, _imports(imports)
|
2010-09-16 15:29:37 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-05-27 10:43:06 +02:00
|
|
|
const Value *TypeScope::lookupMember(const QString &name, const Context *context,
|
2010-11-17 14:20:06 +01:00
|
|
|
const ObjectValue **foundInObject, bool) const
|
2010-09-16 15:29:37 +02:00
|
|
|
{
|
2011-05-27 10:43:06 +02:00
|
|
|
QListIterator<Import> it(_imports->all());
|
2011-01-10 14:39:12 +01:00
|
|
|
it.toBack();
|
|
|
|
while (it.hasPrevious()) {
|
|
|
|
const Import &i = it.previous();
|
|
|
|
const ObjectValue *import = i.object;
|
|
|
|
const ImportInfo &info = i.info;
|
2010-09-16 15:29:37 +02:00
|
|
|
|
2011-05-27 10:43:06 +02:00
|
|
|
// JS import has no types
|
|
|
|
if (info.type() == ImportInfo::FileImport)
|
|
|
|
continue;
|
|
|
|
|
2010-09-16 15:29:37 +02:00
|
|
|
if (!info.id().isEmpty()) {
|
2010-11-17 14:20:06 +01:00
|
|
|
if (info.id() == name) {
|
|
|
|
if (foundInObject)
|
|
|
|
*foundInObject = this;
|
2010-09-16 15:29:37 +02:00
|
|
|
return import;
|
2010-11-17 14:20:06 +01:00
|
|
|
}
|
2010-09-16 15:29:37 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-05-27 10:43:06 +02:00
|
|
|
if (const Value *v = import->lookupMember(name, context, foundInObject))
|
|
|
|
return v;
|
2010-09-16 15:29:37 +02:00
|
|
|
}
|
2010-11-17 14:20:06 +01:00
|
|
|
if (foundInObject)
|
|
|
|
*foundInObject = 0;
|
2010-09-16 15:29:37 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-05-27 10:43:06 +02:00
|
|
|
void TypeScope::processMembers(MemberProcessor *processor) const
|
2010-09-16 15:29:37 +02:00
|
|
|
{
|
2011-05-27 10:43:06 +02:00
|
|
|
QListIterator<Import> it(_imports->all());
|
2011-01-10 14:39:12 +01:00
|
|
|
it.toBack();
|
|
|
|
while (it.hasPrevious()) {
|
|
|
|
const Import &i = it.previous();
|
|
|
|
const ObjectValue *import = i.object;
|
|
|
|
const ImportInfo &info = i.info;
|
2010-09-16 15:29:37 +02:00
|
|
|
|
2011-05-27 10:43:06 +02:00
|
|
|
// JS import has no types
|
|
|
|
if (info.type() == ImportInfo::FileImport)
|
|
|
|
continue;
|
|
|
|
|
2010-09-16 15:29:37 +02:00
|
|
|
if (!info.id().isEmpty()) {
|
|
|
|
processor->processProperty(info.id(), import);
|
|
|
|
} else {
|
2011-05-27 10:43:06 +02:00
|
|
|
import->processMembers(processor);
|
2010-09-16 15:29:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
JSImportScope::JSImportScope(const Imports *imports, ValueOwner *valueOwner)
|
|
|
|
: ObjectValue(valueOwner)
|
2011-05-27 10:43:06 +02:00
|
|
|
, _imports(imports)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
const Value *JSImportScope::lookupMember(const QString &name, const Context *,
|
|
|
|
const ObjectValue **foundInObject, bool) const
|
|
|
|
{
|
|
|
|
QListIterator<Import> it(_imports->all());
|
|
|
|
it.toBack();
|
|
|
|
while (it.hasPrevious()) {
|
|
|
|
const Import &i = it.previous();
|
|
|
|
const ObjectValue *import = i.object;
|
|
|
|
const ImportInfo &info = i.info;
|
|
|
|
|
|
|
|
// JS imports are always: import "somefile.js" as Foo
|
|
|
|
if (info.type() != ImportInfo::FileImport)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (info.id() == name) {
|
|
|
|
if (foundInObject)
|
|
|
|
*foundInObject = this;
|
|
|
|
return import;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (foundInObject)
|
|
|
|
*foundInObject = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JSImportScope::processMembers(MemberProcessor *processor) const
|
|
|
|
{
|
|
|
|
QListIterator<Import> it(_imports->all());
|
|
|
|
it.toBack();
|
|
|
|
while (it.hasPrevious()) {
|
|
|
|
const Import &i = it.previous();
|
|
|
|
const ObjectValue *import = i.object;
|
|
|
|
const ImportInfo &info = i.info;
|
|
|
|
|
|
|
|
if (info.type() == ImportInfo::FileImport)
|
|
|
|
processor->processProperty(info.id(), import);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
Imports::Imports(ValueOwner *valueOwner)
|
|
|
|
: _typeScope(new TypeScope(this, valueOwner))
|
|
|
|
, _jsImportScope(new JSImportScope(this, valueOwner))
|
2011-05-27 10:43:06 +02:00
|
|
|
{}
|
|
|
|
|
|
|
|
void Imports::append(const Import &import)
|
2010-09-16 15:29:37 +02:00
|
|
|
{
|
2011-05-27 11:47:12 +02:00
|
|
|
// when doing lookup, imports with 'as' clause are looked at first
|
|
|
|
if (!import.info.id().isEmpty()) {
|
|
|
|
_imports.append(import);
|
|
|
|
} else {
|
|
|
|
// find first as-import and prepend
|
|
|
|
for (int i = 0; i < _imports.size(); ++i) {
|
|
|
|
if (!_imports.at(i).info.id().isEmpty()) {
|
|
|
|
_imports.insert(i, import);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// not found, append
|
|
|
|
_imports.append(import);
|
|
|
|
}
|
2010-09-16 15:29:37 +02:00
|
|
|
}
|
|
|
|
|
2011-05-27 10:43:06 +02:00
|
|
|
ImportInfo Imports::info(const QString &name, const Context *context) const
|
2010-09-16 15:29:37 +02:00
|
|
|
{
|
|
|
|
QString firstId = name;
|
|
|
|
int dotIdx = firstId.indexOf(QLatin1Char('.'));
|
|
|
|
if (dotIdx != -1)
|
|
|
|
firstId = firstId.left(dotIdx);
|
|
|
|
|
2011-01-10 14:39:12 +01:00
|
|
|
QListIterator<Import> it(_imports);
|
|
|
|
it.toBack();
|
|
|
|
while (it.hasPrevious()) {
|
|
|
|
const Import &i = it.previous();
|
|
|
|
const ObjectValue *import = i.object;
|
|
|
|
const ImportInfo &info = i.info;
|
2010-09-16 15:29:37 +02:00
|
|
|
|
|
|
|
if (!info.id().isEmpty()) {
|
|
|
|
if (info.id() == firstId)
|
|
|
|
return info;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info.type() == ImportInfo::FileImport) {
|
|
|
|
if (import->className() == firstId)
|
|
|
|
return info;
|
|
|
|
} else {
|
2011-05-24 11:50:10 +02:00
|
|
|
if (import->lookupMember(firstId, context))
|
2010-09-16 15:29:37 +02:00
|
|
|
return info;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ImportInfo();
|
|
|
|
}
|
2011-04-20 10:46:04 +02:00
|
|
|
|
2011-05-27 10:43:06 +02:00
|
|
|
QList<Import> Imports::all() const
|
2011-05-12 15:29:00 +02:00
|
|
|
{
|
|
|
|
return _imports;
|
|
|
|
}
|
|
|
|
|
2011-05-27 10:43:06 +02:00
|
|
|
const TypeScope *Imports::typeScope() const
|
|
|
|
{
|
|
|
|
return _typeScope;
|
|
|
|
}
|
|
|
|
|
|
|
|
const JSImportScope *Imports::jsImportScope() const
|
|
|
|
{
|
|
|
|
return _jsImportScope;
|
|
|
|
}
|
|
|
|
|
2011-04-20 10:46:04 +02:00
|
|
|
#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;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-05-27 10:43:06 +02:00
|
|
|
void Imports::dump() const
|
2011-04-20 10:46:04 +02:00
|
|
|
{
|
2011-05-27 10:43:06 +02:00
|
|
|
qDebug() << "Imports contents, in search order:";
|
2011-04-20 10:46:04 +02:00
|
|
|
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
|