qqmlcompiler_p.h 17.27 KiB
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
** GNU Lesser General Public License Usage
** Alternatively, 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, Digia gives you certain additional
** rights.  These rights are described in the Digia 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.
** $QT_END_LICENSE$
****************************************************************************/
#ifndef QQMLCOMPILER_P_H
#define QQMLCOMPILER_P_H
//  W A R N I N G
//  -------------
// This file is not part of the Qt API.  It exists purely as an
// implementation detail.  This header file may change from version to
// version without notice, or even be removed.
// We mean it.
#include "qqml.h"
#include "qqmlerror.h"
#include <private/qv8_p.h>
#include "qqmlinstruction_p.h"
#include "qqmlscript_p.h"
#include "qqmlengine_p.h"
#include <private/qbitfield_p.h>
#include "qqmlpropertycache_p.h"
#include "qqmlintegercache_p.h"
#include "qqmltypenamecache_p.h"
#include "qqmltypeloader_p.h"
#include <QtCore/qbytearray.h>
#include <QtCore/qset.h>
#include <QtCore/QCoreApplication>
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
QT_BEGIN_NAMESPACE class QQmlEngine; class QQmlComponent; class QQmlContext; class QQmlContextData; class Q_AUTOTEST_EXPORT QQmlCompiledData : public QQmlRefCount, public QQmlCleanup { public: QQmlCompiledData(QQmlEngine *engine); virtual ~QQmlCompiledData(); QQmlEngine *engine; QString name; QUrl url; QQmlTypeNameCache *importCache; int metaTypeId; int listMetaTypeId; bool isRegisteredWithEngine; struct TypeReference { TypeReference() : type(0), typePropertyCache(0), component(0) {} QQmlType *type; QQmlPropertyCache *typePropertyCache; QQmlCompiledData *component; QQmlPropertyCache *propertyCache() const; QQmlPropertyCache *createPropertyCache(QQmlEngine *); }; QList<TypeReference> types; struct V8Program { V8Program(const QByteArray &p, QQmlCompiledData *c) : program(p), cdata(c) {} QByteArray program; QV4::PersistentValue bindings; QQmlCompiledData *cdata; }; QList<V8Program> programs; QQmlPropertyCache *rootPropertyCache; QList<QString> primitives; QList<QByteArray> datas; QByteArray bytecode; QList<QQmlPropertyCache *> propertyCaches; QList<QQmlIntegerCache *> contextCaches; QList<QQmlScriptData *> scripts; QList<QUrl> urls; struct Instruction { #define QML_INSTR_DATA_TYPEDEF(I, FMT) typedef QQmlInstructionData<QQmlInstruction::I> I; FOR_EACH_QML_INSTR(QML_INSTR_DATA_TYPEDEF) #undef QML_INSTR_DATA_TYPEDEF private: Instruction(); }; void dumpInstructions(); template <int Instr> int addInstruction(const QQmlInstructionData<Instr> &data)
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
{ QQmlInstruction genericInstr; QQmlInstructionMeta<Instr>::setData(genericInstr, data); return addInstructionHelper(static_cast<QQmlInstruction::Type>(Instr), genericInstr); } int nextInstructionIndex(); QQmlInstruction *instruction(int index); QQmlInstruction::Type instructionType(const QQmlInstruction *instr); bool isInitialized() const { return hasEngine(); } void initialize(QQmlEngine *); protected: virtual void destroy(); // From QQmlRefCount virtual void clear(); // From QQmlCleanup private: friend class QQmlCompiler; int addInstructionHelper(QQmlInstruction::Type type, QQmlInstruction &instr); void dump(QQmlInstruction *, int idx = -1); QQmlCompiledData(const QQmlCompiledData &other); QQmlCompiledData &operator=(const QQmlCompiledData &other); int indexForString(const QString &); int indexForByteArray(const QByteArray &); int indexForUrl(const QUrl &); }; namespace QQmlCompilerTypes { struct BindingContext { BindingContext() : stack(0), owner(0), object(0) {} BindingContext(QQmlScript::Object *o) : stack(0), owner(0), object(o) {} BindingContext incr() const { BindingContext rv(object); rv.stack = stack + 1; return rv; } bool isSubContext() const { return stack != 0; } int stack; int owner; QQmlScript::Object *object; }; struct BindingReference { enum DataType { QtScript, V4, V8, Tr, TrId }; DataType dataType; }; struct JSBindingReference : public QQmlPool::Class, public BindingReference { JSBindingReference() : isSafe(false), nextReference(0) {} QQmlScript::Variant expression; QQmlScript::Property *property; QQmlScript::Value *value; int compiledIndex:15; int sharedIndex:15; bool isSafe:1; QString rewrittenExpression; BindingContext bindingContext;
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
JSBindingReference *nextReference; }; struct TrBindingReference : public QQmlPool::POD, public BindingReference { QStringRef text; QStringRef comment; int n; }; struct IdList : public QFieldList<QQmlScript::Object, &QQmlScript::Object::nextIdObject> { QQmlScript::Object *value(const QString &id) const { for (QQmlScript::Object *o = first(); o; o = next(o)) { if (o->id == id) return o; } return 0; } }; struct DepthStack { DepthStack() : _depth(0), _maxDepth(0) {} DepthStack(const DepthStack &o) : _depth(o._depth), _maxDepth(o._maxDepth) {} DepthStack &operator=(const DepthStack &o) { _depth = o._depth; _maxDepth = o._maxDepth; return *this; } int depth() const { return _depth; } int maxDepth() const { return _maxDepth; } void push() { ++_depth; _maxDepth = qMax(_depth, _maxDepth); } void pop() { --_depth; Q_ASSERT(_depth >= 0); Q_ASSERT(_maxDepth > _depth); } void pushPop(int count) { _maxDepth = qMax(_depth + count, _maxDepth); } private: int _depth; int _maxDepth; }; // Contains all the incremental compiler state about a component. As // a single QML file can have multiple components defined, there may be // more than one of these for each compile struct ComponentCompileState : public QQmlPool::Class { ComponentCompileState() : parserStatusCount(0), totalBindingsCount(0), pushedProperties(0), nested(false), v8BindingProgramLine(-1), root(0) {} IdList ids; int parserStatusCount; int totalBindingsCount; int pushedProperties; bool nested; QByteArray compiledBindingData; QByteArray v8BindingProgram; int v8BindingProgramLine; DepthStack objectDepth; DepthStack listDepth; typedef QQmlCompilerTypes::JSBindingReference B; typedef QFieldList<B, &B::nextReference> JSBindingReferenceList; JSBindingReferenceList bindings; typedef QQmlScript::Object O; typedef QFieldList<O, &O::nextAliasingObject> AliasingObjectsList; AliasingObjectsList aliasingObjects; QQmlScript::Object *root; };
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
}; class QMetaObjectBuilder; class Q_AUTOTEST_EXPORT QQmlCompiler { Q_DECLARE_TR_FUNCTIONS(QQmlCompiler) public: QQmlCompiler(QQmlPool *); bool compile(QQmlEngine *, QQmlTypeData *, QQmlCompiledData *); bool isError() const; QList<QQmlError> errors() const; static bool isAttachedPropertyName(const QString &); static bool isSignalPropertyName(const QString &); static bool isAttachedPropertyName(const QHashedStringRef &); static bool isSignalPropertyName(const QHashedStringRef &); int evaluateEnum(const QHashedStringRef &scope, const QByteArray& enumValue, bool *ok) const; // for QQmlCustomParser::evaluateEnum const QMetaObject *resolveType(const QString& name) const; // for QQmlCustomParser::resolveType int rewriteBinding(const QQmlScript::Variant& value, const QString& name); // for QQmlCustomParser::rewriteBinding QString rewriteSignalHandler(const QQmlScript::Variant& value, const QString &name); // for QQmlCustomParser::rewriteSignalHandler private: typedef QQmlCompiledData::Instruction Instruction; static void reset(QQmlCompiledData *); void compileTree(QQmlScript::Object *tree); bool buildObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); bool buildComponent(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); bool buildSubObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); bool buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); bool buildProperty(QQmlScript::Property *prop, QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); bool buildPropertyInNamespace(QQmlImportNamespace *ns, QQmlScript::Property *prop, QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); bool buildIdProperty(QQmlScript::Property *prop, QQmlScript::Object *obj); bool buildAttachedProperty(QQmlScript::Property *prop, QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &ctxt); bool buildGroupedProperty(QQmlScript::Property *prop, QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &ctxt); bool buildValueTypeProperty(QObject *type, QQmlScript::Object *obj, QQmlScript::Object *baseObj, const QQmlCompilerTypes::BindingContext &ctxt); bool buildListProperty(QQmlScript::Property *prop, QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &ctxt); bool buildScriptStringProperty(QQmlScript::Property *prop, QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &ctxt); bool buildPropertyAssignment(QQmlScript::Property *prop, QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &ctxt); bool buildPropertyObjectAssignment(QQmlScript::Property *prop, QQmlScript::Object *obj, QQmlScript::Value *value, const QQmlCompilerTypes::BindingContext &ctxt); bool buildPropertyOnAssignment(QQmlScript::Property *prop, QQmlScript::Object *obj, QQmlScript::Object *baseObj,
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
QQmlScript::Value *value, const QQmlCompilerTypes::BindingContext &ctxt); bool buildPropertyLiteralAssignment(QQmlScript::Property *prop, QQmlScript::Object *obj, QQmlScript::Value *value, const QQmlCompilerTypes::BindingContext &ctxt); bool doesPropertyExist(QQmlScript::Property *prop, QQmlScript::Object *obj); bool testLiteralAssignment(QQmlScript::Property *prop, QQmlScript::Value *value); bool testQualifiedEnumAssignment(QQmlScript::Property *prop, QQmlScript::Object *obj, QQmlScript::Value *value, bool *isAssignment); enum DynamicMetaMode { Normal, ForceCreation }; bool mergeDynamicMetaProperties(QQmlScript::Object *obj); bool buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mode); bool buildDynamicMetaAliases(QQmlScript::Object *obj); bool checkDynamicMeta(QQmlScript::Object *obj); bool buildBinding(QQmlScript::Value *, QQmlScript::Property *prop, const QQmlCompilerTypes::BindingContext &ctxt); bool buildLiteralBinding(QQmlScript::Value *, QQmlScript::Property *prop, const QQmlCompilerTypes::BindingContext &ctxt); bool buildComponentFromRoot(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); bool completeComponentBuild(); bool checkValidId(QQmlScript::Value *, const QString &); void genObject(QQmlScript::Object *obj, bool parentToSuper = false); void genObjectBody(QQmlScript::Object *obj); void genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Property *); void genComponent(QQmlScript::Object *obj); void genValueProperty(QQmlScript::Property *prop, QQmlScript::Object *obj); void genListProperty(QQmlScript::Property *prop, QQmlScript::Object *obj); void genPropertyAssignment(QQmlScript::Property *prop, QQmlScript::Object *obj, QQmlScript::Property *valueTypeProperty = 0); void genLiteralAssignment(QQmlScript::Property *prop, QQmlScript::Value *value); void genBindingAssignment(QQmlScript::Value *binding, QQmlScript::Property *prop, QQmlScript::Object *obj, QQmlScript::Property *valueTypeProperty = 0); int genContextCache(); QQmlPropertyData genValueTypeData(QQmlScript::Property *prop, QQmlScript::Property *valueTypeProp); int componentTypeRef(); int translationContextIndex(); QQmlType *toQmlType(QQmlScript::Object *from); bool canCoerce(int to, QQmlScript::Object *from); QString elementName(QQmlScript::Object *); QStringList deferredProperties(QQmlScript::Object *); QQmlPropertyCache *propertyCacheForObject(QQmlScript::Object *); QQmlPropertyData *property(QQmlScript::Object *, int); QQmlPropertyData *property(QQmlScript::Object *, const QHashedStringRef &, bool *notInRevision = 0); QQmlPropertyData *signal(QQmlScript::Object *, const QHashedStringRef &, bool *notInRevision = 0); int indexOfProperty(QQmlScript::Object *, const QHashedStringRef &, bool *notInRevision = 0); int indexOfProperty(QQmlScript::Object *, const QString &, bool *notInRevision = 0); int indexOfSignal(QQmlScript::Object *, const QString &, bool *notInRevision = 0); void addId(const QString &, QQmlScript::Object *); void dumpStats();
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
void addBindingReference(QQmlCompilerTypes::JSBindingReference *); QQmlCompilerTypes::ComponentCompileState *compileState; QQmlPool *pool; QQmlCompilerTypes::ComponentCompileState *componentState(QQmlScript::Object *); void saveComponentState(); QList<QQmlError> exceptions; QQmlCompiledData *output; QQmlEngine *engine; QQmlEnginePrivate *enginePrivate; QQmlScript::Object *unitRoot; QQmlTypeData *unit; int cachedComponentTypeRef; int cachedTranslationContextIndex; // Compiler component statistics. Only collected if QML_COMPILER_STATS=1 struct ComponentStat { ComponentStat() : lineNumber(0), ids(0), objects(0) {} quint16 lineNumber; int ids; QList<QQmlScript::LocationSpan> scriptBindings; QList<QQmlScript::LocationSpan> sharedBindings; QList<QQmlScript::LocationSpan> optimizedBindings; int objects; }; struct ComponentStats : public QQmlPool::Class { ComponentStat componentStat; QList<ComponentStat> savedComponentStats; }; ComponentStats *componentStats; }; QT_END_NAMESPACE #endif // QQMLCOMPILER_P_H