Remove html tags from inline page
[qBittorrent.git] / CODING_GUIDELINES.md
blob90c35485e2daf55af1c2f461c6a7016a11e43fdf
1 All new code **must** follow the following coding guidelines.  
2 If you make changes in a file that still uses another coding style, make sure that you follow these guidelines for your changes.  
3 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.
5 **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.  
6 **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.  
7 **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.  
9 ### Table Of Contents
11 * [1. New lines & curly braces](#1-new-lines--curly-braces)
12   * [a. Function blocks, class/struct definitions, namespaces](#a-function-blocks-classstruct-definitions-namespaces)
13   * [b. Other code blocks](#b-other-code-blocks)
14   * [c. Blocks in switch's case labels](#c-blocks-in-switchs-case-labels)
15   * [d. If-else statements](#d-if-else-statements)
16   * [e. Single statement if blocks](#e-single-statement-if-blocks)
17   * [f. Acceptable conditions to omit braces](#f-acceptable-conditions-to-omit-braces)
18   * [g. Brace enclosed initializers](#g-brace-enclosed-initializers)
19 * [2. Indentation](#2-indentation)
20 * [3. File encoding and line endings](#3-file-encoding-and-line-endings)
21 * [4. Initialization lists](#4-initialization-lists)
22 * [5. Enums](#5-enums)
23 * [6. Names](#6-names)
24   * [a. Type names and namespaces](#a-type-names-and-namespaces)
25   * [b. Variable names](#b-variable-names)
26   * [c. Private member variable names](#c-private-member-variable-names)
27 * [7. Header inclusion order](#7-header-inclusion-order)
28 * [8. Include guard](#8-include-guard)
29 * [9. Misc](#9-misc)
30 * [10. Git commit message](#10-git-commit-message)
31 * [11. Not covered above](#11-not-covered-above)
32 ---
34 ### 1. New lines & curly braces ###
36 #### a. Function blocks, class/struct definitions, namespaces ####
37 ```c++
38 int myFunction(int a)
40     // code
43 void myFunction() {} // empty body
45 MyClass::MyClass(int *parent)
46     : m_parent(parent)
48     // initialize
51 int MyClass::myMethod(int a)
53     // code
56 class MyOtherClass
58 public:
59     // code
61 protected:
62     // code
64 private:
65     // code
68 namespace Name
70     // code
73 // Lambdas
74 [](int arg1, int arg2) -> bool { return arg1 < arg2; }
76 [this](int arg)
78     this->acc += arg;
80 ```
82 #### b. Other code blocks ####
83 ```c++
84 if (condition) {
85     // code
88 for (int a = 0; a < b; ++b) {
89     // code
92 switch (a) {
93 case 1:
94     // blah
95 case 2:
96     // blah
97 default:
98     // blah
102 #### c. Blocks in switch's case labels ####
103 ```c++
104 switch (var) {
105 case 1: {
106         // declare local variables
107         // code
108     }
109     break;
110 case 2: {
111         // declare local variables
112         // code
113     }
114     break;
115 default:
116     // code
120 #### d. If-else statements ####
121 The `else if`/`else` must be on their own lines:
122 ```c++
123 if (condition) {
124     // code
126 else if (condition) {
127     // code
129 else {
130     // code
134 #### e. Single statement if blocks ####
135 Most single statement if blocks should look like this:
136 ```c++
137 if (condition)
138     a = a + b;
141 One acceptable exception to this can be `return`, `break` or `continue` statements,
142 provided that the test condition isn't very long and its body statement occupies only one line.
143 However you can still choose to use the first rule.
144 ```c++
145 if (a > 0) return;
147 while (p) {
148     // ...
149     if (!b) continue;
153 #### f. Acceptable conditions to omit braces ####
154 When the conditional statement in `if`/`else` has only one line and its body occupy only one line,
155 this also applies to loops statements.  
156 Notice that for a series of `if - else` branches, if one branch needs braces then all branches must add braces.
157 ```c++
158 if (a < b)  // conditional statement
159     do(a);  // body
161 if (a < b)
162     do(a);
163 else if (a > b)
164     do(b);
165 else
166     do(c);
168 if (a < b) {
169     do(a);
171 else if (a > b) {  // curly braces required here, then all branches should also add them
172     do(b);
173     do(d);
175 else {
176     do(c);
180 #### g. Brace enclosed initializers ####
181 Unlike single-line functions, you must not insert spaces between the brackets and concluded expressions.<br/>
182 But you must insert a space between the variable name and initializer.
183 ```c++
184 Class obj {}; // empty
185 Class obj {expr};
186 Class obj {expr1, /*...,*/ exprN};
187 QVariantMap map {{"key1", 5}, {"key2", 10}};
190 ### 2. Indentation ###
191 4 spaces.
193 ### 3. File encoding and line endings ###
195 UTF-8 and Unix-like line ending (LF). Unless some platform specific files need other encodings/line endings.
197 ### 4. Initialization lists ###
198 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.
199 ```c++
200 myClass::myClass(int a, int b, int c, int d)
201     : m_a(a)
202     , m_b(b)
203     , m_c(c)
204     , m_d(d)
206     // code
210 ### 5. Enums ###
211 Enums should be vertical. This will allow for more easily readable diffs. The members should be indented.
212 ```c++
213 enum Days
215     Monday,
216     Tuesday,
217     Wednesday,
218     Thursday,
219     Friday,
220     Saturday,
221     Sunday
225 ### 6. Names ###
226 All names should be camelCased.
228 #### a. Type names and namespaces ####
229 Type names and namespaces start with Upper case letter (except POD types).
230 ```c++
231 class ClassName {};
233 struct StructName {};
235 enum EnumName {};
237 typedef QList<ClassName> SomeList;
239 namespace NamespaceName
244 #### b. Variable names ####
245 Variable names start with lower case letter.
246 ```c++
247 int myVar;
250 #### c. Private member variable names ####
251 Private member variable names start with lower case letter and should have ```m_``` prefix.
252 ```c++
253 class MyClass
255     int m_myVar;
259 ### 7. Header inclusion order ###
260 The headers should be placed in the following group order:
261   1. Module header (in .cpp)
262   2. C++ Standard Library headers
263   3. System headers
264   4. Boost library headers
265   5. Libtorrent headers
266   6. Qt headers
267   7. qBittorrent's own headers, starting from the *base* headers.
269 The headers should be ordered alphabetically within each group.  
270 If there are conditionals for the same header group, then put them at the bottom of the respective group.  
271 If there are conditionals that contain headers from several different header groups, then put them above the "qBittorrent's own headers" group.
273 One exception is the header containing the library version (for example, QtGlobal), this particular header isn't constrained by the aforementioned order.
275 Example:
276 ```c++
277 // file: examplewidget.cpp
279 // Module header
280 #include "examplewidget.h"
282 // exceptions, headers containing version number
283 #include <boost/version.hpp>
284 #include <libtorrent/version.hpp>
285 #include <QtGlobal>
287 // C++ Standard Library headers
288 #include <cstdio>
290 #ifdef Q_OS_WIN  // conditional
291 #include <cmath>
292 #endif
294 // System headers
295 #ifdef Q_OS_WIN
296 #include <Windows.h>
297 #endif
299 // Boost library headers
300 #include <boost/circular_buffer.hpp>
302 // Libtorrent headers
303 #include <libtorrent/session.hpp>
305 // Qt headers
306 #include <QString>
307 #include <QUrl>
309 #ifdef Q_OS_MAC  // conditional
310 #include <QFont>
311 #endif
313 // conditional that contains headers from several different header groups
314 #if LIBTORRENT_VERSION_NUM >= 10100
315 #include <memory>
316 #include <QElapsedTimer>
317 #endif
319 // qBittorrent's own headers
320 #include "base/bittorrent/infohash.h"
321 #include "anothermodule.h"
322 #include "ui_examplewidget.h"
325 ### 8. Include guard ###
326 `#pragma once` should be used instead of "include guard" in new code:
327 ```c++
328 // examplewidget.h
330 #pragma once
332 #include <QWidget>
334 class ExampleWidget : public QWidget
336     // (some code omitted)
341 ### 9. Misc ###
343 * Line breaks for long lines with operation:
345 ```c++
346 a += "b"
347   + "c"
348   + "d";
351 * **auto** keyword
353 We allow the use of the **auto** keyword only where it is strictly necessary 
354 (for example, to declare a lambda object, etc.), or where it **enhances** the readability of the code.
355 Declarations for which one can gather enough information about the object interface (type) from its name 
356 or the usage pattern (an iterator or a loop variable are good examples of clear patterns) 
357 or the right part of the expression nicely fit here.<br/>
358 <br/>
359 When weighing whether to use an auto-typed variable please think about potential reviewers of your code, 
360 who will read it as a plain diff (on github.com, for instance). Please make sure that such reviewers can 
361 understand the code completely and without excessive effort.<br/>
362 <br/>
363 Some valid use cases:
364 ```c++
365 template <typename List>
366 void doSomethingWithList(const List &list)
368     foreach (const auto &item, list) {
369         // we don't know item type here so we use 'auto' keyword
370         // do something with item
371     }
374 for (auto it = container.begin(), end = container.end(); it != end; ++it) {
375     // we don't need to know the exact iterator type,
376     // because all iterators have the same interface
379 auto spinBox = static_cast<QSpinBox*>(sender());
380 // we know the variable type based on the right-hand expression
383 * Notice the spaces in the following specific situations:
384 ```c++
385 // Before and after the assignment and other binary (and ternary) operators there should be a space
386 // There should not be a space between increment/decrement and its operand
387 a += 20;
388 a = (b <= MAX_B ? b : MAX_B);
389 ++a;
390 --b;
392 for (int a = 0; a < b; ++b) {
395 // Range-based for loop, spaces before and after the colon
396 for (auto i : container) {
399 // Derived class, spaces before and after the colon
400 class Derived : public Base
405 * Prefer pre-increment, pre-decrement operators
406 ```c++
407 ++i, --j;  // Yes
408 i++, j--;  // No
411 * private/public/protected must not be indented
413 * Preprocessor commands must go at line start
415 * Method definitions aren't allowed in header files
417 ### 10. Git commit message ###
418 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)
419 2. Separate subject from body with a blank line
420 3. Capitalize the subject line
421 4. Do not end the subject line with a period
422 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")
423 6. Wrap the body at 72 characters
424 7. Use the body to explain what and why vs. how
425 8. If commit fixes a reported issue, mention it in the message body (e.g. `Closes #4134.`)
427 ### 11. Not covered above ###
428 If something isn't covered above, just follow the same style the file you are editing has.  
429 *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.*