aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qqmltypecompiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/compiler/qqmltypecompiler.cpp')
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp220
1 files changed, 220 insertions, 0 deletions
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
new file mode 100644
index 0000000000..7ff5570f14
--- /dev/null
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the tools applications 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$
+**
+****************************************************************************/
+
+#include "qqmltypecompiler_p.h"
+
+#include <private/qqmlcompiler_p.h>
+#include <private/qqmlobjectcreator_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlCompiledData *compiledData, QQmlTypeData *typeData, QtQml::ParsedQML *parsedQML)
+ : engine(engine)
+ , compiledData(compiledData)
+ , typeData(typeData)
+ , parsedQML(parsedQML)
+{
+}
+
+bool QQmlTypeCompiler::compile()
+{
+ compiledData->importCache = new QQmlTypeNameCache;
+
+ foreach (const QString &ns, typeData->namespaces())
+ compiledData->importCache->add(ns);
+
+ // Add any Composite Singletons that were used to the import cache
+ foreach (const QQmlTypeData::TypeReference &singleton, typeData->compositeSingletons())
+ compiledData->importCache->add(singleton.type->qmlTypeName(), singleton.type->sourceUrl(), singleton.prefix);
+
+ typeData->imports().populateCache(compiledData->importCache);
+ compiledData->importCache->addref();
+
+ const QHash<int, QQmlTypeData::TypeReference> &resolvedTypes = typeData->resolvedTypeRefs();
+ for (QHash<int, QQmlTypeData::TypeReference>::ConstIterator resolvedType = resolvedTypes.constBegin(), end = resolvedTypes.constEnd();
+ resolvedType != end; ++resolvedType) {
+ QQmlCompiledData::TypeReference ref;
+ if (resolvedType->typeData) {
+ ref.component = resolvedType->typeData->compiledData();
+ ref.component->addref();
+ } else {
+ ref.type = resolvedType->type;
+ Q_ASSERT(ref.type);
+ }
+ ref.majorVersion = resolvedType->majorVersion;
+ ref.minorVersion = resolvedType->minorVersion;
+ compiledData->resolvedTypes.insert(resolvedType.key(), ref);
+ }
+
+ // Build property caches and VME meta object data
+
+ const int objectCount = parsedQML->objects.count();
+ compiledData->datas.reserve(objectCount);
+ compiledData->propertyCaches.reserve(objectCount);
+
+ QQmlPropertyCacheCreator propertyCacheBuilder(engine,
+ parsedQML->jsGenerator.strings, compiledData->url,
+ &typeData->imports(), &compiledData->resolvedTypes);
+
+ for (int i = 0; i < objectCount; ++i) {
+ const QtQml::QmlObject *obj = parsedQML->objects.at(i);
+
+ QByteArray vmeMetaObjectData;
+ QQmlPropertyCache *propertyCache = 0;
+
+ // If the object has no type, then it's probably a nested object definition as part
+ // of a group property.
+ const bool objectHasType = !propertyCacheBuilder.stringAt(obj->inheritedTypeNameIndex).isEmpty();
+ if (objectHasType) {
+ if (!propertyCacheBuilder.create(obj, &propertyCache, &vmeMetaObjectData)) {
+ errors << propertyCacheBuilder.errors;
+ return false;
+ }
+ }
+
+ compiledData->datas << vmeMetaObjectData;
+ if (propertyCache)
+ propertyCache->addref();
+ compiledData->propertyCaches << propertyCache;
+
+ if (i == parsedQML->indexOfRootObject) {
+ Q_ASSERT(propertyCache);
+ compiledData->rootPropertyCache = propertyCache;
+ propertyCache->addref();
+ }
+ }
+
+ {
+ SignalHandlerConverter converter(engine, parsedQML, compiledData);
+ if (!converter.convertSignalHandlerExpressionsToFunctionDeclarations()) {
+ errors << converter.errors;
+ return false;
+ }
+ }
+
+ // Collect imported scripts
+ const QList<QQmlTypeData::ScriptReference> &scripts = typeData->resolvedScripts();
+ compiledData->scripts.reserve(scripts.count());
+ for (int scriptIndex = 0; scriptIndex < scripts.count(); ++scriptIndex) {
+ const QQmlTypeData::ScriptReference &script = scripts.at(scriptIndex);
+
+ QString qualifier = script.qualifier;
+ QString enclosingNamespace;
+
+ const int lastDotIndex = qualifier.lastIndexOf(QLatin1Char('.'));
+ if (lastDotIndex != -1) {
+ enclosingNamespace = qualifier.left(lastDotIndex);
+ qualifier = qualifier.mid(lastDotIndex+1);
+ }
+
+ compiledData->importCache->add(qualifier, scriptIndex, enclosingNamespace);
+ QQmlScriptData *scriptData = script.script->scriptData();
+ scriptData->addref();
+ compiledData->scripts << scriptData;
+ }
+
+ // Compile JS binding expressions and signal handlers
+
+ JSCodeGen jsCodeGen(typeData->finalUrlString(), parsedQML->code, &parsedQML->jsModule, &parsedQML->jsParserEngine, parsedQML->program, compiledData->importCache);
+ const QVector<int> runtimeFunctionIndices = jsCodeGen.generateJSCodeForFunctionsAndBindings(parsedQML->functions);
+
+ QV4::ExecutionEngine *v4 = engine->v4engine();
+
+ QScopedPointer<QQmlJS::EvalInstructionSelection> isel(v4->iselFactory->create(engine, v4->executableAllocator, &parsedQML->jsModule, &parsedQML->jsGenerator));
+ isel->setUseFastLookups(false);
+ QV4::CompiledData::CompilationUnit *jsUnit = isel->compile(/*generated unit data*/false);
+
+ // Generate QML compiled type data structures
+
+ QmlUnitGenerator qmlGenerator;
+ QV4::CompiledData::QmlUnit *qmlUnit = qmlGenerator.generate(*parsedQML, runtimeFunctionIndices);
+
+ if (jsUnit) {
+ Q_ASSERT(!jsUnit->data);
+ jsUnit->ownsData = false;
+ jsUnit->data = &qmlUnit->header;
+ }
+
+ compiledData->compilationUnit = jsUnit;
+ if (compiledData->compilationUnit)
+ compiledData->compilationUnit->ref();
+ compiledData->qmlUnit = qmlUnit; // ownership transferred to m_compiledData
+
+ // Resolve component boundaries and aliases
+
+ {
+ // Scan for components, determine their scopes and resolve aliases within the scope.
+ QQmlComponentAndAliasResolver resolver(compiledData->url, compiledData->qmlUnit, compiledData->resolvedTypes, compiledData->propertyCaches,
+ &compiledData->datas, &compiledData->objectIndexToIdForRoot, &compiledData->objectIndexToIdPerComponent);
+ if (!resolver.resolve()) {
+ errors << resolver.errors;
+ return false;
+ }
+ }
+
+ // Add to type registry of composites
+ if (compiledData->isCompositeType())
+ engine->registerInternalCompositeType(compiledData);
+ else {
+ const QV4::CompiledData::Object *obj = qmlUnit->objectAt(qmlUnit->indexOfRootObject);
+ QQmlCompiledData::TypeReference typeRef = compiledData->resolvedTypes.value(obj->inheritedTypeNameIndex);
+ if (typeRef.component) {
+ compiledData->metaTypeId = typeRef.component->metaTypeId;
+ compiledData->listMetaTypeId = typeRef.component->listMetaTypeId;
+ } else {
+ compiledData->metaTypeId = typeRef.type->typeId();
+ compiledData->listMetaTypeId = typeRef.type->qListTypeId();
+ }
+ }
+
+ // Sanity check property bindings
+ QQmlPropertyValidator validator(compiledData->url, compiledData->qmlUnit, compiledData->resolvedTypes,
+ compiledData->propertyCaches, compiledData->objectIndexToIdPerComponent,
+ &compiledData->customParserData);
+ if (!validator.validate()) {
+ errors << validator.errors;
+ return false;
+ }
+
+ return errors.isEmpty();
+}
+
+QT_END_NAMESPACE