QmlDesigner: Improve NodeMetaInfo

Change-Id: I1b31a1b08332f6bdba74c46af3d0a190901e9607
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2023-06-07 17:58:55 +02:00
committed by Tim Jenssen
parent 53bb2f95e5
commit d7ee848efd
12 changed files with 758 additions and 116 deletions

View File

@@ -50,6 +50,8 @@ public:
bool isValid() const;
explicit operator bool() const { return isValid(); }
TypeId id() const { return m_typeId; }
bool isFileComponent() const;
bool hasProperty(::Utils::SmallStringView propertyName) const;
PropertyMetaInfos properties() const;

View File

@@ -49,6 +49,9 @@ public:
return bool(m_nodeMetaInfoPrivateData);
#endif
}
PropertyDeclarationId id() const { return m_id; }
PropertyName name() const;
NodeMetaInfo propertyType() const;
bool isWritable() const;

View File

@@ -1421,7 +1421,7 @@ bool NodeMetaInfo::isValid() const
bool NodeMetaInfo::isFileComponent() const
{
if constexpr (useProjectStorage())
return bool(typeData().traits & Storage::TypeTraits::IsFileComponent);
return isValid() && bool(typeData().traits & Storage::TypeTraits::IsFileComponent);
else
return isValid() && m_privateData->isFileComponent();
}
@@ -1429,7 +1429,7 @@ bool NodeMetaInfo::isFileComponent() const
bool NodeMetaInfo::hasProperty(Utils::SmallStringView propertyName) const
{
if constexpr (useProjectStorage())
return bool(m_projectStorage->propertyDeclarationId(m_typeId, propertyName));
return isValid() && bool(m_projectStorage->propertyDeclarationId(m_typeId, propertyName));
else
return isValid() && m_privateData->properties().contains(propertyName);
}
@@ -1440,11 +1440,12 @@ PropertyMetaInfos NodeMetaInfo::properties() const
return {};
if constexpr (useProjectStorage()) {
return Utils::transform<PropertyMetaInfos>(
m_projectStorage->propertyDeclarationIds(m_typeId), [&](auto id) {
return PropertyMetaInfo{id, m_projectStorage};
});
if (isValid()) {
return Utils::transform<PropertyMetaInfos>(
m_projectStorage->propertyDeclarationIds(m_typeId), [&](auto id) {
return PropertyMetaInfo{id, m_projectStorage};
});
}
} else {
const auto &properties = m_privateData->properties();
@@ -1456,15 +1457,19 @@ PropertyMetaInfos NodeMetaInfo::properties() const
return propertyMetaInfos;
}
return {};
}
PropertyMetaInfos NodeMetaInfo::localProperties() const
{
if constexpr (useProjectStorage()) {
return Utils::transform<PropertyMetaInfos>(
m_projectStorage->localPropertyDeclarationIds(m_typeId), [&](auto id) {
return PropertyMetaInfo{id, m_projectStorage};
});
if (isValid()) {
return Utils::transform<PropertyMetaInfos>(
m_projectStorage->localPropertyDeclarationIds(m_typeId), [&](auto id) {
return PropertyMetaInfo{id, m_projectStorage};
});
}
} else {
const auto &properties = m_privateData->localProperties();
@@ -1476,15 +1481,21 @@ PropertyMetaInfos NodeMetaInfo::localProperties() const
return propertyMetaInfos;
}
return {};
}
PropertyMetaInfo NodeMetaInfo::property(const PropertyName &propertyName) const
{
if constexpr (useProjectStorage()) {
return {m_projectStorage->propertyDeclarationId(m_typeId, propertyName), m_projectStorage};
if (isValid()) {
return {m_projectStorage->propertyDeclarationId(m_typeId, propertyName),
m_projectStorage};
}
} else {
if (hasProperty(propertyName))
if (hasProperty(propertyName)) {
return PropertyMetaInfo{m_privateData, propertyName};
}
}
return {};
@@ -1493,10 +1504,13 @@ PropertyMetaInfo NodeMetaInfo::property(const PropertyName &propertyName) const
PropertyNameList NodeMetaInfo::signalNames() const
{
if constexpr (useProjectStorage()) {
return Utils::transform<PropertyNameList>(m_projectStorage->signalDeclarationNames(m_typeId),
[&](const auto &name) {
return name.toQByteArray();
});
if (isValid()) {
return Utils::transform<PropertyNameList>(m_projectStorage->signalDeclarationNames(
m_typeId),
[&](const auto &name) {
return name.toQByteArray();
});
}
} else {
if (isValid())
return m_privateData->signalNames();
@@ -1508,10 +1522,13 @@ PropertyNameList NodeMetaInfo::signalNames() const
PropertyNameList NodeMetaInfo::slotNames() const
{
if constexpr (useProjectStorage()) {
return Utils::transform<PropertyNameList>(m_projectStorage->functionDeclarationNames(m_typeId),
[&](const auto &name) {
return name.toQByteArray();
});
if (isValid()) {
return Utils::transform<PropertyNameList>(m_projectStorage->functionDeclarationNames(
m_typeId),
[&](const auto &name) {
return name.toQByteArray();
});
}
} else {
if (isValid())
return m_privateData->slotNames();
@@ -1523,9 +1540,11 @@ PropertyNameList NodeMetaInfo::slotNames() const
PropertyName NodeMetaInfo::defaultPropertyName() const
{
if constexpr (useProjectStorage()) {
if (auto name = m_projectStorage->propertyName(typeData().defaultPropertyId))
return name->toQByteArray();
return {};
if (isValid()) {
if (auto name = m_projectStorage->propertyName(typeData().defaultPropertyId)) {
return name->toQByteArray();
}
}
} else {
if (isValid())
return m_privateData->defaultPropertyName();
@@ -1537,10 +1556,14 @@ PropertyName NodeMetaInfo::defaultPropertyName() const
PropertyMetaInfo NodeMetaInfo::defaultProperty() const
{
if constexpr (useProjectStorage()) {
return PropertyMetaInfo(typeData().defaultPropertyId, m_projectStorage);
if (isValid()) {
return PropertyMetaInfo(typeData().defaultPropertyId, m_projectStorage);
}
} else {
return property(defaultPropertyName());
}
return {};
}
bool NodeMetaInfo::hasDefaultProperty() const
{

View File

@@ -91,6 +91,16 @@ public:
return false;
}
bool MatchAndExplain(const QByteArray &s, testing::MatchResultListener *listener) const
{
if (s.isEmpty()) {
return true;
}
*listener << "whose size is " << s.size();
return false;
}
void DescribeTo(std::ostream *os) const { *os << "is empty"; }
void DescribeNegationTo(std::ostream *os) const { *os << "isn't empty"; }

View File

@@ -3,7 +3,16 @@
#include "projectstoragemock.h"
namespace QmlDesigner {
#include <projectstorage/projectstorageinfotypes.h>
using QmlDesigner::ModuleId;
using QmlDesigner::PropertyDeclarationId;
using QmlDesigner::TypeId;
using QmlDesigner::TypeIds;
using QmlDesigner::Storage::PropertyDeclarationTraits;
namespace Storage = QmlDesigner::Storage;
namespace {
template<typename BasicId>
@@ -12,62 +21,6 @@ void incrementBasicId(BasicId &id)
id = BasicId::create(id.internalId() + 1);
}
ModuleId createModule(ProjectStorageMock &mock, Utils::SmallStringView moduleName)
{
static ModuleId moduleId;
incrementBasicId(moduleId);
ON_CALL(mock, moduleId(Eq(moduleName))).WillByDefault(Return(moduleId));
return moduleId;
}
PropertyDeclarationId createProperty(ProjectStorageMock &mock, TypeId typeId, Utils::SmallString name)
{
static PropertyDeclarationId propertyId;
incrementBasicId(propertyId);
ON_CALL(mock, propertyDeclarationId(Eq(typeId), Eq(name))).WillByDefault(Return(propertyId));
ON_CALL(mock, propertyName(Eq(propertyId))).WillByDefault(Return(name));
return propertyId;
}
TypeId createType(ProjectStorageMock &mock,
ModuleId moduleId,
Utils::SmallStringView typeName,
Utils::SmallString defaultPropertyName,
Storage::TypeTraits typeTraits,
TypeIds baseTypeIds = {})
{
static TypeId typeId;
incrementBasicId(typeId);
ON_CALL(mock, typeId(Eq(moduleId), Eq(typeName), _)).WillByDefault(Return(typeId));
PropertyDeclarationId defaultPropertyDeclarationId;
if (defaultPropertyName.size())
defaultPropertyDeclarationId = createProperty(mock, typeId, defaultPropertyName);
ON_CALL(mock, type(Eq(typeId)))
.WillByDefault(Return(Storage::Info::Type{defaultPropertyDeclarationId, typeTraits}));
ON_CALL(mock, isBasedOn(Eq(typeId), Eq(typeId))).WillByDefault(Return(true));
for (TypeId baseTypeId : baseTypeIds)
ON_CALL(mock, isBasedOn(Eq(typeId), Eq(baseTypeId))).WillByDefault(Return(true));
return typeId;
}
TypeId createObject(ProjectStorageMock &mock,
ModuleId moduleId,
Utils::SmallStringView typeName,
Utils::SmallString defaultPropertyName,
TypeIds baseTypeIds = {})
{
return createType(
mock, moduleId, typeName, defaultPropertyName, Storage::TypeTraits::Reference, baseTypeIds);
}
void setupIsBasedOn(ProjectStorageMock &mock)
{
auto call = [&](TypeId typeId, auto... ids) -> bool {
@@ -82,49 +35,208 @@ void setupIsBasedOn(ProjectStorageMock &mock)
}
} // namespace
} // namespace QmlDesigner
ModuleId ProjectStorageMock::createModule(Utils::SmallStringView moduleName)
{
static ModuleId moduleId;
incrementBasicId(moduleId);
ON_CALL(*this, moduleId(Eq(moduleName))).WillByDefault(Return(moduleId));
return moduleId;
}
PropertyDeclarationId ProjectStorageMock::createProperty(TypeId typeId,
Utils::SmallString name,
PropertyDeclarationTraits traits,
TypeId propertyTypeId)
{
static PropertyDeclarationId propertyId;
incrementBasicId(propertyId);
ON_CALL(*this, propertyDeclarationId(Eq(typeId), Eq(name))).WillByDefault(Return(propertyId));
ON_CALL(*this, propertyName(Eq(propertyId))).WillByDefault(Return(name));
ON_CALL(*this, propertyDeclaration(Eq(propertyId)))
.WillByDefault(Return(
QmlDesigner::Storage::Info::PropertyDeclaration{typeId, name, traits, propertyTypeId}));
auto ids = localPropertyDeclarationIds(typeId);
ids.push_back(propertyId);
ON_CALL(*this, propertyDeclarationIds(Eq(typeId))).WillByDefault(Return(ids));
ON_CALL(*this, localPropertyDeclarationIds(Eq(typeId))).WillByDefault(Return(ids));
return propertyId;
}
QmlDesigner::PropertyDeclarationId ProjectStorageMock::createProperty(
QmlDesigner::TypeId typeId, Utils::SmallString name, QmlDesigner::TypeId propertyTypeId)
{
return createProperty(typeId, name, {}, propertyTypeId);
}
void ProjectStorageMock::createSignal(QmlDesigner::TypeId typeId, Utils::SmallString name)
{
auto signalNames = signalDeclarationNames(typeId);
signalNames.push_back(name);
ON_CALL(*this, signalDeclarationNames(Eq(typeId))).WillByDefault(Return(signalNames));
}
void ProjectStorageMock::createFunction(QmlDesigner::TypeId typeId, Utils::SmallString name)
{
auto functionNames = functionDeclarationNames(typeId);
functionNames.push_back(name);
ON_CALL(*this, functionDeclarationNames(Eq(typeId))).WillByDefault(Return(functionNames));
}
TypeId ProjectStorageMock::createType(ModuleId moduleId,
Utils::SmallStringView typeName,
Utils::SmallStringView defaultPropertyName,
PropertyDeclarationTraits defaultPropertyTraits,
TypeId defaultPropertyTypeId,
Storage::TypeTraits typeTraits,
TypeIds baseTypeIds)
{
static TypeId typeId;
incrementBasicId(typeId);
ON_CALL(*this, typeId(Eq(moduleId), Eq(typeName), _)).WillByDefault(Return(typeId));
PropertyDeclarationId defaultPropertyDeclarationId;
if (defaultPropertyName.size()) {
if (!defaultPropertyTypeId) {
defaultPropertyTypeId = typeId;
}
defaultPropertyDeclarationId = createProperty(typeId,
defaultPropertyName,
defaultPropertyTraits,
defaultPropertyTypeId);
}
ON_CALL(*this, type(Eq(typeId)))
.WillByDefault(Return(Storage::Info::Type{defaultPropertyDeclarationId, typeTraits}));
ON_CALL(*this, isBasedOn(Eq(typeId), Eq(typeId))).WillByDefault(Return(true));
for (TypeId baseTypeId : baseTypeIds)
ON_CALL(*this, isBasedOn(Eq(typeId), Eq(baseTypeId))).WillByDefault(Return(true));
return typeId;
}
QmlDesigner::TypeId ProjectStorageMock::createType(QmlDesigner::ModuleId moduleId,
Utils::SmallStringView typeName,
QmlDesigner::Storage::TypeTraits typeTraits,
QmlDesigner::TypeIds baseTypeIds)
{
return createType(moduleId, typeName, {}, {}, TypeId{}, typeTraits, baseTypeIds);
}
TypeId ProjectStorageMock::createObject(ModuleId moduleId,
Utils::SmallStringView typeName,
Utils::SmallStringView defaultPropertyName,
PropertyDeclarationTraits defaultPropertyTraits,
QmlDesigner::TypeId defaultPropertyTypeId,
TypeIds baseTypeIds)
{
return createType(moduleId,
typeName,
defaultPropertyName,
defaultPropertyTraits,
defaultPropertyTypeId,
Storage::TypeTraits::Reference,
baseTypeIds);
}
TypeId ProjectStorageMock::createObject(ModuleId moduleId,
Utils::SmallStringView typeName,
TypeIds baseTypeIds)
{
return createType(moduleId, typeName, Storage::TypeTraits::Reference, baseTypeIds);
}
void ProjectStorageMock::setupQtQtuick()
{
QmlDesigner::setupIsBasedOn(*this);
setupIsBasedOn(*this);
auto qmlModuleId = QmlDesigner::createModule(*this, "QML");
auto qtQmlModelsModuleId = QmlDesigner::createModule(*this, "QtQml.Models");
auto qtQuickModuleId = QmlDesigner::createModule(*this, "QtQuick");
auto qtQuickNativeModuleId = QmlDesigner::createModule(*this, "QtQuick-cppnative");
auto qmlModuleId = createModule("QML");
auto qtQmlModelsModuleId = createModule("QtQml.Models");
auto qtQuickModuleId = createModule("QtQuick");
auto qtQuickNativeModuleId = createModule("QtQuick-cppnative");
auto qtObjectId = QmlDesigner::createObject(*this, qmlModuleId, "QtObject", "children");
auto intId = createType(qmlModuleId, "int", Storage::TypeTraits::Value);
QmlDesigner::createObject(*this, qtQmlModelsModuleId, "ListModel", "children", {qtObjectId});
QmlDesigner::createObject(*this, qtQmlModelsModuleId, "ListElement", "children", {qtObjectId});
auto qtObjectId = createObject(qmlModuleId,
"QtObject",
"children",
PropertyDeclarationTraits::IsList,
TypeId{});
auto itemId = QmlDesigner::createObject(*this, qtQuickModuleId, "Item", "data", {qtObjectId});
QmlDesigner::createObject(*this, qtQuickModuleId, "ListView", "data", {qtObjectId, itemId});
QmlDesigner::createObject(*this, qtQuickModuleId, "StateGroup", "states", {qtObjectId});
QmlDesigner::createObject(*this, qtQuickModuleId, "State", "changes", {qtObjectId});
QmlDesigner::createObject(*this, qtQuickModuleId, "Transition", "animations", {qtObjectId});
QmlDesigner::createObject(*this, qtQuickModuleId, "PropertyAnimation", "", {qtObjectId});
auto stateOperationsId = QmlDesigner::createObject(*this,
qtQuickNativeModuleId,
" QQuickStateOperation",
"",
{qtObjectId});
QmlDesigner::createObject(*this,
qtQuickModuleId,
"PropertyChanges",
"",
{qtObjectId, stateOperationsId});
auto listElementId = createObject(qtQmlModelsModuleId, "ListElement", {qtObjectId});
createObject(qtQmlModelsModuleId,
"ListModel",
"children",
PropertyDeclarationTraits::IsList,
listElementId,
{qtObjectId});
auto qtQuickTimelineModuleId = QmlDesigner::createModule(*this, "QtQuick.Timeline");
QmlDesigner::createObject(*this, qtQuickTimelineModuleId, "KeyframeGroup", "keyframes", {qtObjectId});
QmlDesigner::createObject(*this, qtQuickTimelineModuleId, "Keyframe", "", {qtObjectId});
auto itemId = createObject(qtQuickModuleId,
"Item",
"data",
PropertyDeclarationTraits::IsList,
qtObjectId,
{qtObjectId});
createObject(qtQuickModuleId,
"ListView",
"data",
PropertyDeclarationTraits::IsList,
qtObjectId,
{qtObjectId, itemId});
createObject(qtQuickModuleId, "StateGroup", {qtObjectId});
createObject(qtQuickModuleId,
"State",
"changes",
PropertyDeclarationTraits::IsList,
qtObjectId,
{qtObjectId});
auto animationId = createObject(qtQuickModuleId, "Animation", {qtObjectId});
createObject(qtQuickModuleId,
"Transition",
"animations",
PropertyDeclarationTraits::IsList,
animationId,
{qtObjectId});
createObject(qtQuickModuleId, "PropertyAnimation", {qtObjectId});
auto stateOperationsId = createObject(qtQuickNativeModuleId,
" QQuickStateOperation",
{qtObjectId});
createObject(qtQuickModuleId, "PropertyChanges", {qtObjectId, stateOperationsId});
auto flowViewModuleId = QmlDesigner::createModule(*this, "FlowView");
QmlDesigner::createObject(*this, flowViewModuleId, "FlowActionArea", "data", {qtObjectId, itemId});
QmlDesigner::createObject(*this, flowViewModuleId, "FlowWildcard", "data", {qtObjectId});
QmlDesigner::createObject(*this, flowViewModuleId, "FlowDecision", "", {qtObjectId});
QmlDesigner::createObject(*this, flowViewModuleId, "FlowTransition", "", {qtObjectId});
QmlDesigner::createObject(*this, flowViewModuleId, "FlowItem", "data", {qtObjectId, itemId});
auto qtQuickTimelineModuleId = createModule("QtQuick.Timeline");
createObject(qtQuickTimelineModuleId, "KeyframeGroup", {qtObjectId});
createObject(qtQuickTimelineModuleId, "Keyframe", {qtObjectId});
auto flowViewModuleId = createModule("FlowView");
createObject(flowViewModuleId,
"FlowActionArea",
"data",
PropertyDeclarationTraits::IsList,
qtObjectId,
{qtObjectId, itemId});
createObject(flowViewModuleId,
"FlowWildcard",
"data",
PropertyDeclarationTraits::IsList,
qtObjectId,
{qtObjectId});
createObject(flowViewModuleId, "FlowDecision", {qtObjectId});
createObject(flowViewModuleId, "FlowTransition", {qtObjectId});
createObject(flowViewModuleId,
"FlowItem",
"data",
PropertyDeclarationTraits::IsList,
qtObjectId,
{qtObjectId, itemId});
}
void ProjectStorageMock::setupCommonTypeCache()

View File

@@ -18,6 +18,47 @@ public:
void setupQtQtuick();
void setupCommonTypeCache();
QmlDesigner::ModuleId createModule(Utils::SmallStringView moduleName);
QmlDesigner::TypeId createType(
QmlDesigner::ModuleId moduleId,
Utils::SmallStringView typeName,
Utils::SmallStringView defaultPropertyName,
QmlDesigner::Storage::PropertyDeclarationTraits defaultPropertyTraits,
QmlDesigner::TypeId defaultPropertyTypeId,
QmlDesigner::Storage::TypeTraits typeTraits,
QmlDesigner::TypeIds baseTypeIds = {});
QmlDesigner::TypeId createType(QmlDesigner::ModuleId moduleId,
Utils::SmallStringView typeName,
QmlDesigner::Storage::TypeTraits typeTraits,
QmlDesigner::TypeIds baseTypeIds = {});
QmlDesigner::TypeId createObject(
QmlDesigner::ModuleId moduleId,
Utils::SmallStringView typeName,
Utils::SmallStringView defaultPropertyName,
QmlDesigner::Storage::PropertyDeclarationTraits defaultPropertyTraits,
QmlDesigner::TypeId defaultPropertyTypeId,
QmlDesigner::TypeIds baseTypeIds = {});
QmlDesigner::TypeId createObject(QmlDesigner::ModuleId moduleId,
Utils::SmallStringView typeName,
QmlDesigner::TypeIds baseTypeIds = {});
QmlDesigner::PropertyDeclarationId createProperty(
QmlDesigner::TypeId typeId,
Utils::SmallString name,
QmlDesigner::Storage::PropertyDeclarationTraits traits,
QmlDesigner::TypeId propertyTypeId);
QmlDesigner::PropertyDeclarationId createProperty(QmlDesigner::TypeId typeId,
Utils::SmallString name,
QmlDesigner::TypeId propertyTypeId);
void createSignal(QmlDesigner::TypeId typeId, Utils::SmallString name);
void createFunction(QmlDesigner::TypeId typeId, Utils::SmallString name);
MOCK_METHOD(void,
synchronize,
(QmlDesigner::Storage::Synchronization::SynchronizationPackage package),

View File

@@ -61,6 +61,7 @@ endfunction(unittest_copy_data_folder)
add_subdirectory(listmodeleditor)
add_subdirectory(imagecache)
add_subdirectory(metainfo)
add_subdirectory(model)
add_subdirectory(sqlite)
add_subdirectory(projectstorage)

View File

@@ -0,0 +1,5 @@
# qmldesigner/designercore/model
extend_qtc_test(unittest
SOURCES
nodemetainfo-test.cpp
)

View File

@@ -0,0 +1,415 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "../utils/googletest.h"
#include "../mocks/projectstoragemock.h"
#include <designercore/include/model.h>
#include <designercore/include/modelnode.h>
#include <designercore/include/nodemetainfo.h>
namespace {
using QmlDesigner::ModelNode;
using QmlDesigner::ModelNodes;
template<typename Matcher>
auto PropertyId(const Matcher &matcher)
{
return Property(&QmlDesigner::PropertyMetaInfo::id, matcher);
}
class NodeMetaInfo : public testing::Test
{
protected:
NiceMock<ProjectStorageMockWithQtQtuick> projectStorageMock;
QmlDesigner::Model model{projectStorageMock, "QtQuick.Item"};
ModelNode rootNode = model.rootModelNode();
ModelNode item = model.createModelNode("QtQuick.Item");
ModelNode object = model.createModelNode("QML.QtObject");
QmlDesigner::NodeMetaInfo itemMetaInfo = item.metaInfo();
QmlDesigner::NodeMetaInfo objectMetaInfo = object.metaInfo();
QmlDesigner::TypeId intTypeId = projectStorageMock.typeId(projectStorageMock.moduleId("QML"),
"int",
QmlDesigner::Storage::Version{});
};
TEST_F(NodeMetaInfo, is_true_if_meta_info_exists)
{
auto node = model.createModelNode("QtQuick.Item");
auto metaInfo = node.metaInfo();
auto isValid = bool(metaInfo);
ASSERT_TRUE(isValid);
}
TEST_F(NodeMetaInfo, is_valid_if_meta_info_exists)
{
auto node = model.createModelNode("QtQuick.Item");
auto metaInfo = node.metaInfo();
auto isValid = metaInfo.isValid();
ASSERT_TRUE(isValid);
}
TEST_F(NodeMetaInfo, is_false_if_meta_info_not_exists)
{
auto node = model.createModelNode("QtQuick.Foo");
auto metaInfo = node.metaInfo();
auto isValid = bool(metaInfo);
ASSERT_FALSE(isValid);
}
TEST_F(NodeMetaInfo, default_is_false)
{
auto isValid = bool(QmlDesigner::NodeMetaInfo{});
ASSERT_FALSE(isValid);
}
TEST_F(NodeMetaInfo, is_invalid_if_meta_info_not_exists)
{
auto node = model.createModelNode("QtQuick.Foo");
auto metaInfo = node.metaInfo();
auto isValid = metaInfo.isValid();
ASSERT_FALSE(isValid);
}
TEST_F(NodeMetaInfo, default_is_invalid)
{
auto isValid = QmlDesigner::NodeMetaInfo{}.isValid();
ASSERT_FALSE(isValid);
}
TEST_F(NodeMetaInfo, item_is_based_on_object)
{
bool isBasedOn = itemMetaInfo.isBasedOn(objectMetaInfo);
ASSERT_TRUE(isBasedOn);
}
TEST_F(NodeMetaInfo, item_is_based_on_item)
{
bool isBasedOn = itemMetaInfo.isBasedOn(itemMetaInfo);
ASSERT_TRUE(isBasedOn);
}
TEST_F(NodeMetaInfo, object_is_no_based_on_item)
{
bool isBasedOn = objectMetaInfo.isBasedOn(itemMetaInfo);
ASSERT_FALSE(isBasedOn);
}
TEST_F(NodeMetaInfo, object_is_not_file_component)
{
bool isFileComponent = objectMetaInfo.isFileComponent();
ASSERT_FALSE(isFileComponent);
}
TEST_F(NodeMetaInfo, default_is_not_file_component)
{
bool isFileComponent = QmlDesigner::NodeMetaInfo{}.isFileComponent();
ASSERT_FALSE(isFileComponent);
}
TEST_F(NodeMetaInfo, invalid_is_not_file_component)
{
auto node = model.createModelNode("QtQuick.Foo");
auto metaInfo = node.metaInfo();
bool isFileComponent = metaInfo.isFileComponent();
ASSERT_FALSE(isFileComponent);
}
TEST_F(NodeMetaInfo, component_is_file_component)
{
using QmlDesigner::Storage::TypeTraits;
auto moduleId = projectStorageMock.createModule("/path/to/project");
auto typeId = projectStorageMock.createType(moduleId,
"Foo",
TypeTraits::IsFileComponent | TypeTraits::Reference);
QmlDesigner::NodeMetaInfo metaInfo{typeId, &projectStorageMock};
bool isFileComponent = metaInfo.isFileComponent();
ASSERT_TRUE(isFileComponent);
}
TEST_F(NodeMetaInfo, has_property)
{
auto node = model.createModelNode("QtQuick.Item");
auto metaInfo = node.metaInfo();
projectStorageMock.createProperty(metaInfo.id(), "x", intTypeId);
bool hasProperty = metaInfo.hasProperty("x");
ASSERT_TRUE(hasProperty);
}
TEST_F(NodeMetaInfo, has_not_property)
{
auto node = model.createModelNode("QtQuick.Item");
auto metaInfo = node.metaInfo();
bool hasProperty = metaInfo.hasProperty("foo");
ASSERT_FALSE(hasProperty);
}
TEST_F(NodeMetaInfo, default_has_not_property)
{
auto metaInfo = QmlDesigner::NodeMetaInfo{};
bool hasProperty = metaInfo.hasProperty("x");
ASSERT_FALSE(hasProperty);
}
TEST_F(NodeMetaInfo, invalid_has_not_property)
{
auto node = model.createModelNode("QtQuick.Foo");
auto metaInfo = node.metaInfo();
bool hasProperty = metaInfo.hasProperty("x");
ASSERT_FALSE(hasProperty);
}
TEST_F(NodeMetaInfo, get_property)
{
auto node = model.createModelNode("QtQuick.Item");
auto metaInfo = node.metaInfo();
auto propertyId = projectStorageMock.createProperty(metaInfo.id(), "x", intTypeId);
auto property = metaInfo.property("x");
ASSERT_THAT(property, PropertyId(propertyId));
}
TEST_F(NodeMetaInfo, get_invalid_property_if_not_exists)
{
auto node = model.createModelNode("QtQuick.Item");
auto metaInfo = node.metaInfo();
auto property = metaInfo.property("x");
ASSERT_THAT(property, PropertyId(IsFalse()));
}
TEST_F(NodeMetaInfo, get_invalid_property_for_default)
{
auto metaInfo = QmlDesigner::NodeMetaInfo{};
auto property = metaInfo.property("x");
ASSERT_THAT(property, PropertyId(IsFalse()));
}
TEST_F(NodeMetaInfo, get_invalid_property_if_meta_info_is_invalid)
{
auto node = model.createModelNode("QtQuick.Foo");
auto metaInfo = node.metaInfo();
auto property = metaInfo.property("x");
ASSERT_THAT(property, PropertyId(IsFalse()));
}
TEST_F(NodeMetaInfo, get_properties)
{
auto node = model.createModelNode("QtQuick.Item");
auto metaInfo = node.metaInfo();
auto xPropertyId = projectStorageMock.createProperty(metaInfo.id(), "x", intTypeId);
auto yPropertyId = projectStorageMock.createProperty(metaInfo.id(), "y", intTypeId);
auto properties = metaInfo.properties();
ASSERT_THAT(properties, IsSupersetOf({PropertyId(xPropertyId), PropertyId(yPropertyId)}));
}
TEST_F(NodeMetaInfo, get_no_properties_for_default)
{
auto metaInfo = QmlDesigner::NodeMetaInfo{};
auto properties = metaInfo.properties();
ASSERT_THAT(properties, IsEmpty());
}
TEST_F(NodeMetaInfo, get_no_properties_if_is_invalid)
{
auto node = model.createModelNode("QtQuick.Foo");
auto metaInfo = node.metaInfo();
auto properties = metaInfo.properties();
ASSERT_THAT(properties, IsEmpty());
}
TEST_F(NodeMetaInfo, get_local_properties)
{
auto node = model.createModelNode("QtQuick.Item");
auto metaInfo = node.metaInfo();
auto xPropertyId = projectStorageMock.createProperty(metaInfo.id(), "x", intTypeId);
auto yPropertyId = projectStorageMock.createProperty(metaInfo.id(), "y", intTypeId);
auto properties = metaInfo.localProperties();
ASSERT_THAT(properties, IsSupersetOf({PropertyId(xPropertyId), PropertyId(yPropertyId)}));
}
TEST_F(NodeMetaInfo, get_no_local_properties_for_default_metainfo)
{
auto metaInfo = QmlDesigner::NodeMetaInfo{};
auto properties = metaInfo.localProperties();
ASSERT_THAT(properties, IsEmpty());
}
TEST_F(NodeMetaInfo, get_no_local_properties_if_node_is_invalid)
{
auto node = model.createModelNode("QtQuick.Foo");
auto metaInfo = node.metaInfo();
auto properties = metaInfo.localProperties();
ASSERT_THAT(properties, IsEmpty());
}
TEST_F(NodeMetaInfo, get_signal_names)
{
auto node = model.createModelNode("QtQuick.Item");
auto metaInfo = node.metaInfo();
projectStorageMock.createSignal(metaInfo.id(), "xChanged");
projectStorageMock.createSignal(metaInfo.id(), "yChanged");
auto signalNames = metaInfo.signalNames();
ASSERT_THAT(signalNames, IsSupersetOf({"xChanged", "yChanged"}));
}
TEST_F(NodeMetaInfo, get_no_signal_names_for_default_metainfo)
{
auto metaInfo = QmlDesigner::NodeMetaInfo{};
auto signalNames = metaInfo.signalNames();
ASSERT_THAT(signalNames, IsEmpty());
}
TEST_F(NodeMetaInfo, get_no_signal_names_if_node_is_invalid)
{
auto node = model.createModelNode("QtQuick.Foo");
auto metaInfo = node.metaInfo();
auto signalNames = metaInfo.signalNames();
ASSERT_THAT(signalNames, IsEmpty());
}
TEST_F(NodeMetaInfo, get_function_names)
{
auto node = model.createModelNode("QtQuick.Item");
auto metaInfo = node.metaInfo();
projectStorageMock.createFunction(metaInfo.id(), "setX");
projectStorageMock.createFunction(metaInfo.id(), "setY");
auto functionNames = metaInfo.slotNames();
ASSERT_THAT(functionNames, IsSupersetOf({"setX", "setY"}));
}
TEST_F(NodeMetaInfo, get_no_function_names_for_default_metainfo)
{
auto metaInfo = QmlDesigner::NodeMetaInfo{};
auto functionNames = metaInfo.slotNames();
ASSERT_THAT(functionNames, IsEmpty());
}
TEST_F(NodeMetaInfo, get_no_function_names_if_node_is_invalid)
{
auto node = model.createModelNode("QtQuick.Foo");
auto metaInfo = node.metaInfo();
auto functionNames = metaInfo.slotNames();
ASSERT_THAT(functionNames, IsEmpty());
}
TEST_F(NodeMetaInfo, get_default_property)
{
auto node = model.createModelNode("QtQuick.Item");
auto metaInfo = node.metaInfo();
auto defaultProperty = metaInfo.property("data");
auto property = metaInfo.defaultProperty();
ASSERT_THAT(property, defaultProperty);
}
TEST_F(NodeMetaInfo, get_no_default_property_for_default_metainfo)
{
auto metaInfo = QmlDesigner::NodeMetaInfo{};
auto property = metaInfo.defaultProperty();
ASSERT_THAT(property, IsFalse());
}
TEST_F(NodeMetaInfo, get_no_default_property_if_node_is_invalid)
{
auto node = model.createModelNode("QtQuick.Foo");
auto metaInfo = node.metaInfo();
auto property = metaInfo.defaultProperty();
ASSERT_THAT(property, IsFalse());
}
TEST_F(NodeMetaInfo, get_default_property_name)
{
auto node = model.createModelNode("QtQuick.Item");
auto metaInfo = node.metaInfo();
auto defaultProperty = metaInfo.property("data");
auto property = metaInfo.defaultPropertyName();
ASSERT_THAT(property, "data");
}
TEST_F(NodeMetaInfo, get_no_default_property_name_for_default_metainfo)
{
auto metaInfo = QmlDesigner::NodeMetaInfo{};
auto property = metaInfo.defaultPropertyName();
ASSERT_THAT(property, IsEmpty());
}
TEST_F(NodeMetaInfo, get_no_default_property_name_if_node_is_invalid)
{
auto node = model.createModelNode("QtQuick.Foo");
auto metaInfo = node.metaInfo();
auto property = metaInfo.defaultPropertyName();
ASSERT_THAT(property, IsEmpty());
}
} // namespace

View File

@@ -3,6 +3,7 @@ extend_qtc_test(unittest
SOURCES
import-test.cpp
model-test.cpp
modelnode-test.cpp
nodelistproperty-test.cpp
modelresourcemanagement-test.cpp
)

View File

@@ -0,0 +1,27 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "../utils/googletest.h"
#include "../mocks/projectstoragemock.h"
#include <designercore/include/model.h>
#include <designercore/include/modelnode.h>
#include <designercore/include/nodemetainfo.h>
namespace {
class ModelNode : public testing::Test
{
protected:
NiceMock<ProjectStorageMockWithQtQtuick> projectStorageMock;
QmlDesigner::Model model{projectStorageMock, "QtQuick.Item"};
QmlDesigner::ModelNode rootNode = model.rootModelNode();
};
TEST_F(ModelNode, get_meta_info)
{
auto metaInfo = rootNode.metaInfo();
}
} // namespace

View File

@@ -30,9 +30,11 @@ using testing::Gt;
using testing::HasSubstr;
using testing::InSequence;
using testing::Invoke;
using testing::IsFalse;
using testing::IsNull;
using testing::IsSubsetOf;
using testing::IsSupersetOf;
using testing::IsTrue;
using testing::Le;
using testing::Lt;
using testing::Matcher;