Sync translations from Transifex and run lupdate
[qBittorrent.git] / CODING_GUIDELINES.md
blob0d1ffdb1d30228f592ee5ab484065b1454ae574c
1 # Coding Guidelines
3 All new code **must** follow the following coding guidelines. \
4 If you make changes in a file that still uses another coding style, make sure that you follow these guidelines for your changes. \
5 For programming languages other than C++ (e.g. JavaScript) used in this repository and submodules, unless otherwise specified, coding guidelines listed here applies as much as possible.
7 **Note 1:** I will not take your head if you forget and use another style. However, most probably the request will be delayed until you fix your coding style. \
8 **Note 2:** You can use the `uncrustify` program/tool to clean up any source file. Use it with the `uncrustify.cfg` configuration file found in the root folder. \
9 **Note 3:** There is also a style for QtCreator but it doesn't cover all cases. In QtCreator `Tools->Options...->C++->Code Style->Import...` and choose the `codingStyleQtCreator.xml` file found in the root folder.
11 ## Table Of Contents
13 * [1. New lines & curly braces](#1-new-lines--curly-braces)
14   * [a. Function blocks, class/struct definitions, namespaces](#a-function-blocks-classstruct-definitions-namespaces)
15   * [b. Other code blocks](#b-other-code-blocks)
16   * [c. Blocks in switch's case labels](#c-blocks-in-switchs-case-labels)
17   * [d. If-else statements](#d-if-else-statements)
18   * [e. Single statement if blocks](#e-single-statement-if-blocks)
19   * [f. Acceptable conditions to omit braces](#f-acceptable-conditions-to-omit-braces)
20   * [g. Brace enclosed initializers](#g-brace-enclosed-initializers)
21 * [2. Indentation](#2-indentation)
22 * [3. File encoding and line endings](#3-file-encoding-and-line-endings)
23 * [4. Initialization lists](#4-initialization-lists)
24 * [5. Enums](#5-enums)
25 * [6. Names](#6-names)
26   * [a. Type names and namespaces](#a-type-names-and-namespaces)
27   * [b. Variable names](#b-variable-names)
28   * [c. Private member variable names](#c-private-member-variable-names)
29 * [7. Header inclusion order](#7-header-inclusion-order)
30 * [8. Include guard](#8-include-guard)
31 * [9. Misc](#9-misc)
32 * [10. Git commit message](#10-git-commit-message)
33 * [11. Not covered above](#11-not-covered-above)
35 ---
37 ## 1. New lines & curly braces
39 ### a. Function blocks, class/struct definitions, namespaces
41 ```c++
42 int myFunction(int a)
44     // code
47 void myFunction() {} // empty body
49 MyClass::MyClass(int *parent)
50     : m_parent {parent}
52     // initialize
55 int MyClass::myMethod(int a)
57     // code
60 class MyOtherClass
62 public:
63     // code
65 protected:
66     // code
68 private:
69     // code
72 namespace Name
74     // code
77 // Lambdas
78 [](int arg1, int arg2) -> bool { return arg1 < arg2; }
80 [this](int arg)
82     this->acc += arg;
84 ```
86 ### b. Other code blocks
88 ```c++
89 if (condition)
91     // code
94 for (int a = 0; a < b; ++b)
96     // code
99 switch (a)
101 case 1:
102     // blah
103 case 2:
104     // blah
105 default:
106     // blah
110     // code
114 ### c. Blocks in switch's case labels
116 ```c++
117 switch (var)
119 case 1:
120     {
121         // declare local variables
122         // code
123     }
124     break;
125 case 2:
126     {
127         // declare local variables
128         // code
129     }
130     break;
131 default:
132     // code
136 ### d. If-else statements
138 The `else if`/`else` must be on their own lines:
140 ```c++
141 if (condition)
143     // code
145 else if (condition)
147     // code
149 else
151     // code
155 ### e. Single statement if blocks
157 Most single statement if blocks should look like this:
159 ```c++
160 if (condition)
161     a = a + b;
164 One acceptable exception to this can be `return`, `break` or `continue` statements,
165 provided that the test condition isn't very long and its body statement occupies only one line.
166 However you can still choose to use the first rule.
168 ```c++
169 if (a > 0) return;
171 while (p)
173     // ...
174     if (!b) continue;
178 ### f. Acceptable conditions to omit braces
180 When the conditional statement in `if`/`else` has only one line and its body occupy only one line,
181 this also applies to loops statements. \
182 Notice that for a series of `if - else` branches, if one branch needs braces then all branches must add braces.
184 ```c++
185 if (a < b)  // conditional statement
186     do(a);  // body
188 if (a < b)
189     do(a);
190 else if (a > b)
191     do(b);
192 else
193     do(c);
195 if (a < b)
197     do(a);
199 else if (a > b)
201     // curly braces required here, then all branches should also add them
202     do(b);
203     do(d);
205 else
207     do(c);
211 ### g. Brace enclosed initializers
213 Unlike single-line functions, you must not insert spaces between the brackets and concluded expressions. \
214 But you must insert a space between the variable name and initializer.
216 ```c++
217 Class obj {}; // empty
218 Class obj {expr};
219 Class obj {expr1, /*...,*/ exprN};
220 QVariantMap map {{"key1", 5}, {"key2", 10}};
223 ## 2. Indentation
225 4 spaces.
227 ## 3. File encoding and line endings
229 UTF-8 and Unix-like line ending (LF). Unless some platform specific files need other encodings/line endings.
231 ## 4. Initialization lists
233 Initialization lists should be vertical. This will allow for more easily readable diffs. The initialization colon should be indented and in its own line along with first argument. The rest of the arguments should be indented too and have the comma prepended.
235 ```c++
236 myClass::myClass(int a, int b, int c, int d)
237     : m_a {a}
238     , m_b {b}
239     , m_c {c}
240     , m_d {d}
242     // code
246 ## 5. Enums
248 Enums should be vertical. This will allow for more easily readable diffs. The members should be indented.
250 ```c++
251 enum Days
253     Monday,
254     Tuesday,
255     Wednesday,
256     Thursday,
257     Friday,
258     Saturday,
259     Sunday
263 ## 6. Names
265 All names should be camelCased.
267 ### a. Type names and namespaces
269 Type names and namespaces start with Upper case letter (except POD types).
271 ```c++
272 class ClassName {};
274 struct StructName {};
276 enum EnumName {};
278 typedef QList<ClassName> SomeList;
280 namespace NamespaceName
285 ### b. Variable names
287 Variable names start with lower case letter.
289 ```c++
290 int myVar;
293 ### c. Private member variable names
295 Private member variable names start with lower case letter and should have ```m_``` prefix.
297 ```c++
298 class MyClass
300     int m_myVar;
304 ## 7. Header inclusion order
306 The headers should be placed in the following group order:
308 1. Module header (in .cpp)
309 2. C++ Standard Library headers
310 3. System headers
311 4. Boost library headers
312 5. Libtorrent headers
313 6. Qt headers
314 7. qBittorrent's own headers, starting from the *base* headers.
316 The headers should be ordered alphabetically within each group. \
317 If there are conditionals for the same header group, then put them at the bottom of the respective group. \
318 If there are conditionals that contain headers from several different header groups, then put them above the "qBittorrent's own headers" group.
320 One exception is the header containing the library version (for example, QtGlobal), this particular header isn't constrained by the aforementioned order.
322 Example:
324 ```c++
325 // file: examplewidget.cpp
327 // Module header
328 #include "examplewidget.h"
330 // exceptions, headers containing version number
331 #include <boost/version.hpp>
332 #include <libtorrent/version.hpp>
333 #include <QtGlobal>
335 // C++ Standard Library headers
336 #include <cstdio>
338 #ifdef Q_OS_WIN  // conditional
339 #include <cmath>
340 #endif
342 // System headers
343 #ifdef Q_OS_WIN
344 #include <Windows.h>
345 #endif
347 // Boost library headers
348 #include <boost/circular_buffer.hpp>
350 // Libtorrent headers
351 #include <libtorrent/session.hpp>
353 // Qt headers
354 #include <QString>
355 #include <QUrl>
357 #ifdef Q_OS_MACOS  // conditional
358 #include <QFont>
359 #endif
361 // conditional that contains headers from several different header groups
362 #if LIBTORRENT_VERSION_NUM >= 10100
363 #include <memory>
364 #include <QElapsedTimer>
365 #endif
367 // qBittorrent's own headers
368 #include "base/bittorrent/infohash.h"
369 #include "anothermodule.h"
370 #include "ui_examplewidget.h"
373 ## 8. Include guard
375 `#pragma once` must be used instead of a "classic include guard":
377 ```c++
378 // examplewidget.h
380 #pragma once
382 #include <QWidget>
384 class ExampleWidget : public QWidget
386     // (some code omitted)
391 ## 9. Misc
393 * Line breaks for long lines with operation:
395   ```c++
396   a += "b"
397     + "c"
398     + "d";
399   ```
401 * **auto** keyword
403   We allow the use of the **auto** keyword only where it is strictly necessary (for example, to declare a lambda object, etc.), or where it **enhances** the readability of the code. \
404   Declarations for which one can gather enough information about the object interface (type) from its name or the usage pattern (an iterator or a loop variable are good examples of clear patterns) or the right part of the expression nicely fit here.
406   When weighing whether to use an auto-typed variable please think about potential reviewers of your code, who will read it as a plain diff (on github.com, for instance). \
407   Please make sure that such reviewers can understand the code completely and without excessive effort.
409   Some valid use cases:
411   * Container iteration and casts:
413     ```c++
414     template <typename List>
415     void doSomethingWithList(const List &list)
416     {
417         foreach (const auto &item, list)
418         {
419             // we don't know item type here so we use 'auto' keyword
420             // do something with item
421         }
422     }
424     for (auto it = container.begin(), end = container.end(); it != end; ++it)
425     {
426         // we don't need to know the exact iterator type,
427         // because all iterators have the same interface
428     }
430     auto spinBox = static_cast<QSpinBox*>(sender());
431     // we know the variable type based on the right-hand expression
432     ```
434   * Notice the spaces in the following specific situations:
436     ```c++
437     // Before and after the assignment and other binary (and ternary) operators there should be a space
438     // There should not be a space between increment/decrement and its operand
439     a += 20;
440     a = (b <= MAX_B ? b : MAX_B);
441     ++a;
442     --b;
443     for (int a = 0; a < b; ++b)
444     {
445     }
446     // Range-based for loop, spaces before and after the colon
447     for (auto i : container)
448     {
449     }
450     // Derived class, spaces before and after the colon
451     class Derived : public Base
452     {
453     };
454     ```
456 * Prefer pre-increment, pre-decrement operators
458   ```c++
459   ++i, --j;  // Yes
460   i++, j--;  // No
461   ```
463 * private/public/protected must not be indented
465 * Preprocessor commands must go at line start
467 * Method definitions aren't allowed in header files
469 ## 10. Git commit message
471 1. Limit the subject line to 50 characters. Subject should contain only the very essence of the changes (you should avoid extra details and internals)
472 2. Separate subject from body with a blank line
473 3. Capitalize the subject line
474 4. Do not end the subject line with a period
475 5. Use the imperative mood in the subject line (it's like you're ordering the program to do something (e.g. "Don't create temporary substrings")
476 6. Wrap the body at 72 characters
477 7. Use the body to explain what and why vs. how
478 8. If commit fixes a reported issue, mention it in the message body (e.g. `Closes #4134.`)
480 ## 11. Not covered above
482 If something isn't covered above, just follow the same style the file you are editing has. \
483 *This guide is not exhaustive and the style for a particular piece of code not specified here will be determined by project members on code review.*