From 624637009dd34f2af6197142a14aa111dc2fe9ba Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 24 Aug 2026 19:14:52 +0000 Subject: [PATCH 1/2] Fix format_as to return unquoted strings for string JSON values Co-authored-by: TonyWelte <12954392+TonyWelte@users.noreply.github.com> --- .../src/rosidlcpp_generator_core/generator_utils.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rosidlcpp_generator_core/src/rosidlcpp_generator_core/generator_utils.cpp b/rosidlcpp_generator_core/src/rosidlcpp_generator_core/generator_utils.cpp index 2aef5dd..73b418b 100644 --- a/rosidlcpp_generator_core/src/rosidlcpp_generator_core/generator_utils.cpp +++ b/rosidlcpp_generator_core/src/rosidlcpp_generator_core/generator_utils.cpp @@ -35,11 +35,13 @@ namespace nlohmann { std::string format_as(const json& j) { - return j.dump(); + // dump() would wrap strings in double quotes, which is never what the generators want when + // interpolating names and namespaces into generated code. + return j.is_string() ? j.get() : j.dump(); } std::string format_as(const detail::iter_impl& j) { - return j->dump(); + return format_as(*j); } } // namespace nlohmann From b112d6e3565747b810b652af4a352feefb881a13 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 24 Aug 2026 19:17:15 +0000 Subject: [PATCH 2/2] Add unit tests for format_as functions in rosidlcpp_generator_core Co-authored-by: TonyWelte <12954392+TonyWelte@users.noreply.github.com> --- rosidlcpp_generator_core/CMakeLists.txt | 8 ++ .../unit/rosidlcpp_generator_core_test.cpp | 80 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 rosidlcpp_generator_core/test/unit/rosidlcpp_generator_core_test.cpp diff --git a/rosidlcpp_generator_core/CMakeLists.txt b/rosidlcpp_generator_core/CMakeLists.txt index 022cfb1..16049a1 100644 --- a/rosidlcpp_generator_core/CMakeLists.txt +++ b/rosidlcpp_generator_core/CMakeLists.txt @@ -27,6 +27,14 @@ install(TARGETS ${PROJECT_NAME} install(DIRECTORY include/ DESTINATION include) +if(BUILD_TESTING) + find_package(ament_cmake_gtest REQUIRED) + + ament_add_gtest(rosidlcpp_generator_core_test test/unit/rosidlcpp_generator_core_test.cpp) + target_link_libraries(rosidlcpp_generator_core_test ${PROJECT_NAME}) + target_include_directories(rosidlcpp_generator_core_test PUBLIC include) +endif() + ament_export_include_directories("include/${PROJECT_NAME}") ament_export_libraries(${PROJECT_NAME}) diff --git a/rosidlcpp_generator_core/test/unit/rosidlcpp_generator_core_test.cpp b/rosidlcpp_generator_core/test/unit/rosidlcpp_generator_core_test.cpp new file mode 100644 index 0000000..0cd2b7f --- /dev/null +++ b/rosidlcpp_generator_core/test/unit/rosidlcpp_generator_core_test.cpp @@ -0,0 +1,80 @@ +// Copyright 2025 Anthony Welte +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include + +#include + +using nlohmann::json; + +// Tests for format_as(const json&) + +TEST(FormatAsJsonTest, StringValueIsNotQuoted) { + json j = "hello"; + EXPECT_EQ(nlohmann::format_as(j), "hello"); +} + +TEST(FormatAsJsonTest, StringValueWithSpecialCharacters) { + json j = "msg/UUID"; + EXPECT_EQ(nlohmann::format_as(j), "msg/UUID"); +} + +TEST(FormatAsJsonTest, IntegerValueIsDumped) { + json j = 42; + EXPECT_EQ(nlohmann::format_as(j), "42"); +} + +TEST(FormatAsJsonTest, BoolValueIsDumped) { + json j = true; + EXPECT_EQ(nlohmann::format_as(j), "true"); +} + +TEST(FormatAsJsonTest, NullValueIsDumped) { + json j = nullptr; + EXPECT_EQ(nlohmann::format_as(j), "null"); +} + +TEST(FormatAsJsonTest, ArrayValueIsDumped) { + json j = json::array({1, 2, 3}); + EXPECT_EQ(nlohmann::format_as(j), "[1,2,3]"); +} + +TEST(FormatAsJsonTest, ObjectValueIsDumped) { + json j = {{"key", "value"}}; + EXPECT_EQ(nlohmann::format_as(j), "{\"key\":\"value\"}"); +} + +// Tests for format_as(const detail::iter_impl&) + +TEST(FormatAsIteratorTest, StringValueIsNotQuoted) { + json obj = {{"name", "msg"}}; + auto it = obj.cbegin(); + EXPECT_EQ(nlohmann::format_as(it), "msg"); +} + +TEST(FormatAsIteratorTest, IntegerValueIsDumped) { + json obj = {{"count", 7}}; + auto it = obj.cbegin(); + EXPECT_EQ(nlohmann::format_as(it), "7"); +} + +TEST(FormatAsIteratorTest, ArrayElementStringNotQuoted) { + json arr = json::array({"foo", "bar"}); + auto it = arr.cbegin(); + EXPECT_EQ(nlohmann::format_as(it), "foo"); + ++it; + EXPECT_EQ(nlohmann::format_as(it), "bar"); +}