void ModuleMerger::mergeOutProps(Item::PropertyMap *dst, const Item::PropertyMap &src) { for (auto it = src.constBegin(); it != src.constEnd(); ++it) { ValuePtr &v = (*dst)[it.key()]; if (!v) { v = it.value(); QBS_ASSERT(it.value(), continue); continue; } // possible conflict JSSourceValuePtr dstVal = v.dynamicCast<JSSourceValue>(); if (!dstVal) continue; JSSourceValuePtr srcVal = it.value().dynamicCast<JSSourceValue>(); if (!srcVal) continue; const PropertyDeclaration pd = m_decls.value(srcVal); if (!pd.isValid()) continue; if (pd.isScalar()) { if (dstVal->sourceCode() != srcVal->sourceCode()) { m_logger.qbsWarning() << Tr::tr("Conflicting scalar values at %1 and %2.").arg( dstVal->location().toString(), srcVal->location().toString()); // TODO: yield error with a hint how to solve the conflict. } v = it.value(); } else { lastInNextChain(dstVal)->setNext(srcVal); } }
void ModuleMerger::pushScalarProperties(Item::PropertyMap *dst, Item *srcItem) { Item *origSrcItem = srcItem; do { if (!m_seenInstancesTopDown.contains(srcItem)) { m_seenInstancesTopDown.insert(srcItem); for (auto it = srcItem->properties().constBegin(); it != srcItem->properties().constEnd(); ++it) { const ValuePtr &srcVal = it.value(); if (srcVal->type() != Value::JSSourceValueType) continue; const PropertyDeclaration srcDecl = srcItem->propertyDeclaration(it.key()); if (!srcDecl.isValid() || !srcDecl.isScalar()) continue; ValuePtr &v = (*dst)[it.key()]; if (v) continue; ValuePtr clonedVal = srcVal->clone(); m_decls[clonedVal] = srcDecl; clonedVal->setDefiningItem(origSrcItem); v = clonedVal; } } srcItem = srcItem->prototype(); } while (srcItem && srcItem->isModuleInstance()); }
static void makeTypeError(const PropertyDeclaration &decl, const CodeLocation &location, QScriptValue &v) { const ErrorInfo error(Tr::tr("Value assigned to property '%1' does not have type '%2'.") .arg(decl.name(), decl.typeString()), location); makeTypeError(error, v); }
void ModuleMerger::insertProperties(Item::PropertyMap *dst, Item *srcItem, PropertiesType type) { QSet<const Item *> &seenInstances = type == ScalarProperties ? m_seenInstancesTopDown : m_seenInstancesBottomUp; Item *origSrcItem = srcItem; do { if (!seenInstances.contains(srcItem)) { seenInstances.insert(srcItem); for (Item::PropertyMap::const_iterator it = srcItem->properties().constBegin(); it != srcItem->properties().constEnd(); ++it) { const ValuePtr &srcVal = it.value(); if (srcVal->type() != Value::JSSourceValueType) continue; const PropertyDeclaration srcDecl = srcItem->propertyDeclaration(it.key()); if (!srcDecl.isValid() || srcDecl.isScalar() != (type == ScalarProperties)) continue; ValuePtr &v = (*dst)[it.key()]; if (v && type == ScalarProperties) continue; ValuePtr clonedVal = srcVal->clone(); m_decls[clonedVal] = srcDecl; clonedVal->setDefiningItem(origSrcItem); if (v) { QBS_CHECK(!clonedVal->next()); clonedVal->setNext(v); } v = clonedVal; } } srcItem = srcItem->prototype(); } while (srcItem && srcItem->type() == ItemType::ModuleInstance); }
bool ItemReaderASTVisitor::visit(AST::UiPublicMember *ast) { PropertyDeclaration p; if (Q_UNLIKELY(ast->name.isEmpty())) throw ErrorInfo(Tr::tr("public member without name")); if (Q_UNLIKELY(ast->memberType.isEmpty())) throw ErrorInfo(Tr::tr("public member without type")); if (Q_UNLIKELY(ast->type == AST::UiPublicMember::Signal)) throw ErrorInfo(Tr::tr("public member with signal type not supported")); p.setName(ast->name.toString()); p.setType(PropertyDeclaration::propertyTypeFromString(ast->memberType.toString())); if (p.type() == PropertyDeclaration::UnknownType) { throw ErrorInfo(Tr::tr("Unknown type '%1' in property declaration.") .arg(ast->memberType.toString()), toCodeLocation(ast->typeToken)); } if (ast->typeModifier.compare(QLatin1String("list"))) { p.setFlags(p.flags() | PropertyDeclaration::ListProperty); } else if (Q_UNLIKELY(!ast->typeModifier.isEmpty())) { throw ErrorInfo(Tr::tr("public member with type modifier '%1' not supported").arg( ast->typeModifier.toString())); } m_item->m_propertyDeclarations.insert(p.name(), p); const JSSourceValuePtr value = JSSourceValue::create(); value->setFile(m_file); if (ast->statement) { handleBindingRhs(ast->statement, value); const QStringList bindingName(p.name()); checkDuplicateBinding(m_item, bindingName, ast->colonToken); } m_item->setProperty(p.name(), value); return false; }
void ParserTest::parsePropertyDeclaration() { CREATE_PARSER(par); PropertyDeclaration propDec; par >> propDec; COMPARE_STRING(propDec.variableDeclaration().objectName(), "data"); COMPARE_STRING(propDec.variableDeclaration().type().name(), "NSData*"); QTRUE(propDec.variableDeclaration().type().isPointer()); QCOMPARE(propDec.variableDeclaration().type().starNumber(), 1U); }
void EvaluatorScriptClass::convertToPropertyType(const Item *item, const PropertyDeclaration& decl, const Value *value, QScriptValue &v) { if (value->type() == Value::VariantValueType && v.isUndefined() && !decl.isScalar()) { v = v.engine()->newArray(); // QTBUG-51237 return; } convertToPropertyType_impl(m_pathPropertiesBaseDir, item, decl, value->location(), v); }
void ModuleMerger::appendPrototypeValueToNextChain(Item *moduleProto, const QString &propertyName, const ValuePtr &sv) { const PropertyDeclaration pd = m_mergedModuleItem->propertyDeclaration(propertyName); if (pd.isScalar()) return; ValuePtr protoValue = moduleProto->property(propertyName); QBS_CHECK(protoValue); if (!m_clonedModulePrototype) { m_clonedModulePrototype = moduleProto->clone(); Item * const scope = Item::create(m_clonedModulePrototype->pool()); scope->setFile(m_clonedModulePrototype->file()); m_mergedModuleItem->scope()->copyProperty(QLatin1String("project"), scope); m_mergedModuleItem->scope()->copyProperty(QLatin1String("product"), scope); m_clonedModulePrototype->setScope(scope); } const ValuePtr clonedValue = protoValue->clone(); clonedValue->setDefiningItem(m_clonedModulePrototype); lastInNextChain(sv)->setNext(clonedValue); }
static void convertToPropertyType_impl(const QString &pathPropertiesBaseDir, const Item *item, const PropertyDeclaration& decl, const CodeLocation &location, QScriptValue &v) { if (v.isUndefined() || v.isError()) return; QString srcDir; QString actualBaseDir; if (item && !pathPropertiesBaseDir.isEmpty()) { const VariantValueConstPtr itemSourceDir = item->variantProperty(QLatin1String("sourceDirectory")); actualBaseDir = itemSourceDir ? itemSourceDir->value().toString() : pathPropertiesBaseDir; } switch (decl.type()) { case PropertyDeclaration::UnknownType: case PropertyDeclaration::Variant: break; case PropertyDeclaration::Boolean: if (!v.isBool()) v = v.toBool(); break; case PropertyDeclaration::Integer: if (!v.isNumber()) makeTypeError(decl, location, v); break; case PropertyDeclaration::Path: { if (!v.isString()) { makeTypeError(decl, location, v); break; } const QString srcDir = item ? overriddenSourceDirectory(item, actualBaseDir) : pathPropertiesBaseDir; if (!srcDir.isEmpty()) v = v.engine()->toScriptValue(QDir::cleanPath( FileInfo::resolvePath(srcDir, v.toString()))); break; } case PropertyDeclaration::String: if (!v.isString()) makeTypeError(decl, location, v); break; case PropertyDeclaration::PathList: srcDir = item ? overriddenSourceDirectory(item, actualBaseDir) : pathPropertiesBaseDir; // Fall-through. case PropertyDeclaration::StringList: { if (!v.isArray()) { QScriptValue x = v.engine()->newArray(1); x.setProperty(0, v); v = x; } const quint32 c = v.property(StringConstants::lengthProperty()).toUInt32(); for (quint32 i = 0; i < c; ++i) { QScriptValue elem = v.property(i); if (elem.isUndefined()) { ErrorInfo error(Tr::tr("Element at index %1 of list property '%2' is undefined. " "String expected.").arg(i).arg(decl.name()), location); makeTypeError(error, v); break; } if (elem.isNull()) { ErrorInfo error(Tr::tr("Element at index %1 of list property '%2' is null. " "String expected.").arg(i).arg(decl.name()), location); makeTypeError(error, v); break; } if (!elem.isString()) { ErrorInfo error(Tr::tr("Element at index %1 of list property '%2' does not have " "string type.").arg(i).arg(decl.name()), location); makeTypeError(error, v); break; } if (srcDir.isEmpty()) continue; elem = v.engine()->toScriptValue( QDir::cleanPath(FileInfo::resolvePath(srcDir, elem.toString()))); v.setProperty(i, elem); } break; } case PropertyDeclaration::VariantList: if (!v.isArray()) { QScriptValue x = v.engine()->newArray(1); x.setProperty(0, v); v = x; } break; } }