src/declarative/qml/qdeclarativecompiler.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
child 37 758a864f9613
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
   226             }
   226             }
   227             if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: int expected"));
   227             if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: int expected"));
   228             }
   228             }
   229             break;
   229             break;
   230         case QMetaType::Float:
   230         case QMetaType::Float:
   231             if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: float expected"));
   231             if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: number expected"));
   232             break;
   232             break;
   233         case QVariant::Double:
   233         case QVariant::Double:
   234             if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: double expected"));
   234             if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: number expected"));
   235             break;
   235             break;
   236         case QVariant::Color:
   236         case QVariant::Color:
   237             {
   237             {
   238             bool ok;
   238             bool ok;
   239             QDeclarativeStringConverters::colorFromString(string, &ok);
   239             QDeclarativeStringConverters::colorFromString(string, &ok);
   240             if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: color expected"));
   240             if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: color expected"));
   241             }
   241             }
   242             break;
   242             break;
       
   243 #ifndef QT_NO_TEXTDATE
   243         case QVariant::Date:
   244         case QVariant::Date:
   244             {
   245             {
   245             bool ok;
   246             bool ok;
   246             QDeclarativeStringConverters::dateFromString(string, &ok);
   247             QDeclarativeStringConverters::dateFromString(string, &ok);
   247             if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: date expected"));
   248             if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: date expected"));
   259             bool ok;
   260             bool ok;
   260             QDeclarativeStringConverters::dateTimeFromString(string, &ok);
   261             QDeclarativeStringConverters::dateTimeFromString(string, &ok);
   261             if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: datetime expected"));
   262             if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: datetime expected"));
   262             }
   263             }
   263             break;
   264             break;
       
   265 #endif // QT_NO_TEXTDATE
   264         case QVariant::Point:
   266         case QVariant::Point:
   265         case QVariant::PointF:
   267         case QVariant::PointF:
   266             {
   268             {
   267             bool ok;
   269             bool ok;
   268             QPointF point = QDeclarativeStringConverters::pointFFromString(string, &ok);
   270             QPointF point = QDeclarativeStringConverters::pointFFromString(string, &ok);
   412             instr.type = QDeclarativeInstruction::StoreColor;
   414             instr.type = QDeclarativeInstruction::StoreColor;
   413             instr.storeColor.propertyIndex = prop.propertyIndex();
   415             instr.storeColor.propertyIndex = prop.propertyIndex();
   414             instr.storeColor.value = c.rgba();
   416             instr.storeColor.value = c.rgba();
   415             }
   417             }
   416             break;
   418             break;
       
   419 #ifndef QT_NO_TEXTDATE
   417         case QVariant::Date:
   420         case QVariant::Date:
   418             {
   421             {
   419             QDate d = QDeclarativeStringConverters::dateFromString(string);
   422             QDate d = QDeclarativeStringConverters::dateFromString(string);
   420             instr.type = QDeclarativeInstruction::StoreDate;
   423             instr.type = QDeclarativeInstruction::StoreDate;
   421             instr.storeDate.propertyIndex = prop.propertyIndex();
   424             instr.storeDate.propertyIndex = prop.propertyIndex();
   445             instr.type = QDeclarativeInstruction::StoreDateTime;
   448             instr.type = QDeclarativeInstruction::StoreDateTime;
   446             instr.storeDateTime.propertyIndex = prop.propertyIndex();
   449             instr.storeDateTime.propertyIndex = prop.propertyIndex();
   447             instr.storeDateTime.valueIndex = index;
   450             instr.storeDateTime.valueIndex = index;
   448             }
   451             }
   449             break;
   452             break;
       
   453 #endif // QT_NO_TEXTDATE
   450         case QVariant::Point:
   454         case QVariant::Point:
   451         case QVariant::PointF:
   455         case QVariant::PointF:
   452             {
   456             {
   453             bool ok;
   457             bool ok;
   454             QPointF point =
   458             QPointF point =
   809             defaultProperty = obj->defaultProperty;
   813             defaultProperty = obj->defaultProperty;
   810             defaultProperty->addref();
   814             defaultProperty->addref();
   811         }
   815         }
   812     }
   816     }
   813 
   817 
       
   818     QDeclarativeCustomParser *cp = 0;
       
   819     if (isCustomParser)
       
   820         cp = output->types.at(obj->type).type->customParser();
       
   821 
   814     // Build all explicit properties specified
   822     // Build all explicit properties specified
   815     foreach(Property *prop, obj->properties) {
   823     foreach(Property *prop, obj->properties) {
   816 
   824 
   817         if (prop == skipProperty)
   825         if (prop == skipProperty)
   818             continue;
   826             continue;
   819         if (prop->name == "id")
   827         if (prop->name == "id")
   820             continue;
   828             continue;
       
   829 
       
   830         bool canDefer = false;
       
   831         if (isCustomParser) {
       
   832             if (doesPropertyExist(prop, obj) && 
       
   833                 (!(cp->flags() & QDeclarativeCustomParser::AcceptsAttachedProperties) ||
       
   834                  !isAttachedPropertyName(prop->name))) {
       
   835                 int ids = compileState.ids.count();
       
   836                 COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
       
   837                 canDefer = ids == compileState.ids.count();
       
   838             } else {
       
   839                 customProps << QDeclarativeCustomParserNodePrivate::fromProperty(prop);
       
   840             }
       
   841         } else {
       
   842             if (isSignalPropertyName(prop->name)) {
       
   843                 COMPILE_CHECK(buildSignal(prop,obj,objCtxt));
       
   844             } else {
       
   845                 int ids = compileState.ids.count();
       
   846                 COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
       
   847                 canDefer = ids == compileState.ids.count();
       
   848             }
       
   849         }
       
   850 
       
   851         if (canDefer && !deferredList.isEmpty() &&
       
   852             deferredList.contains(QString::fromUtf8(prop->name)))
       
   853             prop->isDeferred = true;
       
   854 
       
   855     }
       
   856 
       
   857     // Build the default property
       
   858     if (defaultProperty)  {
       
   859         Property *prop = defaultProperty;
   821 
   860 
   822         bool canDefer = false;
   861         bool canDefer = false;
   823         if (isCustomParser) {
   862         if (isCustomParser) {
   824             if (doesPropertyExist(prop, obj)) {
   863             if (doesPropertyExist(prop, obj)) {
   825                 int ids = compileState.ids.count();
   864                 int ids = compileState.ids.count();
   827                 canDefer = ids == compileState.ids.count();
   866                 canDefer = ids == compileState.ids.count();
   828             } else {
   867             } else {
   829                 customProps << QDeclarativeCustomParserNodePrivate::fromProperty(prop);
   868                 customProps << QDeclarativeCustomParserNodePrivate::fromProperty(prop);
   830             }
   869             }
   831         } else {
   870         } else {
   832             if (isSignalPropertyName(prop->name)) {
   871             int ids = compileState.ids.count();
   833                 COMPILE_CHECK(buildSignal(prop,obj,objCtxt));
   872             COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
   834             } else {
   873             canDefer = ids == compileState.ids.count();
   835                 int ids = compileState.ids.count();
       
   836                 COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
       
   837                 canDefer = ids == compileState.ids.count();
       
   838             }
       
   839         }
   874         }
   840 
   875 
   841         if (canDefer && !deferredList.isEmpty() &&
   876         if (canDefer && !deferredList.isEmpty() &&
   842             deferredList.contains(QString::fromUtf8(prop->name)))
   877             deferredList.contains(QString::fromUtf8(prop->name)))
   843             prop->isDeferred = true;
   878             prop->isDeferred = true;
   844 
       
   845     }
       
   846 
       
   847     // Build the default property
       
   848     if (defaultProperty)  {
       
   849         Property *prop = defaultProperty;
       
   850 
       
   851         bool canDefer = false;
       
   852         if (isCustomParser) {
       
   853             if (doesPropertyExist(prop, obj)) {
       
   854                 int ids = compileState.ids.count();
       
   855                 COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
       
   856                 canDefer = ids == compileState.ids.count();
       
   857             } else {
       
   858                 customProps << QDeclarativeCustomParserNodePrivate::fromProperty(prop);
       
   859             }
       
   860         } else {
       
   861             int ids = compileState.ids.count();
       
   862             COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
       
   863             canDefer = ids == compileState.ids.count();
       
   864         }
       
   865 
       
   866         if (canDefer && !deferredList.isEmpty() &&
       
   867             deferredList.contains(QString::fromUtf8(prop->name)))
       
   868             prop->isDeferred = true;
       
   869     }
   879     }
   870 
   880 
   871     if (defaultProperty) 
   881     if (defaultProperty) 
   872         defaultProperty->release();
   882         defaultProperty->release();
   873 
   883 
   874     // Compile custom parser parts
   884     // Compile custom parser parts
   875     if (isCustomParser/* && !customProps.isEmpty()*/) {
   885     if (isCustomParser && !customProps.isEmpty()) {
   876         QDeclarativeCustomParser *cp = output->types.at(obj->type).type->customParser();
       
   877         cp->clearErrors();
   886         cp->clearErrors();
   878         cp->compiler = this;
   887         cp->compiler = this;
   879         cp->object = obj;
   888         cp->object = obj;
   880         obj->custom = cp->compile(customProps);
   889         obj->custom = cp->compile(customProps);
   881         cp->compiler = 0;
   890         cp->compiler = 0;
  1350 
  1359 
  1351 /*!
  1360 /*!
  1352     Returns true if (value) property \a prop exists on obj, false otherwise.
  1361     Returns true if (value) property \a prop exists on obj, false otherwise.
  1353 */
  1362 */
  1354 bool QDeclarativeCompiler::doesPropertyExist(QDeclarativeParser::Property *prop,
  1363 bool QDeclarativeCompiler::doesPropertyExist(QDeclarativeParser::Property *prop,
  1355                                     QDeclarativeParser::Object *obj)
  1364                                              QDeclarativeParser::Object *obj)
  1356 {
  1365 {
  1357     if(isAttachedPropertyName(prop->name) || prop->name == "id")
  1366     if(isAttachedPropertyName(prop->name) || prop->name == "id")
  1358         return true;
  1367         return true;
  1359 
  1368 
  1360     const QMetaObject *mo = obj->metaObject();
  1369     const QMetaObject *mo = obj->metaObject();
  2170         }
  2179         }
  2171     }
  2180     }
  2172     return -1;
  2181     return -1;
  2173 }
  2182 }
  2174 
  2183 
       
  2184 const QMetaObject *QDeclarativeCompiler::resolveType(const QByteArray& name) const
       
  2185 {
       
  2186     QDeclarativeType *qmltype = 0;
       
  2187     if (!enginePrivate->importDatabase.resolveType(unit->imports, name, &qmltype, 
       
  2188                                                    0, 0, 0, 0)) 
       
  2189         return 0;
       
  2190     if (!qmltype)
       
  2191         return 0;
       
  2192     return qmltype->metaObject();
       
  2193 }
       
  2194 
       
  2195 
  2175 // Ensures that the dynamic meta specification on obj is valid
  2196 // Ensures that the dynamic meta specification on obj is valid
  2176 bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
  2197 bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
  2177 {
  2198 {
  2178     QSet<QByteArray> propNames;
  2199     QSet<QByteArray> propNames;
  2179     QSet<QByteArray> methodNames;
  2200     QSet<QByteArray> methodNames;
  2193         if (propNames.contains(prop.name))
  2214         if (propNames.contains(prop.name))
  2194             COMPILE_EXCEPTION(&prop, tr("Duplicate property name"));
  2215             COMPILE_EXCEPTION(&prop, tr("Duplicate property name"));
  2195 
  2216 
  2196         if (QString::fromUtf8(prop.name).at(0).isUpper()) 
  2217         if (QString::fromUtf8(prop.name).at(0).isUpper()) 
  2197             COMPILE_EXCEPTION(&prop, tr("Property names cannot begin with an upper case letter"));
  2218             COMPILE_EXCEPTION(&prop, tr("Property names cannot begin with an upper case letter"));
       
  2219 
       
  2220         if (QDeclarativeEnginePrivate::get(engine)->globalClass->illegalNames().contains(prop.name))
       
  2221             COMPILE_EXCEPTION(&prop, tr("Illegal property name"));
       
  2222 
  2198         propNames.insert(prop.name);
  2223         propNames.insert(prop.name);
  2199     }
  2224     }
  2200 
  2225 
  2201     for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) {
  2226     for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) {
  2202         QByteArray name = obj->dynamicSignals.at(ii).name;
  2227         QByteArray name = obj->dynamicSignals.at(ii).name;
  2203         if (methodNames.contains(name))
  2228         if (methodNames.contains(name))
  2204             COMPILE_EXCEPTION(obj, tr("Duplicate signal name"));
  2229             COMPILE_EXCEPTION(obj, tr("Duplicate signal name"));
  2205         if (QString::fromUtf8(name).at(0).isUpper()) 
  2230         if (QString::fromUtf8(name).at(0).isUpper()) 
  2206             COMPILE_EXCEPTION(obj, tr("Signal names cannot begin with an upper case letter"));
  2231             COMPILE_EXCEPTION(obj, tr("Signal names cannot begin with an upper case letter"));
       
  2232         if (QDeclarativeEnginePrivate::get(engine)->globalClass->illegalNames().contains(name))
       
  2233             COMPILE_EXCEPTION(obj, tr("Illegal signal name"));
  2207         methodNames.insert(name);
  2234         methodNames.insert(name);
  2208     }
  2235     }
  2209     for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
  2236     for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
  2210         QByteArray name = obj->dynamicSlots.at(ii).name;
  2237         QByteArray name = obj->dynamicSlots.at(ii).name;
  2211         if (methodNames.contains(name))
  2238         if (methodNames.contains(name))
  2212             COMPILE_EXCEPTION(obj, tr("Duplicate method name"));
  2239             COMPILE_EXCEPTION(obj, tr("Duplicate method name"));
  2213         if (QString::fromUtf8(name).at(0).isUpper()) 
  2240         if (QString::fromUtf8(name).at(0).isUpper()) 
  2214             COMPILE_EXCEPTION(obj, tr("Method names cannot begin with an upper case letter"));
  2241             COMPILE_EXCEPTION(obj, tr("Method names cannot begin with an upper case letter"));
       
  2242         if (QDeclarativeEnginePrivate::get(engine)->globalClass->illegalNames().contains(name))
       
  2243             COMPILE_EXCEPTION(obj, tr("Illegal method name"));
  2215         methodNames.insert(name);
  2244         methodNames.insert(name);
  2216     }
  2245     }
  2217 
  2246 
  2218     return true;
  2247     return true;
  2219 }
  2248 }
  2418     QStringList funcScripts;
  2447     QStringList funcScripts;
  2419 
  2448 
  2420     for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
  2449     for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
  2421         Object::DynamicSlot &s = obj->dynamicSlots[ii];
  2450         Object::DynamicSlot &s = obj->dynamicSlots[ii];
  2422         QByteArray sig(s.name + '(');
  2451         QByteArray sig(s.name + '(');
  2423         QString funcScript(QLatin1String("(function("));
  2452         QString funcScript(QLatin1String("(function ") + s.name + QLatin1Char('('));
  2424 
  2453 
  2425         for (int jj = 0; jj < s.parameterNames.count(); ++jj) {
  2454         for (int jj = 0; jj < s.parameterNames.count(); ++jj) {
  2426             if (jj) { 
  2455             if (jj) { 
  2427                 sig.append(',');
  2456                 sig.append(',');
  2428                 funcScript.append(QLatin1Char(','));
  2457                 funcScript.append(QLatin1Char(','));