--- name: pre-reviewer description: Automated pre-review tool to inspect C++ style, concurrency safety, test quality, and CL descriptions before submitting code for human review. --- # Pre-Reviewer Skill This skill acts as a pre-review confidence check tool for WebRTC C++ contributions. Use this skill to evaluate code changes for common C++ anti-patterns, concurrency bugs, test hygiene issues, and CL description completeness. ______________________________________________________________________ ## 1. C++ Style and Modernization Guardrails ### Lambda Expressions - **No Capture Renaming:** Do not use captures with initializers to introduce new names. Capture variables with their original names. - *Correct:* `[on_certificate_ready = std::move(on_certificate_ready)]` - *Incorrect:* `[callback = std::move(on_certificate_ready)]` - *Reference:* [Google C++ Style Guide - Lambda expressions](https://google.github.io/styleguide/cppguide.html#Lambda_expressions) - **Prefer Implicit Captures for Inline/Local Lambdas:** If the lambda cannot escape the current scope (e.g. executed inside `BlockingCall`), prefer auto-capture (`[&]`). Do not explicitly list captures as it reduces readability. - *Reference:* [C++ Readability Advice - Lambda capture clauses](http://go/c-readability-advice#explicit-vs-implicit-lambda-capture-clauses) ### Pointer and Value Checks - **Explicit `nullptr` Comparisons:** Always compare pointer types to `nullptr` explicitly. Avoid implicit boolean conversion in conditions. - *Correct:* `if (tq_ != nullptr)` / `RTC_DCHECK(transport == nullptr);` - *Incorrect:* `if (tq_)` / `RTC_DCHECK(!transport);` - *Reference:* [Abseil Tip #141: Test Container Emptiness with Boolean Functions](https://abseil.io/tips/141) ### Structs vs. Classes - **Classes for API Invariants:** Use a class if the object has invariants, has wide visibility, or is expected to evolve. Use a struct only for passive data. - *Reference:* [Google C++ Style Guide - Structs vs. Classes](https://google.github.io/styleguide/cppguide.html#Structs_vs._Classes) - **Encapsulation:** Make classes' data members private unless they are constants. - *Reference:* [Google C++ Style Guide - Access Control](https://google.github.io/styleguide/cppguide.html#Access_Control) ### Virtual Functions - **No Default Arguments on Virtuals:** Banned on virtual functions because default arguments are bound statically at compile time, which leads to unexpected behavior when overriding. - *Reference:* [Google C++ Style Guide - Default Arguments](https://google.github.io/styleguide/cppguide.html#Default_Arguments) ### Type Deduction (`auto`) - **Avoid Excessive `auto`:** Explicitly spell out types unless the type is overly verbose (e.g. templates) or using `auto` directly improves safety. Do not use it merely to avoid writing the type. - *Reference:* [Google C++ Style Guide - Type deduction](https://google.github.io/styleguide/cppguide.html#Type_deduction) ### Operator Style - **Pre-increment/decrement:** Prefer the prefix form (`++i`, `--i`) unless postfix semantics are required. - *Reference:* [Google C++ Style Guide - Preincrement and Predecrement](https://google.github.io/styleguide/cppguide.html#Preincrement_and_Predecrement) ### Smart Pointer Initialization - **Assignment Syntax:** Use assignment syntax when initializing directly with smart pointers. - *Correct:* `std::unique_ptr foo = std::make_unique();` - *Incorrect:* `std::unique_ptr foo(std::make_unique());` - *Reference:* [Abseil Tip #88: Use Assignment Syntax for Smart Pointer Initialization](https://abseil.io/tips/88) ### Modern C++ Patterns (C++20 & Standard Library) - **Constinit:** Use `constinit` directly instead of `ABSL_CONST_INIT`. - *Reference:* [cppreference - constinit](https://en.cppreference.com/w/cpp/language/constinit.html) - **std::exchange:** Use `std::exchange` to simplify reset-and-return logic. - *Reference:* [cppreference - std::exchange](https://en.cppreference.com/w/cpp/utility/exchange.html) - **Avoid std::make_pair / std::make_tuple:** Prefer brace initialization or class template argument deduction (CTAD) like `std::pair{a, b}` instead of `std::make_pair(a, b)`. - **absl::flat_hash_map:** Prefer as the default map type unless ordering is required. - *Reference:* [Abseil Container Guide](https://abseil.io/docs/cpp/guides/container) ### Move Semantics - **Move First, Dereference After (for std::optional):** For `std::optional`, it is recommended to move first and dereference after (e.g. `*std::move(opt)`). Note that this is generally not recommended for `std::unique_ptr`. - *Reference:* [Abseil Tip #181: Move First, Dereference After](https://abseil.io/tips/181) - *Reference:* [Abseil Tip #224: Avoid value() accessors](https://abseil.io/tips/224) - **Avoid Redundant Return moves:** Do not use `std::move` on return statements when it prevents copy elision (NRVO/RVO). Moving a member variable out of a class when returning can still be useful. - **Avoid Brittle Move Loops:** Avoid moving a member variable into an argument of a method only to move it back inside the method. This looks like a "use after move" and makes code brittle. - *Example:* Avoid `RecreateEncoder(std::move(config_))` which internally updates `config_` back. Prefer separating it into a parameterless reset method or a config updater. ______________________________________________________________________ ## 2. Concurrency, Threading, and Destructors - **Prevent Reentrancy in Destructors:** When executing callbacks during destruction, move or swap the callback list/queue into a local variable first, then execute. This prevents callbacks from accessing a partially destroyed class. - **No Sequence Checkers in Destructors:** Remove or omit sequence/thread checks (`RTC_DCHECK_RUN_ON`) inside destructors. In C++, it is assumed that no other threads can call into an object while it is being destroyed. - **Atomic Safety:** Do not use relaxed memory order atomics when safety invariants depend on the ordering of operations not protected by the same lock. - *Reference:* [Abseil - Atomic Danger](https://abseil.io/docs/cpp/atomic_danger) ______________________________________________________________________ ## 3. Testing Best Practices - **Omit GMock Default Cardinality:** Do not add `.Times(1)` to `EXPECT_CALL` as it is the default. - **Omit Wildcard GMock Parameters:** Omit parameter lists in `EXPECT_CALL` when all parameters are wildcards (applicable to non-overloaded methods). - *Reference:* [GoogleTest Mocking Reference - EXPECT_CALL](https://google.github.io/googletest/reference/mocking.html#EXPECT_CALL) - **Avoid Unrelated Assertions:** Do not assert expectations on calls that are not the focus of the test scenario. Use `ON_CALL` instead of `EXPECT_CALL` for setting default behavior without setting expectations. - *Reference:* [GoogleTest Cookbook - Use ON_CALL](https://google.github.io/googletest/gmock_cook_book.html#UseOnCall) - **Descriptive Test Names:** Include the test scenario and expected outcome in test names. - *Reference:* [Testing on the Toilet: Writing Descriptive Test Names](https://testing.googleblog.com/2014/10/testing-on-toilet-writing-descriptive.html) - **Do Not Crash in Tests:** Use `FAIL() << "message";` instead of triggering a crash when verifying preconditions or expectations. - *Reference:* [GoogleTest Reference: Success/Failure Assertions](https://google.github.io/googletest/reference/assertions.html#success-failure) - **Avoid Double Negations:** Use positive assertions for better readability. - *Reference:* [Testing Blog: Improve Readability with Positive Assertions](https://testing.googleblog.com/2023/10/improve-readability-with-positive.html) ______________________________________________________________________ ## 4. Code Review and CL Process - **Meaningful CL Descriptions:** The CL description must explain **why** the change is made, not just *what* changed. List major goals, link issue tickets, and clarify the bigger architectural plan. - *Reference:* [Google Engineering Practices: CL Descriptions](https://google.github.io/eng-practices/review/developer/cl-descriptions.html) - **Keep CLs Small:** Split large changes into multiple CLs. Introduce interface definitions in one CL, and migrate callers in subsequent CLs. - *Reference:* [Google Engineering Practices: Small CLs](https://google.github.io/eng-practices/review/developer/small-cls.html) - **Documentation Freshness:** When adding new `.md` files, always include freshness metadata to track ownership. - *Reference:* [WebRTC Documentation Guidelines](https://webrtc.googlesource.com/src/+/refs/heads/main/g3doc/how_to_write_documentation.md) ______________________________________________________________________ ## 5. Inclusive Language Guidelines - **Use Inclusive Terminology:** Avoid gendered pronouns and non-inclusive terms in code, comments, and documentation. Use precise, neutral technical alternatives. - *Reference:* [Inclusive Chromium Code](https://chromium.googlesource.com/chromium/src/+/HEAD/styleguide/inclusive_code.md) - *Reference:* [Google Developer Documentation Style Guide - Word List](https://developers.google.com/style/word-list)