style-guide.rst 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. Espressif IoT Development Framework Style Guide
  2. ===============================================
  3. About This Guide
  4. ----------------
  5. Purpose of this style guide is to encourage use of common coding practices within the ESP-IDF.
  6. Style guide is a set of rules which are aimed to help create readable, maintainable, and robust code. By writing code which looks the same way across the code base we help others read and comprehend the code. By using same conventions for spaces and newlines we reduce chances that future changes will produce huge unreadable diffs. By following common patterns for module structure and by using language features consistently we help others understand code behavior.
  7. We try to keep rules simple enough, which means that they can not cover all potential cases. In some cases one has to bend these simple rules to achieve readability, maintainability, or robustness.
  8. When doing modifications to third-party code used in ESP-IDF, follow the way that particular project is written. That will help propose useful changes for merging into upstream project.
  9. C Code Formatting
  10. -----------------
  11. .. highlight:: c
  12. .. _style-guide-naming:
  13. Naming
  14. ^^^^^^
  15. * Any variable or function which is only used in a single source file should be declared ``static``.
  16. * Public names (non-static variables and functions) should be namespaced with a per-component or per-unit prefix, to avoid naming collisions. ie ``esp_vfs_register()`` or ``esp_console_run()``. Starting the prefix with ``esp_`` for Espressif-specific names is optional, but should be consistent with any other names in the same component.
  17. * Static variables should be prefixed with ``s_`` for easy identification. For example, ``static bool s_invert``.
  18. * Avoid unnecessary abbreviations (ie shortening ``data`` to ``dat``), unless the resulting name would otherwise be very long.
  19. Indentation
  20. ^^^^^^^^^^^
  21. Use 4 spaces for each indentation level. Don't use tabs for indentation. Configure the editor to emit 4 spaces each time you press tab key.
  22. Vertical Space
  23. ^^^^^^^^^^^^^^
  24. Place one empty line between functions. Don't begin or end a function with an empty line.
  25. ::
  26. void function1()
  27. {
  28. do_one_thing();
  29. do_another_thing();
  30. // INCORRECT, don't place empty line here
  31. }
  32. // place empty line here
  33. void function2()
  34. {
  35. // INCORRECT, don't use an empty line here
  36. int var = 0;
  37. while (var < SOME_CONSTANT) {
  38. do_stuff(&var);
  39. }
  40. }
  41. The maximum line length is 120 characters as long as it doesn't seriously affect the readability.
  42. Horizontal Space
  43. ^^^^^^^^^^^^^^^^
  44. Always add single space after conditional and loop keywords::
  45. if (condition) { // correct
  46. // ...
  47. }
  48. switch (n) { // correct
  49. case 0:
  50. // ...
  51. }
  52. for(int i = 0; i < CONST; ++i) { // INCORRECT
  53. // ...
  54. }
  55. Add single space around binary operators. No space is necessary for unary operators. It is okay to drop space around multiply and divide operators::
  56. const int y = y0 + (x - x0) * (y1 - y0) / (x1 - x0); // correct
  57. const int y = y0 + (x - x0)*(y1 - y0)/(x1 - x0); // also okay
  58. int y_cur = -y; // correct
  59. ++y_cur;
  60. const int y = y0+(x-x0)*(y1-y0)/(x1-x0); // INCORRECT
  61. No space is necessary around ``.`` and ``->`` operators.
  62. Sometimes adding horizontal space within a line can help make code more readable. For example, you can add space to align function arguments::
  63. esp_rom_gpio_connect_in_signal(PIN_CAM_D6, I2S0I_DATA_IN14_IDX, false);
  64. esp_rom_gpio_connect_in_signal(PIN_CAM_D7, I2S0I_DATA_IN15_IDX, false);
  65. esp_rom_gpio_connect_in_signal(PIN_CAM_HREF, I2S0I_H_ENABLE_IDX, false);
  66. esp_rom_gpio_connect_in_signal(PIN_CAM_PCLK, I2S0I_DATA_IN15_IDX, false);
  67. Note however that if someone goes to add new line with a longer identifier as first argument (e.g. ``PIN_CAM_VSYNC``), it will not fit. So other lines would have to be realigned, adding meaningless changes to the commit.
  68. Therefore, use horizontal alignment sparingly, especially if you expect new lines to be added to the list later.
  69. Never use TAB characters for horizontal alignment.
  70. Never add trailing whitespace at the end of the line.
  71. Braces
  72. ^^^^^^
  73. - Function definition should have a brace on a separate line::
  74. // This is correct:
  75. void function(int arg)
  76. {
  77. }
  78. // NOT like this:
  79. void function(int arg) {
  80. }
  81. - Within a function, place opening brace on the same line with conditional and loop statements::
  82. if (condition) {
  83. do_one();
  84. } else if (other_condition) {
  85. do_two();
  86. }
  87. Comments
  88. ^^^^^^^^
  89. Use ``//`` for single line comments. For multi-line comments it is okay to use either ``//`` on each line or a ``/* */`` block.
  90. Although not directly related to formatting, here are a few notes about using comments effectively.
  91. - Don't use single comments to disable some functionality::
  92. void init_something()
  93. {
  94. setup_dma();
  95. // load_resources(); // WHY is this thing commented, asks the reader?
  96. start_timer();
  97. }
  98. - If some code is no longer required, remove it completely. If you need it you can always look it up in git history of this file. If you disable some call because of temporary reasons, with an intention to restore it in the future, add explanation on the adjacent line::
  99. void init_something()
  100. {
  101. setup_dma();
  102. // TODO: we should load resources here, but loader is not fully integrated yet.
  103. // load_resources();
  104. start_timer();
  105. }
  106. - Same goes for ``#if 0 ... #endif`` blocks. Remove code block completely if it is not used. Otherwise, add comment explaining why the block is disabled. Don't use ``#if 0 ... #endif`` or comments to store code snippets which you may need in the future.
  107. - Don't add trivial comments about authorship and change date. You can always look up who modified any given line using git. E.g. this comment adds clutter to the code without adding any useful information::
  108. void init_something()
  109. {
  110. setup_dma();
  111. // XXX add 2016-09-01
  112. init_dma_list();
  113. fill_dma_item(0);
  114. // end XXX add
  115. start_timer();
  116. }
  117. Line Endings
  118. ^^^^^^^^^^^^
  119. Commits should only contain files with LF (Unix style) endings.
  120. Windows users can configure git to check out CRLF (Windows style) endings locally and commit LF endings by setting the ``core.autocrlf`` setting. `Github has a document about setting this option <github-line-endings>`. However because MSYS2 uses Unix-style line endings, it is often easier to configure your text editor to use LF (Unix style) endings when editing ESP-IDF source files.
  121. If you accidentally have some commits in your branch that add LF endings, you can convert them to Unix by running this command in an MSYS2 or Unix terminal (change directory to the IDF working directory and check the correct branch is currently checked out, beforehand):
  122. .. code-block:: bash
  123. git rebase --exec 'git diff-tree --no-commit-id --name-only -r HEAD | xargs dos2unix && git commit -a --amend --no-edit --allow-empty' master
  124. (Note that this line rebases on master, change the branch name at the end to rebase on another branch.)
  125. For updating a single commit, it's possible to run ``dos2unix FILENAME`` and then run ``git commit --amend``
  126. Formatting Your Code
  127. ^^^^^^^^^^^^^^^^^^^^
  128. You can use ``astyle`` program to format your code according to the above recommendations.
  129. If you are writing a file from scratch, or doing a complete rewrite, feel free to re-format the entire file. If you are changing a small portion of file, don't re-format the code you didn't change. This will help others when they review your changes.
  130. To re-format a file, run:
  131. .. code-block:: bash
  132. tools/format.sh components/my_component/file.c
  133. Type Definitions
  134. ^^^^^^^^^^^^^^^^
  135. Should be snake_case, ending with _t suffix::
  136. typedef int signed_32_bit_t;
  137. Enum
  138. ^^^^
  139. Enums should be defined through the `typedef` and be namespaced::
  140. typedef enum
  141. {
  142. MODULE_FOO_ONE,
  143. MODULE_FOO_TWO,
  144. MODULE_FOO_THREE
  145. } module_foo_t;
  146. .. _assertions:
  147. Assertions
  148. ^^^^^^^^^^
  149. The standard C ``assert()`` function, defined in ``assert.h`` should be used to check conditions that should be true in source code. In the default configuration, an assert condition that returns ``false`` or 0 will call ``abort()`` and trigger a :doc:`Fatal Error</api-guides/fatal-errors>`.
  150. ``assert()`` should only be used to detect unrecoverable errors due to a serious internal logic bug or corruption, where it's not possible for the program to continue. For recoverable errors, including errors that are possible due to invalid external input, an :doc:`error value should be returned </api-guides/error-handling>`.
  151. .. note::
  152. When asserting a value of type ``esp_err_t``is equal to ``ESP_OK``, use the :ref:`esp-error-check-macro` instead of an ``assert()``.
  153. It's possible to configure ESP-IDF projects with assertions disabled (see :ref:`CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL`). Therefore, functions called in an ``assert()`` statement should not have side-effects.
  154. It's also necessary to use particular techniques to avoid "variable set but not used" warnings when assertions are disabled, due to code patterns such as::
  155. int res = do_something();
  156. assert(res == 0);
  157. Once the ``assert`` is optimized out, the ``res`` value is unused and the compiler will warn about this. However the function ``do_something()`` must still be called, even if assertions are disabled.
  158. When the variable is declared and initialized in a single statement, a good strategy is to cast it to ``void`` on a new line. The compiler will not produce a warning, and the variable can still be optimized out of the final binary::
  159. int res = do_something();
  160. assert(res == 0);
  161. (void)res;
  162. If the variable is declared separately, for example if it is used for multiple assertions, then it can be declared with the GCC attribute ``__attribute__((unused))``. The compiler will not produce any unused variable warnings, but the variable can still be optimized out::
  163. int res __attribute__((unused));
  164. res = do_something();
  165. assert(res == 0);
  166. res = do_something_else();
  167. assert(res != 0);
  168. Header file guards
  169. ------------------
  170. All public facing header files should have preprocessor guards. A pragma is preferred::
  171. #pragma once
  172. over the following pattern::
  173. #ifndef FILE_NAME_H
  174. #define FILE_NAME_H
  175. ...
  176. #endif // FILE_NAME_H
  177. In addition to guard macros, all C header files should have ``extern "C"`` guards to allow the header to be used from C++ code. Note that the following order should be used: ``pragma once``, then any ``#include`` statements, then ``extern "C"`` guards::
  178. #pragma once
  179. #include <stdint.h>
  180. #ifdef __cplusplus
  181. extern "C" {
  182. #endif
  183. /* declarations go here */
  184. #ifdef __cplusplus
  185. }
  186. #endif
  187. Include statements
  188. ------------------
  189. When writing ``#include`` statements, try to maintain the following order:
  190. * C standard library headers.
  191. * Other POSIX standard headers and common extensions to them (such as ``sys/queue.h``.)
  192. * Common IDF headers (``esp_log.h``, ``esp_system.h``, ``esp_timer.h``, ``esp_sleep.h``, etc.)
  193. * Headers of other components, such as FreeRTOS.
  194. * Public headers of the current component.
  195. * Private headers.
  196. Use angle brackets for C standard library headers and other POSIX headers (``#include <stdio.h>``).
  197. Use double quotes for all other headers (``#include "esp_log.h"``).
  198. C++ Code Formatting
  199. -------------------
  200. The same rules as for C apply. Where they are not enough, apply the following rules.
  201. File Naming
  202. ^^^^^^^^^^^^
  203. C++ Header files have the extension ``.hpp``. C++ source files have the extension ``.cpp``. The latter is important for the compiler to distinguish them from normal C source files.
  204. Naming
  205. ^^^^^^
  206. * **Class and struct** names shall be written in ``CamelCase`` with a capital letter as beginning. Member variables and methods shall be in ``snake_case``.
  207. * **Namespaces** shall be in lower ``snake_case``.
  208. * **Templates** are specified in the line above the function declaration.
  209. * Interfaces in terms of Object-Oriented Programming shall be named without the suffix ``...Interface``. Later, this makes it easier to extract interfaces from normal classes and vice versa without making a breaking change.
  210. Member Order in Classes
  211. ^^^^^^^^^^^^^^^^^^^^^^^
  212. In order of precedence:
  213. * First put the public members, then the protected, then private ones. Omit public, protected or private sections without any members.
  214. * First put constructors/destructors, then member functions, then member variables.
  215. For example:
  216. ::
  217. class ForExample {
  218. public:
  219. // first constructors, then default constructor, then destructor
  220. ForExample(double example_factor_arg);
  221. ForExample();
  222. ~ForExample();
  223. // then remaining pubic methods
  224. set_example_factor(double example_factor_arg);
  225. // then public member variables
  226. uint32_t public_data_member;
  227. private:
  228. // first private methods
  229. void internal_method();
  230. // then private member variables
  231. double example_factor;
  232. };
  233. Spacing
  234. ^^^^^^^
  235. * Don't indent inside namespaces.
  236. * Put ``public``, ``protected`` and ``private`` labels at the same indentation level as the corresponding ``class`` label.
  237. Simple Example
  238. ^^^^^^^^^^^^^^^
  239. ::
  240. // file spaceship.h
  241. #ifndef SPACESHIP_H_
  242. #define SPACESHIP_H_
  243. #include <cstdlib>
  244. namespace spaceships {
  245. class SpaceShip {
  246. public:
  247. SpaceShip(size_t crew);
  248. size_t get_crew_size() const;
  249. private:
  250. const size_t crew;
  251. };
  252. class SpaceShuttle : public SpaceShip {
  253. public:
  254. SpaceShuttle();
  255. };
  256. class Sojuz : public SpaceShip {
  257. public:
  258. Sojuz();
  259. };
  260. template <typename T>
  261. class CargoShip {
  262. public:
  263. CargoShip(const T &cargo);
  264. private:
  265. T cargo;
  266. };
  267. } // namespace spaceships
  268. #endif // SPACESHIP_H_
  269. // file spaceship.cpp
  270. #include "spaceship.h"
  271. namespace spaceships {
  272. // Putting the curly braces in the same line for constructors is OK if it only initializes
  273. // values in the initializer list
  274. SpaceShip::SpaceShip(size_t crew) : crew(crew) { }
  275. size_t SpaceShip::get_crew_size() const
  276. {
  277. return crew;
  278. }
  279. SpaceShuttle::SpaceShuttle() : SpaceShip(7)
  280. {
  281. // doing further initialization
  282. }
  283. Sojuz::Sojuz() : SpaceShip(3)
  284. {
  285. // doing further initialization
  286. }
  287. template <typename T>
  288. CargoShip<T>::CargoShip(const T &cargo) : cargo(cargo) { }
  289. } // namespace spaceships
  290. CMake Code Style
  291. ----------------
  292. - Indent with four spaces.
  293. - Maximum line length 120 characters. When splitting lines, try to
  294. focus on readability where possible (for example, by pairing up
  295. keyword/argument pairs on individual lines).
  296. - Don't put anything in the optional parentheses after ``endforeach()``, ``endif()``, etc.
  297. - Use lowercase (``with_underscores``) for command, function, and macro names.
  298. - For locally scoped variables, use lowercase (``with_underscores``).
  299. - For globally scoped variables, use uppercase (``WITH_UNDERSCORES``).
  300. - Otherwise follow the defaults of the cmake-lint_ project.
  301. Configuring the Code Style for a Project Using EditorConfig
  302. -----------------------------------------------------------
  303. EditorConfig helps developers define and maintain consistent coding styles between different editors and IDEs. The EditorConfig project consists of a file format for defining coding styles and a collection of text editor plugins that enable editors to read the file format and adhere to defined styles. EditorConfig files are easily readable and they work nicely with version control systems.
  304. For more information, see `EditorConfig <https://editorconfig.org>`_ Website.
  305. Documenting Code
  306. ----------------
  307. Please see the guide here: :doc:`documenting-code`.
  308. Structure
  309. ---------
  310. To be written.
  311. Language Features
  312. -----------------
  313. To be written.
  314. .. _cmake-lint: https://github.com/richq/cmake-lint