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;
}
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;
    }
}