mirror of
https://github.com/esphome/esphome.git
synced 2026-01-10 04:00:51 -07:00
Update AI instructions with C++ style guidelines from developers docs (#11743)
This commit is contained in:
@@ -51,7 +51,79 @@ This document provides essential context for AI models interacting with this pro
|
|||||||
|
|
||||||
* **Naming Conventions:**
|
* **Naming Conventions:**
|
||||||
* **Python:** Follows PEP 8. Use clear, descriptive names following snake_case.
|
* **Python:** Follows PEP 8. Use clear, descriptive names following snake_case.
|
||||||
* **C++:** Follows the Google C++ Style Guide.
|
* **C++:** Follows the Google C++ Style Guide with these specifics (following clang-tidy conventions):
|
||||||
|
- Function, method, and variable names: `lower_snake_case`
|
||||||
|
- Class/struct/enum names: `UpperCamelCase`
|
||||||
|
- Top-level constants (global/namespace scope): `UPPER_SNAKE_CASE`
|
||||||
|
- Function-local constants: `lower_snake_case`
|
||||||
|
- Protected/private fields: `lower_snake_case_with_trailing_underscore_`
|
||||||
|
- Favor descriptive names over abbreviations
|
||||||
|
|
||||||
|
* **C++ Field Visibility:**
|
||||||
|
* **Prefer `protected`:** Use `protected` for most class fields to enable extensibility and testing. Fields should be `lower_snake_case_with_trailing_underscore_`.
|
||||||
|
* **Use `private` for safety-critical cases:** Use `private` visibility when direct field access could introduce bugs or violate invariants:
|
||||||
|
1. **Pointer lifetime issues:** When setters validate and store pointers from known lists to prevent dangling references.
|
||||||
|
```cpp
|
||||||
|
// Helper to find matching string in vector and return its pointer
|
||||||
|
inline const char *vector_find(const std::vector<const char *> &vec, const char *value) {
|
||||||
|
for (const char *item : vec) {
|
||||||
|
if (strcmp(item, value) == 0)
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClimateDevice {
|
||||||
|
public:
|
||||||
|
void set_custom_fan_modes(std::initializer_list<const char *> modes) {
|
||||||
|
this->custom_fan_modes_ = modes;
|
||||||
|
this->active_custom_fan_mode_ = nullptr; // Reset when modes change
|
||||||
|
}
|
||||||
|
bool set_custom_fan_mode(const char *mode) {
|
||||||
|
// Find mode in supported list and store that pointer (not the input pointer)
|
||||||
|
const char *validated_mode = vector_find(this->custom_fan_modes_, mode);
|
||||||
|
if (validated_mode != nullptr) {
|
||||||
|
this->active_custom_fan_mode_ = validated_mode;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::vector<const char *> custom_fan_modes_; // Pointers to string literals in flash
|
||||||
|
const char *active_custom_fan_mode_{nullptr}; // Must point to entry in custom_fan_modes_
|
||||||
|
};
|
||||||
|
```
|
||||||
|
2. **Invariant coupling:** When multiple fields must remain synchronized to prevent buffer overflows or data corruption.
|
||||||
|
```cpp
|
||||||
|
class Buffer {
|
||||||
|
public:
|
||||||
|
void resize(size_t new_size) {
|
||||||
|
auto new_data = std::make_unique<uint8_t[]>(new_size);
|
||||||
|
if (this->data_) {
|
||||||
|
std::memcpy(new_data.get(), this->data_.get(), std::min(this->size_, new_size));
|
||||||
|
}
|
||||||
|
this->data_ = std::move(new_data);
|
||||||
|
this->size_ = new_size; // Must stay in sync with data_
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::unique_ptr<uint8_t[]> data_;
|
||||||
|
size_t size_{0}; // Must match allocated size of data_
|
||||||
|
};
|
||||||
|
```
|
||||||
|
3. **Resource management:** When setters perform cleanup or registration operations that derived classes might skip.
|
||||||
|
* **Provide `protected` accessor methods:** When derived classes need controlled access to `private` members.
|
||||||
|
|
||||||
|
* **C++ Preprocessor Directives:**
|
||||||
|
* **Avoid `#define` for constants:** Using `#define` for constants is discouraged and should be replaced with `const` variables or enums.
|
||||||
|
* **Use `#define` only for:**
|
||||||
|
- Conditional compilation (`#ifdef`, `#ifndef`)
|
||||||
|
- Compile-time sizes calculated during Python code generation (e.g., configuring `std::array` or `StaticVector` dimensions via `cg.add_define()`)
|
||||||
|
|
||||||
|
* **C++ Additional Conventions:**
|
||||||
|
* **Member access:** Prefix all class member access with `this->` (e.g., `this->value_` not `value_`)
|
||||||
|
* **Indentation:** Use spaces (two per indentation level), not tabs
|
||||||
|
* **Type aliases:** Prefer `using type_t = int;` over `typedef int type_t;`
|
||||||
|
* **Line length:** Wrap lines at no more than 120 characters
|
||||||
|
|
||||||
* **Component Structure:**
|
* **Component Structure:**
|
||||||
* **Standard Files:**
|
* **Standard Files:**
|
||||||
|
|||||||
Reference in New Issue
Block a user