bool ItemReaderASTVisitor::handleBindingRhs(AST::Statement *statement, const JSSourceValuePtr &value) { QBS_CHECK(statement); QBS_CHECK(value); if (AST::cast<AST::Block *>(statement)) value->m_flags |= JSSourceValue::HasFunctionForm; value->setFile(m_file); value->setSourceCode(textRefOf(m_file->content(), statement)); value->setLocation(statement->firstSourceLocation().startLine, statement->firstSourceLocation().startColumn); bool usesBase, usesOuter, usesOriginal; IdentifierSearch idsearch; idsearch.add(QLatin1String("base"), &usesBase); idsearch.add(QLatin1String("outer"), &usesOuter); idsearch.add(QLatin1String("original"), &usesOriginal); idsearch.start(statement); if (usesBase) value->m_flags |= JSSourceValue::SourceUsesBase; if (usesOuter) value->m_flags |= JSSourceValue::SourceUsesOuter; if (usesOriginal) value->m_flags |= JSSourceValue::SourceUsesOriginal; return false; }
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 ItemReaderASTVisitor::inheritItem(Item *dst, const Item *src) { int insertPos = 0; for (int i = 0; i < src->m_children.count(); ++i) { Item *child = src->m_children.at(i); dst->m_children.insert(insertPos++, child); child->m_parent = dst; } for (auto it = src->properties().constBegin(); it != src->properties().constEnd(); ++it) { ValuePtr &v = dst->m_properties[it.key()]; if (!v) { v = it.value(); continue; } if (v->type() == Value::ItemValueType && it.value()->type() != Value::ItemValueType) throw ErrorInfo(Tr::tr("Binding to non-item property."), v->location()); if (v->type() != it.value()->type()) continue; switch (v->type()) { case Value::JSSourceValueType: { JSSourceValuePtr sv = v.staticCast<JSSourceValue>(); QBS_CHECK(!sv->baseValue()); const JSSourceValuePtr baseValue = it.value().staticCast<JSSourceValue>(); sv->setBaseValue(baseValue); for (auto it = sv->m_alternatives.begin(); it != sv->m_alternatives.end(); ++it) it->value->setBaseValue(baseValue); break; } case Value::ItemValueType: inheritItem(v.staticCast<ItemValue>()->item(), it.value().staticCast<const ItemValue>()->item()); break; default: QBS_CHECK(!"unexpected value type"); } } for (auto it = src->propertyDeclarations().constBegin(); it != src->propertyDeclarations().constEnd(); ++it) { dst->setPropertyDeclaration(it.key(), it.value()); } }
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); } }