forked from qt-creator/qt-creator
QmlDesigner: Add Model::moduleIdsStartsWith()
Get modul ids that start with that string and are of that kind. If no string is given there are no ids returned. The returned ids are not sorted. auto moduleIds = model->moduleIdsStartsWith("QtQuick", Storage::ModuleKind::QmlLibrary); std::ranges::sort(moduleIds); auto isQtQuickModule = Utils::set_has_common_element(otherSortedModuleIds, moduleIds); Change-Id: I85f7dadca5be88885e54237b5d560ba02b61c75b Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: Burak Hancerli <burak.hancerli@qt.io>
This commit is contained in:
@@ -148,6 +148,8 @@ public:
|
||||
#endif
|
||||
|
||||
Module module(Utils::SmallStringView moduleName, Storage::ModuleKind moduleKind);
|
||||
SmallModuleIds<128> moduleIdsStartsWith(Utils::SmallStringView startsWith,
|
||||
Storage::ModuleKind kind) const;
|
||||
NodeMetaInfo metaInfo(const TypeName &typeName, int majorVersion = -1, int minorVersion = -1) const;
|
||||
NodeMetaInfo metaInfo(Module module,
|
||||
Utils::SmallStringView typeName,
|
||||
|
@@ -45,6 +45,8 @@ using EnumerationDeclarationIds = std::vector<EnumerationDeclarationId>;
|
||||
using ModuleId = Sqlite::BasicId<ProjectStorageIdType::Module, int>;
|
||||
using ModuleIds = std::vector<ModuleId>;
|
||||
using ModuleIdSpan = Utils::span<ModuleId>;
|
||||
template<std::size_t size>
|
||||
using SmallModuleIds = QVarLengthArray<ModuleId, size>;
|
||||
|
||||
using ProjectPartId = Sqlite::BasicId<ProjectStorageIdType::ProjectPartId>;
|
||||
using ProjectPartIds = std::vector<ProjectPartId>;
|
||||
|
@@ -2917,6 +2917,15 @@ Module Model::module(Utils::SmallStringView moduleName, Storage::ModuleKind modu
|
||||
return {};
|
||||
}
|
||||
|
||||
SmallModuleIds<128> Model::moduleIdsStartsWith(Utils::SmallStringView startsWith,
|
||||
Storage::ModuleKind kind) const
|
||||
{
|
||||
if constexpr (useProjectStorage())
|
||||
return d->projectStorage->moduleIdsStartsWith(startsWith, kind);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
/*! \name View related functions
|
||||
*/
|
||||
//\{
|
||||
|
@@ -1424,7 +1424,8 @@ ModuleId ProjectStorage::moduleId(Utils::SmallStringView moduleName, Storage::Mo
|
||||
using NanotraceHR::keyValue;
|
||||
NanotraceHR::Tracer tracer{"get module id",
|
||||
projectStorageCategory(),
|
||||
keyValue("module name", moduleName)};
|
||||
keyValue("module name", moduleName),
|
||||
keyValue("module kind", kind)};
|
||||
|
||||
if (moduleName.empty())
|
||||
return ModuleId{};
|
||||
@@ -1436,6 +1437,27 @@ ModuleId ProjectStorage::moduleId(Utils::SmallStringView moduleName, Storage::Mo
|
||||
return moduleId;
|
||||
}
|
||||
|
||||
SmallModuleIds<128> ProjectStorage::moduleIdsStartsWith(Utils::SmallStringView startsWith,
|
||||
Storage::ModuleKind kind) const
|
||||
{
|
||||
using NanotraceHR::keyValue;
|
||||
NanotraceHR::Tracer tracer{"get module ids that starts with",
|
||||
projectStorageCategory(),
|
||||
keyValue("module name starts with", startsWith),
|
||||
keyValue("module kind", kind)};
|
||||
|
||||
if (startsWith.isEmpty())
|
||||
return {};
|
||||
|
||||
auto projection = [&](ModuleView view) -> ModuleView {
|
||||
return {view.name.substr(0, startsWith.size()), view.kind};
|
||||
};
|
||||
|
||||
auto moduleIds = moduleCache.ids<128>({startsWith, kind}, projection);
|
||||
|
||||
return moduleIds;
|
||||
}
|
||||
|
||||
Storage::Module ProjectStorage::module(ModuleId moduleId) const
|
||||
{
|
||||
using NanotraceHR::keyValue;
|
||||
|
@@ -62,6 +62,9 @@ public:
|
||||
|
||||
ModuleId moduleId(Utils::SmallStringView moduleName, Storage::ModuleKind kind) const override;
|
||||
|
||||
SmallModuleIds<128> moduleIdsStartsWith(Utils::SmallStringView startsWith,
|
||||
Storage::ModuleKind kind) const override;
|
||||
|
||||
Storage::Module module(ModuleId moduleId) const override;
|
||||
|
||||
TypeId typeId(ModuleId moduleId,
|
||||
@@ -252,9 +255,9 @@ private:
|
||||
Utils::SmallStringView name;
|
||||
Storage::ModuleKind kind;
|
||||
|
||||
friend bool operator<(ModuleView first, ModuleView second)
|
||||
friend std::strong_ordering operator<=>(ModuleView first, ModuleView second)
|
||||
{
|
||||
return std::tie(first.kind, first.name) < std::tie(second.kind, second.name);
|
||||
return std::tie(first.kind, first.name) <=> std::tie(second.kind, second.name);
|
||||
}
|
||||
|
||||
friend bool operator==(const Storage::Module &first, ModuleView second)
|
||||
|
@@ -32,6 +32,8 @@ public:
|
||||
virtual void removeObserver(ProjectStorageObserver *observer) = 0;
|
||||
|
||||
virtual ModuleId moduleId(::Utils::SmallStringView name, Storage::ModuleKind kind) const = 0;
|
||||
virtual SmallModuleIds<128>
|
||||
moduleIdsStartsWith(Utils::SmallStringView startsWith, Storage::ModuleKind kind) const = 0;
|
||||
virtual QmlDesigner::Storage::Module module(ModuleId moduleId) const = 0;
|
||||
virtual std::optional<Storage::Info::PropertyDeclaration>
|
||||
propertyDeclaration(PropertyDeclarationId propertyDeclarationId) const = 0;
|
||||
|
@@ -201,38 +201,50 @@ public:
|
||||
{
|
||||
std::shared_lock<Mutex> sharedLock(m_mutex);
|
||||
|
||||
auto found = find(view);
|
||||
auto [iter, found] = find(view);
|
||||
|
||||
if (found != m_entries.end())
|
||||
return found->id;
|
||||
if (found)
|
||||
return iter->id;
|
||||
|
||||
sharedLock.unlock();
|
||||
std::lock_guard<Mutex> exclusiveLock(m_mutex);
|
||||
|
||||
if constexpr (!std::is_base_of_v<NonLockingMutex, Mutex>)
|
||||
found = find(view);
|
||||
if (found == m_entries.end())
|
||||
found = insertEntry(found, view, m_storage.fetchId(view));
|
||||
std::tie(iter, found) = find(view);
|
||||
if (!found)
|
||||
iter = insertEntry(iter, view, m_storage.fetchId(view));
|
||||
|
||||
return found->id;
|
||||
return iter->id;
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
std::vector<IndexType> ids(const Container &values)
|
||||
template<typename ValueType = ViewType>
|
||||
std::vector<IndexType> ids(Utils::span<const ValueType> values)
|
||||
{
|
||||
std::vector<IndexType> ids;
|
||||
ids.reserve(values.size());
|
||||
|
||||
std::ranges::transform(values, std::back_inserter(ids), [&](const auto &values) {
|
||||
return this->id(values);
|
||||
std::ranges::transform(values, std::back_inserter(ids), [&](ViewType value) {
|
||||
return this->id(value);
|
||||
});
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
std::vector<IndexType> ids(std::initializer_list<Type> values)
|
||||
template<std::indirectly_readable I, std::indirectly_regular_unary_invocable<I> Proj>
|
||||
using projected_value_t = std::remove_cvref_t<std::invoke_result_t<Proj &, std::iter_value_t<I> &>>;
|
||||
|
||||
template<std::size_t size,
|
||||
typename Projection = std::identity,
|
||||
typename Value = projected_value_t<std::ranges::iterator_t<CacheEntries>, Projection>>
|
||||
QVarLengthArray<IndexType, size> ids(Value value, Projection projection)
|
||||
{
|
||||
return ids<std::initializer_list<Type>>(values);
|
||||
std::shared_lock<Mutex> sharedLock(m_mutex);
|
||||
|
||||
auto range = std::ranges::equal_range(m_entries, value, Compare{}, projection);
|
||||
|
||||
QVarLengthArray<IndexType, size> ids;
|
||||
std::ranges::transform(range, std::back_inserter(ids), &CacheEntry::id);
|
||||
return ids;
|
||||
}
|
||||
|
||||
ResultType value(IndexType id)
|
||||
@@ -250,7 +262,7 @@ public:
|
||||
std::lock_guard<Mutex> exclusiveLock(m_mutex);
|
||||
|
||||
Type value{m_storage.fetchValue(id)};
|
||||
auto interator = insertEntry(find(value), value, id);
|
||||
auto interator = insertEntry(std::get<0>(find(value)), value, id);
|
||||
|
||||
return interator->value;
|
||||
}
|
||||
@@ -290,24 +302,21 @@ private:
|
||||
}
|
||||
|
||||
template<typename Entries>
|
||||
static auto find(Entries &&entries, ViewType view)
|
||||
static std::tuple<std::ranges::iterator_t<Entries>, bool> find(Entries &&entries, ViewType view)
|
||||
{
|
||||
auto found = std::ranges::lower_bound(entries, view, Compare{});
|
||||
|
||||
if (found != entries.end() && *found == view)
|
||||
return found;
|
||||
|
||||
return entries.end();
|
||||
return {found, found != entries.end() && *found == view};
|
||||
}
|
||||
|
||||
IndexType id(ViewType view) const
|
||||
{
|
||||
std::shared_lock<Mutex> sharedLock(m_mutex);
|
||||
|
||||
auto found = find(view);
|
||||
auto [iter, found] = find(view);
|
||||
|
||||
if (found != m_entries.end())
|
||||
return found->id;
|
||||
if (found)
|
||||
return iter->id;
|
||||
|
||||
return IndexType();
|
||||
}
|
||||
|
@@ -133,6 +133,10 @@ public:
|
||||
moduleId,
|
||||
(::Utils::SmallStringView, QmlDesigner::Storage::ModuleKind moduleKind),
|
||||
(const, override));
|
||||
MOCK_METHOD(QmlDesigner::SmallModuleIds<128>,
|
||||
moduleIdsStartsWith,
|
||||
(::Utils::SmallStringView, QmlDesigner::Storage::ModuleKind moduleKind),
|
||||
(const, override));
|
||||
MOCK_METHOD(QmlDesigner::Storage::Module, module, (QmlDesigner::ModuleId), (const, override));
|
||||
|
||||
MOCK_METHOD(std::optional<QmlDesigner::Storage::Info::PropertyDeclaration>,
|
||||
|
@@ -1137,6 +1137,16 @@ TEST_F(Model_MetaInfo, get_invalid_meta_info_by_module_for_wrong_module)
|
||||
ASSERT_THAT(metaInfo, IsFalse());
|
||||
}
|
||||
|
||||
TEST_F(Model_MetaInfo, get_module_ids_that_starts_with)
|
||||
{
|
||||
ON_CALL(projectStorageMock, moduleIdsStartsWith(Eq("Q"), ModuleKind::QmlLibrary))
|
||||
.WillByDefault(Return(QmlDesigner::SmallModuleIds<128>{qtQuickModuleId}));
|
||||
|
||||
auto moduleIds = model.moduleIdsStartsWith("Q", ModuleKind::QmlLibrary);
|
||||
|
||||
ASSERT_THAT(moduleIds, Contains(qtQuickModuleId));
|
||||
}
|
||||
|
||||
TEST_F(Model_MetaInfo, add_project_storage_observer_to_project_storage)
|
||||
{
|
||||
EXPECT_CALL(projectStorageMock, addObserver(_));
|
||||
|
@@ -5827,6 +5827,30 @@ TEST_F(ProjectStorage, populate_module_cache)
|
||||
ASSERT_THAT(newStorage.module(id), IsModule("Qml", ModuleKind::QmlLibrary));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage, get_no_module_ids_if_they_starts_with_nothing)
|
||||
{
|
||||
storage.moduleId("QtQml", ModuleKind::QmlLibrary);
|
||||
|
||||
auto ids = storage.moduleIdsStartsWith("", ModuleKind::QmlLibrary);
|
||||
|
||||
ASSERT_THAT(ids, IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage, get_module_ids_if_they_starts_with_New)
|
||||
{
|
||||
auto quickId = storage.moduleId("NewQuick", ModuleKind::QmlLibrary);
|
||||
storage.moduleId("NewQuick", ModuleKind::CppLibrary);
|
||||
auto quick3dId = storage.moduleId("NewQuick3D", ModuleKind::QmlLibrary);
|
||||
storage.moduleId("NewQml", ModuleKind::CppLibrary);
|
||||
auto qmlId = storage.moduleId("NewQml", ModuleKind::QmlLibrary);
|
||||
storage.moduleId("Foo", ModuleKind::QmlLibrary);
|
||||
storage.moduleId("Zoo", ModuleKind::QmlLibrary);
|
||||
|
||||
auto ids = storage.moduleIdsStartsWith("New", ModuleKind::QmlLibrary);
|
||||
|
||||
ASSERT_THAT(ids, UnorderedElementsAre(qmlId, quickId, quick3dId));
|
||||
}
|
||||
|
||||
TEST_F(ProjectStorage, add_directory_infoes)
|
||||
{
|
||||
Storage::Synchronization::DirectoryInfo directoryInfo1{qmlProjectDirectoryPathId,
|
||||
|
@@ -514,4 +514,41 @@ TYPED_TEST(StorageCache, fetch_ids_from_storage_calls)
|
||||
|
||||
this->cache.ids({"foo", "bar"});
|
||||
}
|
||||
|
||||
TYPED_TEST(StorageCache, getting_ids_that_start_with_po)
|
||||
{
|
||||
ON_CALL(this->mockStorage, fetchDirectoryPathId(Eq("poh"))).WillByDefault(Return(this->id43));
|
||||
this->cache.add({"poo", "foo", "poh", "taa"});
|
||||
auto projection = [](Utils::SmallStringView text) -> Utils::SmallStringView {
|
||||
return text.substr(0, 2);
|
||||
};
|
||||
|
||||
auto ids = this->cache.template ids<4>("po", projection);
|
||||
|
||||
ASSERT_THAT(ids, UnorderedElementsAre(this->id43, this->id44));
|
||||
}
|
||||
|
||||
TYPED_TEST(StorageCache, getting_no_ids_if_there_is_no_entry_starts_with_oh)
|
||||
{
|
||||
this->cache.add({"poo", "taa", "foo", "bar"});
|
||||
auto projection = [](Utils::SmallStringView text) -> Utils::SmallStringView {
|
||||
return text.substr(0, 2);
|
||||
};
|
||||
|
||||
auto ids = this->cache.template ids<4>("oh", projection);
|
||||
|
||||
ASSERT_THAT(ids, IsEmpty());
|
||||
}
|
||||
|
||||
TYPED_TEST(StorageCache, get_all_ids_if_the_string_is_empty)
|
||||
{
|
||||
this->cache.add({"foo", "bar", "poo", "taa"});
|
||||
auto projection = [](Utils::SmallStringView text) -> Utils::SmallStringView {
|
||||
return text.substr(0, 0);
|
||||
};
|
||||
|
||||
auto ids = this->cache.template ids<4>("", projection);
|
||||
|
||||
ASSERT_THAT(ids, UnorderedElementsAre(this->id42, this->id43, this->id44, this->id45));
|
||||
}
|
||||
} // namespace
|
||||
|
Reference in New Issue
Block a user