From ee05b2a65aea1de4b6d01b5e2b1d9d21a8fd2bac Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Thu, 13 Mar 2025 16:22:27 +0100 Subject: [PATCH] QmlDesigner: Add source cache name id getter To test if a source name exists we add a getter to the id. Change-Id: If5d430402189474b85897dbe0b47f3558916d096 Reviewed-by: Burak Hancerli Reviewed-by: Thomas Hartmann --- .../sourcepathstorage/sourcepathcache.h | 34 ++++++--- .../sourcepathcacheinterface.h | 4 + .../sourcepathexceptions.cpp | 10 +++ .../sourcepathstorage/sourcepathexceptions.h | 7 ++ tests/unit/tests/mocks/sourcepathcachemock.h | 8 ++ .../sourcepathcache-test.cpp | 74 +++++++++++++++++++ 6 files changed, 126 insertions(+), 11 deletions(-) diff --git a/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathcache.h b/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathcache.h index 1fc3fcab84d..cc7d0a89f98 100644 --- a/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathcache.h +++ b/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathcache.h @@ -43,9 +43,9 @@ public: void populateIfEmpty() override { - if (m_sourcePathCache.isEmpty()) { + if (m_sourceNameCache.isEmpty()) { m_sourceContextPathCache.populate(); - m_sourcePathCache.populate(); + m_sourceNameCache.populate(); } } @@ -57,15 +57,19 @@ public: Utils::SmallStringView sourceName = sourcePath.name(); - auto sourceId = m_sourcePathCache.id(sourceName); + auto sourceNameId = m_sourceNameCache.id(sourceName); - return SourceId::create(sourceId, sourceContextId); + return SourceId::create(sourceNameId, sourceContextId); } - SourceId sourceId(SourceContextId sourceContextId, - Utils::SmallStringView sourceName) const override + SourceNameId sourceNameId(Utils::SmallStringView sourceName) const override { - SourceNameId sourceNameId = m_sourcePathCache.id(sourceName); + return m_sourceNameCache.id(sourceName); + } + + SourceId sourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName) const override + { + SourceNameId sourceNameId = m_sourceNameCache.id(sourceName); return SourceId::create(sourceNameId, sourceContextId); } @@ -81,10 +85,10 @@ public: SourcePath sourcePath(SourceId sourceId) const override { - if (Q_UNLIKELY(!sourceId.isValid())) + if (!sourceId) [[unlikely]] throw NoSourcePathForInvalidSourceId(); - auto sourceName = m_sourcePathCache.value(sourceId.mainId()); + auto sourceName = m_sourceNameCache.value(sourceId.mainId()); Utils::PathString sourceContextPath = m_sourceContextPathCache.value(sourceId.contextId()); @@ -93,12 +97,20 @@ public: Utils::PathString sourceContextPath(SourceContextId sourceContextId) const override { - if (Q_UNLIKELY(!sourceContextId.isValid())) + if (!sourceContextId) [[unlikely]] throw NoSourceContextPathForInvalidSourceContextId(); return m_sourceContextPathCache.value(sourceContextId); } + Utils::SmallString sourceName(SourceNameId sourceNameId) const override + { + if (!sourceNameId) [[unlikely]] + throw NoSourceNameForInvalidSourceNameId(); + + return m_sourceNameCache.value(sourceNameId); + } + private: class SourceContextStorageAdapter { @@ -157,7 +169,7 @@ private: SourceContextStorageAdapter m_sourceContextStorageAdapter; SourceNameStorageAdapter m_sourceNameStorageAdapter; mutable SourceContextPathCache m_sourceContextPathCache{m_sourceContextStorageAdapter}; - mutable SourceNameCache m_sourcePathCache{m_sourceNameStorageAdapter}; + mutable SourceNameCache m_sourceNameCache{m_sourceNameStorageAdapter}; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathcacheinterface.h b/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathcacheinterface.h index 1f78bec1eb8..6f2378643f7 100644 --- a/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathcacheinterface.h +++ b/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathcacheinterface.h @@ -28,12 +28,16 @@ public: Utils::SmallStringView sourceName) const = 0; + virtual SourceNameId sourceNameId(Utils::SmallStringView sourceName) const = 0; + virtual SourceContextId sourceContextId(Utils::SmallStringView sourceContextPath) const = 0; virtual SourcePath sourcePath(SourceId sourceId) const = 0; virtual Utils::PathString sourceContextPath(SourceContextId sourceContextId) const = 0; + virtual Utils::SmallString sourceName(SourceNameId sourceNameId) const = 0; + protected: ~SourcePathCacheInterface() = default; }; diff --git a/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathexceptions.cpp b/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathexceptions.cpp index 48c1af71a7c..04365236e71 100644 --- a/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathexceptions.cpp +++ b/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathexceptions.cpp @@ -56,4 +56,14 @@ const char *SourceNameIdDoesNotExists::what() const noexcept return "The source id does not exist in the database!"; } +NoSourceNameForInvalidSourceNameId::NoSourceNameForInvalidSourceNameId() +{ + category().threadEvent("NoSourceNameForInvalidSourceNameId"); +} + +const char *NoSourceNameForInvalidSourceNameId::what() const noexcept +{ + return "You cannot get a source name for an invalid source name id!"; +} + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathexceptions.h b/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathexceptions.h index 12dcd1d7700..958f99fab93 100644 --- a/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathexceptions.h +++ b/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathexceptions.h @@ -27,6 +27,13 @@ public: const char *what() const noexcept override; }; +class QMLDESIGNERCORE_EXPORT NoSourceNameForInvalidSourceNameId : public SourcePathError +{ +public: + NoSourceNameForInvalidSourceNameId(); + const char *what() const noexcept override; +}; + class QMLDESIGNERCORE_EXPORT NoSourceContextPathForInvalidSourceContextId : public SourcePathError { public: diff --git a/tests/unit/tests/mocks/sourcepathcachemock.h b/tests/unit/tests/mocks/sourcepathcachemock.h index 77560057f35..5b4f16fe175 100644 --- a/tests/unit/tests/mocks/sourcepathcachemock.h +++ b/tests/unit/tests/mocks/sourcepathcachemock.h @@ -24,6 +24,10 @@ public: sourceId, (QmlDesigner::SourceContextId sourceContextId, Utils::SmallStringView sourceName), (const, override)); + MOCK_METHOD(QmlDesigner::SourceNameId, + sourceNameId, + (Utils::SmallStringView sourceName), + (const, override)); MOCK_METHOD(QmlDesigner::SourcePath, sourcePath, (QmlDesigner::SourceId sourceId), @@ -36,6 +40,10 @@ public: sourceContextPath, (QmlDesigner::SourceContextId directoryPathId), (const, override)); + MOCK_METHOD(Utils::SmallString, + sourceName, + (QmlDesigner::SourceNameId sourceName), + (const, override)); MOCK_METHOD(void, populateIfEmpty, (), (override)); }; diff --git a/tests/unit/tests/unittests/sourcepathstorage/sourcepathcache-test.cpp b/tests/unit/tests/unittests/sourcepathstorage/sourcepathcache-test.cpp index dd30127cbb9..ea10cde418e 100644 --- a/tests/unit/tests/unittests/sourcepathstorage/sourcepathcache-test.cpp +++ b/tests/unit/tests/unittests/sourcepathstorage/sourcepathcache-test.cpp @@ -372,4 +372,78 @@ TEST_F(SourcePathCache, get_file_path_after_populate_if_empty) ASSERT_THAT(path, Eq("/path/to/file.cpp")); } +TEST_F(SourcePathCache, source_name_id_calls_fetch_source_name_id) +{ + EXPECT_CALL(storageMock, fetchSourceNameId(Eq("file.cpp"))); + + cache.sourceNameId(Utils::SmallString("file.cpp")); +} + +TEST_F(SourcePathCache, second_source_name_id_calls_not_fetch_source_name_id) +{ + cache.sourceNameId(Utils::SmallString("file.cpp")); + + EXPECT_CALL(storageMock, fetchSourceNameId(Eq("file.cpp"))).Times(0); + + cache.sourceNameId(Utils::SmallString("file.cpp")); +} + +TEST_F(SourcePathCache, source_name_id) +{ + auto id = cache.sourceNameId(Utils::SmallString("file.cpp")); + + ASSERT_THAT(id, Eq(sourceNameId42)); +} + +TEST_F(SourcePathCache, source_name_id_is_already_in_cache) +{ + auto firstId = cache.sourceNameId(Utils::SmallString("file.cpp")); + + auto secondId = cache.sourceNameId(Utils::SmallString("file.cpp")); + + ASSERT_THAT(secondId, firstId); +} + +TEST_F(SourcePathCache, throw_for_getting_source_name_with_an_invalid_id) +{ + SourceNameId sourceNameId; + + ASSERT_THROW(cache.sourceName(sourceNameId), QmlDesigner::NoSourceNameForInvalidSourceNameId); +} + +TEST_F(SourcePathCache, get_a_source_name) +{ + SourceNameId sourceNameId{sourceNameId42}; + + auto sourceName = cache.sourceName(sourceNameId); + + ASSERT_THAT(sourceName, Eq(Utils::SmallStringView{"file.cpp"})); +} + +TEST_F(SourcePathCache, get_a_source_name_with_cached_source_name_id) +{ + SourceNameId sourceNameId{sourceNameId42}; + cache.sourceName(sourceNameId); + + auto sourceName = cache.sourceName(sourceNameId); + + ASSERT_THAT(sourceName, Eq(Utils::SmallStringView{"file.cpp"})); +} + +TEST_F(SourcePathCache, source_name_calls_fetch_source_name) +{ + EXPECT_CALL(storageMock, fetchSourceName(Eq(sourceNameId42))); + + cache.sourceName(sourceNameId42); +} + +TEST_F(SourcePathCache, second_source_name_calls_not_fetch_source_name) +{ + cache.sourceName(sourceNameId42); + + EXPECT_CALL(storageMock, fetchSourceName(_)).Times(0); + + cache.sourceName(sourceNameId42); +} + } // namespace