src/declarative/qml/qdeclarativecompiler.cpp
changeset 37 758a864f9613
parent 33 3e2da88830cd
--- a/src/declarative/qml/qdeclarativecompiler.cpp	Fri Sep 17 08:34:18 2010 +0300
+++ b/src/declarative/qml/qdeclarativecompiler.cpp	Mon Oct 04 01:19:32 2010 +0300
@@ -41,7 +41,6 @@
 
 #include "private/qdeclarativecompiler_p.h"
 
-#include "private/qdeclarativecompositetypedata_p.h"
 #include "private/qdeclarativeparser_p.h"
 #include "private/qdeclarativescriptparser_p.h"
 #include "qdeclarativepropertyvaluesource.h"
@@ -240,7 +239,7 @@
             if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: color expected"));
             }
             break;
-#ifndef QT_NO_TEXTDATE
+#ifndef QT_NO_DATESTRING
         case QVariant::Date:
             {
             bool ok;
@@ -262,7 +261,7 @@
             if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: datetime expected"));
             }
             break;
-#endif // QT_NO_TEXTDATE
+#endif // QT_NO_DATESTRING
         case QVariant::Point:
         case QVariant::PointF:
             {
@@ -416,7 +415,7 @@
             instr.storeColor.value = c.rgba();
             }
             break;
-#ifndef QT_NO_TEXTDATE
+#ifndef QT_NO_DATESTRING
         case QVariant::Date:
             {
             QDate d = QDeclarativeStringConverters::dateFromString(string);
@@ -450,7 +449,7 @@
             instr.storeDateTime.valueIndex = index;
             }
             break;
