forked from qt-creator/qt-creator
		
	Implemented the binding phase for QML.
Done-with: Christian Kamm
This commit is contained in:
		@@ -22,7 +22,8 @@ HEADERS += \
 | 
			
		||||
    $$PWD/qmljsscanner.h \
 | 
			
		||||
    $$PWD/qmljssymbol.h \
 | 
			
		||||
    $$PWD/qmljstypesystem.h \
 | 
			
		||||
    $$PWD/qmljsinterpreter.h
 | 
			
		||||
    $$PWD/qmljsinterpreter.h \
 | 
			
		||||
    $$PWD/qmljsmetatypesystem.h
 | 
			
		||||
 | 
			
		||||
SOURCES += \
 | 
			
		||||
    $$PWD/qmljsbind.cpp \
 | 
			
		||||
@@ -34,7 +35,8 @@ SOURCES += \
 | 
			
		||||
    $$PWD/qmljsscanner.cpp \
 | 
			
		||||
    $$PWD/qmljssymbol.cpp \
 | 
			
		||||
    $$PWD/qmljstypesystem.cpp \
 | 
			
		||||
    $$PWD/qmljsinterpreter.cpp
 | 
			
		||||
    $$PWD/qmljsinterpreter.cpp \
 | 
			
		||||
    $$PWD/qmljsmetatypesystem.cpp
 | 
			
		||||
 | 
			
		||||
