blob: b2081eac6987c4b13e90d7cc37872fceaa1129f7 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** 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.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "private/qdeclarativeparser_p.h"
#include "qdeclarativepropertyvaluesource.h"
#include "private/qdeclarativevme_p.h"
#include "qdeclarative.h"
#include "private/qdeclarativecomponent_p.h"
#include "qdeclarativecomponent.h"
#include "private/qmetaobjectbuilder_p.h"
#include "private/qdeclarativevmemetaobject_p.h"
#include "private/qdeclarativecompiler_p.h"
#include "parser/qdeclarativejsast_p.h"
#include "parser/qdeclarativejsengine_p.h"
#include <QStack>
#include <QColor>
#include <QPointF>
#include <QSizeF>
#include <QRectF>
#include <QStringBuilder>
#include <QtDebug>
QT_BEGIN_NAMESPACE
using namespace QDeclarativeJS;
using namespace QDeclarativeParser;
QDeclarativeParser::Object::Object()
: type(-1), majorVersion(-1), minorVersion(-1), idIndex(-1), metatype(0), synthCache(0), defaultProperty(0), parserStatusCast(-1)
{
}
QDeclarativeParser::Object::~Object()
{
if (defaultProperty) defaultProperty->release();
if (synthCache) synthCache->release();
foreach(Property *prop, properties)
prop->release();
foreach(Property *prop, valueProperties)
prop->release();
foreach(Property *prop, signalProperties)
prop->release();
foreach(Property *prop, attachedProperties)
prop->release();
foreach(Property *prop, groupedProperties)
prop->release();
foreach(Property *prop, valueTypeProperties)
prop->release();
typedef QPair<Property *, int> PropPair;
foreach(const PropPair &prop, scriptStringProperties)
prop.first->release();
foreach(const DynamicProperty &prop, dynamicProperties)
if (prop.defaultValue) prop.defaultValue->release();
}
void Object::setBindingBit(int b)
{
while (bindingBitmask.size() < 4 * (1 + b / 32))
bindingBitmask.append(char(0));
quint32 *bits = (quint32 *)bindingBitmask.data();
bits[b / 32] |= (1 << (b % 32));
}
const QMetaObject *Object::metaObject() const
{
if (!metadata.isEmpty() && metatype)
return &extObject;
else
return metatype;
}
QDeclarativeParser::Property *Object::getDefaultProperty()
{
if (!defaultProperty) {
defaultProperty = new Property;
defaultProperty->parent = this;
}
return defaultProperty;
}
void QDeclarativeParser::Object::addValueProperty(Property *p)
{
p->addref();
valueProperties << p;
}
void QDeclarativeParser::Object::addSignalProperty(Property *p)
{
p->addref();
signalProperties << p;
}
void QDeclarativeParser::Object::addAttachedProperty(Property *p)
{
p->addref();
attachedProperties << p;
}
void QDeclarativeParser::Object::addGroupedProperty(Property *p)
{
p->addref();
groupedProperties << p;
}
void QDeclarativeParser::Object::addValueTypeProperty(Property *p)
{
p->addref();
valueTypeProperties << p;
}
void QDeclarativeParser::Object::addScriptStringProperty(Property *p, int stack)
{
p->addref();
scriptStringProperties << qMakePair(p, stack);
}
Property *QDeclarativeParser::Object::getProperty(const QByteArray &name, bool create)
{
if (!properties.contains(name)) {
if (create) {
Property *property = new Property(name);
property->parent = this;
properties.insert(name, property);
} else {
return 0;
}
}
return properties[name];
}
QDeclarativeParser::Object::DynamicProperty::DynamicProperty()
: isDefaultProperty(false), type(Variant), defaultValue(0)
{
}
QDeclarativeParser::Object::DynamicProperty::DynamicProperty(const DynamicProperty &o)
: isDefaultProperty(o.isDefaultProperty),
type(o.type),
customType(o.customType),
name(o.name),
defaultValue(o.defaultValue),
location(o.location)
{
}
QDeclarativeParser::Object::DynamicSignal::DynamicSignal()
{
}
QDeclarativeParser::Object::DynamicSignal::DynamicSignal(const DynamicSignal &o)
: name(o.name), parameterTypes(o.parameterTypes),
parameterNames(o.parameterNames)
{
}
QDeclarativeParser::Object::DynamicSlot::DynamicSlot()
{
}
QDeclarativeParser::Object::DynamicSlot::DynamicSlot(const DynamicSlot &o)
: name(o.name), body(o.body), parameterNames(o.parameterNames), location(o.location)
{
}
QDeclarativeParser::Property::Property()
: parent(0), type(0), index(-1), value(0), isDefault(true), isDeferred(false),
isValueTypeSubProperty(false), isAlias(false)
{
}
QDeclarativeParser::Property::Property(const QByteArray &n)
: parent(0), type(0), index(-1), value(0), name(n), isDefault(false),
isDeferred(false), isValueTypeSubProperty(false), isAlias(false)
{
}
QDeclarativeParser::Property::~Property()
{
foreach(Value *value, values)
value->release();
foreach(Value *value, onValues)
value->release();
if (value) value->release();
}
Object *QDeclarativeParser::Property::getValue(const LocationSpan &l)
{
if (!value) { value = new Object; value->location = l; }
return value;
}
void QDeclarativeParser::Property::addValue(Value *v)
{
values << v;
}
void QDeclarativeParser::Property::addOnValue(Value *v)
{
onValues << v;
}
bool QDeclarativeParser::Property::isEmpty() const
{
return !value && values.isEmpty() && onValues.isEmpty();
}
QDeclarativeParser::Value::Value()
: type(Unknown), object(0)
{
}
QDeclarativeParser::Value::~Value()
{
if (object) object->release();
}
QDeclarativeParser::Variant::Variant()
: t(Invalid) {}
QDeclarativeParser::Variant::Variant(const Variant &o)
: t(o.t), d(o.d), s(o.s)
{
}
QDeclarativeParser::Variant::Variant(bool v)
: t(Boolean), b(v)
{
}
QDeclarativeParser::Variant::Variant(double v, const QString &asWritten)
: t(Number), d(v), s(asWritten)
{
}
QDeclarativeParser::Variant::Variant(const QString &v)
: t(String), s(v)
{
}
QDeclarativeParser::Variant::Variant(const QString &v, QDeclarativeJS::AST::Node *n)
: t(Script), n(n), s(v)
{
}
QDeclarativeParser::Variant &QDeclarativeParser::Variant::operator=(const Variant &o)
{
t = o.t;
d = o.d;
s = o.s;
return *this;
}
QDeclarativeParser::Variant::Type QDeclarativeParser::Variant::type() const
{
return t;
}
bool QDeclarativeParser::Variant::asBoolean() const
{
return b;
}
QString QDeclarativeParser::Variant::asString() const
{
return s;
}
double QDeclarativeParser::Variant::asNumber() const
{
return d;
}
//reverse of Lexer::singleEscape()
QString escapedString(const QString &string)
{
QString tmp = QLatin1String("\"");
for (int i = 0; i < string.length(); ++i) {
const QChar &c = string.at(i);
switch(c.unicode()) {
case 0x08:
tmp += QLatin1String("\\b");
break;
case 0x09:
tmp += QLatin1String("\\t");
break;
case 0x0A:
tmp += QLatin1String("\\n");
break;
case 0x0B:
tmp += QLatin1String("\\v");
break;
case 0x0C:
tmp += QLatin1String("\\f");
break;
case 0x0D:
tmp += QLatin1String("\\r");
break;
case 0x22:
tmp += QLatin1String("\\\"");
break;
case 0x27:
tmp += QLatin1String("\\\'");
break;
case 0x5C:
tmp += QLatin1String("\\\\");
break;
default:
tmp += c;
break;
}
}
tmp += QLatin1Char('\"');
return tmp;
}
QString QDeclarativeParser::Variant::asScript() const
{
switch(type()) {
default:
case Invalid:
return QString();
case Boolean:
return b?QLatin1String("true"):QLatin1String("false");
case Number:
if (s.isEmpty())
return QString::number(d);
else
return s;
case String:
return escapedString(s);
case Script:
return s;
}
}
QDeclarativeJS::AST::Node *QDeclarativeParser::Variant::asAST() const
{
if (type() == Script)
return n;
else
return 0;
}
bool QDeclarativeParser::Variant::isStringList() const
{
if (isString())
return true;
if (type() != Script || !n)
return false;
AST::ArrayLiteral *array = AST::cast<AST::ArrayLiteral *>(n);
if (!array)
return false;
AST::ElementList *elements = array->elements;
while (elements) {
if (!AST::cast<AST::StringLiteral *>(elements->expression))
return false;
elements = elements->next;
}
return true;
}
QStringList QDeclarativeParser::Variant::asStringList() const
{
QStringList rv;
if (isString()) {
rv << asString();
return rv;
}
AST::ArrayLiteral *array = AST::cast<AST::ArrayLiteral *>(n);
if (!array)
return rv;
AST::ElementList *elements = array->elements;
while (elements) {
AST::StringLiteral *string = AST::cast<AST::StringLiteral *>(elements->expression);
if (!string)
return QStringList();
rv.append(string->value->asString());
elements = elements->next;
}
return rv;
}
QT_END_NAMESPACE