-
Notifications
You must be signed in to change notification settings - Fork 787
Add Clang tidy and many fixes #1047
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Caution Review failedThe pull request is closed. 📝 WalkthroughWalkthroughAdds clang‑tidy tooling and CI; introduces many non‑copyable/non‑movable public types; broad const/noexcept/default‑init fixes; reworks TimerQueue and decorator timer logic; improves SafeAny/SimpleString and conversion checks; removes example; adds SimpleString tests; assorted safety and serialization cleanups. Changes
Sequence Diagram(s)(omitted) Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
📜 Recent review detailsConfiguration used: defaults Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/behavior_tree.cpp (1)
35-38: Inconsistent nullptr guard between const and non-constapplyRecursiveVisitor.The non-const version (lines 59-62) now guards against
decorator->child() != nullptrbefore recursing, but the const version (line 37) does not have this guard. If a decorator can have a null child, both versions should handle it consistently.🔎 Proposed fix for const version
else if(auto decorator = dynamic_cast<const BT::DecoratorNode*>(node)) { - applyRecursiveVisitor(decorator->child(), visitor); + if(decorator->child() != nullptr) + { + applyRecursiveVisitor(decorator->child(), visitor); + } }Also applies to: 57-63
src/decorators/delay_node.cpp (1)
42-49: The config-based constructor is missing initialization ofread_parameter_from_ports_.The review comment correctly identifies a critical issue: the
DelayNodeconfig-based constructor at line 15 initializesmsec_to 0 but never setsread_parameter_from_ports_to true. This prevents the port-based configuration from working, even though the header declaresInputPort<unsigned>("delay_msec")and the documentation promises the delay can be passed via port. Other similar nodes (timeout_node, retry_node, repeat_node, parallel_node) all explicitly setread_parameter_from_ports_(true)in their config-based constructors. The config-based constructor should do the same.
🧹 Nitpick comments (4)
src/controls/reactive_sequence.cpp (1)
58-58: LGTM! The explicit cast improves type safety.The change to use
static_cast<int>(index)makes the size_t-to-int conversion explicit, which is a good practice for type safety and aligns with clang-tidy recommendations.Optional: Consider consistent casting style throughout the method.
For consistency, line 56 could also use
static_cast<int>(index)instead ofint(index):🔎 Optional consistency improvement
- running_child_ = int(index); + running_child_ = static_cast<int>(index);include/behaviortree_cpp/utils/convert_impl.hpp (1)
157-171: Inconsistent behavior between floating-point and integer to bool conversions.Floating-point values allow C-style conversion (any non-zero becomes
true), but integer values only allow 0 or 1. This means2.0converts totrue, while integer2throws an exception.If the intent is strict conversion for safety, consider also validating floating-point values:
if constexpr (std::is_floating_point<SRC>::value && is_same<DST, bool>()) { if(source != 0.0 && source != 1.0) { throw std::runtime_error("Implicit casting to bool is not allowed"); } target = static_cast<DST>(source); }Otherwise, if C-style permissiveness is desired, the integer path could also allow any non-zero value.
src/basic_types.cpp (1)
200-206: Good const-correctness improvements.The refactoring correctly saves and restores the locale. Note that
setlocaleis not thread-safe (it modifies global state), but this appears to be pre-existing behavior. For thread-safe parsing, considerstd::strtodwith a thread-local orstd::from_chars(C++17 for floating-point, though support varies).src/loggers/groot2_publisher.cpp (1)
103-103: Consider fixing the typo in the variable name.The variable name
recording_fist_timeappears to be a typo and should likely berecording_first_time. This name is used throughout the file (lines 221, 440).🔎 Proposed fix
- std::chrono::microseconds recording_fist_time{}; + std::chrono::microseconds recording_first_time{};Then update references on lines 221 and 440 accordingly.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (47)
.clang-tidy.gitignore.pre-commit-config.yamlinclude/behaviortree_cpp/actions/pop_from_queue.hppinclude/behaviortree_cpp/actions/sleep_node.hinclude/behaviortree_cpp/utils/convert_impl.hppinclude/behaviortree_cpp/utils/locked_reference.hppinclude/behaviortree_cpp/utils/safe_any.hppinclude/behaviortree_cpp/utils/simple_string.hppinclude/behaviortree_cpp/utils/wildcards.hpprun_clang_tidy.shsrc/action_node.cppsrc/actions/sleep_node.cppsrc/actions/updated_action.cppsrc/basic_types.cppsrc/behavior_tree.cppsrc/blackboard.cppsrc/bt_factory.cppsrc/control_node.cppsrc/controls/fallback_node.cppsrc/controls/if_then_else_node.cppsrc/controls/manual_node.cppsrc/controls/parallel_all_node.cppsrc/controls/reactive_fallback.cppsrc/controls/reactive_sequence.cppsrc/controls/sequence_node.cppsrc/controls/switch_node.cppsrc/controls/while_do_else_node.cppsrc/decorator_node.cppsrc/decorators/delay_node.cppsrc/decorators/repeat_node.cppsrc/decorators/retry_node.cppsrc/decorators/subtree_node.cppsrc/decorators/timeout_node.cppsrc/decorators/updated_decorator.cppsrc/example.cppsrc/json_export.cppsrc/loggers/bt_cout_logger.cppsrc/loggers/bt_file_logger_v2.cppsrc/loggers/bt_minitrace_logger.cppsrc/loggers/bt_sqlite_logger.cppsrc/loggers/groot2_publisher.cppsrc/script_parser.cppsrc/shared_library.cppsrc/shared_library_UNIX.cppsrc/tree_node.cppsrc/xml_parsing.cpp
💤 Files with no reviewable changes (1)
- src/example.cpp
🧰 Additional context used
🧬 Code graph analysis (19)
src/decorators/subtree_node.cpp (2)
src/tree_node.cpp (2)
status(276-280)status(276-276)tests/navigation_test.cpp (1)
status(126-146)
src/loggers/bt_cout_logger.cpp (1)
include/behaviortree_cpp/loggers/bt_cout_logger.h (1)
StdCoutLogger(14-25)
src/loggers/bt_file_logger_v2.cpp (2)
src/tree_node.cpp (2)
status(276-280)status(276-276)src/shared_library_UNIX.cpp (3)
lock(13-13)lock(32-32)lock(48-48)
src/controls/fallback_node.cpp (1)
src/tree_node.cpp (2)
setRegistrationID(433-436)setRegistrationID(433-433)
include/behaviortree_cpp/utils/locked_reference.hpp (3)
include/behaviortree_cpp/utils/simple_string.hpp (8)
other(36-44)other(36-36)other(51-59)other(51-51)other(111-115)other(111-111)other(117-121)other(117-117)include/behaviortree_cpp/utils/safe_any.hpp (6)
other(119-119)other(121-121)other(309-317)other(309-309)other(319-324)other(319-319)src/tree_node.cpp (2)
other(60-64)other(60-60)
src/controls/sequence_node.cpp (1)
src/tree_node.cpp (2)
setRegistrationID(433-436)setRegistrationID(433-433)
src/decorators/updated_decorator.cpp (5)
src/loggers/groot2_publisher.cpp (2)
lk(118-118)lk(198-198)src/loggers/bt_sqlite_logger.cpp (2)
lk(189-189)lk(208-208)src/actions/sleep_node.cpp (1)
lk(28-28)src/decorators/delay_node.cpp (2)
lk(43-43)lk(52-52)src/decorators/timeout_node.cpp (2)
lk(44-44)lk(55-55)
src/control_node.cpp (1)
src/decorator_node.cpp (4)
child(38-41)child(38-38)child(43-46)child(43-43)
src/bt_factory.cpp (1)
src/behavior_tree.cpp (4)
applyRecursiveVisitor(18-39)applyRecursiveVisitor(18-19)applyRecursiveVisitor(41-64)applyRecursiveVisitor(41-41)
src/action_node.cpp (3)
src/tree_node.cpp (10)
name(293-296)name(293-293)config(345-348)config(345-345)config(350-353)config(350-350)setStatus(151-172)setStatus(151-151)emitWakeUpSignal(420-426)emitWakeUpSignal(420-420)3rdparty/minicoro/minicoro.h (2)
mco_create(1684-1711)mco_destroy(1713-1729)src/bt_factory.cpp (2)
emitWakeUpSignal(525-528)emitWakeUpSignal(525-525)
src/controls/while_do_else_node.cpp (3)
src/control_node.cpp (2)
resetChildren(38-48)resetChildren(38-38)src/tree_node.cpp (2)
status(276-280)status(276-276)tests/navigation_test.cpp (1)
status(126-146)
src/actions/updated_action.cpp (5)
src/loggers/groot2_publisher.cpp (2)
lk(118-118)lk(198-198)src/loggers/bt_sqlite_logger.cpp (2)
lk(189-189)lk(208-208)src/actions/sleep_node.cpp (1)
lk(28-28)src/decorators/delay_node.cpp (2)
lk(43-43)lk(52-52)src/decorators/timeout_node.cpp (2)
lk(44-44)lk(55-55)
src/decorators/delay_node.cpp (1)
include/behaviortree_cpp/decorators/delay_node.h (1)
DelayNode(34-66)
src/controls/if_then_else_node.cpp (2)
src/tree_node.cpp (2)
status(276-280)status(276-276)src/control_node.cpp (2)
resetChildren(38-48)resetChildren(38-38)
src/shared_library.cpp (1)
include/behaviortree_cpp/exceptions.h (1)
RuntimeError(58-67)
src/decorators/timeout_node.cpp (2)
src/decorator_node.cpp (6)
child(38-41)child(38-38)child(43-46)child(43-43)resetChild(53-64)resetChild(53-53)include/behaviortree_cpp/basic_types.h (1)
isStatusCompleted(47-50)
src/tree_node.cpp (1)
include/behaviortree_cpp/tree_node.h (1)
TreeNode(131-295)
src/shared_library_UNIX.cpp (3)
src/shared_library.cpp (1)
SharedLibrary(4-7)include/behaviortree_cpp/utils/shared_library.h (1)
SharedLibrary(47-139)include/behaviortree_cpp/exceptions.h (1)
RuntimeError(58-67)
include/behaviortree_cpp/utils/safe_any.hpp (1)
include/behaviortree_cpp/utils/simple_string.hpp (16)
other(36-44)other(36-36)other(51-59)other(51-51)other(111-115)other(111-111)other(117-121)other(117-117)other(123-126)other(123-123)other(128-131)other(128-128)other(133-142)other(133-133)other(144-153)other(144-144)
🪛 Cppcheck (2.19.0)
src/xml_parsing.cpp
[error] 376-376: Found an exit path from function with non-void return type that has missing return statement
(missingReturn)
🪛 GitHub Actions: cmake Ubuntu
src/bt_factory.cpp
[error] 109-109: Error: 'const std::set<std::__cxx11::basic_string >' has no member named 'contains'. Use 'find' or 'count' instead.
🪛 Shellcheck (0.11.0)
run_clang_tidy.sh
[warning] 62-62: Quote this to prevent word splitting.
(SC2046)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: build (windows-latest)
- GitHub Check: pixi_conda_build (windows-latest)
- GitHub Check: pixi_conda_build (ubuntu-latest)
- GitHub Check: industrial_ci (humble, main)
- GitHub Check: industrial_ci (jazzy, main)
- GitHub Check: industrial_ci (rolling, main)
- GitHub Check: build (ubuntu-22.04, tsan)
- GitHub Check: build (ubuntu-22.04, asan_ubsan)
🔇 Additional comments (117)
src/json_export.cpp (1)
91-91: Good const-correctness improvement.Marking
first_elementas const is appropriate since it's only used for type inspection and is never modified. This aligns with clang-tidy recommendations and modern C++ best practices.src/script_parser.cpp (5)
26-26: LGTM: const-correctness improvement.Marking
exprsasconstis appropriate since the vector is not modified after initialization. This is a typical clang-tidy recommendation for improved immutability.
35-35: Unsigned literal aligns with size_t comparison.Using
0Umakes the loop index type consistent withexprs.size(), which returnssize_t(unsigned). The loop logic correctly handles all cases given the empty check at lines 27-30.
52-52: LGTM: reduced nesting by removing redundant else.Since all paths within the
ifblock return, theelseis unnecessary. This change reduces indentation and aligns with clang-tidy's readability recommendations.
62-63: LGTM: simplified control flow.Removing the
elseblock and adding the forwarding comment clarifies that this path only executes whenexecutoris false. The change reduces nesting while preserving the same behavior.
78-78: LGTM: const-correctness improvement.Same as line 26—marking the parsed expressions vector as
constis appropriate since it's not mutated after initialization.src/controls/reactive_fallback.cpp (1)
58-58: LGTM: Modernized cast tostatic_cast.The change from C-style cast to
static_cast<int>correctly modernizes the code and aligns with clang-tidy best practices for explicit type conversions.include/behaviortree_cpp/utils/wildcards.hpp (2)
3-6: LGTM: Explicit includes improve maintainability.Adding explicit includes for
<cstddef>,<cstdint>,<string_view>, and<vector>ensures that the file declares all dependencies rather than relying on transitive includes. This prevents potential breakage if included headers change their own dependencies in the future.
43-43: LGTM: Initialization ensures defined behavior.Initializing
resulttofalseat declaration is defensive programming that prevents potential static analyzer warnings about uninitialized variables. While all current code paths assign toresultbefore use, this initialization guards against future logic changes and aligns with the PR's clang-tidy objectives.include/behaviortree_cpp/actions/pop_from_queue.hpp (2)
74-79: LGTM! Clean refactoring that improves readability.The removal of the redundant else block after the early return (line 72) follows clang-tidy's readability-else-after-return guideline. The logic remains functionally equivalent—lines 74-77 execute only when the queue is non-empty, and line 79 correctly handles the case where queue retrieval fails or the pointer is null.
122-123: LGTM! Consistent refactoring improves code clarity.This change mirrors the PopFromQueue refactoring by removing the unnecessary else block after the early return at line 120. The simplified control flow is clearer and follows the same clang-tidy guideline.
src/basic_types.cpp (6)
9-9: LGTM!The
<tuple>include is needed forstd::ignoreusage below.
121-122: LGTM!Using
std::ignoreto explicitly discard the unusedptris a clean way to silence warnings.
143-156: LGTM!The anonymous namespace properly encapsulates this internal helper. The bounds checking via
int64_tis safe since all target types (8/16/32-bit signed and unsigned) fit withinint64_trange.
447-447: LGTM!Casting to
unsigned charbeforeisalphaavoids undefined behavior whencharis signed and has a negative value.
475-475: LGTM!Making the parsed JSON object
constcorrectly reflects that it's not modified after parsing.
494-508: LGTM!The explicit size check and manual comparison is correct. If targeting C++20 or later,
std::string_view::starts_with()could simplify this, but the current implementation is compatible with C++17.src/loggers/groot2_publisher.cpp (11)
4-4: LGTM! Good use of anonymous namespace and necessary include.The
<tuple>include supportsstd::ignoreusage later in the file. WrappingCreateRandomUUIDin an anonymous namespace properly limits its linkage to this translation unit, which is appropriate for internal helper functions.Also applies to: 33-57
37-40: LGTM! Safe zero-initialization.The explicit zero-initialization with
{}ensures deterministic initial state for the array.
44-49: LGTM! Explicit casts improve type safety.The
static_cast<char>additions make narrowing conversions explicit and prevent potential issues with signed char types in bitwise operations.
66-66: LGTM! Improved const-correctness.Marking these timeout values as
constcorrectly documents their immutability and prevents accidental modification.Also applies to: 70-70
118-118: LGTM! Improved const-correctness for lock guards.Marking these
std::unique_lockinstances asconstcorrectly documents that they are not reassigned or moved after construction. This is appropriate for scoped RAII lock guards.Also applies to: 198-198, 207-207, 289-289, 417-417, 446-446, 460-460, 489-489, 591-591, 598-598, 659-659, 707-707
212-212: LGTM! Type-safe conversions and initialization.The explicit
static_castchain ensures type safety through arithmetic operations, and zero-initialization of theTransitionstruct provides deterministic initial state.Also applies to: 218-218
320-320: LGTM! Consistent const-correctness.These variables are correctly marked
constas they are not modified after initialization.Also applies to: 364-367, 405-405
419-421: LGTM! Clear marking of intentionally unused variables.Using
std::ignoreto explicitly mark unused structured binding elements is a good practice that documents intent and silences compiler warnings.Also applies to: 490-492, 689-691
513-513: LGTM! Appropriate const qualification.The
constqualification correctly documents that this captured state is not modified.
554-554: LGTM! Proper const qualification of pointers.These
TreeNode::Ptrinstances are correctly markedconstas they are not reassigned after initialization. The pointed-to objects remain mutable as intended.Also applies to: 613-613, 646-646
568-568: LGTM! Const-correct object.The
constqualification is appropriate as this request header is not modified after construction..gitignore (1)
21-23: LGTM! Appropriate gitignore entries for clang-tidy tooling.The added entries correctly exclude clang-tidy related artifacts from version control.
include/behaviortree_cpp/actions/sleep_node.h (1)
38-38: LGTM! Good defensive programming practice.Initializing
timer_id_to 0 prevents undefined behavior and is a best practice for member variables.src/controls/sequence_node.cpp (1)
22-29: LGTM! Improved consistency with explicit braces.Adding braces to both branches follows common coding standards and reduces the risk of future errors when modifying these blocks.
src/controls/switch_node.cpp (1)
82-82: LGTM! Clean simplification of conditional logic.Converting the multi-line if-statement to a single return expression improves readability while preserving the exact same behavior.
.pre-commit-config.yaml (1)
46-53: LGTM! Useful documentation for optional clang-tidy integration.The commented-out hook provides a clear example for contributors who want to enable clang-tidy in their pre-commit workflow.
src/controls/fallback_node.cpp (1)
21-28: LGTM! Consistent with similar refactoring in sequence_node.cpp.Adding explicit braces improves code consistency across control nodes and aligns with common coding standards.
src/shared_library.cpp (1)
12-16: LGTM! Improved clarity with explicit nullptr comparison.The explicit
!= nullptrcheck is more readable and aligns with modern C++ best practices. The control flow remains identical.src/controls/parallel_all_node.cpp (1)
50-50: LGTM! Modern and more expressive membership check.Using
.contains()is more idiomatic than.count() != 0for checking set membership and clearly expresses the intent.src/decorators/repeat_node.cpp (1)
50-51: LGTM: Const-correctness improvement.Making these local status variables const is appropriate since they're not modified after initialization. This aligns with modern C++ best practices and clang-tidy recommendations.
src/controls/while_do_else_node.cpp (2)
39-39: LGTM: Const-correctness improvement.Making
condition_statusconst is appropriate since it's not modified after initialization.
73-74: LGTM: Control flow simplification.The removal of the else block is correct. After the early return for
RUNNINGat line 71, the code always resets children and returns status. This simplifies the logic without changing behavior.src/decorators/subtree_node.cpp (1)
22-22: LGTM: Const-correctness improvement.Making
prev_statusconst is appropriate since it's not modified after initialization.src/decorators/updated_decorator.cpp (1)
53-53: LGTM: Const-qualified lock for read-only critical section.Making the
std::unique_lockconst is appropriate here since the lock object itself doesn't need to be modified (no explicit unlock or lock operations). The RAII semantics still work correctly.src/actions/sleep_node.cpp (1)
28-28: LGTM: Const-qualified lock in lambda.Making the lock const within the timer callback is appropriate since the lock object doesn't need to be modified. The RAII semantics remain intact.
src/actions/updated_action.cpp (1)
43-43: LGTM: Const-qualified lock for read-only critical section.Consistent with the pattern used throughout this PR. The lock protects a read-only access to
entry->sequence_id, so making it const is appropriate.src/loggers/bt_minitrace_logger.cpp (1)
24-44: LGTM: Internal linkage for helper function.Moving
toConstStrinto an anonymous namespace gives it internal linkage, which is best practice for helper functions that don't need to be exported. This prevents potential ODR violations.src/control_node.cpp (2)
40-40: LGTM: Explicit pointer type.Using
auto*instead ofautomakes the pointer type explicit and improves code clarity. This aligns with modern C++ best practices and clang-tidy recommendations.
57-57: LGTM: Explicit pointer type.Making the pointer type explicit with
auto*improves code clarity and consistency with the change at line 40.src/decorators/retry_node.cpp (1)
55-56: LGTM!Adding
consttoprev_statusandchild_statusis appropriate since these values are captured once per loop iteration and never modified. This aligns with the broader const-correctness improvements in this PR.src/decorator_node.cpp (3)
24-24: LGTM!Explicit
!= nullptrcomparison is clearer than implicit truthiness check, aligning with clang-tidy best practices.
55-55: LGTM!Consistent use of explicit
== nullptrfor the early return guard.
79-80: LGTM!Both
statusandchild_statusare only read after assignment, makingconstappropriate here.src/loggers/bt_cout_logger.cpp (2)
8-8: LGTM!Defaulted destructor is appropriate here since no custom cleanup logic is required.
18-18: LGTM!Adding
consttosince_epochcorrectly reflects its immutable nature.src/controls/if_then_else_node.cpp (3)
42-42: LGTM!Adding
consttocondition_statusis correct since the value is evaluated once and not modified.
48-61: LGTM!The restructured conditional logic is clearer. For
FAILURE:
- If 3 children exist, proceed to else branch (child_idx_ = 2)
- Otherwise, return FAILURE immediately
This correctly handles both 2-child and 3-child configurations.
67-74: LGTM!The simplified control flow correctly resets children and returns the status for any non-RUNNING outcome, eliminating the redundant else branch.
src/loggers/bt_file_logger_v2.cpp (4)
8-14: LGTM!Wrapping
ToUsecin an anonymous namespace correctly restricts its linkage to this translation unit.
57-59: LGTM!Using
std::array<char, 8>with value initialization anddata()accessor is safer and more idiomatic than raw C-style buffers.
85-90: LGTM!Value-initializing
Transitionwith{}and usingconst std::scoped_lockaligns with the project's const-correctness patterns.
120-120: LGTM!Using
std::array<char, 9>{}ensures zero-initialization of the write buffer before populating it withmemcpy.src/decorators/timeout_node.cpp (2)
44-44: LGTM!Adding
constto theunique_lockin the timer callback correctly reflects that the lock variable itself isn't reassigned.
62-71: Pattern is safe and no race condition exists.The unlock/relock window around
timer_.cancel()is intentionally designed to prevent deadlock while maintaining correctness. During the unlock window (lines 66-68), the timer callback cannot corrupt state because:
child_statusis already completed when reaching line 63, meaningchild()->status()is notRUNNING- The timer callback's condition at line 45 checks exactly this (
if(child()->status() == RUNNING))- Since the child is not running, the callback will not execute any state-modifying operations
child_halted_isstd::atomic_bool, ensuring thread-safe updates regardless of timing- Mutex re-acquisition at line 68 synchronizes before calling
resetChild()The pattern correctly avoids deadlock while ensuring no data races occur.
src/loggers/bt_sqlite_logger.cpp (4)
21-25: LGTM!Good defensive null-check for
err_msgbefore using it.sqlite3_execcan leaveerr_msgasnullptrin certain error conditions.
133-145: LGTM!Wrapping destructor operations in try/catch is essential to prevent exceptions from escaping and causing
std::terminate. Thesqlite3_close(db_)correctly remains outside the try block to ensure the database handle is always closed.
157-157: LGTM!Adding
consttotm_useccorrectly reflects its immutable use after assignment.
189-189: LGTM!Using
const std::scoped_lockaligns with the project's const-correctness patterns for lock objects.src/action_node.cpp (4)
75-81: LGTM!Wrapping
CoroEntryin an anonymous namespace correctly restricts its linkage to this translation unit, preventing symbol conflicts.
89-96: LGTM!Essential try/catch in the destructor prevents exceptions from
destroyCoroutine()escaping and causingstd::terminate.
148-156: LGTM!The explicit
nullptrcheck before callingmco_destroyadds clarity, even thoughmco_destroyhandles null pointers internally (returnsMCO_INVALID_COROUTINE). Theconstonrescorrectly reflects its immutable use.
224-232: LGTM!Adding
constto thelock_typevariables correctly reflects that the lock objects themselves aren't reassigned after construction.include/behaviortree_cpp/utils/locked_reference.hpp (2)
37-48: Verify move assignment self-assignment safety.The move assignment operator uses
std::swapwithout a self-assignment guard. While swapping with oneself is typically safe and results in a no-op, adding an explicit check (if (this != &other)) would make the intent clearer and align with best practices seen in other files in this PR (e.g.,safe_any.hpp,blackboard.cpp).However, this may be acceptable as-is since
std::swap(x, x)is well-defined. Consider whether consistency with the rest of the codebase is more important than the minor performance cost of the check.
28-31: LGTM! Explicit nullptr checks improve clarity.The changes from implicit truthiness checks to explicit
!= nullptrcomparisons make the code more readable and align with modern C++ best practices.Also applies to: 57-60, 65-68
src/shared_library_UNIX.cpp (3)
9-9: LGTM! Defaulted constructor is appropriate.Since
_handlehas an in-class initializer (= nullptrin the header), using= defaultis the idiomatic choice and eliminates the explicit initialization in the constructor body.
13-13: Excellent const-correctness improvement.Marking locks as
constprevents accidental modifications to the lock object itself and makes the code safer. This aligns with the broader const-correctness improvements across the PR.Also applies to: 32-32, 48-48
15-15: LGTM! Explicit nullptr comparisons improve readability.The changes from implicit boolean conversion to explicit
!= nullptrand== nullptrcomparisons make the intent clearer and align with modern C++ best practices.Also applies to: 21-25, 34-34, 51-51
src/controls/manual_node.cpp (4)
76-76: LGTM! Const qualifier prevents accidental modification.Using
constfor the result variable is good practice and prevents accidental reassignment.
86-86: Verify control flow behavior with separate if statements.The code at lines 109 and 114 changed from
else ifto separateifstatements. This means ifchmatches multiple conditions (which shouldn't happen with keyboard input), multiple branches could execute. While this is likely safe since the loop breaks in each branch, the originalelse ifchain was more explicit about mutual exclusivity.The current implementation is functionally equivalent for valid keyboard input but slightly less clear about intent. Consider whether the original
else ifchain was preferable for documenting mutual exclusivity.Also applies to: 101-120
102-102: LGTM!while(true)is more idiomatic thanwhile(1).This change improves readability and is a standard modernization.
Also applies to: 169-169
149-149: Verify format specifier compatibility for size_t.Line 159 uses
%2zuforsize_t, which is correct. Line 149 castschildren_counttointfornewwin()height parameter. Ensure thatchildren_countcannot exceedINT_MAXin practice, as the cast could overflow for very large values (though this is extremely unlikely for a behavior tree).Also applies to: 159-159
include/behaviortree_cpp/utils/safe_any.hpp (3)
73-75: LGTM! Move constructor correctly marked noexcept.The move constructor properly initializes members and is marked noexcept, which is appropriate since moving the internal
linb::anyand copying the type index should not throw.
309-317: LGTM! Self-assignment guard protects copy assignment.The copy assignment operator includes a proper self-assignment check (
if(this != &other)), which prevents unnecessary work and potential issues.
319-324: Add self-assignment guard to move assignment operator.The move assignment operator lacks a self-assignment check. While self-move is rare and often considered undefined behavior, adding a guard (
if(this != &other)) would:
- Make the code consistent with the copy assignment operator
- Prevent potential issues with self-move scenarios
- Align with best practices seen in
SimpleString(lines 50-58 in relevant_code_snippets)🔎 Proposed fix
inline Any& Any::operator=(Any&& other) noexcept { + if(this != &other) + { this->_any = std::move(other._any); this->_original_type = other._original_type; + } return *this; }Likely an incorrect or invalid review comment.
src/xml_parsing.cpp (8)
89-94: LGTM! Anonymous namespace appropriately scopes helper.Moving the
StrEquallambda into an anonymous namespace is good practice and prevents potential naming conflicts.
121-121: Question: Why change factory from reference to pointer?The factory member was changed from a reference to a pointer initialized to
nullptr. This introduces the possibility of null dereference and requires checking throughout. References are preferred when an object must always be valid.Was this change necessary to support some use case, or could the reference have been retained?
Also applies to: 129-129
151-152: LGTM! Move constructor properly marked noexcept.The move constructor for
XMLParsercorrectly specifiesnoexcept, which is appropriate when moving aunique_ptr.
165-165: Excellent use of std::make_unique.Replacing raw
newwithstd::make_uniqueis safer and exception-safe. This is a best practice modernization.Also applies to: 177-177, 314-314
244-246: LGTM! Proper use of std::ignore for unused variables.Using
std::ignoreto explicitly mark unused structured binding elements or variables is good practice and silences compiler warnings appropriately.Also applies to: 370-371, 378-379, 777-777
882-882: LGTM! Pointer-based dynamic_cast is safer.Using
dynamic_castto pointers instead of references is safer because it returnsnullptron failure rather than throwing an exception. This aligns with the explicit nullptr checking pattern throughout the PR.Also applies to: 886-886, 1127-1127, 1171-1171, 1178-1178
1204-1204: LGTM!contains()is more expressive thancount().Using
contains()(C++20) instead ofcount() == 0is more idiomatic and clearly expresses intent.
1062-1063: LGTM! Anonymous namespace appropriately scopes internal helpers.Moving helper functions into anonymous namespaces prevents external linkage and is good practice for internal implementation details.
Also applies to: 1215-1215
src/blackboard.cpp (5)
9-15: LGTM! Anonymous namespace appropriately scopes helper.Moving
IsPrivateKeyinto an anonymous namespace is good practice and prevents naming conflicts.
47-47: LGTM! NOLINTNEXTLINE comments document necessary const_cast.The
const_castoperations are appropriately documented with NOLINTNEXTLINE comments, making it clear these are intentional design decisions required by the API design.Also applies to: 326-326
61-61: Excellent const-correctness for read-only locks.Marking locks as
constin read-only critical sections is a great practice that prevents accidental modification of the lock object itself.Also applies to: 139-139, 224-224
310-321: LGTM! Self-assignment guard is essential.The self-assignment check in
Entry::operator=prevents issues when assigning an object to itself and aligns with best practices.
174-177: LGTM! Clear intent with renamed variable and std::ignore.Renaming the loop variable from
_toentryand usingstd::ignoremakes the code more readable and explicitly documents that the entry value is unused in this loop..clang-tidy (3)
1-24: Well-balanced clang-tidy configuration.The configuration enables comprehensive static analysis while pragmatically disabling checks that would generate excessive noise:
-bugprone-easily-swappable-parameters: Reduces false positives for parameter ordering-cppcoreguidelines-avoid-magic-numbers: Avoids requiring named constants everywhere-misc-no-recursion: Allows recursion where appropriate (e.g., tree traversal)This strikes a good balance between code quality enforcement and practical development.
27-27: Pragmatic exclusion of cognitive complexity from errors.Excluding
readability-function-cognitive-complexityfromWarningsAsErrorsis sensible, as complexity is often a judgment call and shouldn't block compilation. The configuration still reports complexity warnings, just doesn't escalate them to errors.
29-42: Well-documented CheckOptions with clear rationale.Each check option includes a comment explaining why it's configured, which is excellent documentation:
- IgnoreMacros for RCLCPP LOG macros
- MISRA:2023 compliance note
- ROS API callback rationale for shared_ptr
This makes the configuration maintainable and understandable.
run_clang_tidy.sh (4)
1-1: LGTM! Strict bash flags improve script safety.Using
#!/bin/bash -euensures the script exits on errors and treats unset variables as errors, which prevents silent failures.
7-19: Excellent user experience for missing dependencies.The script provides clear, actionable error messages with specific installation instructions when
clangd-21is missing. This significantly improves developer experience.
35-44: Maintainable skip list implementation.The skip list approach makes it easy to add/remove paths to exclude, and the conversion to find arguments is clean.
62-72: Efficient parallel execution with good error handling.Using
xargs -P $(nproc)for parallel execution andset -o pipefailin the subprocess ensures efficient processing and proper error propagation. The per-file output prefixing is also helpful for debugging.src/decorators/delay_node.cpp (2)
8-16: LGTM on constructor initialization.Initializing
timer_id_to 0 in both constructors ensures deterministic state. The distinction between the two constructors (one with explicit milliseconds, one with config for port-based reading) is preserved correctly.
52-71: LGTM on tick() control flow.The const lock and the restructured control flow correctly handle delay completion, child execution, and state reset. The
emitWakeUpSignal()in the timer callback ensures the tree wakes up promptly when delay completes.include/behaviortree_cpp/utils/simple_string.hpp (3)
21-25: LGTM on default constructor.Properly initializes SOO storage with capacity and null-terminator, creating a valid empty string state.
133-153: LGTM on comparison operators.The lexicographic comparison using
memcmpwith size-based tie-breaking is correct and follows standard string comparison semantics. Usingconstfor local variables aligns with clang-tidy guidelines.
176-181: Union default initialization may cause issues with non-trivial members.The union contains a
Stringstruct with default member initializers (data = nullptr,size = 0). In C++, a union with non-trivial members requires explicit constructor handling. The= {}initialization for_storagemay not behave as expected across all compilers.Consider verifying this compiles and behaves correctly on all target platforms.
src/tree_node.cpp (3)
57-66: LGTM on move constructor and defaulted destructor.Using the member initializer list for the move constructor and defaulting the destructor is cleaner and follows modern C++ idioms.
309-328: LGTM on callback setters with move semantics.The
NOLINTcomments correctly suppress theperformance-unnecessary-value-paramwarning since the callbacks are intentionally taken by value and moved into storage. The const locks ensure thread-safe assignment.
388-392: Good fix: null-check before dereferencing.Adding
stripped_pointer != nullptrbefore dereferencing prevents undefined behavior when the caller passes a null output parameter.src/behavior_tree.cpp (2)
21-24: LGTM on explicit nullptr comparisons.Replacing
!nodewithnode == nullptrimproves clarity and satisfies clang-tidy's readability checks.Also applies to: 43-46, 75-79
101-102: LGTM on const-correctness forbuildSerializedStatusSnapshot.Taking
const TreeNode*is appropriate since the function only reads node status without modification.src/bt_factory.cpp (6)
105-105: LGTM on defaulted destructor.Defaulting the destructor is appropriate for a class using the PImpl idiom with
std::unique_ptr.
140-158: LGTM on const qualifiers for local variables.Adding
consttobuilderandmanifestvariables is good practice and aligns with clang-tidy recommendations.
179-184: LGTM on plugin symbol loading.The
usingalias for the function pointer type is cleaner than a typedef. TheNOLINTcomment appropriately suppresses the reinterpret_cast warning which is unavoidable for dynamic library symbol loading.
251-280: LGTM on substitution rule handling.Using
const auto* constfor thestd::get_ifresults is correct and explicit. TheNOLINTforreadability-else-after-returnat line 266 is appropriate since the else-if chain improves readability here.
420-420: LGTM onstd::movefor substitution rule.Moving the rule avoids unnecessary copies of potentially complex
SubstitutionRulevariants.
477-477: LGTM on Tree cleanup changes.Defaulting
Tree()constructor, addingNOLINTfor non-const member functions, and using!subtrees.empty()instead of size comparison are all good improvements.Also applies to: 491-494, 552-552
run_clang_tidy.sh
Outdated
| find $clang_tidy_paths \( -name '*.cpp' -o -name '*.hpp' \) -not -name '*_WIN.cpp' "${skip_paths[@]}" -print0 \ | ||
| | xargs -0 -n 1 -P $(nproc) bash -c ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quote $clang_tidy_paths to prevent word splitting.
Shellcheck reports SC2046 because $clang_tidy_paths is unquoted in the find command. If any path contains spaces, this will cause word splitting and unexpected behavior.
🔎 Proposed fix
-find $clang_tidy_paths \( -name '*.cpp' -o -name '*.hpp' \) -not -name '*_WIN.cpp' "${skip_paths[@]}" -print0 \
+find "$ws_dir/src" "$ws_dir/include" \( -name '*.cpp' -o -name '*.hpp' \) -not -name '*_WIN.cpp' "${skip_paths[@]}" -print0 \Alternatively, if you want to keep the variable:
-clang_tidy_paths="$ws_dir/src $ws_dir/include"
+clang_tidy_paths=("$ws_dir/src" "$ws_dir/include")
...
-find $clang_tidy_paths \( -name '*.cpp' -o -name '*.hpp' \) -not -name '*_WIN.cpp' "${skip_paths[@]}" -print0 \
+find "${clang_tidy_paths[@]}" \( -name '*.cpp' -o -name '*.hpp' \) -not -name '*_WIN.cpp' "${skip_paths[@]}" -print0 \📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| find $clang_tidy_paths \( -name '*.cpp' -o -name '*.hpp' \) -not -name '*_WIN.cpp' "${skip_paths[@]}" -print0 \ | |
| | xargs -0 -n 1 -P $(nproc) bash -c ' | |
| find "$ws_dir/src" "$ws_dir/include" \( -name '*.cpp' -o -name '*.hpp' \) -not -name '*_WIN.cpp' "${skip_paths[@]}" -print0 \ | |
| | xargs -0 -n 1 -P $(nproc) bash -c ' |
🧰 Tools
🪛 Shellcheck (0.11.0)
[warning] 62-62: Quote this to prevent word splitting.
(SC2046)
🤖 Prompt for AI Agents
In run_clang_tidy.sh around lines 61-62, the find command uses an unquoted
$clang_tidy_paths which can undergo word-splitting and break when paths contain
spaces; update the invocation to quote the variable (use "${clang_tidy_paths}"
if it's a single string of paths, or use the array expansion
"${clang_tidy_paths[@]}" if it is an array) so that each path is treated as a
single argument and shellcheck SC2046 is resolved.
f1906d8 to
87b7bbe
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/controls/manual_node.cpp (1)
86-124: Critical bug: Uninitialized window pointer used throughout function.The window pointer
winis initialized tonullptr(line 86) but is never assigned a valid window vianewwin(). Subsequently,winis passed to multiple ncurses functions that require a validWINDOW*:
mvwprintw(win, ...)(lines 90-93)wrefresh(win)(line 95)keypad(win, TRUE)(line 97)wgetch(win)(line 119)werase(win)(line 121)wrefresh(win)(line 122)delwin(win)(line 123)Passing
nullptrto these functions will cause undefined behavior or crash. Compare withselectChild()which properly creates a window at line 149.Either create a window with
newwin()afterinitscr(), or usestdscrdirectly instead ofwin.🔎 Proposed fix: Create window or use stdscr
Option 1: Create a window (consistent with selectChild)
WINDOW* win = nullptr; initscr(); cbreak(); +win = newwin(10, 70, 1, 1); // create a new window mvwprintw(win, 0, 0, "No children.");Option 2: Use stdscr directly
-WINDOW* win = nullptr; initscr(); cbreak(); -mvwprintw(win, 0, 0, "No children."); -mvwprintw(win, 1, 0, "Press: S to return SUCCESSFUL,"); -mvwprintw(win, 2, 0, " F to return FAILURE, or"); -mvwprintw(win, 3, 0, " R to return RUNNING."); +mvwprintw(stdscr, 0, 0, "No children."); +mvwprintw(stdscr, 1, 0, "Press: S to return SUCCESSFUL,"); +mvwprintw(stdscr, 2, 0, " F to return FAILURE, or"); +mvwprintw(stdscr, 3, 0, " R to return RUNNING."); -wrefresh(win); -noecho(); -keypad(win, TRUE); -curs_set(0); +wrefresh(stdscr); +noecho(); +keypad(stdscr, TRUE); +curs_set(0); // ... in the loop: -ch = wgetch(win); +ch = wgetch(stdscr); // ... at the end: -werase(win); -wrefresh(win); -delwin(win); +werase(stdscr); +wrefresh(stdscr); endwin();
♻️ Duplicate comments (1)
src/xml_parsing.cpp (1)
1204-1204: Fix C++20-onlycontains()causing pipeline failure.The call to
temp_factory.builtinNodes().contains(registration_ID)usesstd::set::contains()which is a C++20 feature, causing compilation failures in C++17 builds as shown in the pipeline logs.🔎 Proposed fix
- if(add_builtin_models || !temp_factory.builtinNodes().contains(registration_ID)) + if(add_builtin_models || temp_factory.builtinNodes().count(registration_ID) == 0)
🧹 Nitpick comments (4)
src/controls/reactive_sequence.cpp (1)
58-58: Good modernization, but line 56 has the same C-style cast.The change to
static_cast<int>(index)improves type-safety and is consistent with modern C++ practices. However, line 56 still uses the C-style castint(index)for the same conversion. For consistency, consider updating line 56 as well.🔎 Suggested consistency fix for line 56
- running_child_ = int(index); + running_child_ = static_cast<int>(index);src/tree_node.cpp (1)
205-216: Consider: else-if made mutual exclusivity clearer.While functionally equivalent (each branch returns), using
else ifwould make it more explicit that these conditions are mutually exclusive. The current structure works correctly but is slightly less clear in intent.Optional refactoring for clarity
if(preID == PreCond::FAILURE_IF) { return NodeStatus::FAILURE; } -if(preID == PreCond::SUCCESS_IF) +else if(preID == PreCond::SUCCESS_IF) { return NodeStatus::SUCCESS; } -if(preID == PreCond::SKIP_IF) +else if(preID == PreCond::SKIP_IF) { return NodeStatus::SKIPPED; }src/loggers/groot2_publisher.cpp (2)
118-118: Consider consistency with codebase style for lock declarations.The
constqualifier onstd::unique_lockis valid when used purely for RAII scope-locking. However, looking at the relevant code snippets from other files (e.g.,src/decorators/delay_node.cpp,src/loggers/bt_sqlite_logger.cpp), they use non-const locks:lk(delay_mutex_).This is a minor stylistic inconsistency. The code is functionally correct since these locks don't call
unlock()/lock()explicitly.
489-493: Variable name shadowing: innerlkshadows outerlk.Line 493 declares a new
lkthat shadows thelkfrom line 489. While this works correctly (different scopes), it can cause confusion during maintenance. Consider renaming the inner lock (e.g.,hook_lk) for clarity.🔎 Suggested rename
const std::unique_lock<std::mutex> lk(_p->hooks_map_mutex); for(const auto& [node_uid, hook] : _p->pre_hooks) { std::ignore = node_uid; // unused in this loop - std::unique_lock<std::mutex> lk(hook->mutex); + std::unique_lock<std::mutex> hook_lk(hook->mutex); hook->enabled = enable; // when disabling, remember to wake up blocked ones if(!hook->enabled && hook->mode == Monitor::Hook::Mode::BREAKPOINT) { - lk.unlock(); + hook_lk.unlock(); hook->wakeup.notify_all(); } }
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (97)
.clang-tidy.gitignore.pre-commit-config.yamlinclude/behaviortree_cpp/action_node.hinclude/behaviortree_cpp/actions/always_failure_node.hinclude/behaviortree_cpp/actions/always_success_node.hinclude/behaviortree_cpp/actions/pop_from_queue.hppinclude/behaviortree_cpp/actions/script_condition.hinclude/behaviortree_cpp/actions/script_node.hinclude/behaviortree_cpp/actions/set_blackboard_node.hinclude/behaviortree_cpp/actions/sleep_node.hinclude/behaviortree_cpp/actions/test_node.hinclude/behaviortree_cpp/actions/unset_blackboard_node.hinclude/behaviortree_cpp/actions/updated_action.hinclude/behaviortree_cpp/behavior_tree.hinclude/behaviortree_cpp/bt_factory.hinclude/behaviortree_cpp/bt_parser.hinclude/behaviortree_cpp/condition_node.hinclude/behaviortree_cpp/control_node.hinclude/behaviortree_cpp/controls/fallback_node.hinclude/behaviortree_cpp/controls/if_then_else_node.hinclude/behaviortree_cpp/controls/manual_node.hinclude/behaviortree_cpp/controls/parallel_all_node.hinclude/behaviortree_cpp/controls/parallel_node.hinclude/behaviortree_cpp/controls/reactive_fallback.hinclude/behaviortree_cpp/controls/reactive_sequence.hinclude/behaviortree_cpp/controls/sequence_node.hinclude/behaviortree_cpp/controls/sequence_with_memory_node.hinclude/behaviortree_cpp/controls/switch_node.hinclude/behaviortree_cpp/controls/while_do_else_node.hinclude/behaviortree_cpp/decorators/consume_queue.hinclude/behaviortree_cpp/decorators/delay_node.hinclude/behaviortree_cpp/decorators/force_failure_node.hinclude/behaviortree_cpp/decorators/force_success_node.hinclude/behaviortree_cpp/decorators/inverter_node.hinclude/behaviortree_cpp/decorators/keep_running_until_failure_node.hinclude/behaviortree_cpp/decorators/loop_node.hinclude/behaviortree_cpp/decorators/repeat_node.hinclude/behaviortree_cpp/decorators/retry_node.hinclude/behaviortree_cpp/decorators/run_once_node.hinclude/behaviortree_cpp/decorators/script_precondition.hinclude/behaviortree_cpp/decorators/timeout_node.hinclude/behaviortree_cpp/decorators/updated_decorator.hinclude/behaviortree_cpp/exceptions.hinclude/behaviortree_cpp/leaf_node.hinclude/behaviortree_cpp/scripting/any_types.hppinclude/behaviortree_cpp/scripting/operators.hppinclude/behaviortree_cpp/scripting/script_parser.hppinclude/behaviortree_cpp/tree_node.hinclude/behaviortree_cpp/utils/convert_impl.hppinclude/behaviortree_cpp/utils/locked_reference.hppinclude/behaviortree_cpp/utils/safe_any.hppinclude/behaviortree_cpp/utils/simple_string.hppinclude/behaviortree_cpp/utils/wildcards.hpprun_clang_tidy.shsrc/action_node.cppsrc/actions/sleep_node.cppsrc/actions/updated_action.cppsrc/basic_types.cppsrc/behavior_tree.cppsrc/blackboard.cppsrc/bt_factory.cppsrc/condition_node.cppsrc/control_node.cppsrc/controls/fallback_node.cppsrc/controls/if_then_else_node.cppsrc/controls/manual_node.cppsrc/controls/parallel_all_node.cppsrc/controls/parallel_node.cppsrc/controls/reactive_fallback.cppsrc/controls/reactive_sequence.cppsrc/controls/sequence_node.cppsrc/controls/sequence_with_memory_node.cppsrc/controls/switch_node.cppsrc/controls/while_do_else_node.cppsrc/decorator_node.cppsrc/decorators/delay_node.cppsrc/decorators/inverter_node.cppsrc/decorators/repeat_node.cppsrc/decorators/retry_node.cppsrc/decorators/subtree_node.cppsrc/decorators/timeout_node.cppsrc/decorators/updated_decorator.cppsrc/example.cppsrc/json_export.cppsrc/loggers/bt_cout_logger.cppsrc/loggers/bt_file_logger_v2.cppsrc/loggers/bt_minitrace_logger.cppsrc/loggers/bt_sqlite_logger.cppsrc/loggers/groot2_publisher.cppsrc/script_parser.cppsrc/shared_library.cppsrc/shared_library_UNIX.cppsrc/tree_node.cppsrc/xml_parsing.cpptests/CMakeLists.txttests/gtest_simple_string.cpp
💤 Files with no reviewable changes (1)
- src/example.cpp
✅ Files skipped from review due to trivial changes (47)
- include/behaviortree_cpp/bt_parser.h
- include/behaviortree_cpp/controls/reactive_sequence.h
- include/behaviortree_cpp/decorators/delay_node.h
- src/controls/parallel_node.cpp
- include/behaviortree_cpp/behavior_tree.h
- include/behaviortree_cpp/decorators/repeat_node.h
- include/behaviortree_cpp/actions/test_node.h
- include/behaviortree_cpp/controls/while_do_else_node.h
- include/behaviortree_cpp/controls/fallback_node.h
- include/behaviortree_cpp/controls/sequence_with_memory_node.h
- include/behaviortree_cpp/decorators/loop_node.h
- include/behaviortree_cpp/controls/parallel_node.h
- include/behaviortree_cpp/decorators/updated_decorator.h
- include/behaviortree_cpp/decorators/force_failure_node.h
- include/behaviortree_cpp/actions/unset_blackboard_node.h
- include/behaviortree_cpp/decorators/script_precondition.h
- include/behaviortree_cpp/actions/script_condition.h
- include/behaviortree_cpp/condition_node.h
- include/behaviortree_cpp/controls/manual_node.h
- src/controls/sequence_with_memory_node.cpp
- include/behaviortree_cpp/actions/updated_action.h
- include/behaviortree_cpp/controls/if_then_else_node.h
- include/behaviortree_cpp/action_node.h
- include/behaviortree_cpp/decorators/timeout_node.h
- include/behaviortree_cpp/tree_node.h
- include/behaviortree_cpp/actions/script_node.h
- include/behaviortree_cpp/decorators/run_once_node.h
- include/behaviortree_cpp/decorators/force_success_node.h
- include/behaviortree_cpp/actions/set_blackboard_node.h
- include/behaviortree_cpp/bt_factory.h
- include/behaviortree_cpp/scripting/any_types.hpp
- include/behaviortree_cpp/scripting/script_parser.hpp
- include/behaviortree_cpp/scripting/operators.hpp
- include/behaviortree_cpp/decorators/retry_node.h
- include/behaviortree_cpp/controls/switch_node.h
- include/behaviortree_cpp/actions/always_success_node.h
- tests/gtest_simple_string.cpp
- include/behaviortree_cpp/actions/always_failure_node.h
- include/behaviortree_cpp/controls/parallel_all_node.h
- include/behaviortree_cpp/control_node.h
- src/decorators/inverter_node.cpp
- include/behaviortree_cpp/controls/reactive_fallback.h
- include/behaviortree_cpp/decorators/consume_queue.h
- include/behaviortree_cpp/leaf_node.h
- src/condition_node.cpp
- src/controls/if_then_else_node.cpp
- include/behaviortree_cpp/exceptions.h
🚧 Files skipped from review as they are similar to previous changes (20)
- src/json_export.cpp
- src/shared_library_UNIX.cpp
- src/control_node.cpp
- src/controls/fallback_node.cpp
- src/loggers/bt_sqlite_logger.cpp
- src/actions/sleep_node.cpp
- src/decorator_node.cpp
- src/decorators/repeat_node.cpp
- include/behaviortree_cpp/utils/safe_any.hpp
- .clang-tidy
- src/controls/switch_node.cpp
- src/loggers/bt_minitrace_logger.cpp
- run_clang_tidy.sh
- src/controls/while_do_else_node.cpp
- src/controls/parallel_all_node.cpp
- src/decorators/updated_decorator.cpp
- .gitignore
- include/behaviortree_cpp/utils/simple_string.hpp
- src/decorators/subtree_node.cpp
- src/controls/reactive_fallback.cpp
🧰 Additional context used
🧬 Code graph analysis (11)
src/actions/updated_action.cpp (5)
src/actions/sleep_node.cpp (1)
lk(28-28)src/decorators/delay_node.cpp (2)
lk(43-43)lk(52-52)src/decorators/timeout_node.cpp (2)
lk(44-44)lk(55-55)src/loggers/bt_sqlite_logger.cpp (2)
lk(189-189)lk(208-208)src/loggers/groot2_publisher.cpp (2)
lk(118-118)lk(198-198)
src/loggers/bt_cout_logger.cpp (1)
include/behaviortree_cpp/loggers/bt_cout_logger.h (1)
StdCoutLogger(14-25)
src/shared_library.cpp (1)
include/behaviortree_cpp/exceptions.h (1)
RuntimeError(58-67)
src/loggers/groot2_publisher.cpp (5)
src/actions/sleep_node.cpp (1)
lk(28-28)src/decorators/delay_node.cpp (2)
lk(43-43)lk(52-52)src/decorators/timeout_node.cpp (2)
lk(44-44)lk(55-55)src/loggers/bt_sqlite_logger.cpp (2)
lk(189-189)lk(208-208)src/tree_node.cpp (2)
status(276-280)status(276-276)
src/script_parser.cpp (2)
include/behaviortree_cpp/scripting/any_types.hpp (1)
result(33-41)tests/gtest_preconditions.cpp (1)
i(290-298)
src/tree_node.cpp (1)
include/behaviortree_cpp/tree_node.h (1)
TreeNode(131-295)
src/controls/sequence_node.cpp (1)
src/tree_node.cpp (2)
setRegistrationID(433-436)setRegistrationID(433-433)
src/loggers/bt_file_logger_v2.cpp (2)
src/tree_node.cpp (2)
status(276-280)status(276-276)src/shared_library_UNIX.cpp (3)
lock(13-13)lock(32-32)lock(48-48)
src/decorators/delay_node.cpp (1)
include/behaviortree_cpp/decorators/delay_node.h (1)
DelayNode(34-66)
src/action_node.cpp (2)
include/behaviortree_cpp/action_node.h (1)
CoroActionNode(196-229)3rdparty/minicoro/minicoro.h (2)
mco_create(1684-1711)mco_destroy(1713-1729)
src/decorators/timeout_node.cpp (3)
src/decorator_node.cpp (6)
child(38-41)child(38-38)child(43-46)child(43-43)resetChild(53-64)resetChild(53-53)include/behaviortree_cpp/basic_types.h (1)
isStatusCompleted(47-50)src/decorators/delay_node.cpp (2)
lk(43-43)lk(52-52)
🪛 GitHub Actions: cmake Ubuntu
src/xml_parsing.cpp
[error] 1204-1204: error: 'const class std::set<std::__cxx11::basic_string >' has no member named 'contains' (use 'count' or 'find' instead)
🪛 GitHub Actions: cmake Ubuntu Sanitizers
src/xml_parsing.cpp
[error] 1204-1204: Compilation error: 'std::set<...>::contains' is not a member in this C++ version; use find() or count() instead. Code references 'temp_factory.builtinNodes().contains(registration_ID)'.
[error] Compilation halted due to previous error in xml_parsing.cpp during 'cmake --build --preset conan-debug'.
🔇 Additional comments (87)
src/loggers/bt_cout_logger.cpp (2)
8-8: LGTM! Good modernization.Defaulting the destructor is the correct approach when no custom cleanup is needed, aligning with modern C++ best practices.
18-18: LGTM! Good const-correctness improvement.The variable is correctly qualified as
constsince it's never modified after initialization.include/behaviortree_cpp/actions/sleep_node.h (1)
38-38: LGTM! Good initialization practice.Initializing
timer_id_to 0 at declaration prevents undefined behavior and aligns with modern C++ best practices. This change is consistent with the existing initialization oftimer_waiting_and is likely a clang-tidy fix for uninitialized member variables.include/behaviortree_cpp/controls/sequence_node.h (1)
1-12: LGTM!The copyright year update and license text corrections are appropriate maintenance changes with no functional impact.
src/shared_library.cpp (1)
12-15: LGTM! Improved readability with explicit nullptr check and braces.The explicit nullptr comparison and added braces align with modern C++ best practices and improve code clarity. The control flow remains functionally identical, and the change is consistent with the explicit nullptr check already present in
hasSymbolat Line 21.src/controls/sequence_node.cpp (1)
22-29: LGTM! Good style improvement.Adding explicit braces around both branches improves consistency and prevents potential issues if additional statements are added later. This aligns with clang-tidy best practices.
src/script_parser.cpp (3)
26-26: LGTM: const-correctness improvements.The
constqualifier is correctly applied since theexprsvector is never modified after initialization. InParseScript, the lambda captures by value, so the const on the original doesn't affect the captured copy.Also applies to: 78-78
35-35: LGTM: Style consistency for unsigned literal.Using uppercase
0Uis the more conventional form and aligns with common style guidelines.
52-52: LGTM: Simplified control flow by removing redundant else blocks.Removing explicit
elseafter early returns reduces nesting and improves readability. This follows the clang-tidyreadability-else-after-returnrecommendation.Also applies to: 62-63
src/loggers/bt_file_logger_v2.cpp (6)
8-14: LGTM!Good use of anonymous namespace to give
ToUsecinternal linkage. This prevents potential ODR violations and allows better compiler optimization.
57-59: LGTM!Good modernization:
std::array<char, 8>with value initialization provides type safety and guarantees zero-initialization, eliminating potential UB from uninitialized memory.
62-62: LGTM!Explicit
std::streamsizecast is correct forostream::writeand silences sign-conversion warnings from clang-tidy.
67-69: LGTM!Correct 8-byte buffer usage for writing the 64-bit timestamp.
85-91: LGTM!Value initialization of
Transition trans{}ensures all members are properly initialized. Theconst std::scoped_lockis correct since the lock object itself isn't modified after construction.
119-126: LGTM!Good modernization to
std::array<char, 9>with value initialization. The buffer size correctly matches the 9-byte record format (6 + 2 + 1 bytes).Note: The partial
memcpyof larger integer types (e.g., 6 bytes fromuint64_t) assumes little-endian byte order—this is pre-existing behavior, not introduced by this change.src/decorators/retry_node.cpp (3)
2-2: LGTM: Copyright year updated.The copyright year update to 2025 is appropriate and routine maintenance.
55-56: LGTM: Excellent const-correctness improvement.Adding
consttoprev_statusandchild_statusis good practice since these variables are never modified after initialization. This improves code clarity and prevents accidental modification.
44-46: Verify NUM_ATTEMPTS is properly defined in the header.The AI summary indicates that
NUM_ATTEMPTSstatic member declaration was removed from this class. The code still usesNUM_ATTEMPTSat lines 44, 46, and 69. Ensure thatNUM_ATTEMPTSis properly defined as an inline constexpr in the header file (src/main/include/behaviortree_cpp/decorators/retry_node.h) to maintain accessibility and prevent compilation errors.src/blackboard.cpp (7)
2-2: LGTM! Good modernization practices.The
<tuple>include is correctly added forstd::ignoreusage at line 176, and movingIsPrivateKeyinto an anonymous namespace properly limits its linkage to this translation unit, preventing potential ODR violations.Also applies to: 9-15
47-48: LGTM! Appropriate suppression.The NOLINTNEXTLINE suppression is justified here. The const_cast is safe and necessary for the implementation pattern where the non-const overload delegates to the const version.
61-61: Verify const qualification on lock objects.Making
std::unique_lockobjects const is unusual. While technically correct (the destructor can still unlock a const lock object), standard practice typically leaves lock objects non-const. This appears to be a clang-tidy suggestion for const-correctness, but the practical benefit is minimal since these locks are never reassigned.If this is a project-wide convention from clang-tidy, it's acceptable. Otherwise, consider whether this deviates from typical C++ mutex usage patterns for marginal gain.
Also applies to: 139-139, 224-224
174-176: LGTM! Better unused variable handling.Using
std::ignore = entry;with an explicit comment is clearer and more standard than using_as the variable name. This properly suppresses unused variable warnings in a portable way.
281-281: LGTM! Good const-correctness.Making
nameconst is a simple improvement that clearly indicates the variable won't be modified after initialization.
312-320: LGTM! Essential best practice.The self-assignment guard is a recommended best practice for assignment operators. While the members likely handle self-assignment safely, this guard:
- Prevents unnecessary work when
x = x- Provides defensive programming against edge cases
- Improves performance by short-circuiting the copy
326-327: LGTM! Appropriate suppression.Similar to line 47, this NOLINTNEXTLINE suppression is justified. The const_cast is safe and necessary for the implementation pattern where the non-const overload delegates to the const version.
src/controls/manual_node.cpp (3)
76-76: LGTM: Const-correctness improvement.The addition of
constis appropriate since the variable is assigned once and never modified.
145-149: LGTM: Proper initialization and type-safe conversions.The changes demonstrate good practices:
- Line 145-149: Pointer initialized to
nullptrthen properly assigned vianewwin()- Lines 149, 159: Explicit
static_cast<int>()conversions make type conversions clear and safe- Line 159: Format specifier
%2zuis correct forsize_ttype- Line 169:
while(true)is more idiomatic C++ thanwhile(1)Also applies to: 159-159, 169-169
101-102: LGTM: Proper initialization.Initializing
retto a default value (RUNNING) before the loop is good defensive programming. Thewhile(true)construct is also more idiomatic thanwhile(1).include/behaviortree_cpp/decorators/keep_running_until_failure_node.h (1)
1-1: LGTM!Copyright year update is appropriate.
include/behaviortree_cpp/decorators/inverter_node.h (1)
2-2: LGTM!Copyright year update is appropriate.
.pre-commit-config.yaml (1)
46-54: Commented-out clang-tidy hook provides useful documentation.The commented configuration serves as a reference for contributors who want to enable clang-tidy locally. This is reasonable given that clang-tidy requires a
compile_commands.jsonin the build directory, which may not always be present.Consider adding a brief comment explaining why it's commented out (e.g., "requires a build directory with compile_commands.json") to help future contributors.
include/behaviortree_cpp/utils/wildcards.hpp (2)
3-7: LGTM!Adding explicit includes for the types used (
size_t,int8_t,std::string_view,std::vector) improves portability and aligns with best practices for header self-containment.
43-43: Good fix for uninitialized variable warning.Explicitly initializing
resulttofalseeliminates the clang-tidy warning about potentially uninitialized variables, even though all code paths ultimately assign a value.src/actions/updated_action.cpp (2)
1-1: LGTM!Copyright year update is appropriate.
43-43: Good const-correctness improvement.Adding
constto the lock is appropriate since the lock object itself isn't modified after construction. This aligns with clang-tidy's const-correctness recommendations.include/behaviortree_cpp/actions/pop_from_queue.hpp (3)
1-1: LGTM!Copyright year update is appropriate.
74-79: LGTM!The restructured control flow is cleaner and functionally equivalent. Early return on empty queue, then the happy path proceeds linearly.
118-125: Verify the behavioral change for empty queues.The previous implementation likely returned FAILURE for empty queues. The new structure maintains this behavior, but consider whether an empty queue should return SUCCESS with size=0 instead of FAILURE.
If returning FAILURE for empty queues is intentional (e.g., to signal "nothing to process"), the current behavior is correct.
include/behaviortree_cpp/utils/convert_impl.hpp (2)
1-1: LGTM!Copyright year update is appropriate.
157-171: Verify the asymmetric handling of float→bool vs int→bool conversions.The new logic treats these conversions differently:
- Float→bool (lines 161-165): Any non-zero value becomes
true(C-style semantics).- Int→bool (lines 167-170): Only
0or1are valid; other values throw viacheckLowerLimit.This means
convertNumber(2.0f, boolVal)succeeds (→true), butconvertNumber(2, boolVal)throws. If this asymmetry is intentional (e.g., stricter integer validation), the implementation is correct. Otherwise, consider applying consistent rules to both numeric types.include/behaviortree_cpp/utils/locked_reference.hpp (4)
28-31: LGTM!Using explicit
mutex_ != nullptrinstead of implicit boolean conversion is clearer and satisfies clang-tidy's explicit comparison checks.
37-41: LGTM!Adding
noexceptto the move constructor is correct sincestd::swapon pointers is noexcept. This enables better optimization and is a best practice for move operations.
43-48: LGTM!Adding
noexceptto the move assignment operator is appropriate. The swap-based implementation only operates on pointers, which cannot throw.
55-69: LGTM!Consistent use of explicit
mutex_ != nullptrchecks inlock()andunlock()methods.src/action_node.cpp (3)
75-81: LGTM: Good use of anonymous namespace for internal linkage.Wrapping
CoroEntryin an anonymous namespace provides internal linkage, preventing potential symbol collisions across translation units.
89-96: LGTM: Exception-safe destructor implementation.The try/catch block prevents exceptions from escaping the destructor, which would cause program termination. Logging to
std::cerris appropriate for destructor failures.
148-156: LGTM: Explicit nullptr check improves safety.The explicit check
_p->coro != nullptrbefore callingmco_destroyprevents potential issues and makes the code more defensive.src/xml_parsing.cpp (2)
89-94: LGTM: Anonymous namespace for internal helper.Using an anonymous namespace for the
StrEquallambda provides internal linkage and prevents naming conflicts.
121-129: LGTM: Factory pointer conversion improves const-correctness.Converting the factory from a reference to a
const BehaviorTreeFactory*with pointer-based access throughout the class is a good refactor that maintains immutability guarantees.src/bt_factory.cpp (3)
109-109: LGTM: C++17-compatible implementation.Using
count() != 0instead ofcontains()ensures C++17 compatibility, unlike the issue in xml_parsing.cpp line 1204.
140-146: LGTM: Const-correctness for builder and manifest.Marking both
builderandmanifestas const prevents accidental modifications and aligns with best practices for lambda captures and registration flow.
420-420: LGTM: Efficient use of move semantics.Using
std::move(rule)avoids unnecessary copies when inserting into the substitution rules map.tests/CMakeLists.txt (1)
32-32: LGTM: Test coverage for SimpleString.Adding
gtest_simple_string.cppto the test suite provides coverage for the SimpleString utility class.src/basic_types.cpp (4)
50-72: Switch statement improves maintainability.Replacing nested if-else with an explicit switch statement makes the colored status logic more readable and maintainable.
Note: The color comments on lines 55 and 59 are swapped (already flagged in previous review).
143-156: LGTM: Anonymous namespace for internal helper.Placing the
ConvertWithBoundChecktemplate in an anonymous namespace provides proper internal linkage for this implementation detail.
200-206: LGTM: Thread-safe locale handling with const-correctness.The const qualifiers on
old_locale,str_copy, andvalimprove const-correctness. Proper locale save/restore ensures thread-safe string-to-double conversion.
447-447: LGTM: Cast prevents undefined behavior.Casting to
unsigned charbefore callingstd::isalphaprevents sign-extension issues whencharis signed, which would cause undefined behavior for values outside [0, 127].src/tree_node.cpp (6)
57-58: LGTM: Move constructor modernized.Using the member initializer list for the move constructor is better practice than body initialization.
66-66: LGTM: Defaulted destructor is appropriate.Since
_pis aunique_ptr, defaulting the destructor is correct and allows the compiler to generate optimal cleanup code.
160-160: LGTM: Explicit initialization of prev_status.Explicitly initializing
prev_statustoNodeStatus::IDLEis good defensive programming and prevents potential undefined behavior.Also applies to: 261-261
197-197: LGTM: static_cast is safer than C-style cast.Using
static_castis more explicit and type-safe than C-style casting.
309-328: LGTM: Pass-by-value + move pattern is correct.The
NOLINTNEXTLINEsuppressions are justified. The pass-by-value followed bystd::movepattern is actually the recommended approach for move-enabled types likestd::function, as it efficiently handles both lvalue and rvalue arguments without requiring two overloads. The locking ensures thread-safe callback updates.
388-391: LGTM: Explicit nullptr check improves clarity.The explicit
!= nullptrcomparison is clearer and more self-documenting than implicit pointer-to-bool conversion.src/behavior_tree.cpp (6)
21-21: Explicit nullptr comparison improves readability.The change from
!nodetonode == nullptrfollows modern C++ best practices and clang-tidy recommendations.
43-43: Explicit nullptr comparison improves readability.The change from
!nodetonode == nullptrfollows modern C++ best practices and clang-tidy recommendations.
59-62: Defensive null-check added for decorator child.The added guard prevents recursing into a null decorator child. However, this creates a behavioral difference from the const overload at line 37, which lacks this check. See the comment on lines 35-38 for details.
75-75: Explicit nullptr comparison improves readability.The change from
!nodetonode == nullptrfollows modern C++ best practices and clang-tidy recommendations.
101-102: Const-correctness improvement for read-only function parameter.Adding
constto theTreeNode*parameter is appropriate. This change is source-compatible in C++ (callers can pass non-const pointers to const parameters), so it's not a breaking API change. Please verify that the function implementation only performs read operations on the parameter and that all call sites remain unaffected.
35-38: Unable to verify the specific inconsistency without access to the actual code at lines 35-38 and 59-62 of src/behavior_tree.cpp. The repository could not be cloned, and web searches confirm that both const and non-const overloads ofapplyRecursiveVisitorexist, and that DecoratorNode'schild()method can return nullptr (per the library's recommended defensive null-checking pattern). However, the exact code structure and presence or absence of null guards in each overload cannot be confirmed.Manual code inspection is required to verify whether the non-const overload at lines 59-62 actually contains a null guard for
decorator->child()while the const overload at lines 35-38 lacks it, or whether both overloads have consistent handling.src/loggers/groot2_publisher.cpp (12)
4-4: LGTM!The
<tuple>include is correctly added to supportstd::ignoreusage throughout the file.
33-57: LGTM!Good improvements:
- Anonymous namespace provides internal linkage for this helper function
std::random_deviceseeding improves randomness quality over a fixed seed- Value initialization
out{}ensures zero-initialization- Explicit
static_cast<char>for 0xBF and 0x80 is correct since these values exceed the signed char range (127), avoiding implementation-defined behavior
66-72: LGTM!Adding
constto these configuration variables improves code safety and intent clarity.
103-103: LGTM!Value initialization
{}is a safer default for duration types.
212-212: LGTM!The explicit cast chain clarifies the intent: enum to int for arithmetic, then to char for storage.
218-218: LGTM!Value initialization
{}zeroes the entire struct including padding bytes, which is important for consistent serialization behavior.
364-367: LGTM!Good const-correctness on these parsed values that are only read, not modified.
419-423: LGTM!Using
std::ignoreto explicitly mark unused structured binding variables is a clean way to suppress compiler warnings while documenting intent.
513-513: LGTM!Adding
constclarifies this is a snapshot value used for comparison.
554-554: LGTM!Making the
TreeNode::Ptr(shared_ptr) const prevents reassignment while still allowing operations on the pointed-to node.
684-692: LGTM!Using
auto*explicitly shows pointer intent, andstd::ignoreproperly marks the unusedhook_ptrvariable.
706-707: LGTM!Consistent with the style improvements made elsewhere in the file.
src/decorators/timeout_node.cpp (2)
44-44: LGTM onconstlock qualifier.The
conston theunique_lockcorrectly signals that this lock is never explicitly unlocked in the callback, improving code clarity.
62-71: Well-structured refactor of the completion flow.Capturing
child_statusonce and then handling the completion path is cleaner than the previous nested logic. The unlock/cancel/relock pattern correctly avoids holding the mutex during timer cancellation while ensuringresetChild()runs under the lock.src/decorators/delay_node.cpp (4)
9-9: Good: explicit initialization oftimer_id_.Initializing
timer_id_to 0 in both constructors ensures defined state before first use.Also applies to: 15-15
43-43: Consistent use ofconstlock qualifiers.Both locks are correctly marked
constsince neither is explicitly unlocked before scope exit, matching the pattern intimeout_node.cpp.Also applies to: 52-52
60-71: Clean control flow for delay completion handling.The logic correctly executes the child only after delay completes, resets state on child completion, and falls through to return
RUNNINGwhen delay is still pending.
54-58:delay_aborted_is set totruein thehalt()method.The review's conclusion appears to be incorrect. According to the BehaviorTree.CPP documentation, the
halt()implementation does setdelay_aborted_to signal that the delay operation was aborted. This flag is used to stop the timer/wait loop, allowing the node to exit the RUNNING state early. Therefore, the condition at line 54 is not dead code—it is a valid code path that executes whenhalt()is called on a running delay node.Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (2)
src/xml_parsing.cpp (1)
693-695: Variable name typo: is_blacbkboard should be is_blackboard.This typo was already flagged in a previous review. The variable name should be corrected to
is_blackboardto fix the spelling and improve readability.run_clang_tidy.sh (1)
62-63: Quote$clang_tidy_pathsto prevent word splitting.The variable
$clang_tidy_pathsis unquoted, which can cause issues if paths contain spaces. This was flagged in a previous review.🔎 Proposed fix using array
-clang_tidy_paths="$ws_dir/src $ws_dir/include" +clang_tidy_paths=("$ws_dir/src" "$ws_dir/include") ... -find $clang_tidy_paths \( -name '*.cpp' -o -name '*.hpp' -o -name '*.h' \) -not -name '*_WIN.cpp' "${skip_paths[@]}" -print0 \ +find "${clang_tidy_paths[@]}" \( -name '*.cpp' -o -name '*.hpp' -o -name '*.h' \) -not -name '*_WIN.cpp' "${skip_paths[@]}" -print0 \
🧹 Nitpick comments (5)
src/xml_parsing.cpp (1)
207-211: Consider std::array for type safety.The C-style array works correctly, but using
std::arraywould provide compile-time size checking and better type safety.🔎 Proposed refactor
- const std::pair<const char*, BT::PortDirection> port_types[3] = { + const std::array<std::pair<const char*, BT::PortDirection>, 3> port_types = {{ { "input_port", BT::PortDirection::INPUT }, { "output_port", BT::PortDirection::OUTPUT }, { "inout_port", BT::PortDirection::INOUT } - }; + }};.clang-tidy (2)
27-27: Minor: Potential redundancy in check configuration.The check
misc-non-private-member-variables-in-classesis disabled at line 27 (-misc-non-private-member-variables-in-classes), but there's also aCheckOptionsentry at lines 38-40 configuringIgnoreClassesWithAllMemberVariablesBeingPublicfor the same check. Since the check is disabled, the option has no effect.Consider either:
- Removing the disable entry if you want the check enabled with the custom option, or
- Removing the
CheckOptionsentry if the check should remain fully disabled.Also applies to: 38-40
48-48: Incomplete reference comment.Line 48 references the identifier-naming documentation but no corresponding
CheckOptionsare configured. If this is a placeholder for future configuration, consider adding a TODO comment or removing the incomplete reference.include/behaviortree_cpp/action_node.h (2)
131-153: Consider adding explicit deleted copy/move operations to ThreadedAction for consistency.
ThreadedActionis implicitly non-copyable due tostd::futureandstd::mutexmembers, but other action node classes in this file now explicitly delete these operations. Explicit deletion improves code clarity and produces better error messages.Suggested addition after the constructor
ThreadedAction(const std::string& name, const NodeConfig& config) : ActionNodeBase(name, config) {} + + ThreadedAction(const ThreadedAction&) = delete; + ThreadedAction& operator=(const ThreadedAction&) = delete; + ThreadedAction(ThreadedAction&&) = delete; + ThreadedAction& operator=(ThreadedAction&&) = delete; bool isHaltRequested() const
174-202: Consider adding explicit deleted copy/move operations to StatefulActionNode for consistency.Similar to
ThreadedAction, this class would benefit from explicit deletion to match the pattern applied to other action node classes in this file.Suggested addition after the constructor
StatefulActionNode(const std::string& name, const NodeConfig& config) : ActionNodeBase(name, config) {} + + StatefulActionNode(const StatefulActionNode&) = delete; + StatefulActionNode& operator=(const StatefulActionNode&) = delete; + StatefulActionNode(StatefulActionNode&&) = delete; + StatefulActionNode& operator=(StatefulActionNode&&) = delete; /// Method called once, when transitioning from the state IDLE.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (41)
.clang-tidy.gitignoreCMakeLists.txtinclude/behaviortree_cpp/action_node.hinclude/behaviortree_cpp/actions/sleep_node.hinclude/behaviortree_cpp/actions/updated_action.hinclude/behaviortree_cpp/blackboard.hinclude/behaviortree_cpp/condition_node.hinclude/behaviortree_cpp/control_node.hinclude/behaviortree_cpp/controls/fallback_node.hinclude/behaviortree_cpp/controls/if_then_else_node.hinclude/behaviortree_cpp/controls/manual_node.hinclude/behaviortree_cpp/controls/parallel_all_node.hinclude/behaviortree_cpp/controls/parallel_node.hinclude/behaviortree_cpp/controls/sequence_node.hinclude/behaviortree_cpp/controls/sequence_with_memory_node.hinclude/behaviortree_cpp/controls/switch_node.hinclude/behaviortree_cpp/controls/while_do_else_node.hinclude/behaviortree_cpp/decorator_node.hinclude/behaviortree_cpp/decorators/delay_node.hinclude/behaviortree_cpp/decorators/inverter_node.hinclude/behaviortree_cpp/decorators/repeat_node.hinclude/behaviortree_cpp/decorators/retry_node.hinclude/behaviortree_cpp/decorators/script_precondition.hinclude/behaviortree_cpp/decorators/subtree_node.hinclude/behaviortree_cpp/decorators/timeout_node.hinclude/behaviortree_cpp/decorators/updated_decorator.hinclude/behaviortree_cpp/json_export.hinclude/behaviortree_cpp/leaf_node.hinclude/behaviortree_cpp/loggers/bt_cout_logger.hinclude/behaviortree_cpp/loggers/bt_minitrace_logger.hinclude/behaviortree_cpp/loggers/bt_observer.hinclude/behaviortree_cpp/loggers/bt_sqlite_logger.hinclude/behaviortree_cpp/loggers/groot2_protocol.hinclude/behaviortree_cpp/utils/demangle_util.hinclude/behaviortree_cpp/utils/shared_library.hinclude/behaviortree_cpp/utils/timer_queue.hrun_clang_tidy.shsrc/blackboard.cppsrc/controls/parallel_all_node.cppsrc/xml_parsing.cpp
🚧 Files skipped from review as they are similar to previous changes (9)
- include/behaviortree_cpp/actions/updated_action.h
- .gitignore
- include/behaviortree_cpp/decorators/updated_decorator.h
- src/blackboard.cpp
- include/behaviortree_cpp/decorators/retry_node.h
- include/behaviortree_cpp/controls/manual_node.h
- include/behaviortree_cpp/decorators/timeout_node.h
- include/behaviortree_cpp/leaf_node.h
- include/behaviortree_cpp/controls/fallback_node.h
🧰 Additional context used
🧬 Code graph analysis (19)
include/behaviortree_cpp/utils/shared_library.h (3)
src/shared_library.cpp (1)
SharedLibrary(4-7)src/shared_library_UNIX.cpp (1)
SharedLibrary(9-9)src/shared_library_WIN.cpp (1)
SharedLibrary(9-12)
include/behaviortree_cpp/loggers/bt_cout_logger.h (1)
src/loggers/bt_cout_logger.cpp (2)
StdCoutLogger(6-7)StdCoutLogger(8-8)
include/behaviortree_cpp/loggers/bt_observer.h (1)
src/loggers/bt_observer.cpp (2)
TreeObserver(7-44)TreeObserver(46-47)
include/behaviortree_cpp/loggers/bt_sqlite_logger.h (1)
src/loggers/bt_sqlite_logger.cpp (2)
SqliteLogger(55-129)SqliteLogger(131-146)
include/behaviortree_cpp/action_node.h (1)
src/action_node.cpp (5)
ActionNodeBase(21-23)SyncActionNode(53-55)SimpleActionNode(27-31)CoroActionNode(83-85)CoroActionNode(87-97)
include/behaviortree_cpp/actions/sleep_node.h (1)
src/actions/sleep_node.cpp (1)
SleepNode(6-8)
include/behaviortree_cpp/decorator_node.h (1)
src/decorator_node.cpp (2)
DecoratorNode(18-20)SimpleDecoratorNode(66-70)
include/behaviortree_cpp/controls/parallel_all_node.h (1)
src/controls/parallel_all_node.cpp (1)
ParallelAllNode(21-23)
include/behaviortree_cpp/decorators/subtree_node.h (1)
src/decorators/subtree_node.cpp (1)
SubTreeNode(3-7)
include/behaviortree_cpp/condition_node.h (1)
src/condition_node.cpp (2)
ConditionNode(18-20)SimpleConditionNode(22-26)
include/behaviortree_cpp/decorators/delay_node.h (1)
src/decorators/delay_node.cpp (2)
DelayNode(8-12)DelayNode(14-16)
include/behaviortree_cpp/decorators/repeat_node.h (1)
src/decorators/repeat_node.cpp (2)
RepeatNode(19-26)RepeatNode(28-33)
include/behaviortree_cpp/loggers/bt_minitrace_logger.h (1)
src/loggers/bt_minitrace_logger.cpp (2)
MinitraceLogger(10-16)MinitraceLogger(18-22)
src/xml_parsing.cpp (1)
include/behaviortree_cpp/xml_parsing.h (1)
XMLParser(16-44)
include/behaviortree_cpp/blackboard.h (1)
src/blackboard.cpp (3)
Entry(310-316)other(318-329)other(318-318)
include/behaviortree_cpp/control_node.h (1)
src/control_node.cpp (1)
ControlNode(18-20)
include/behaviortree_cpp/controls/sequence_with_memory_node.h (1)
src/controls/sequence_with_memory_node.cpp (1)
SequenceWithMemory(18-22)
include/behaviortree_cpp/decorators/inverter_node.h (1)
src/decorators/inverter_node.cpp (1)
InverterNode(18-21)
include/behaviortree_cpp/controls/while_do_else_node.h (1)
src/controls/while_do_else_node.cpp (1)
WhileDoElseNode(17-21)
🪛 Cppcheck (2.19.0)
src/xml_parsing.cpp
[error] 376-376: Found an exit path from function with non-void return type that has missing return statement
(missingReturn)
🪛 Shellcheck (0.11.0)
run_clang_tidy.sh
[warning] 63-63: Quote this to prevent word splitting.
(SC2046)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: industrial_ci (rolling, main)
- GitHub Check: build (ubuntu-22.04, tsan)
- GitHub Check: build (ubuntu-22.04, asan_ubsan)
- GitHub Check: pixi_conda_build (windows-latest)
- GitHub Check: pixi_conda_build (ubuntu-latest)
- GitHub Check: build (ubuntu-22.04)
- GitHub Check: build (windows-latest)
- GitHub Check: industrial_ci (humble, main)
- GitHub Check: industrial_ci (jazzy, main)
🔇 Additional comments (54)
include/behaviortree_cpp/loggers/groot2_protocol.h (1)
142-143: LGTM! Good modernization.The refactor correctly moves initialization from the constructor body to the member initializer list, which is the preferred modern C++ idiom. The behavior remains identical (zero-initialization of the array).
include/behaviortree_cpp/utils/demangle_util.h (1)
46-49: LGTM! Explicit move deletion follows the Rule of Five.The class already had implicitly suppressed move operations due to the user-declared destructor and deleted copy operations. Explicitly deleting them improves clarity and satisfies clang-tidy's
cppcoreguidelines-special-member-functionscheck.include/behaviortree_cpp/actions/sleep_node.h (2)
25-28: Good practice: Explicitly deleted special member functions.Making SleepNode non-copyable and non-movable is appropriate given that it manages timer resources (timer_, timer_id_) and has a non-trivial destructor that calls
halt(). This follows the Rule of Five and prevents accidental misuse of a stateful action node.
43-43: Good practice: Explicit member initialization.Initializing
timer_id_to 0 prevents potential undefined behavior and provides a clear sentinel value for "no active timer." This defensive initialization aligns with modern C++ best practices.include/behaviortree_cpp/decorators/repeat_node.h (2)
42-42: LGTM: Redundantvirtualkeyword removed.The
virtualkeyword is redundant whenoverrideis present, asoverridealready implies the function is virtual. This cleanup aligns with modern C++ best practices.
44-47: The copy/move semantics deletions are properly implemented and consistent. The base classDecoratorNodehas identical deleted copy/move operators (lines 16-19 ofdecorator_node.h), and all concrete decorator nodes in the codebase follow this pattern uniformly. No usage ofRepeatNodecopy or move operations exists in the codebase, confirming that deleting these semantics aligns with the tree's ownership model where nodes are owned by the tree itself rather than copied or moved by user code.include/behaviortree_cpp/controls/switch_node.h (2)
55-55: LGTM: Cleaner destructor declaration.Removing the explicit
virtualkeyword whenoverrideis present is correct—the destructor remains virtual through inheritance. This improves code clarity by avoiding redundancy.
57-60: LGTM: Deleted copy/move operations prevent misuse.Explicitly deleting copy and move operations is best practice for behavior tree node types. SwitchNode instances are managed through the factory pattern and
std::unique_ptr, ensuring tree integrity and preventing unintended ownership issues. This pattern is consistent across other control nodes in the codebase.include/behaviortree_cpp/utils/timer_queue.h (2)
180-181: LGTM! Correctly prevents moving of active TimerQueue.Deleting the move operations is necessary because the worker thread (started in the constructor at line 82) captures
thisand runs asynchronously. Moving the object would invalidate the pointer used by the running thread, leading to undefined behavior. This change aligns with the already-deleted copy operations and prevents unsafe usage.
258-258: LGTM! Good defensive initialization.Adding the default initializer
id = 0ensures WorkItem starts in a safe "cancelled" state (consistent with the semantic meaning ofid == 0used throughout the code at lines 136, 168, and 244). This prevents potential uninitialized memory issues if WorkItem is ever default-constructed without explicit initialization.include/behaviortree_cpp/loggers/bt_observer.h (1)
23-26: LGTM! Good design enforcement for observer semantics.Making
TreeObservernon-copyable and non-movable is appropriate for an observer class that maintains internal mappings to a specific tree and registers callbacks. The parent classStatusChangeLoggerallows move semantics but deletes copies;TreeObserverfurther restricts by deleting moves as well, which is a valid design choice for stable observer identity. Current usage patterns in tests and examples confirm no code relies on copy or move semantics—all instances are constructed locally and used in place.include/behaviortree_cpp/utils/shared_library.h (1)
130-133: LGTM! No breaking changes found.The deleted copy and move operations are correctly declared and align with the class's resource-management responsibilities. The codebase only instantiates
SharedLibraryas local variables (as seen inbt_factory.cpp), never copying or moving instances. This deletion does not affect any existing usage patterns.src/xml_parsing.cpp (10)
20-20: LGTM: Clean addition of helper and include.The tuple include supports
std::ignoreusage later in the file, and theStrEquallambda in the anonymous namespace provides a clearer, more expressive alternative to rawstrcmpcalls.Also applies to: 89-94
121-121: LGTM: Factory pointer conversion properly initialized.Converting the factory member from a reference to a pointer with default initialization improves flexibility. The constructor correctly initializes it to the address of the factory parameter, ensuring a valid pointer throughout the object's lifetime.
Also applies to: 129-129
151-152: LGTM: Move constructor correctly marked noexcept.Marking the move constructor as
noexceptis a best practice that enables optimizations in standard containers and algorithms, particularly for move operations in vectors and other containers.
165-165: LGTM: Excellent modernization with std::make_unique.Replacing raw
newwithstd::make_uniqueimproves exception safety, clarifies ownership semantics, and follows modern C++ best practices. This change is consistently applied across all XMLDocument allocations.Also applies to: 177-177, 314-314
244-245: LGTM: Proper use of std::ignore for discarded values.Using
std::ignoreexplicitly documents the intent to discard return values and suppresses compiler warnings, which is cleaner than void casts or other alternatives.Also applies to: 370-371, 378-379, 777-777
296-296: LGTM: NOLINT appropriately used.The
NOLINT(misc-const-correctness)is correctly applied here since the variable's const-correctness depends on conditional compilation paths. In theUSING_ROS2case, it's assigned from a function call, justifying the suppression.
220-220: LGTM: Explicit nullptr checks improve clarity.Converting implicit pointer checks to explicit
nullptrcomparisons enhances code readability and aligns with modern C++ style guidelines. This change is consistently applied throughout the file.Also applies to: 250-250, 256-256, 274-274, 287-287, 349-349, 396-396, 402-406, 411-411, 423-423, 446-446, 638-638, 646-646, 669-670, 679-679, 767-767, 880-880
882-882: LGTM: Pointer semantics with auto improves clarity.*Using
auto*withdynamic_castexplicitly communicates that the result is a pointer, making the code more self-documenting compared to plainauto. This is a good modern C++ practice.Also applies to: 886-886, 1127-1127, 1171-1171, 1178-1178
632-632: LGTM: Using count() for broader C++ standard compatibility.Replacing
contains()withcount() == 0maintains compatibility with C++ standards prior to C++20, while providing the same functionality for set-like containers.Also applies to: 1204-1204
1062-1063: LGTM: Anonymous namespace properly scopes helper functions.Placing the helper functions
addNodeModelToXMLandaddTreeToXMLin an anonymous namespace provides internal linkage, preventing potential name collisions and clearly indicating these are file-local utilities.Also applies to: 1215-1215
include/behaviortree_cpp/loggers/bt_sqlite_logger.h (1)
58-63: LGTM! Non-copyable/non-movable semantics are appropriate.The deleted copy/move operations are appropriate for
SqliteLoggersince it manages resources like a database connection (sqlite3* db_) and a writer thread (std::thread writer_thread_). The destructor change removes the redundantvirtualkeyword while keepingoverride, which is a style improvement.CMakeLists.txt (1)
309-322: LGTM! Helpful addition for IDE support and clang-tidy integration.The generated
.clangdconfiguration provides proper compile flags and include paths for the clangd language server, which improves developer experience and enables better static analysis. The configuration correctly matches the project's C++17 standard and includes all necessary paths.include/behaviortree_cpp/controls/parallel_all_node.h (2)
1-1: Copyright update looks good.Routine maintenance updating the copyright year range.
48-51: LGTM! Appropriate for control nodes managing child lifecycle.Deleting copy/move operations is appropriate for
ParallelAllNodesince it manages child nodes and maintains execution state (completed_list_,failure_count_). This prevents accidental copying of complex control flow state.src/controls/parallel_all_node.cpp (1)
1-1: Copyright update looks good.Routine maintenance updating the copyright year range.
include/behaviortree_cpp/controls/parallel_node.h (2)
2-2: Copyright update looks good.Routine maintenance updating the copyright year range.
59-62: LGTM! Appropriate for control nodes managing execution state.Deleting copy/move operations is appropriate for
ParallelNodesince it manages child node execution and maintains state (completed_list_,success_count_,failure_count_).include/behaviortree_cpp/controls/if_then_else_node.h (2)
1-1: Copyright update looks good.Routine maintenance updating the copyright year range.
39-44: LGTM! Good defensive programming practices.The destructor change removes the redundant
virtualkeyword (implied byoverride), and the deleted copy/move operations appropriately prevent accidental copying of control flow state.include/behaviortree_cpp/loggers/bt_minitrace_logger.h (1)
12-17: LGTM! Appropriate for logger managing external resources.The destructor change removes the redundant
virtualkeyword, and the deleted copy/move operations are appropriate sinceMinitraceLoggermanages minitrace library resources (initialized viamtr_initand cleaned up viamtr_flush/mtr_shutdown).include/behaviortree_cpp/loggers/bt_cout_logger.h (1)
20-23: LGTM! Consistent with other logger hardening.Deleting copy/move operations is appropriate for
StdCoutLoggerto prevent accidental duplication of logger state and tree observation callbacks.include/behaviortree_cpp/decorators/subtree_node.h (1)
57-62: LGTM!The destructor style update (removing redundant
virtualwithoverride) and explicit deletion of copy/move operations align with the PR's goal of enforcing non-copyable/non-movable semantics across BT nodes. This is consistent with the broader pattern applied throughout the codebase.include/behaviortree_cpp/controls/while_do_else_node.h (1)
38-43: LGTM!Consistent with the repository-wide pattern of enforcing non-copyable/non-movable semantics for control nodes.
include/behaviortree_cpp/controls/sequence_node.h (1)
40-45: LGTM!The changes consistently apply non-copyable/non-movable semantics to
SequenceNode, matching the pattern across other control and decorator nodes in this PR.include/behaviortree_cpp/decorators/script_precondition.h (1)
30-35: LGTM!Explicit deletion of copy/move operations is appropriate for
PreconditionNodegiven its stateful members (_executor,_children_running). This aligns with the PR-wide enforcement of non-copyable/non-movable semantics.include/behaviortree_cpp/json_export.h (2)
54-64: LGTM!The changes properly enforce the singleton pattern for
JsonExporterby:
- Making the default constructor private
- Deleting copy/move operations
- Preserving the public
static get()accessorThis prevents unintended instantiation or duplication of the exporter.
256-276: LGTM!The
NOLINTBEGIN/NOLINTENDannotations appropriately suppressbugprone-macro-parenthesesfor this macro, which intentionally uses unparenthesized parameters as part of its design pattern for JSON converters.include/behaviortree_cpp/condition_node.h (2)
26-31: LGTM!Consistent application of non-copyable/non-movable semantics to the
ConditionNodebase class.
66-69: LGTM!Deleting copy/move operations for
SimpleConditionNodeis appropriate given itsTickFunctormember (which wraps astd::function). This prevents unintended sharing of callback state.run_clang_tidy.sh (1)
66-72: No action needed on--checkflag usage.The
--checkflag has been available since clangd-12 and is not a new feature. The--check-locations=falseflag disables exercising language features (hover, analyses) at every point in the file—a performance optimization when checking a single file—not a suppression of diagnostics. This flag combination is appropriate and recommended for this use case.Likely an incorrect or invalid review comment.
include/behaviortree_cpp/action_node.h (4)
41-45: LGTM! Explicit non-copyable/non-movable semantics for ActionNodeBase.The deletion of copy/move operations is appropriate for tree node types that have identity semantics and shouldn't be duplicated.
63-67: LGTM! Consistent pattern applied to SyncActionNode.
100-104: LGTM! SimpleActionNode correctly marked non-copyable/non-movable.The class stores a
std::functioncallback, and explicit deletion prevents accidental copies that could lead to unexpected behavior.
215-220: LGTM! CoroActionNode properly marked non-copyable/non-movable.The destructor declaration change (line 215) and explicit deletions are correct. The class uses Pimpl idiom with
std::unique_ptr, so explicit deletion reinforces the intended semantics.include/behaviortree_cpp/decorators/delay_node.h (1)
46-50: LGTM! Explicit non-copyable/non-movable semantics for DelayNode.The class manages timer resources (
TimerQueue,timer_id_) and synchronization primitives, making explicit deletion of copy/move operations appropriate. The destructor properly callshalt()to clean up timer resources.include/behaviortree_cpp/control_node.h (1)
29-34: LGTM! ControlNode properly updated with non-copyable/non-movable semantics.The destructor change (removing redundant
virtualsinceoverrideimplies virtuality) and explicit deletion of copy/move operations are correct. Control nodes manage child relationships and shouldn't be copied.include/behaviortree_cpp/controls/sequence_with_memory_node.h (1)
39-44: LGTM! SequenceWithMemory correctly marked non-copyable/non-movable.The class maintains execution state (
current_child_idx_,skipped_count_) that would cause incorrect behavior if copied. The destructor change and explicit deletions are consistent with the baseControlNodeclass.include/behaviortree_cpp/decorators/inverter_node.h (1)
30-35: LGTM! InverterNode correctly marked non-copyable/non-movable.Consistent with the base
DecoratorNodeclass and the broader PR pattern for tree node types.include/behaviortree_cpp/decorator_node.h (2)
16-21: LGTM! DecoratorNode base class properly marked non-copyable/non-movable.The destructor change (removing redundant
virtual) and explicit deletion of copy/move operations are correct. As a base class for all decorators, this establishes the non-copyable/non-movable pattern for the entire decorator hierarchy.
68-71: LGTM! SimpleDecoratorNode correctly marked non-copyable/non-movable.Consistent with the base
DecoratorNodeclass. The class stores aTickFunctorcallback, and explicit deletion prevents accidental copies that could lead to unexpected behavior.include/behaviortree_cpp/blackboard.h (2)
43-46: LGTM: Non-copyable and non-movable semantics are appropriate.Deleting copy and move operations is the correct design choice for
Blackboard, which is intended to be used exclusively viastd::shared_ptr(as evidenced by the protected constructor and staticcreate()factory method). This prevents accidental copying and enforces shared ownership semantics.
62-66: Entry special member functions correctly omit the mutex member.The custom copy operations and deleted move operations are necessary because
Entrycontains amutable std::mutex entry_mutexwhich is neither copyable nor movable. The implementation insrc/blackboard.cppcorrectly omits the mutex from copy operations (default-constructing it instead) and includes a self-assignment check.Entry objects are never copied directly in the codebase; they are accessed exclusively through
shared_ptr<Entry>pointers. The primary use case for copying Entry fields is incloneInto(), which copies field values individually while holding locks on both the source and destination Blackboard storage mutexes—not using the Entry copy operations at all. Thread safety is properly maintained through Blackboard-level locking combined with per-Entry value access protection viaentry_mutex.Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
include/behaviortree_cpp/loggers/abstract_logger.h (1)
47-50: Comment contradicts initialization value — pre-existing documentation issue.The comment on line 47 states "false by default," but
show_transition_to_idle_has been initialized totruethroughout the repository history. This means IDLE transitions are logged by default (see line 76), contrary to what the comment documents.This is a pre-existing inconsistency unrelated to the refactor. Either update the comment to "true by default" or verify the intended behavior and adjust the initialization accordingly.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
include/behaviortree_cpp/basic_types.hinclude/behaviortree_cpp/bt_factory.hinclude/behaviortree_cpp/controls/switch_node.hinclude/behaviortree_cpp/decorators/script_precondition.hinclude/behaviortree_cpp/loggers/abstract_logger.hinclude/behaviortree_cpp/loggers/groot2_protocol.hinclude/behaviortree_cpp/tree_node.hinclude/behaviortree_cpp/utils/demangle_util.hinclude/behaviortree_cpp/utils/timer_queue.h
✅ Files skipped from review due to trivial changes (1)
- include/behaviortree_cpp/basic_types.h
🚧 Files skipped from review as they are similar to previous changes (1)
- include/behaviortree_cpp/tree_node.h
🧰 Additional context used
🧬 Code graph analysis (2)
include/behaviortree_cpp/bt_factory.h (3)
sample_nodes/crossdoor_nodes.cpp (1)
BT_REGISTER_NODES(80-84)sample_nodes/dummy_nodes.cpp (1)
BT_REGISTER_NODES(5-8)sample_nodes/movebase_node.cpp (1)
BT_REGISTER_NODES(6-9)
include/behaviortree_cpp/decorators/script_precondition.h (1)
include/behaviortree_cpp/basic_types.h (1)
NodeStatus(33-230)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: pixi_conda_build (ubuntu-latest)
- GitHub Check: pixi_conda_build (windows-latest)
- GitHub Check: build (ubuntu-22.04, tsan)
- GitHub Check: build (ubuntu-22.04)
- GitHub Check: build (windows-latest)
- GitHub Check: industrial_ci (rolling, main)
- GitHub Check: build (ubuntu-22.04, asan_ubsan)
- GitHub Check: industrial_ci (jazzy, main)
- GitHub Check: industrial_ci (humble, main)
🔇 Additional comments (20)
include/behaviortree_cpp/loggers/groot2_protocol.h (3)
135-135: LGTM! Good modernization.Using default member initialization for
tree_idis a best practice that simplifies the struct and eliminates the need for an explicit constructor. The= {}syntax correctly zero-initializes all 16 bytes of the array.
150-155: LGTM! Cleaner code.Removing the unnecessary
reinterpret_cast<char*>simplifies the code sincememcpyacceptsvoid*arguments. This change makes the code more idiomatic and easier to read.
184-184: LGTM! Good defensive programming.Explicitly initializing
typeto 0 before deserialization ensures the variable is in a known state, even if deserialization fails. This is a clang-tidy best practice that improves code safety.include/behaviortree_cpp/utils/demangle_util.h (3)
48-49: LGTM! Proper resource management.Deleting the move operations is correct. The class manages a resource via
demangle_alloc/demangle_freewithout implementing move semantics, so preventing moves avoids resource management bugs.
63-63: LGTM! Appropriate linter suppression.The
NOLINTNEXTLINEis correct. The code interfaces with__cxa_demangle, which allocates viamalloc, sostd::freeis unavoidable.
109-113: LGTM! Improved readability.The explicit
nullptrcheck and simplified control flow (removing theelsebranch) make the code clearer without changing behavior.include/behaviortree_cpp/bt_factory.h (2)
2-2: LGTM! Copyright year updated.Standard maintenance to reflect current year.
81-84: LGTM! Appropriate NOLINT directives for plugin macro.The suppressions are well-justified for this legitimate macro use case:
cppcoreguidelines-macro-usage: The macro abstracts cross-platform plugin export (extern "C"+ visibility attributes) and provides a clean public API that cannot be easily replaced with inline functions or constexpr.bugprone-macro-parentheses: Thefactoryparameter is used as a typed function parameter (BT::BehaviorTreeFactory& factory), not as an expression requiring parentheses.The directives are properly scoped with BEGIN/END markers.
include/behaviortree_cpp/controls/switch_node.h (4)
1-1: LGTM!Copyright year update is appropriate.
55-60: LGTM!Good improvements:
- Removing redundant
virtualwhenoverrideis present aligns withmodernize-use-override.- Explicitly deleting copy and move operations follows the Rule of Five and is appropriate for tree-managed nodes that maintain runtime state (
running_child_).
67-67: LGTM!Using in-class default member initialization ensures
running_child_is consistently initialized, even if additional constructors are added later.
78-78: LGTM!Constructor initializer list correctly simplified after moving
running_child_initialization to the member declaration.include/behaviortree_cpp/decorators/script_precondition.h (3)
30-30: LGTM: Redundantvirtualkeyword removed.The
virtualkeyword is redundant whenoverrideis specified, as the function is already virtual through inheritance fromDecoratorNode. This cleanup improves code clarity.
32-35: LGTM: Explicit non-copyable/non-movable semantics.Explicitly deleting copy and move operations clarifies that behavior tree nodes have unique ownership semantics and should not be duplicated or transferred. This defensive pattern prevents subtle bugs and aligns with the behavior tree lifecycle model.
50-50: LGTM: Defensive initialization added.Initializing
else_returntoNodeStatus::FAILURE(matching the port's default value) is good defensive programming. WhilegetInputshould always succeed due to the default port value, explicit initialization prevents potential use-before-initialization issues if the control flow is modified in future refactorings.include/behaviortree_cpp/loggers/abstract_logger.h (1)
59-62: Modern initialization pattern is a good practice.Using default member initializers is a clean, modern C++ approach that ensures these members are always initialized consistently. This refactor improves code clarity by making default values visible at the declaration site.
Note: Ensure the value for
show_transition_to_idle_on line 60 matches the intended default behavior (see the previous comment regarding the inconsistency with the comment on line 47).include/behaviortree_cpp/utils/timer_queue.h (4)
74-75: Good naming convention fix.Renaming from
_Clock/_DurationtoClockT/DurationTavoids identifiers that start with underscore followed by uppercase, which are reserved by the C++ standard for implementation use.
178-181: LGTM: Completing Rule of Five by deleting move operations.The class manages a running thread and synchronization primitives (
std::mutex, atomics), making it non-trivially movable. Explicitly deleting move operations is the correct defensive choice here.
255-264: Good addition of explicit default initialization.The
id = 0default initialization (line 258) ensures the member is always initialized, preventing potential undefined behavior from uninitialized reads.
99-114: Consistent template parameter usage throughout.All time-point calculations and type references have been correctly updated to use
ClockTandDurationT. The logic remains unchanged - default-constructedtime_point(epoch) correctly represents "immediate execution" for cancelled timers.Also applies to: 121-153, 158-176, 184-209, 211-231, 233-248
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (1)
.github/workflows/pre-commit.yaml (1)
23-28: Consider verifying the install script or using alternative installation methods.Downloading and executing scripts with
sudowithout checksum verification poses a security risk. Whileapt.llvm.orgis the official LLVM repository and this pattern is common, consider adding checksum verification or using GitHub's setup actions.💡 Alternative approaches
Option 1: Verify script checksum before execution
- name: Install LLVM 21 run: | wget https://apt.llvm.org/llvm.sh + echo "expected_checksum llvm.sh" | sha256sum -c chmod +x llvm.sh sudo ./llvm.sh 21 sudo apt-get install -y clangd-21 clang-tidy-21Option 2: Use existing GitHub action
- name: Install LLVM 21 uses: KyleMayes/install-llvm-action@v2 with: version: "21"
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/pre-commit.yaml
🧰 Additional context used
🪛 actionlint (1.7.9)
.github/workflows/pre-commit.yaml
21-21: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: build (windows-latest)
- GitHub Check: pixi_conda_build (windows-latest)
- GitHub Check: pixi_conda_build (ubuntu-latest)
- GitHub Check: industrial_ci (jazzy, main)
- GitHub Check: industrial_ci (rolling, main)
- GitHub Check: build (ubuntu-22.04, tsan)
- GitHub Check: build (ubuntu-22.04, asan_ubsan)
- GitHub Check: industrial_ci (humble, main)
- GitHub Check: build (ubuntu-22.04)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
.github/workflows/pre-commit.yaml (1)
14-14: Update deprecated action to prevent CI failures.Both the
pre-commitandclang-tidyjobs useactions/checkout@v3, which targets the deprecated Node.js 16 runner and will eventually stop working.🔎 Proposed fix
- - uses: actions/checkout@v3 + - uses: actions/checkout@v4Apply this change to both line 14 and line 21.
Also applies to: 21-21
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/pre-commit.yaml
🧰 Additional context used
🪛 actionlint (1.7.9)
.github/workflows/pre-commit.yaml
21-21: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: industrial_ci (jazzy, main)
- GitHub Check: industrial_ci (humble, main)
- GitHub Check: industrial_ci (rolling, main)
- GitHub Check: build (ubuntu-22.04)
- GitHub Check: pixi_conda_build (windows-latest)
- GitHub Check: build (windows-latest)
- GitHub Check: pixi_conda_build (ubuntu-latest)
- GitHub Check: build (ubuntu-22.04, tsan)
- GitHub Check: build (ubuntu-22.04, asan_ubsan)
🔇 Additional comments (2)
.github/workflows/pre-commit.yaml (2)
23-28: LLVM and clang-tidy installation looks good.The installation of
clangd-21andclang-tidy-21addresses the concern from the previous review about missing dependencies. The approach using the officialllvm.shscript is appropriate.
38-39: No action needed. The scriptrun_clang_tidy.shis already committed with executable permissions (755), so the workflow will execute correctly without additional chmod steps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (4)
src/blackboard.cpp (1)
174-176: Consider using structured bindings with just the key.Using
std::ignoreworks but is slightly verbose. You could use a single-element binding since only the key is needed.🔎 Alternative using a simpler binding
- for(const auto& [key, entry] : dst_storage) - { - std::ignore = entry; // unused in this loop + for(const auto& [key, _] : dst_storage) + {Note: Using
_as a placeholder is supported in C++26 but may generate warnings on older standards. The current approach withstd::ignoreis safer for broader compatibility.run_clang_tidy.sh (2)
3-4: Consider usingdirnamefor clarity.The parameter expansion
${0%/*}works correctly butdirname "$0"is more readable and conventional for extracting the directory path.🔎 Proposed refactor
-script_dir=${0%/*} +script_dir=$(dirname "$0") ws_dir=$(realpath "$script_dir")
32-32: Remove or use theclang_tidy_pathsvariable consistently.The variable
clang_tidy_pathsis assigned but never used in the actualfindcommand at line 62, which directly specifies"$ws_dir/src" "$ws_dir/include"instead. This creates maintenance confusion.🔎 Proposed refactor
Either remove the unused variable:
-clang_tidy_paths="$ws_dir/src $ws_dir/include" cmake_build_path="$ws_dir/${1:-build}"Or use an array and reference it consistently:
-clang_tidy_paths="$ws_dir/src $ws_dir/include" +clang_tidy_paths=("$ws_dir/src" "$ws_dir/include") cmake_build_path="$ws_dir/${1:-build}" ... -find "$ws_dir/src" "$ws_dir/include" \( -name '*.cpp' -o -name '*.hpp' -o -name '*.h' \) -not -name '*_WIN.cpp' "${skip_paths[@]}" -print0 \ +find "${clang_tidy_paths[@]}" \( -name '*.cpp' -o -name '*.hpp' -o -name '*.h' \) -not -name '*_WIN.cpp' "${skip_paths[@]}" -print0 \include/behaviortree_cpp/utils/simple_string.hpp (1)
36-44: Consider copy-and-swap idiom for exception safety.While the current implementation is functionally safe (if
createImplthrows, the object remains in a valid empty state), explicitly calling the destructor and continuing to use the object is unconventional and error-prone. The copy-and-swap idiom is more idiomatic and clearly exception-safe.🔎 Recommended refactor using copy-and-swap
SimpleString& operator=(const SimpleString& other) { if(this != &other) { - this->~SimpleString(); - createImpl(other.data(), other.size()); + SimpleString temp(other); + std::swap(_storage, temp._storage); } return *this; }This allows the temporary to clean up the old resources via its destructor, making the exception safety explicit.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
.github/dependabot.yml.github/workflows/pre-commit.yamlinclude/behaviortree_cpp/blackboard.hinclude/behaviortree_cpp/utils/simple_string.hpprun_clang_tidy.shsrc/basic_types.cppsrc/blackboard.cppsrc/controls/reactive_fallback.cppsrc/xml_parsing.cpp
✅ Files skipped from review due to trivial changes (1)
- .github/dependabot.yml
🚧 Files skipped from review as they are similar to previous changes (2)
- .github/workflows/pre-commit.yaml
- src/controls/reactive_fallback.cpp
🧰 Additional context used
🧬 Code graph analysis (1)
src/xml_parsing.cpp (1)
include/behaviortree_cpp/xml_parsing.h (1)
XMLParser(16-44)
🪛 Cppcheck (2.19.0)
src/xml_parsing.cpp
[error] 376-376: Found an exit path from function with non-void return type that has missing return statement
(missingReturn)
🪛 Shellcheck (0.11.0)
run_clang_tidy.sh
[warning] 63-63: Quote this to prevent word splitting.
(SC2046)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
- GitHub Check: industrial_ci (rolling, main)
- GitHub Check: build (ubuntu-22.04, tsan)
- GitHub Check: build (ubuntu-22.04)
- GitHub Check: build (ubuntu-22.04, asan_ubsan)
- GitHub Check: pixi_conda_build (ubuntu-latest)
- GitHub Check: build (windows-latest)
- GitHub Check: clang-tidy
- GitHub Check: industrial_ci (jazzy, main)
- GitHub Check: industrial_ci (humble, main)
- GitHub Check: pixi_conda_build (windows-latest)
🔇 Additional comments (38)
include/behaviortree_cpp/blackboard.h (2)
43-46: LGTM! Non-copyable/non-movable semantics are appropriate for Blackboard.Since
Blackboardis designed to be shared viastd::shared_ptr<Blackboard>(thePtralias) and created through the static factorycreate(), explicitly deleting copy/move operations prevents accidental slicing or unintended duplication of the shared state.
62-66: LGTM! Explicit deletion clarifies intent.
Entrywas already implicitly non-copyable/non-movable due to thestd::mutex entry_mutexmember. Explicitly deleting these operations documents the design intent and prevents future confusion if the mutex were ever removed.src/blackboard.cpp (8)
2-2: LGTM!The
<tuple>header is required forstd::ignoreusage introduced incloneInto().
9-15: LGTM! Anonymous namespace provides internal linkage.Wrapping
IsPrivateKeyin an anonymous namespace is a modern C++ best practice for file-local functions, equivalent tostaticbut preferred in C++.
47-48: LGTM!The
NOLINTNEXTLINEcomment appropriately suppresses the clang-tidy warning for this intentionalconst_cast. The cast is a valid pattern here to avoid duplicating the implementation of the const overload.
61-61: LGTM!Making the
unique_lockconst enforces that it won't be unlocked or released prematurely, which is appropriate for simple scoped locking.
139-139: LGTM!Consistent with the const-lock pattern used elsewhere in this file.
224-224: LGTM!Consistent const-lock pattern for scoped mutex acquisition.
281-281: LGTM!Making
nameconst is a good const-correctness improvement since it's not modified after initialization.
313-314: LGTM!The
NOLINTNEXTLINEappropriately suppresses the warning for this standard const/non-const overload pattern where the non-const version delegates to the const version and casts away constness.run_clang_tidy.sh (6)
6-19: LGTM!The clangd-21 availability check is properly implemented using
command -v, and the installation instructions are helpful and accurate.
35-45: LGTM!The skip list setup is well-structured with proper array handling and quoting. The conversion to find exclusion patterns is correct.
47-52: LGTM!The compile_commands.json existence check is properly implemented with a helpful error message guiding users on resolution.
54-60: LGTM!The informational banner is helpful for users to understand what paths are being checked and skipped.
72-72: Verify sed substitution handles special characters in filenames.The sed command
sed "s/^/${1//\//\\/}: /"attempts to escape forward slashes in the filename for use in the sed substitution pattern. However, if filenames contain other sed special characters (e.g.,&,\,[,]), the substitution could break or produce incorrect output.Consider testing with filenames containing special characters, or use a more robust approach such as:
# Alternative: use awk or printf instead of sed for prefixing 2>&1 | awk -v prefix="$1: " '{print prefix $0}'This avoids sed metacharacter issues entirely.
75-77: LGTM!The completion banner provides clear feedback that the process has finished.
src/basic_types.cpp (6)
50-72: Color code comments are now correct.The previous review flagged swapped comments for ANSI codes. This has been fixed:
\x1b[32mis correctly commented as GREEN (line 55)\x1b[31mis correctly commented as RED (line 59)
121-122: LGTM!Using
std::ignoreto suppress the unusedptrfromstd::from_charsis an idiomatic approach. The error handling viaecis preserved.
143-156: LGTM!The
ConvertWithBoundCheckhelper cleanly extracts common bounds-checking logic. Usingint64_tas the intermediate type works correctly for all target types (int8 through uint32), as they all fit within its representable range.
200-217: LGTM!The locale handling pattern is correct: save the current locale, set to "C" for consistent parsing, parse the value, then restore the original locale. The use of
std::ignoreto silence the unused return fromsetlocaleis appropriate.
446-450: Good fix for potential UB.Casting to
unsigned charbefore callingstd::isalphais the correct approach. Without this cast, a signedcharwith a negative value (extended ASCII) would invoke undefined behavior.
494-508: LGTM!The rewritten
StartWithfunction is safer forStringViewusage. It properly handles bounds checking first (line 496) and performs explicit character comparison, avoiding assumptions about null-termination thatstrncmpwould require.src/xml_parsing.cpp (9)
89-94: LGTM!The
StrEqualhelper lambda in the anonymous namespace is a clean way to encapsulate thestrcmpcomparison logic.
121-130: LGTM!The change from reference to pointer for
factorywith explicit initialization enables proper move semantics. Thesuffix_countinitialization to 0 is good for clarity. The constructor correctly takes the address of the factory reference.
165-167: LGTM!Using
std::make_unique<XMLDocument>()is the preferred approach for exception safety and cleaner code compared to rawnew.
376-381: Static analysis false positive - no action needed.The Cppcheck warning about a missing return statement is a false positive. The
ThrowErrorlambda always exits viathrow RuntimeError(buffer), which is a valid exit path. Since the lambda never returns normally, no return statement is required.
693-697: Typo has been fixed.The variable is now correctly named
is_blackboard(previouslyis_blacbkboardas flagged in a prior review).
220-223: LGTM!The consistent use of explicit
== nullptrcomparisons throughout the file improves readability and aligns with modern C++ style guidelines.
244-246: LGTM!Using
std::ignoreto suppress the unused return value fromsnprintfis appropriate here. The buffer is fixed-size and the context (error message formatting) tolerates truncation if it were to occur.
882-890: LGTM!The
dynamic_castusage withauto*is clean and the null checks are correctly performed before dereferencing.
775-778: LGTM!Using
std::ignoreto explicitly indicate thatremap_valueis intentionally unused in this loop is a good practice for clarity and silencing warnings.include/behaviortree_cpp/utils/simple_string.hpp (7)
21-25: LGTM! Default constructor correctly initializes empty SOO state.The default constructor properly initializes an empty small-string-optimized string by setting
capacity_left = CAPACITYand null-terminating the buffer.
46-58: Excellent! Move semantics correctly fixed.The previous issue with calling the destructor before swap in move assignment has been properly addressed. The current implementation correctly uses only
std::swap, allowing the moved-from object to naturally clean up the original resources. Both move constructor and move assignment are nownoexceptand follow best practices.
112-130: Good refactoring of relational operators.The refactoring of
operator<=andoperator>=to delegate to the existing<and>implementations follows the DRY principle and improves maintainability.
132-152: LGTM! Lexicographic comparison correctly implemented.The refactored
operator<andoperator>correctly implement lexicographic ordering usingmemcmpfor byte-wise comparison up to the minimum length, with size as the tie-breaker. This is the standard approach for string comparison.
154-157: LGTM! isSOO() correctly identifies storage mode.The implementation correctly checks whether the
IS_LONG_BITis unset to determine SOO (small-string-optimized) mode, consistent with howcreateImplsets this bit for heap-allocated strings.
162-164: Good practice: explicit default member initializers.Adding default member initializers (
data = nullptr,size = 0,capacity_left = CAPACITY,_storage = {}) makes the initialization semantics explicit and improves code clarity.Also applies to: 178-180
194-194: LGTM! Appropriate use of NOLINT for intentional memory management.The
NOLINTannotation is justified here sinceSimpleStringintentionally manages raw memory with explicit ownership semantics (allocation here, deallocation in the destructor).
| # Display help message if --help is passed as an argument | ||
| if [[ "${1:-}" == "--help" ]]; then | ||
| echo "Usage: $(basename "$0") [source_path] [build_path]" | ||
| echo "Run clang-tidy on the specified paths." | ||
| echo | ||
| echo "Arguments:" | ||
| echo " build_path Path to build directory containing compile_commands.json (default: build)" | ||
| exit 0 | ||
| fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix inconsistency between help message and actual argument handling.
The help message at line 23 documents two arguments [source_path] [build_path], but the script only uses one argument at line 33 (${1:-build}). The source paths are hardcoded at line 32, not configurable via arguments.
🔎 Proposed fix
- echo "Usage: $(basename "$0") [source_path] [build_path]"
+ echo "Usage: $(basename "$0") [build_path]"
echo "Run clang-tidy on the specified paths."
echo
echo "Arguments:"🤖 Prompt for AI Agents
In run_clang_tidy.sh around lines 21-29, the help text mentions two positional
arguments ([source_path] [build_path]) but the script only reads one argument
and uses hardcoded source paths; update the script to accept and document both
positional args: set source_path="${1:-.}" and build_path="${2:-build}", update
the usage string to reflect defaults, replace any hardcoded source-path lists
with references to "$source_path" (or derive file lists from that directory),
and continue to use "$build_path" for compile_commands.json lookups so the help
and actual behavior are consistent.
| find "$ws_dir/src" "$ws_dir/include" \( -name '*.cpp' -o -name '*.hpp' -o -name '*.h' \) -not -name '*_WIN.cpp' "${skip_paths[@]}" -print0 \ | ||
| | xargs -0 -n 1 -P $(nproc) bash -c ' | ||
| set -o pipefail | ||
| echo "$@" | ||
| cd "'"$ws_dir"'" && clangd-21 \ | ||
| --log=error \ | ||
| --clang-tidy \ | ||
| --compile-commands-dir="'"$cmake_build_path"'" \ | ||
| --check-locations=false \ | ||
| --check="$@" \ | ||
| 2>&1 | sed "s/^/${1//\//\\/}: /" | ||
| ' _ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quote $(nproc) to prevent word splitting.
Shellcheck SC2046 warns that $(nproc) should be quoted. While xargs -P expects a numeric value and will typically work, quoting prevents potential issues if nproc returns unexpected output or fails.
🔎 Proposed fix
- | xargs -0 -n 1 -P $(nproc) bash -c '
+ | xargs -0 -n 1 -P "$(nproc)" bash -c '📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| find "$ws_dir/src" "$ws_dir/include" \( -name '*.cpp' -o -name '*.hpp' -o -name '*.h' \) -not -name '*_WIN.cpp' "${skip_paths[@]}" -print0 \ | |
| | xargs -0 -n 1 -P $(nproc) bash -c ' | |
| set -o pipefail | |
| echo "$@" | |
| cd "'"$ws_dir"'" && clangd-21 \ | |
| --log=error \ | |
| --clang-tidy \ | |
| --compile-commands-dir="'"$cmake_build_path"'" \ | |
| --check-locations=false \ | |
| --check="$@" \ | |
| 2>&1 | sed "s/^/${1//\//\\/}: /" | |
| ' _ | |
| find "$ws_dir/src" "$ws_dir/include" \( -name '*.cpp' -o -name '*.hpp' -o -name '*.h' \) -not -name '*_WIN.cpp' "${skip_paths[@]}" -print0 \ | |
| | xargs -0 -n 1 -P "$(nproc)" bash -c ' | |
| set -o pipefail | |
| echo "$@" | |
| cd "'"$ws_dir"'" && clangd-21 \ | |
| --log=error \ | |
| --clang-tidy \ | |
| --compile-commands-dir="'"$cmake_build_path"'" \ | |
| --check-locations=false \ | |
| --check="$@" \ | |
| 2>&1 | sed "s/^/${1//\//\\/}: /" | |
| ' _ |
🧰 Tools
🪛 Shellcheck (0.11.0)
[warning] 63-63: Quote this to prevent word splitting.
(SC2046)
🤖 Prompt for AI Agents
In run_clang_tidy.sh around lines 62 to 73, the xargs -P uses an unquoted
command substitution $(nproc); update it to quote the substitution to prevent
word splitting and unexpected tokenization by changing xargs -P $(nproc) to
xargs -P "$(nproc)". Ensure you only add the quotes around the substitution and
leave the rest of the command intact.
Summary by CodeRabbit
Bug Fixes
Refactor
Chores
Tests
Breaking Changes
✏️ Tip: You can customize this high-level summary in your review settings.