-#endif // QT_NO_TEXTDATE
+#endif // QT_NO_DATESTRING
         case QVariant::Point:
         case QVariant::PointF:
             {
@@ -562,7 +561,7 @@
     on a successful compiler.
 */
 bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine,
-                                   QDeclarativeCompositeTypeData *unit,
+                                   QDeclarativeTypeData *unit,
                                    QDeclarativeCompiledData *out)
 {
     exceptions.clear();
@@ -573,10 +572,15 @@
     output = out;
 
     // Compile types
-    for (int ii = 0; ii < unit->types.count(); ++ii) {
-        QDeclarativeCompositeTypeData::TypeReference &tref = unit->types[ii];
+    const QList<QDeclarativeTypeData::TypeReference>  &resolvedTypes = unit->resolvedTypes();
+    QList<QDeclarativeScriptParser::TypeReference *> referencedTypes = unit->parser().referencedTypes();
+
+    for (int ii = 0; ii < resolvedTypes.count(); ++ii) {
         QDeclarativeCompiledData::TypeReference ref;
-        QDeclarativeScriptParser::TypeReference *parserRef = unit->data.referencedTypes().at(ii);
+
+        const QDeclarativeTypeData::TypeReference &tref = resolvedTypes.at(ii);
+        QDeclarativeScriptParser::TypeReference *parserRef = referencedTypes.at(ii);
+
         if (tref.type) {
             ref.type = tref.type;
             if (!ref.type->isCreatable()) {
@@ -585,33 +589,16 @@
                     err = tr( "Element is not creatable.");
                 COMPILE_EXCEPTION(parserRef->refObjects.first(), err);
             }
-        } else if (tref.unit) {
-            ref.component = tref.unit->toComponent(engine);
-
-            if (ref.component->isError()) {
-                QDeclarativeError error;
-                error.setUrl(output->url);
-                error.setDescription(QLatin1String("Unable to create type ") +
-                                     parserRef->name);
-                if (!parserRef->refObjects.isEmpty()) {
-                    QDeclarativeParser::Object *parserObject = parserRef->refObjects.first();
-                    error.setLine(parserObject->location.start.line);
-                    error.setColumn(parserObject->location.start.column);
-                }
-
-                exceptions << error;
-                exceptions << ref.component->errors();
-                reset(out);
-                return false;
-            }
-            ref.ref = tref.unit;
+        } else if (tref.typeData) {
+            ref.component = tref.typeData->component();
+            ref.ref = tref.typeData;
             ref.ref->addref();
         }
         ref.className = parserRef->name.toUtf8();
         out->types << ref;
     }
 
-    Object *root = unit->data.tree();
+    Object *root = unit->parser().tree();
     Q_ASSERT(root);
 
     this->engine = engine;
@@ -664,17 +651,18 @@
     QHash<QString, Object::ScriptBlock> importedScripts;
     QStringList importedScriptIndexes;
 
-    for (int ii = 0; ii < unit->scripts.count(); ++ii) {
-        QString scriptCode = QString::fromUtf8(unit->scripts.at(ii).resource->data);
-        Object::ScriptBlock::Pragmas pragmas = QDeclarativeScriptParser::extractPragmas(scriptCode);
+    foreach (const QDeclarativeTypeData::ScriptReference &script, unit->resolvedScripts()) {
+        QString scriptCode = script.script->scriptSource();
+        Object::ScriptBlock::Pragmas pragmas = script.script->pragmas();
+
+        Q_ASSERT(!importedScripts.contains(script.qualifier));
 
         if (!scriptCode.isEmpty()) {
-            Object::ScriptBlock &scriptBlock = importedScripts[unit->scripts.at(ii).qualifier];
-
-            scriptBlock.codes.append(scriptCode);
-            scriptBlock.lineNumbers.append(1);
-            scriptBlock.files.append(unit->scripts.at(ii).resource->url);
-            scriptBlock.pragmas.append(pragmas);
+            Object::ScriptBlock &scriptBlock = importedScripts[script.qualifier];
+
+            scriptBlock.code = scriptCode;
+            scriptBlock.file = script.script->finalUrl().toString();
+            scriptBlock.pragmas = pragmas;
         }
     }
 
@@ -703,7 +691,7 @@
     for (int ii = 0; ii < importedScriptIndexes.count(); ++ii) 
         output->importCache->add(importedScriptIndexes.at(ii), ii);
 
-    unit->imports.cache(output->importCache, engine);
+    unit->imports().populateCache(output->importCache, engine);
 
     Q_ASSERT(tree->metatype);
 
@@ -986,7 +974,7 @@
     }
 
     // Begin the class
-    if (obj->parserStatusCast != -1) {
+    if (tr.type && obj->parserStatusCast != -1) {
         QDeclarativeInstruction begin;
         begin.type = QDeclarativeInstruction::BeginObject;
         begin.begin.castValue = obj->parserStatusCast;
@@ -1070,6 +1058,7 @@
             store.storeSignal.value =
                 output->indexForString(v->value.asScript().trimmed());
             store.storeSignal.context = ctxt.stack;
+            store.storeSignal.name = output->indexForByteArray(prop->name);
             output->bytecode << store;
 
         }
@@ -1373,7 +1362,7 @@
             return p.name() != 0;
         } else {
             int idx = mo->indexOfProperty(prop->name.constData());
-            return idx != -1;
+            return idx != -1 && mo->property(idx).isScriptable();
         }
     }
 
@@ -1402,8 +1391,7 @@
 
         QDeclarativeType *type = 0;
         QDeclarativeImportedNamespace *typeNamespace = 0;
-        enginePrivate->importDatabase.resolveType(unit->imports, prop->name, 
-                                                  &type, 0, 0, 0, &typeNamespace);
+        unit->imports().resolveType(prop->name, &type, 0, 0, 0, &typeNamespace);
 
         if (typeNamespace) {
             // ### We might need to indicate that this property is a namespace 
@@ -1439,6 +1427,11 @@
             if (prop->index != -1) {
                 p = metaObject->property(prop->index);
                 Q_ASSERT(p.name());
+
+                if (!p.isScriptable()) {
+                    prop->index = -1;
+                    p = QMetaProperty();
+                }
             }
         }
 
@@ -1511,7 +1504,7 @@
         // Setup attached property data
 
         QDeclarativeType *type = 0;
-        enginePrivate->importDatabase.resolveTypeInNamespace(ns, prop->name, &type, 0, 0, 0);
+        unit->imports().resolveType(ns, prop->name, &type, 0, 0, 0);
 
         if (!type || !type->attachedPropertiesType()) 
             COMPILE_EXCEPTION(prop, tr("Non-existent attached object"));
@@ -1771,9 +1764,7 @@
     Q_ASSERT(prop->index != -1);
 
     if (QDeclarativeValueTypeFactory::isValueType(prop->type)) {
-        QDeclarativeEnginePrivate *ep =
-            static_cast<QDeclarativeEnginePrivate *>(QObjectPrivate::get(engine));
-        if (prop->type >= 0 /* QVariant == -1 */ && ep->valueTypes[prop->type]) {
+        if (prop->type >= 0 /* QVariant == -1 */ && enginePrivate->valueTypes[prop->type]) {
 
             if (prop->values.count()) {
                 if (prop->values.at(0)->location < prop->value->location) {
@@ -1787,7 +1778,7 @@
                 COMPILE_EXCEPTION(prop, tr( "Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name)));
             }
 
-            COMPILE_CHECK(buildValueTypeProperty(ep->valueTypes[prop->type],
+            COMPILE_CHECK(buildValueTypeProperty(enginePrivate->valueTypes[prop->type],
                                                  prop->value, obj, ctxt.incr()));
             obj->addValueTypeProperty(prop);
         } else {
@@ -1825,6 +1816,8 @@
         if (idx == -1)
             COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(prop->name)));
         QMetaProperty p = type->metaObject()->property(idx);
+        if (!p.isScriptable())
+            COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(prop->name)));
         prop->index = idx;
         prop->type = p.userType();
         prop->isValueTypeSubProperty = true;
@@ -2138,8 +2131,7 @@
 
     QString typeName = parts.at(0);
     QDeclarativeType *type = 0;
-    enginePrivate->importDatabase.resolveType(unit->imports, typeName.toUtf8(),
-                                              &type, 0, 0, 0, 0);
+    unit->imports().resolveType(typeName.toUtf8(), &type, 0, 0, 0, 0);
 
     if (!type || obj->typeName != type->qmlTypeName())
         return true;
@@ -2166,7 +2158,7 @@
     int dot = script.indexOf('.');
     if (dot > 0) {
         QDeclarativeType *type = 0;
-        enginePrivate->importDatabase.resolveType(unit->imports, script.left(dot), &type, 0, 0, 0, 0);
+        unit->imports().resolveType(script.left(dot), &type, 0, 0, 0, 0);
         if (!type)
             return -1;
         const QMetaObject *mo = type->metaObject();
@@ -2184,8 +2176,7 @@
 const QMetaObject *QDeclarativeCompiler::resolveType(const QByteArray& name) const
 {
     QDeclarativeType *qmltype = 0;
-    if (!enginePrivate->importDatabase.resolveType(unit->imports, name, &qmltype, 
-                                                   0, 0, 0, 0)) 
+    if (!unit->imports().resolveType(name, &qmltype, 0, 0, 0, 0)) 
         return 0;
     if (!qmltype)
         return 0;
@@ -2214,10 +2205,11 @@
         if (propNames.contains(prop.name))
             COMPILE_EXCEPTION(&prop, tr("Duplicate property name"));
 
-        if (QString::fromUtf8(prop.name).at(0).isUpper()) 
+        QString propName = QString::fromUtf8(prop.name);
+        if (propName.at(0).isUpper())
             COMPILE_EXCEPTION(&prop, tr("Property names cannot begin with an upper case letter"));
 
-        if (QDeclarativeEnginePrivate::get(engine)->globalClass->illegalNames().contains(prop.name))
+        if (enginePrivate->globalClass->illegalNames().contains(propName))
             COMPILE_EXCEPTION(&prop, tr("Illegal property name"));
 
         propNames.insert(prop.name);
@@ -2227,9 +2219,10 @@
         QByteArray name = obj->dynamicSignals.at(ii).name;
         if (methodNames.contains(name))
             COMPILE_EXCEPTION(obj, tr("Duplicate signal name"));
-        if (QString::fromUtf8(name).at(0).isUpper()) 
+        QString nameStr = QString::fromUtf8(name);
+        if (nameStr.at(0).isUpper())
             COMPILE_EXCEPTION(obj, tr("Signal names cannot begin with an upper case letter"));
-        if (QDeclarativeEnginePrivate::get(engine)->globalClass->illegalNames().contains(name))
+        if (enginePrivate->globalClass->illegalNames().contains(nameStr))
             COMPILE_EXCEPTION(obj, tr("Illegal signal name"));
         methodNames.insert(name);
     }
@@ -2237,9 +2230,10 @@
         QByteArray name = obj->dynamicSlots.at(ii).name;
         if (methodNames.contains(name))
             COMPILE_EXCEPTION(obj, tr("Duplicate method name"));
-        if (QString::fromUtf8(name).at(0).isUpper()) 
+        QString nameStr = QString::fromUtf8(name);
+        if (nameStr.at(0).isUpper())
             COMPILE_EXCEPTION(obj, tr("Method names cannot begin with an upper case letter"));
-        if (QDeclarativeEnginePrivate::get(engine)->globalClass->illegalNames().contains(name))
+        if (enginePrivate->globalClass->illegalNames().contains(nameStr))
             COMPILE_EXCEPTION(obj, tr("Illegal method name"));
         methodNames.insert(name);
     }
@@ -2340,17 +2334,18 @@
                 QByteArray customTypeName;
                 QDeclarativeType *qmltype = 0;
                 QUrl url;
-                if (!enginePrivate->importDatabase.resolveType(unit->imports, p.customType, &qmltype, 
-                                                               &url, 0, 0, 0)) 
+                if (!unit->imports().resolveType(p.customType, &qmltype, &url, 0, 0, 0)) 
                     COMPILE_EXCEPTION(&p, tr("Invalid property type"));
 
                 if (!qmltype) {
-                    QDeclarativeCompositeTypeData *tdata = enginePrivate->typeManager.get(url);
+                    QDeclarativeTypeData *tdata = enginePrivate->typeLoader.get(url);
                     Q_ASSERT(tdata);
-                    Q_ASSERT(tdata->status == QDeclarativeCompositeTypeData::Complete);
-
-                    QDeclarativeCompiledData *data = tdata->toCompiledComponent(engine);
+                    Q_ASSERT(tdata->isComplete());
+
+                    QDeclarativeCompiledData *data = tdata->compiledData();
                     customTypeName = data->root->className();
+                    data->release();
+                    tdata->release();
                 } else {
                     customTypeName = qmltype->typeName();
                 }
@@ -2416,17 +2411,20 @@
         builder.addSignal(p.name + "Changed()");
         QMetaPropertyBuilder propBuilder = 
             builder.addProperty(p.name, type, builder.methodCount() - 1);
-        propBuilder.setScriptable(true);
         propBuilder.setWritable(!readonly);
     }
 
-    if (mode == ResolveAliases) {
-        for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
-            const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
-
-            if (p.type == Object::DynamicProperty::Alias) {
+    for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
+        const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+
+        if (p.type == Object::DynamicProperty::Alias) {
+            if (mode == ResolveAliases) {
                 ((QDeclarativeVMEMetaData *)dynamicData.data())->aliasCount++;
                 compileAlias(builder, dynamicData, obj, p);
+            } else {
+                // Need a fake signal so that the metaobject remains consistent across
+                // the resolve and non-resolve alias runs
+                builder.addSignal(p.name + "Changed()");
             }
         }
     }
@@ -2582,6 +2580,9 @@
             COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
 
         QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx);
+        if (!aliasProperty.isScriptable())
+            COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
+
         writable = aliasProperty.isWritable();
 
         if (aliasProperty.isEnumType()) 
@@ -2618,7 +2619,6 @@
     builder.addSignal(prop.name + "Changed()");
     QMetaPropertyBuilder propBuilder = 
         builder.addProperty(prop.name, typeName.constData(), builder.methodCount() - 1);
-    propBuilder.setScriptable(true);
     propBuilder.setWritable(writable);
     return true;
 }
@@ -2745,7 +2745,7 @@
         expr.context = binding.bindingContext.object;
         expr.property = binding.property;
         expr.expression = binding.expression;
-        expr.imports = unit->imports;
+        expr.imports = unit->imports();
 
         int index = bindingCompiler.compile(expr, enginePrivate);
         if (index != -1) {
@@ -2765,6 +2765,7 @@
         bool isSharable = sharableTest.isSharable(expression);
         
         QDeclarativeRewrite::RewriteBinding rewriteBinding;
+        rewriteBinding.setName('$'+binding.property->name);
         expression = rewriteBinding(expression);
 
         quint32 length = expression.length();