From ee011dc19ceb497401c28eb4f9c731a87eec3e9f Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Fri, 23 May 2025 00:02:21 +0200 Subject: [PATCH] QmlDesigner: Add common path to SourcePathView Change-Id: I685a35a70ad597ac5b0a57f39dcc5037a7489d1a Reviewed-by: Thomas Hartmann --- .../sourcepathstorage/sourcepathview.h | 24 ++++++-- .../sourcepathstorage/sourcepathview-test.cpp | 58 +++++++++++++++++++ 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathview.h b/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathview.h index 9100154d7e2..d8203e372fd 100644 --- a/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathview.h +++ b/src/plugins/qmldesigner/libs/designercore/sourcepathstorage/sourcepathview.h @@ -6,6 +6,7 @@ #include #include +#include #include namespace QmlDesigner { @@ -60,13 +61,28 @@ public: std::size_t(std::ptrdiff_t(size()) - m_slashIndex - std::ptrdiff_t(1))); } - static - std::ptrdiff_t lastSlashIndex(Utils::SmallStringView filePath) + static constexpr std::tuple commonPath( + std::string_view first, std::string_view second) { - auto foundReverse = std::find(filePath.rbegin(), filePath.rend(), separator); + auto [firstSplit, secondSplit] = std::ranges::mismatch(first, second); + + firstSplit = std::ranges::find(std::make_reverse_iterator(firstSplit), + std::make_reverse_iterator(first.begin()), + separator) + .base(); + + secondSplit = std::ranges::next(second.begin(), + std::ranges::distance(first.begin(), firstSplit)); + + return {{first.begin(), firstSplit}, {firstSplit, first.end()}, {secondSplit, second.end()}}; + } + + static constexpr std::ptrdiff_t lastSlashIndex(Utils::SmallStringView filePath) + { + auto foundReverse = std::ranges::find(filePath.rbegin(), filePath.rend(), separator); auto found = foundReverse.base(); - auto distance = std::distance(filePath.begin(), found); + auto distance = std::ranges::distance(filePath.begin(), found); return distance - 1; } diff --git a/tests/unit/tests/unittests/sourcepathstorage/sourcepathview-test.cpp b/tests/unit/tests/unittests/sourcepathstorage/sourcepathview-test.cpp index c5f35f921c9..a90c0ec0900 100644 --- a/tests/unit/tests/unittests/sourcepathstorage/sourcepathview-test.cpp +++ b/tests/unit/tests/unittests/sourcepathstorage/sourcepathview-test.cpp @@ -98,4 +98,62 @@ TEST(SourcePathView, file_name_for_file_name_only) ASSERT_THAT(filePath.name(), "file.h"); } +TEST(SourcePathView, common_path_for_same_path) +{ + std::string_view input{"/foo/"}; + + auto matched = QmlDesigner::SourcePathView::commonPath(input, input); + + ASSERT_THAT(matched, FieldsAre("/foo/", IsEmpty(), IsEmpty())); +} + +TEST(SourcePathView, common_path) +{ + std::string_view input1{"/foo/bar"}; + std::string_view input2{"/foo/hoo"}; + + auto matched = QmlDesigner::SourcePathView::commonPath(input1, input2); + + ASSERT_THAT(matched, FieldsAre("/foo/", "bar", "hoo")); +} + +TEST(SourcePathView, common_path_last_is_sub_path) +{ + std::string_view input1{"/foo/bar"}; + std::string_view input2{"/foo/"}; + + auto matched = QmlDesigner::SourcePathView::commonPath(input1, input2); + + ASSERT_THAT(matched, FieldsAre("/foo/", "bar", IsEmpty())); +} + +TEST(SourcePathView, common_path_first_is_sub_path) +{ + std::string_view input1{"/foo/"}; + std::string_view input2{"/foo/bar"}; + + auto matched = QmlDesigner::SourcePathView::commonPath(input1, input2); + + ASSERT_THAT(matched, FieldsAre("/foo/", IsEmpty(), "bar")); +} + +TEST(SourcePathView, common_path_last_is_file) +{ + std::string_view input1{"/foo/bar"}; + std::string_view input2{"/foo"}; + + auto matched = QmlDesigner::SourcePathView::commonPath(input1, input2); + + ASSERT_THAT(matched, FieldsAre("/", "foo/bar", "foo")); +} + +TEST(SourcePathView, common_path_first_is_file) +{ + std::string_view input1{"/foo"}; + std::string_view input2{"/foo/bar"}; + + auto matched = QmlDesigner::SourcePathView::commonPath(input1, input2); + + ASSERT_THAT(matched, FieldsAre("/", "foo", "foo/bar")); +} }