contains(QT_CONFIG, declarative) {
 | 
			
		||||
    QT += declarative
 | 
			
		||||
 
 | 
			
		||||
@@ -27,10 +27,13 @@
 | 
			
		||||
**
 | 
			
		||||
**************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "qmljsbind.h"
 | 
			
		||||
#include "parser/qmljsast_p.h"
 | 
			
		||||
#include "qmljsbind.h"
 | 
			
		||||
#include "qmljsmetatypesystem.h"
 | 
			
		||||
 | 
			
		||||
using namespace QmlJS;
 | 
			
		||||
using namespace QmlJS::AST;
 | 
			
		||||
using namespace QmlJS::Interpreter;
 | 
			
		||||
 | 
			
		||||
Bind::Bind()
 | 
			
		||||
{
 | 
			
		||||
@@ -40,462 +43,629 @@ Bind::~Bind()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Bind::operator()(Document::Ptr doc)
 | 
			
		||||
Interpreter::ObjectValue *Bind::operator()(Document::Ptr doc, Snapshot &snapshot, UiObjectMember *member, Interpreter::Engine &interp)
 | 
			
		||||
{
 | 
			
		||||
    UiProgram *program = doc->qmlProgram();
 | 
			
		||||
    if (!program)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    _doc = doc;
 | 
			
		||||
    _snapshot = &snapshot;
 | 
			
		||||
    _interestingMember = member;
 | 
			
		||||
    _interp = &interp;
 | 
			
		||||
 | 
			
		||||
    _currentObjectValue = 0;
 | 
			
		||||
    _typeEnvironment = _interp->newObject(0);
 | 
			
		||||
    _idEnvironment = _interp->newObject(0);
 | 
			
		||||
    _interestingObjectValue = 0;
 | 
			
		||||
    _rootObjectValue = 0;
 | 
			
		||||
 | 
			
		||||
    accept(program);
 | 
			
		||||
 | 
			
		||||
    if (_interestingObjectValue) {
 | 
			
		||||
        _idEnvironment->setScope(_interestingObjectValue);
 | 
			
		||||
 | 
			
		||||
        if (_interestingObjectValue != _rootObjectValue)
 | 
			
		||||
            _interestingObjectValue->setScope(_rootObjectValue);
 | 
			
		||||
    } else {
 | 
			
		||||
        _idEnvironment->setScope(_rootObjectValue);
 | 
			
		||||
    }
 | 
			
		||||
    _typeEnvironment->setScope(_idEnvironment);
 | 
			
		||||
 | 
			
		||||
    return _typeEnvironment;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Bind::accept(AST::Node *node)
 | 
			
		||||
void Bind::accept(Node *node)
 | 
			
		||||
{
 | 
			
		||||
    AST::Node::accept(node, this);
 | 
			
		||||
    Node::accept(node, this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UiProgram *)
 | 
			
		||||
bool Bind::visit(UiProgram *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UiImportList *)
 | 
			
		||||
bool Bind::visit(UiImportList *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UiImport *)
 | 
			
		||||
static QString serialize(UiQualifiedId *qualifiedId, QChar delimiter)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
    QString result;
 | 
			
		||||
 | 
			
		||||
    for (UiQualifiedId *iter = qualifiedId; iter; iter = iter->next) {
 | 
			
		||||
        if (iter != qualifiedId)
 | 
			
		||||
            result += delimiter;
 | 
			
		||||
 | 
			
		||||
        if (iter->name)
 | 
			
		||||
            result += iter->name->asString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UiPublicMember *)
 | 
			
		||||
/*
 | 
			
		||||
  import Qt 4.6
 | 
			
		||||
  import Qt 4.6 as Xxx
 | 
			
		||||
  (import com.nokia.qt is the same as the ones above)
 | 
			
		||||
 | 
			
		||||
  import "content"
 | 
			
		||||
  import "content" as Xxx
 | 
			
		||||
  import "content" 4.6
 | 
			
		||||
  import "content" 4.6 as Xxx
 | 
			
		||||
 | 
			
		||||
  import "http://www.ovi.com/" as Ovi
 | 
			
		||||
 */
 | 
			
		||||
bool Bind::visit(UiImport *ast)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
    ObjectValue *namespaceObject;
 | 
			
		||||
 | 
			
		||||
    if (ast->asToken.isValid()) { // with namespace we insert an object in the type env. to hold the imported types
 | 
			
		||||
        namespaceObject = _interp->newObject(0);
 | 
			
		||||
        if (!ast->importId)
 | 
			
		||||
            return false; // this should never happen, but better be safe than sorry
 | 
			
		||||
        _typeEnvironment->setProperty(ast->importId->asString(), namespaceObject);
 | 
			
		||||
    } else { // without namespace we insert all types directly into the type env.
 | 
			
		||||
        namespaceObject = _typeEnvironment;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // look at files first
 | 
			
		||||
 | 
			
		||||
    // else try the metaobject system
 | 
			
		||||
    if (!ast->importUri)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    const QString package = serialize(ast->importUri, '/');
 | 
			
		||||
    int majorVersion = -1; // ### TODO: Check these magic version numbers
 | 
			
		||||
    int minorVersion = -1; // ### TODO: Check these magic version numbers
 | 
			
		||||
 | 
			
		||||
    if (ast->versionToken.isValid()) {
 | 
			
		||||
        const QString versionString = _doc->source().mid(ast->versionToken.offset, ast->versionToken.length);
 | 
			
		||||
        int dotIdx = versionString.indexOf('.');
 | 
			
		||||
        if (dotIdx == -1) {
 | 
			
		||||
            // only major (which is probably invalid, but let's handle it anyway)
 | 
			
		||||
            majorVersion = versionString.toInt();
 | 
			
		||||
            minorVersion = 0; // ### TODO: Check with magic version numbers above
 | 
			
		||||
        } else {
 | 
			
		||||
            majorVersion = versionString.left(dotIdx).toInt();
 | 
			
		||||
            minorVersion = versionString.mid(dotIdx + 1).toInt();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifndef NO_DECLARATIVE_BACKEND
 | 
			
		||||
    foreach (QmlObjectValue *object, _interp->metaTypeSystem().staticTypesForImport(package, majorVersion, minorVersion)) {
 | 
			
		||||
        namespaceObject->setProperty(object->qmlTypeName(), object);
 | 
			
		||||
    }
 | 
			
		||||
#endif // NO_DECLARATIVE_BACKEND
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UiSourceElement *)
 | 
			
		||||
bool Bind::visit(UiPublicMember *ast)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
    if (! (ast->name && ast->memberType))
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    const QString propName = ast->name->asString();
 | 
			
		||||
    const QString propType = ast->memberType->asString();
 | 
			
		||||
 | 
			
		||||
    // ### TODO: generalize
 | 
			
		||||
    if (propType == QLatin1String("string"))
 | 
			
		||||
        _currentObjectValue->setProperty(propName, _interp->stringValue());
 | 
			
		||||
    else if (propType == QLatin1String("bool"))
 | 
			
		||||
        _currentObjectValue->setProperty(propName, _interp->booleanValue());
 | 
			
		||||
    else if (propType == QLatin1String("int") || propType == QLatin1String("real"))
 | 
			
		||||
        _currentObjectValue->setProperty(propName, _interp->numberValue());
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UiObjectDefinition *)
 | 
			
		||||
bool Bind::visit(UiSourceElement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UiObjectInitializer *)
 | 
			
		||||
const ObjectValue *Bind::lookupType(UiQualifiedId *qualifiedTypeNameId)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
    const ObjectValue *objectValue = _typeEnvironment;
 | 
			
		||||
 | 
			
		||||
    for (UiQualifiedId *iter = qualifiedTypeNameId; iter; iter = iter->next) {
 | 
			
		||||
        if (! (iter->name))
 | 
			
		||||
            return 0;
 | 
			
		||||
        const Value *value = objectValue->property(iter->name->asString());
 | 
			
		||||
        if (!value)
 | 
			
		||||
            return 0;
 | 
			
		||||
        objectValue = value->asObjectValue();
 | 
			
		||||
        if (!objectValue)
 | 
			
		||||
            return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return objectValue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UiObjectBinding *)
 | 
			
		||||
ObjectValue *Bind::bindObject(UiQualifiedId *qualifiedTypeNameId, UiObjectInitializer *initializer)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
    const ObjectValue *prototype = lookupType(qualifiedTypeNameId);
 | 
			
		||||
    ObjectValue *objectValue = _interp->newObject(prototype);
 | 
			
		||||
    ObjectValue *oldObjectValue = switchObjectValue(objectValue);
 | 
			
		||||
    if (oldObjectValue)
 | 
			
		||||
        objectValue->setProperty("parent", oldObjectValue);
 | 
			
		||||
    else
 | 
			
		||||
        _rootObjectValue = objectValue;
 | 
			
		||||
 | 
			
		||||
    accept(initializer);
 | 
			
		||||
 | 
			
		||||
    return switchObjectValue(oldObjectValue);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(UiObjectDefinition *ast)
 | 
			
		||||
{
 | 
			
		||||
    ObjectValue *value = bindObject(ast->qualifiedTypeNameId, ast->initializer);
 | 
			
		||||
 | 
			
		||||
    if (_interestingMember == ast)
 | 
			
		||||
        _interestingObjectValue = value;
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(UiObjectBinding *ast)
 | 
			
		||||
{
 | 
			
		||||
//    const QString name = serialize(ast->qualifiedId);
 | 
			
		||||
    ObjectValue *value = bindObject(ast->qualifiedTypeNameId, ast->initializer);
 | 
			
		||||
    // ### FIXME: we don't handle dot-properties correctly (i.e. font.size)
 | 
			
		||||
//    _currentObjectValue->setProperty(name, value);
 | 
			
		||||
 | 
			
		||||
    if (_interestingMember == ast)
 | 
			
		||||
        _interestingObjectValue = value;
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UiScriptBinding *)
 | 
			
		||||
bool Bind::visit(UiObjectInitializer *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UiArrayBinding *)
 | 
			
		||||
bool Bind::visit(UiScriptBinding *ast)
 | 
			
		||||
{
 | 
			
		||||
    if (!(ast->qualifiedId->next) && ast->qualifiedId->name->asString() == "id")
 | 
			
		||||
        if (ExpressionStatement *e = cast<ExpressionStatement*>(ast->statement))
 | 
			
		||||
            if (IdentifierExpression *i = cast<IdentifierExpression*>(e->expression))
 | 
			
		||||
                if (i->name)
 | 
			
		||||
                    _idEnvironment->setProperty(i->name->asString(), _currentObjectValue);
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(UiArrayBinding *)
 | 
			
		||||
{
 | 
			
		||||
    // ### FIXME: do we need to store the members into the property? Or, maybe the property type is an JS Array?
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UiObjectMemberList *)
 | 
			
		||||
bool Bind::visit(UiObjectMemberList *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UiArrayMemberList *)
 | 
			
		||||
bool Bind::visit(UiArrayMemberList *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UiQualifiedId *)
 | 
			
		||||
bool Bind::visit(UiQualifiedId *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UiSignature *)
 | 
			
		||||
bool Bind::visit(UiSignature *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UiFormalList *)
 | 
			
		||||
bool Bind::visit(UiFormalList *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UiFormal *)
 | 
			
		||||
bool Bind::visit(UiFormal *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::ThisExpression *)
 | 
			
		||||
bool Bind::visit(ThisExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::IdentifierExpression *)
 | 
			
		||||
bool Bind::visit(IdentifierExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::NullExpression *)
 | 
			
		||||
bool Bind::visit(NullExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::TrueLiteral *)
 | 
			
		||||
bool Bind::visit(TrueLiteral *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::FalseLiteral *)
 | 
			
		||||
bool Bind::visit(FalseLiteral *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::StringLiteral *)
 | 
			
		||||
bool Bind::visit(StringLiteral *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::NumericLiteral *)
 | 
			
		||||
bool Bind::visit(NumericLiteral *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::RegExpLiteral *)
 | 
			
		||||
bool Bind::visit(RegExpLiteral *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::ArrayLiteral *)
 | 
			
		||||
bool Bind::visit(ArrayLiteral *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::ObjectLiteral *)
 | 
			
		||||
bool Bind::visit(ObjectLiteral *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::ElementList *)
 | 
			
		||||
bool Bind::visit(ElementList *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::Elision *)
 | 
			
		||||
bool Bind::visit(Elision *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::PropertyNameAndValueList *)
 | 
			
		||||
bool Bind::visit(PropertyNameAndValueList *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::NestedExpression *)
 | 
			
		||||
bool Bind::visit(NestedExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::IdentifierPropertyName *)
 | 
			
		||||
bool Bind::visit(IdentifierPropertyName *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::StringLiteralPropertyName *)
 | 
			
		||||
bool Bind::visit(StringLiteralPropertyName *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::NumericLiteralPropertyName *)
 | 
			
		||||
bool Bind::visit(NumericLiteralPropertyName *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::ArrayMemberExpression *)
 | 
			
		||||
bool Bind::visit(ArrayMemberExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::FieldMemberExpression *)
 | 
			
		||||
bool Bind::visit(FieldMemberExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::NewMemberExpression *)
 | 
			
		||||
bool Bind::visit(NewMemberExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::NewExpression *)
 | 
			
		||||
bool Bind::visit(NewExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::CallExpression *)
 | 
			
		||||
bool Bind::visit(CallExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::ArgumentList *)
 | 
			
		||||
bool Bind::visit(ArgumentList *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::PostIncrementExpression *)
 | 
			
		||||
bool Bind::visit(PostIncrementExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::PostDecrementExpression *)
 | 
			
		||||
bool Bind::visit(PostDecrementExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::DeleteExpression *)
 | 
			
		||||
bool Bind::visit(DeleteExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::VoidExpression *)
 | 
			
		||||
bool Bind::visit(VoidExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::TypeOfExpression *)
 | 
			
		||||
bool Bind::visit(TypeOfExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::PreIncrementExpression *)
 | 
			
		||||
bool Bind::visit(PreIncrementExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::PreDecrementExpression *)
 | 
			
		||||
bool Bind::visit(PreDecrementExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UnaryPlusExpression *)
 | 
			
		||||
bool Bind::visit(UnaryPlusExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::UnaryMinusExpression *)
 | 
			
		||||
bool Bind::visit(UnaryMinusExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::TildeExpression *)
 | 
			
		||||
bool Bind::visit(TildeExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::NotExpression *)
 | 
			
		||||
bool Bind::visit(NotExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::BinaryExpression *)
 | 
			
		||||
bool Bind::visit(BinaryExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::ConditionalExpression *)
 | 
			
		||||
bool Bind::visit(ConditionalExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::Expression *)
 | 
			
		||||
bool Bind::visit(Expression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::Block *)
 | 
			
		||||
bool Bind::visit(Block *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::StatementList *)
 | 
			
		||||
bool Bind::visit(StatementList *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::VariableStatement *)
 | 
			
		||||
bool Bind::visit(VariableStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::VariableDeclarationList *)
 | 
			
		||||
bool Bind::visit(VariableDeclarationList *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::VariableDeclaration *)
 | 
			
		||||
bool Bind::visit(VariableDeclaration *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::EmptyStatement *)
 | 
			
		||||
bool Bind::visit(EmptyStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::ExpressionStatement *)
 | 
			
		||||
bool Bind::visit(ExpressionStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::IfStatement *)
 | 
			
		||||
bool Bind::visit(IfStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::DoWhileStatement *)
 | 
			
		||||
bool Bind::visit(DoWhileStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::WhileStatement *)
 | 
			
		||||
bool Bind::visit(WhileStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::ForStatement *)
 | 
			
		||||
bool Bind::visit(ForStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::LocalForStatement *)
 | 
			
		||||
bool Bind::visit(LocalForStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::ForEachStatement *)
 | 
			
		||||
bool Bind::visit(ForEachStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::LocalForEachStatement *)
 | 
			
		||||
bool Bind::visit(LocalForEachStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::ContinueStatement *)
 | 
			
		||||
bool Bind::visit(ContinueStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::BreakStatement *)
 | 
			
		||||
bool Bind::visit(BreakStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::ReturnStatement *)
 | 
			
		||||
bool Bind::visit(ReturnStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::WithStatement *)
 | 
			
		||||
bool Bind::visit(WithStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::SwitchStatement *)
 | 
			
		||||
bool Bind::visit(SwitchStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::CaseBlock *)
 | 
			
		||||
bool Bind::visit(CaseBlock *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::CaseClauses *)
 | 
			
		||||
bool Bind::visit(CaseClauses *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::CaseClause *)
 | 
			
		||||
bool Bind::visit(CaseClause *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::DefaultClause *)
 | 
			
		||||
bool Bind::visit(DefaultClause *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::LabelledStatement *)
 | 
			
		||||
bool Bind::visit(LabelledStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::ThrowStatement *)
 | 
			
		||||
bool Bind::visit(ThrowStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::TryStatement *)
 | 
			
		||||
bool Bind::visit(TryStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::Catch *)
 | 
			
		||||
bool Bind::visit(Catch *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::Finally *)
 | 
			
		||||
bool Bind::visit(Finally *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::FunctionDeclaration *)
 | 
			
		||||
bool Bind::visit(FunctionDeclaration *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::FunctionExpression *)
 | 
			
		||||
bool Bind::visit(FunctionExpression *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::FormalParameterList *)
 | 
			
		||||
bool Bind::visit(FormalParameterList *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::FunctionBody *)
 | 
			
		||||
bool Bind::visit(FunctionBody *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::Program *)
 | 
			
		||||
bool Bind::visit(Program *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::SourceElements *)
 | 
			
		||||
bool Bind::visit(SourceElements *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::FunctionSourceElement *)
 | 
			
		||||
bool Bind::visit(FunctionSourceElement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::StatementSourceElement *)
 | 
			
		||||
bool Bind::visit(StatementSourceElement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Bind::visit(AST::DebuggerStatement *)
 | 
			
		||||
bool Bind::visit(DebuggerStatement *)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ObjectValue *Bind::switchObjectValue(ObjectValue *newObjectValue)
 | 
			
		||||
{
 | 
			
		||||
    ObjectValue *oldObjectValue = _currentObjectValue;
 | 
			
		||||
    _currentObjectValue = newObjectValue;
 | 
			
		||||
    return oldObjectValue;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,8 +30,9 @@
 | 
			
		||||
#ifndef QMLBIND_H
 | 
			
		||||
#define QMLBIND_H
 | 
			
		||||
 | 
			
		||||
#include "parser/qmljsastvisitor_p.h"
 | 
			
		||||
#include "qmljsdocument.h"
 | 
			
		||||
#include <qmljs/parser/qmljsastvisitor_p.h>
 | 
			
		||||
#include <qmljs/qmljsdocument.h>
 | 
			
		||||
#include <qmljs/qmljsinterpreter.h>
 | 
			
		||||
 | 
			
		||||
namespace QmlJS {
 | 
			
		||||
 | 
			
		||||
@@ -41,7 +42,7 @@ public:
 | 
			
		||||
    Bind();
 | 
			
		||||
    virtual ~Bind();
 | 
			
		||||
 | 
			
		||||
    void operator()(QmlJS::Document::Ptr doc);
 | 
			
		||||
    Interpreter::ObjectValue* operator()(Document::Ptr doc, Snapshot &snapshot, AST::UiObjectMember *member, Interpreter::Engine &interp);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void accept(AST::Node *node);
 | 
			
		||||
@@ -140,8 +141,23 @@ protected:
 | 
			
		||||
    virtual bool visit(AST::StatementSourceElement *ast);
 | 
			
		||||
    virtual bool visit(AST::DebuggerStatement *ast);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    Interpreter::ObjectValue *switchObjectValue(Interpreter::ObjectValue *newObjectValue);
 | 
			
		||||
    const Interpreter::ObjectValue *lookupType(AST::UiQualifiedId *qualifiedTypeNameId);
 | 
			
		||||
    Interpreter::ObjectValue *bindObject(AST::UiQualifiedId *qualifiedTypeNameId, AST::UiObjectInitializer *initializer);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    QmlJS::Document::Ptr _doc;
 | 
			
		||||
    Document::Ptr _doc;
 | 
			
		||||
    Snapshot *_snapshot;
 | 
			
		||||
    AST::UiObjectMember *_interestingMember;
 | 
			
		||||
    Interpreter::Engine *_interp;
 | 
			
		||||
 | 
			
		||||
    Interpreter::ObjectValue *_currentObjectValue;
 | 
			
		||||
 | 
			
		||||
    Interpreter::ObjectValue *_typeEnvironment;
 | 
			
		||||
    Interpreter::ObjectValue *_idEnvironment;
 | 
			
		||||
    Interpreter::ObjectValue *_interestingObjectValue;
 | 
			
		||||
    Interpreter::ObjectValue *_rootObjectValue;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // end of namespace Qml
 | 
			
		||||
 
 | 
			
		||||
@@ -225,6 +225,8 @@ void Snapshot::insert(const Document::Ptr &document)
 | 
			
		||||
 | 
			
		||||
Document::PtrList Snapshot::importedDocuments(const Document::Ptr &doc, const QString &importPath) const
 | 
			
		||||
{
 | 
			
		||||
    // ### TODO: maybe we should add all imported documents in the parse Document::parse() method, regardless of whether they're in the path or not.
 | 
			
		||||
 | 
			
		||||
    Document::PtrList result;
 | 
			
		||||
 | 
			
		||||
    const QString docPath = doc->path() + '/' + importPath;
 | 
			
		||||
 
 | 
			
		||||
@@ -43,8 +43,6 @@
 | 
			
		||||
 | 
			
		||||
using namespace QmlJS::Interpreter;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
#ifndef NO_DECLARATIVE_BACKEND
 | 
			
		||||
 | 
			
		||||
class QmlAttachedKeys: public ObjectValue
 | 
			
		||||
@@ -166,93 +164,102 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class QmlObjectValue: public ObjectValue
 | 
			
		||||
QmlObjectValue::QmlObjectValue(const QMetaObject *metaObject, const QString &qmlTypeName, int majorVersion, int minorVersion, Engine *engine)
 | 
			
		||||
    : ObjectValue(engine), _metaObject(metaObject), _qmlTypeName(qmlTypeName), _majorVersion(majorVersion), _minorVersion(minorVersion)
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
QmlObjectValue::~QmlObjectValue() {}
 | 
			
		||||
 | 
			
		||||
const Value *QmlObjectValue::lookupMember(const QString &name) const
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    QmlObjectValue(const QMetaObject *metaObject, Engine *engine)
 | 
			
		||||
        : ObjectValue(engine), _metaObject(metaObject)
 | 
			
		||||
    {
 | 
			
		||||
    for (int index = 0; index < _metaObject->propertyCount(); ++index) {
 | 
			
		||||
        QMetaProperty prop = _metaObject->property(index);
 | 
			
		||||
 | 
			
		||||
        if (name == QString::fromUtf8(prop.name()))
 | 
			
		||||
            return propertyValue(prop);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual ~QmlObjectValue() {}
 | 
			
		||||
    for (int index = 0; index < _metaObject->methodCount(); ++index) {
 | 
			
		||||
        QMetaMethod method = _metaObject->method(index);
 | 
			
		||||
 | 
			
		||||
    virtual const Value *lookupMember(const QString &name) const
 | 
			
		||||
    {
 | 
			
		||||
        for (int index = 0; index < _metaObject->propertyCount(); ++index) {
 | 
			
		||||
            QMetaProperty prop = _metaObject->property(index);
 | 
			
		||||
        const QString signature = QString::fromUtf8(method.signature());
 | 
			
		||||
 | 
			
		||||
            if (name == QString::fromUtf8(prop.name()))
 | 
			
		||||
                return propertyValue(prop);
 | 
			
		||||
        const int indexOfParen = signature.indexOf(QLatin1Char('('));
 | 
			
		||||
        if (indexOfParen == -1)
 | 
			
		||||
            continue; // skip it, invalid signature.
 | 
			
		||||
 | 
			
		||||
        const QString methodName = signature.left(indexOfParen);
 | 
			
		||||
 | 
			
		||||
        if (methodName != name) {
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        } else if (method.methodType() == QMetaMethod::Slot && method.access() == QMetaMethod::Public) {
 | 
			
		||||
            return new MetaFunction(method, engine());
 | 
			
		||||
 | 
			
		||||
        } else if (method.methodType() == QMetaMethod::Signal && method.access() != QMetaMethod::Private) {
 | 
			
		||||
            return new MetaFunction(method, engine());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        for (int index = 0; index < _metaObject->methodCount(); ++index) {
 | 
			
		||||
            QMetaMethod method = _metaObject->method(index);
 | 
			
		||||
    return ObjectValue::lookupMember(name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
            const QString signature = QString::fromUtf8(method.signature());
 | 
			
		||||
void QmlObjectValue::processMembers(MemberProcessor *processor) const
 | 
			
		||||
{
 | 
			
		||||
    for (int index = 0; index < _metaObject->propertyCount(); ++index) {
 | 
			
		||||
        QMetaProperty prop = _metaObject->property(index);
 | 
			
		||||
 | 
			
		||||
            const int indexOfParen = signature.indexOf(QLatin1Char('('));
 | 
			
		||||
            if (indexOfParen == -1)
 | 
			
		||||
                continue; // skip it, invalid signature.
 | 
			
		||||
        processor->processProperty(prop.name(), propertyValue(prop));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
            const QString methodName = signature.left(indexOfParen);
 | 
			
		||||
    for (int index = 0; index < _metaObject->methodCount(); ++index) {
 | 
			
		||||
        QMetaMethod method = _metaObject->method(index);
 | 
			
		||||
 | 
			
		||||
            if (methodName != name) {
 | 
			
		||||
                continue;
 | 
			
		||||
        const QString signature = QString::fromUtf8(method.signature());
 | 
			
		||||
 | 
			
		||||
            } else if (method.methodType() == QMetaMethod::Slot && method.access() == QMetaMethod::Public) {
 | 
			
		||||
                return new MetaFunction(method, engine());
 | 
			
		||||
        const int indexOfParen = signature.indexOf(QLatin1Char('('));
 | 
			
		||||
        if (indexOfParen == -1)
 | 
			
		||||
            continue; // skip it, invalid signature.
 | 
			
		||||
 | 
			
		||||
            } else if (method.methodType() == QMetaMethod::Signal && method.access() != QMetaMethod::Private) {
 | 
			
		||||
                return new MetaFunction(method, engine());
 | 
			
		||||
        const QString methodName = signature.left(indexOfParen);
 | 
			
		||||
 | 
			
		||||
        if (method.methodType() == QMetaMethod::Slot && method.access() == QMetaMethod::Public) {
 | 
			
		||||
            processor->processSlot(methodName, engine()->undefinedValue());
 | 
			
		||||
 | 
			
		||||
        } else if (method.methodType() == QMetaMethod::Signal && method.access() != QMetaMethod::Private) {
 | 
			
		||||
            // process the signal
 | 
			
		||||
            processor->processSignal(methodName, engine()->undefinedValue());
 | 
			
		||||
 | 
			
		||||
            QString slotName;
 | 
			
		||||
            slotName += QLatin1String("on");
 | 
			
		||||
            slotName += methodName.at(0).toUpper();
 | 
			
		||||
            slotName += methodName.midRef(1);
 | 
			
		||||
 | 
			
		||||
            // process the generated slot
 | 
			
		||||
            processor->processGeneratedSlot(slotName, engine()->undefinedValue());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ObjectValue::processMembers(processor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Value *QmlObjectValue::propertyValue(const QMetaProperty &prop) const
 | 
			
		||||
{
 | 
			
		||||
    if (QmlMetaType::isObject(prop.userType())) {
 | 
			
		||||
        QmlType *qmlPropertyType = QmlMetaType::qmlType(QmlMetaType::metaObjectForType(prop.userType()));
 | 
			
		||||
 | 
			
		||||
        if (qmlPropertyType && !qmlPropertyType->qmlTypeName().isEmpty()) {
 | 
			
		||||
            QString typeName = qmlPropertyType->qmlTypeName();
 | 
			
		||||
            int slashIdx = typeName.lastIndexOf(QLatin1Char('/'));
 | 
			
		||||
            QString package;
 | 
			
		||||
            if (slashIdx != -1) {
 | 
			
		||||
                package = typeName.left(slashIdx);
 | 
			
		||||
                typeName = typeName.mid(slashIdx + 1);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return ObjectValue::lookupMember(name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void processMembers(MemberProcessor *processor) const
 | 
			
		||||
    {
 | 
			
		||||
        for (int index = 0; index < _metaObject->propertyCount(); ++index) {
 | 
			
		||||
            QMetaProperty prop = _metaObject->property(index);
 | 
			
		||||
 | 
			
		||||
            processor->processProperty(prop.name(), propertyValue(prop));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (int index = 0; index < _metaObject->methodCount(); ++index) {
 | 
			
		||||
            QMetaMethod method = _metaObject->method(index);
 | 
			
		||||
 | 
			
		||||
            const QString signature = QString::fromUtf8(method.signature());
 | 
			
		||||
 | 
			
		||||
            const int indexOfParen = signature.indexOf(QLatin1Char('('));
 | 
			
		||||
            if (indexOfParen == -1)
 | 
			
		||||
                continue; // skip it, invalid signature.
 | 
			
		||||
 | 
			
		||||
            const QString methodName = signature.left(indexOfParen);
 | 
			
		||||
 | 
			
		||||
            if (method.methodType() == QMetaMethod::Slot && method.access() == QMetaMethod::Public) {
 | 
			
		||||
                processor->processSlot(methodName, engine()->undefinedValue());
 | 
			
		||||
 | 
			
		||||
            } else if (method.methodType() == QMetaMethod::Signal && method.access() != QMetaMethod::Private) {
 | 
			
		||||
                // process the signal
 | 
			
		||||
                processor->processSignal(methodName, engine()->undefinedValue());
 | 
			
		||||
 | 
			
		||||
                QString slotName;
 | 
			
		||||
                slotName += QLatin1String("on");
 | 
			
		||||
                slotName += methodName.at(0).toUpper();
 | 
			
		||||
                slotName += methodName.midRef(1);
 | 
			
		||||
 | 
			
		||||
                // process the generated slot
 | 
			
		||||
                processor->processGeneratedSlot(slotName, engine()->undefinedValue());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ObjectValue::processMembers(processor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Value *propertyValue(const QMetaProperty &prop) const {
 | 
			
		||||
        const Value *value = engine()->undefinedValue();
 | 
			
		||||
 | 
			
		||||
        if (QmlMetaType::isObject(prop.userType())) {
 | 
			
		||||
            if (const ObjectValue *objectValue = engine()->newQmlObject(typeName, package, qmlPropertyType->majorVersion(), qmlPropertyType->minorVersion()))
 | 
			
		||||
                return objectValue;
 | 
			
		||||
        } else {
 | 
			
		||||
            QString typeName = QString::fromUtf8(prop.typeName());
 | 
			
		||||
 | 
			
		||||
            if (typeName.endsWith(QLatin1Char('*')))
 | 
			
		||||
@@ -260,78 +267,78 @@ public:
 | 
			
		||||
 | 
			
		||||
            typeName.replace(QLatin1Char('.'), QLatin1Char('/'));
 | 
			
		||||
 | 
			
		||||
            if (const ObjectValue *objectValue = engine()->newQmlObject(typeName))
 | 
			
		||||
            if (const ObjectValue *objectValue = engine()->newQmlObject(typeName, "", -1, -1))  // ### we should extend this to lookup the property types in the QmlType object, instead of the QMetaProperty.
 | 
			
		||||
                return objectValue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        switch (prop.type()) {
 | 
			
		||||
        case QMetaType::QByteArray:
 | 
			
		||||
        case QMetaType::QString:
 | 
			
		||||
        case QMetaType::QUrl:
 | 
			
		||||
            value = engine()->stringValue();
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case QMetaType::Bool:
 | 
			
		||||
            value = engine()->booleanValue();
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case QMetaType::Int:
 | 
			
		||||
        case QMetaType::Float:
 | 
			
		||||
        case QMetaType::Double:
 | 
			
		||||
            value = engine()->numberValue();
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case QMetaType::QFont: {
 | 
			
		||||
            // ### cache
 | 
			
		||||
            ObjectValue *object = engine()->newObject(/*prototype =*/ 0);
 | 
			
		||||
            object->setProperty("family", engine()->stringValue());
 | 
			
		||||
            object->setProperty("weight", engine()->undefinedValue()); // ### make me an object
 | 
			
		||||
            object->setProperty("copitalization", engine()->undefinedValue()); // ### make me an object
 | 
			
		||||
            object->setProperty("bold", engine()->booleanValue());
 | 
			
		||||
            object->setProperty("italic", engine()->booleanValue());
 | 
			
		||||
            object->setProperty("underline", engine()->booleanValue());
 | 
			
		||||
            object->setProperty("overline", engine()->booleanValue());
 | 
			
		||||
            object->setProperty("strikeout", engine()->booleanValue());
 | 
			
		||||
            object->setProperty("pointSize", engine()->numberValue());
 | 
			
		||||
            object->setProperty("pixelSize", engine()->numberValue());
 | 
			
		||||
            object->setProperty("letterSpacing", engine()->numberValue());
 | 
			
		||||
            object->setProperty("wordSpacing", engine()->numberValue());
 | 
			
		||||
            value = object;
 | 
			
		||||
        } break;
 | 
			
		||||
 | 
			
		||||
        case QMetaType::QPoint:
 | 
			
		||||
        case QMetaType::QPointF: {
 | 
			
		||||
            // ### cache
 | 
			
		||||
            ObjectValue *object = engine()->newObject(/*prototype =*/ 0);
 | 
			
		||||
            object->setProperty("x", engine()->numberValue());
 | 
			
		||||
            object->setProperty("y", engine()->numberValue());
 | 
			
		||||
            value = object;
 | 
			
		||||
        } break;
 | 
			
		||||
 | 
			
		||||
        case QMetaType::QRect:
 | 
			
		||||
        case QMetaType::QRectF: {
 | 
			
		||||
            // ### cache
 | 
			
		||||
            ObjectValue *object = engine()->newObject(/*prototype =*/ 0);
 | 
			
		||||
            object->setProperty("x", engine()->numberValue());
 | 
			
		||||
            object->setProperty("y", engine()->numberValue());
 | 
			
		||||
            object->setProperty("width", engine()->numberValue());
 | 
			
		||||
            object->setProperty("height", engine()->numberValue());
 | 
			
		||||
            value = object;
 | 
			
		||||
        } break;
 | 
			
		||||
 | 
			
		||||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
        } // end of switch
 | 
			
		||||
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    const QMetaObject *_metaObject;
 | 
			
		||||
};
 | 
			
		||||
    const Value *value = engine()->undefinedValue();
 | 
			
		||||
 | 
			
		||||
    switch (prop.type()) {
 | 
			
		||||
    case QMetaType::QByteArray:
 | 
			
		||||
    case QMetaType::QString:
 | 
			
		||||
    case QMetaType::QUrl:
 | 
			
		||||
        value = engine()->stringValue();
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case QMetaType::Bool:
 | 
			
		||||
        value = engine()->booleanValue();
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case QMetaType::Int:
 | 
			
		||||
    case QMetaType::Float:
 | 
			
		||||
    case QMetaType::Double:
 | 
			
		||||
        value = engine()->numberValue();
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case QMetaType::QFont: {
 | 
			
		||||
        // ### cache
 | 
			
		||||
        ObjectValue *object = engine()->newObject(/*prototype =*/ 0);
 | 
			
		||||
        object->setProperty("family", engine()->stringValue());
 | 
			
		||||
        object->setProperty("weight", engine()->undefinedValue()); // ### make me an object
 | 
			
		||||
        object->setProperty("copitalization", engine()->undefinedValue()); // ### make me an object
 | 
			
		||||
        object->setProperty("bold", engine()->booleanValue());
 | 
			
		||||
        object->setProperty("italic", engine()->booleanValue());
 | 
			
		||||
        object->setProperty("underline", engine()->booleanValue());
 | 
			
		||||
        object->setProperty("overline", engine()->booleanValue());
 | 
			
		||||
        object->setProperty("strikeout", engine()->booleanValue());
 | 
			
		||||
        object->setProperty("pointSize", engine()->numberValue());
 | 
			
		||||
        object->setProperty("pixelSize", engine()->numberValue());
 | 
			
		||||
        object->setProperty("letterSpacing", engine()->numberValue());
 | 
			
		||||
        object->setProperty("wordSpacing", engine()->numberValue());
 | 
			
		||||
        value = object;
 | 
			
		||||
    } break;
 | 
			
		||||
 | 
			
		||||
    case QMetaType::QPoint:
 | 
			
		||||
    case QMetaType::QPointF: {
 | 
			
		||||
        // ### cache
 | 
			
		||||
        ObjectValue *object = engine()->newObject(/*prototype =*/ 0);
 | 
			
		||||
        object->setProperty("x", engine()->numberValue());
 | 
			
		||||
        object->setProperty("y", engine()->numberValue());
 | 
			
		||||
        value = object;
 | 
			
		||||
    } break;
 | 
			
		||||
 | 
			
		||||
    case QMetaType::QRect:
 | 
			
		||||
    case QMetaType::QRectF: {
 | 
			
		||||
        // ### cache
 | 
			
		||||
        ObjectValue *object = engine()->newObject(/*prototype =*/ 0);
 | 
			
		||||
        object->setProperty("x", engine()->numberValue());
 | 
			
		||||
        object->setProperty("y", engine()->numberValue());
 | 
			
		||||
        object->setProperty("width", engine()->numberValue());
 | 
			
		||||
        object->setProperty("height", engine()->numberValue());
 | 
			
		||||
        value = object;
 | 
			
		||||
    } break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
        break;
 | 
			
		||||
    } // end of switch
 | 
			
		||||
 | 
			
		||||
    return value;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// constructors
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
@@ -1300,8 +1307,9 @@ Engine::Engine()
 | 
			
		||||
      _convertToString(this),
 | 
			
		||||
      _convertToObject(this)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    initializePrototypes();
 | 
			
		||||
 | 
			
		||||
    _metaTypeSystem.reload(this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Engine::~Engine()
 | 
			
		||||
@@ -1780,19 +1788,19 @@ const Value *Engine::defaultValueForBuiltinType(const QString &typeName) const
 | 
			
		||||
    return undefinedValue();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ObjectValue *Engine::newQmlObject(const QString &name)
 | 
			
		||||
{
 | 
			
		||||
#ifndef NO_DECLARATIVE_BACKEND
 | 
			
		||||
QmlObjectValue *Engine::newQmlObject(const QString &name, const QString &prefix, int majorVersion, int minorVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (name == QLatin1String("QmlGraphicsAnchors")) {
 | 
			
		||||
        QmlObjectValue *object = new QmlObjectValue(&QmlGraphicsAnchors::staticMetaObject, this);
 | 
			
		||||
        QmlObjectValue *object = new QmlObjectValue(&QmlGraphicsAnchors::staticMetaObject, QLatin1String("Anchors"), -1, -1, this);
 | 
			
		||||
        _objects.append(object);
 | 
			
		||||
        return object;
 | 
			
		||||
    } else if (name == QLatin1String("QmlGraphicsPen")) {
 | 
			
		||||
        QmlObjectValue *object = new QmlObjectValue(&QmlGraphicsPen::staticMetaObject, this);
 | 
			
		||||
        QmlObjectValue *object = new QmlObjectValue(&QmlGraphicsPen::staticMetaObject, QLatin1String("Pen"), -1, -1, this);
 | 
			
		||||
        _objects.append(object);
 | 
			
		||||
        return object;
 | 
			
		||||
    } else if (name == QLatin1String("QmlGraphicsScaleGrid")) {
 | 
			
		||||
        ObjectValue *object = newObject(/*prototype =*/ 0);
 | 
			
		||||
        QmlObjectValue *object = new QmlObjectValue(&QObject::staticMetaObject, QLatin1String("ScaleGrid"), -1, -1, this);
 | 
			
		||||
        object->setProperty("left", numberValue());
 | 
			
		||||
        object->setProperty("top", numberValue());
 | 
			
		||||
        object->setProperty("right", numberValue());
 | 
			
		||||
@@ -1801,20 +1809,17 @@ ObjectValue *Engine::newQmlObject(const QString &name)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // ### TODO: add support for QML packages
 | 
			
		||||
    QString componentName;
 | 
			
		||||
    componentName += QLatin1String("Qt/");
 | 
			
		||||
    componentName += name;
 | 
			
		||||
    componentName.replace(QLatin1Char('.'), QLatin1Char('/'));
 | 
			
		||||
    const QString componentName = prefix + QLatin1Char('/') + name;
 | 
			
		||||
 | 
			
		||||
    if (QmlType *qmlType = QmlMetaType::qmlType(componentName.toUtf8(), 4, 6)) {
 | 
			
		||||
        QmlObjectValue *object = new QmlObjectValue(qmlType->metaObject(), this);
 | 
			
		||||
    if (QmlType *qmlType = QmlMetaType::qmlType(componentName.toUtf8(), majorVersion, minorVersion)) {
 | 
			
		||||
        const QString typeName = qmlType->qmlTypeName();
 | 
			
		||||
        const QString strippedTypeName = typeName.mid(typeName.lastIndexOf('/') + 1);
 | 
			
		||||
        QmlObjectValue *object = new QmlObjectValue(qmlType->metaObject(), strippedTypeName, majorVersion, minorVersion, this);
 | 
			
		||||
        _objects.append(object);
 | 
			
		||||
        return object;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
#else
 | 
			
		||||
    return newObject(/*prototype = */ 0);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,8 @@
 | 
			
		||||
#ifndef QMLJS_INTERPRETER_H
 | 
			
		||||
#define QMLJS_INTERPRETER_H
 | 
			
		||||
 | 
			
		||||
#include "qmljs_global.h"
 | 
			
		||||
#include <qmljs/qmljs_global.h>
 | 
			
		||||
#include <qmljs/qmljsmetatypesystem.h>
 | 
			
		||||
 | 
			
		||||
#include <QtCore/QList>
 | 
			
		||||
#include <QtCore/QString>
 | 
			
		||||
@@ -250,6 +251,36 @@ private:
 | 
			
		||||
    QString _className;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifndef NO_DECLARATIVE_BACKEND
 | 
			
		||||
 | 
			
		||||
class QmlObjectValue: public ObjectValue
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    QmlObjectValue(const QMetaObject *metaObject, const QString &qmlTypeName, int majorVersion, int minorVersion, Engine *engine);
 | 
			
		||||
    virtual ~QmlObjectValue();
 | 
			
		||||
 | 
			
		||||
    virtual const Value *lookupMember(const QString &name) const;
 | 
			
		||||
    virtual void processMembers(MemberProcessor *processor) const;
 | 
			
		||||
    const Value *propertyValue(const QMetaProperty &prop) const;
 | 
			
		||||
 | 
			
		||||
    QString qmlTypeName() const
 | 
			
		||||
    { return _qmlTypeName; }
 | 
			
		||||
 | 
			
		||||
    int majorVersion() const
 | 
			
		||||
    { return _majorVersion; }
 | 
			
		||||
 | 
			
		||||
    int minorVersion() const
 | 
			
		||||
    { return _minorVersion; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    const QMetaObject *_metaObject;
 | 
			
		||||
    QString _qmlTypeName;
 | 
			
		||||
    int _majorVersion;
 | 
			
		||||
    int _minorVersion;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // !NO_DECLARATIVE_BACKEND
 | 
			
		||||
 | 
			
		||||
class QMLJS_EXPORT Activation: public ObjectValue
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
@@ -440,9 +471,11 @@ public:
 | 
			
		||||
    const Value *newArray(); // ### remove me
 | 
			
		||||
 | 
			
		||||
    // QML objects
 | 
			
		||||
    ObjectValue *newQmlObject(const QString &name);
 | 
			
		||||
    const ObjectValue *qmlKeysObject();
 | 
			
		||||
    const Value *defaultValueForBuiltinType(const QString &typeName) const;
 | 
			
		||||
#ifndef NO_DECLARATIVE_BACKEND
 | 
			
		||||
    QmlObjectValue *newQmlObject(const QString &name, const QString &prefix, int majorVersion, int minorVersion);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // global object
 | 
			
		||||
    ObjectValue *globalObject() const;
 | 
			
		||||
@@ -477,6 +510,11 @@ public:
 | 
			
		||||
    const Value *convertToObject(const Value *value);
 | 
			
		||||
    QString typeId(const Value *value);
 | 
			
		||||
 | 
			
		||||
    // typing:
 | 
			
		||||
    const MetaTypeSystem &metaTypeSystem() const
 | 
			
		||||
    { return _metaTypeSystem; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void initializePrototypes();
 | 
			
		||||
 | 
			
		||||
@@ -519,6 +557,8 @@ private:
 | 
			
		||||
    ConvertToString _convertToString;
 | 
			
		||||
    ConvertToObject _convertToObject;
 | 
			
		||||
    TypeId _typeId;
 | 
			
		||||
 | 
			
		||||
    MetaTypeSystem _metaTypeSystem;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} } // end of namespace QmlJS::Interpreter
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user