Exemple #1
0
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);
        }
    }
Exemple #2
0
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;
    }
}