diff options
Diffstat (limited to 'CodingStyle.md')
-rw-r--r-- | CodingStyle.md | 394 |
1 files changed, 0 insertions, 394 deletions
diff --git a/CodingStyle.md b/CodingStyle.md deleted file mode 100644 index 37e242df0..000000000 --- a/CodingStyle.md +++ /dev/null @@ -1,394 +0,0 @@ -# Coding Style - -Here are some of the basics that we are trying to enforce for our coding style -and conventions. The existing code (as of the commit that adds these lines) is -not yet fully consistent to these rules, but following these rules will make -sure that no one yells at you about your patches. - -We have a script that can be used to reformat code to be reasonably close -to these rules; it's in scripts/whitespace.pl - this script requires -clang-format to be installed (which sadly isn't installed by default on -any of our platforms; even on Mac where clang is the default compiler). - -At the end of this file are some ideas for your .emacs file (if that's -your editor of choice) as well as for QtCreator. If you have settings for -other editors that implement this coding style, please add them here. - -## Basic rules - -* all indentation is tabs (set to 8 char) with the exception of - continuation lines that are aligned with tabs and then spaces - -* all keywords followed by a '(' have a space in between - ``` - if (condition) - - for (i = 0; i < 5; i++) - ``` - -* function calls do NOT have a space between their name and argument - ``` - i = some_function(argument); - ``` - -* usually there is no space on the inside of parenthesis (see examples - above) - -* function / method implementations have their opening curly braces in - column 1 - -* all other opening curly braces follow at the end of the line, with a - space separating them: - ``` - if (condition) { - dosomething(); - dosomethingelse(); - } - ``` - -* both sides of an if / else clause either use or do not use curly braces: - ``` - if (condition) - i = 4; - else - j = 6; - - if (condition) { - i = 6; - } else { - i = 4; - j = 6; - } - ``` - -* use space to make visual separation easier - ``` - a = b + 3 + e / 4; - ``` - -* continuation lines have the operator / comma at the end - ``` - if (very_long_condition_1 || - condition_2) - - b = a + (c + d + - f + z); - ``` - -* in a C++ constructor initialization list, the colon is on the same line and - continuation lines are aligned as the rule above: - ``` - ClassName::ClassName() : x(1), - y(2), - z(3) - { - } - ``` - -* unfortunate inconsistency - - C code usually uses underscores to structure names - ``` - variable_in_C - ``` - - In contrast, C++ code usually uses camelCase - ``` - variableInCPlusPlus - ``` - - where the two meet, use your best judgment and go for best consistency - (i.e., where does the variable "originate") - -* there is a strong preference for lower case file names; sometimes conventions - or outside requirements make camelCase filenames the better (or only) choice, - but absent such an outside reason all file names should be lower case - -* switch statements with blocks are a little bit special (to avoid indenting - too far) - ``` - switch (foo) { - case FIRST: - whatever(); - break; - case SECOND: { - int i; - for (i = 0; i < 5; i++) - do_something(i); - } - } - ``` - -## Coding conventions - -* variable declarations - In C code we really like them to be at the beginning of a code block, - not interspersed in the middle. - in C++ we are a bit less strict about this - but still, try not to go - crazy. Notably, in C++ the lifetime of a variable often coincides with the - lifetime of a resource (e.g. file) and therefore the variable is defined - at the place where the resource is needed. - -* The `*`, `&` and `&&` declarators are grouped with the name, not the type - (classical C-style) as in `char *string` instead of `char* string`. This - reflects the precedence rules of the language: `int &i` means that the name - `i` stands for a reference [to an object with type `int`], not that - `i` stands for an object of the type [reference to `int`]. - Although this may seem like hairsplitting (both interpretations - have the same effect) it is crucial in the - definition of multiple variables, such - as - ``` - struct dive *next, **pprev; - ``` - -* In C++ code, we generally use explicit types in variable declarations for clarity. - Use `auto` sparingly and only in cases where code readability improves. - Two classical examples are: - - Iterators, whose type names often are verbose: - ``` - auto it = m_trackers.find(when); - ``` - is not only distinctly shorter than - ``` - QMap<qint64, gpsTracker>::iterator it = m_trackers.find(when); - ``` - it will also continue working if a different data structure is chosen. - - If the type is given in the same line anyway. Thus, - ``` - auto service = qobject_cast<QLowEnergyService*>(sender()); - ``` - is easier to read than and conveys the same information as - ``` - QLowEnergyService *service = qobject_cast<QLowEnergyService*>(sender()); - ``` - - If the variable is a container that is only assigned to a local variable to - be able to use it in a range-based for loop - ``` - const auto l = device.serviceUuids(); - for (QBluetoothUuid id: serviceUuids) { - ``` - The variable has also to be const to avoid that Qt containers will do a - deep copy when the range bases for loop will call the begin() method - internally. - -* text strings - The default language of subsurface is US English so please use US English - spelling and terminology. - User-visible strings should be passed to the tr() function to enable - translation into other languages. - - like this - ``` - QString msgTitle = tr("Submit user survey."); - ``` - - rather than - ``` - QString msgTitle = "Submit user survey."; - ``` - - This works by default in classes (indirectly) derived from QObject. Each - string to be translated is associated with a context, which corresponds - to the class name. Classes that are not derived from QObject can generate - the tr() functions by using the `Q_DECLARE_TR_FUNCTIONS` macro: - ``` - #include <QCoreApplication> - - class myClass { - Q_DECLARE_TR_FUNCTIONS(gettextfromC) - ... - }; - ``` - - As an alternative, which also works outside of class context, the tr() - function of a different class can be called. This avoids creating multiple - translations for the same string: - ``` - gettextFromC::tr("%1km") - ``` - - The gettextFromC class in the above example was created as a catch-all - context for translations accessed in C code. But it can also be used - from C++ helper functions. To use it from C, include the "core/gettext.h" - header and invoke the translate() macro: - ``` - #include "core/gettext.h" - - report_error(translate("gettextFromC", "Remote storage and local data diverged")); - ``` - It is crucial to pass "gettextFromC" as a first macro argument so that Qt - is able to associate the string with the correct context. - The translate macro returns a cached C-style string, which is generated at runtime - when the particular translation string is encountered for the first time. - It remains valid during the whole application's life time. - - Outside of function context, the `QT_TRANSLATE_NOOP` macro can be used as in - ``` - struct ws_info_t ws_info[100] = { - { QT_TRANSLATE_NOOP("gettextFromC", "integrated"), 0 }, - { QT_TRANSLATE_NOOP("gettextFromC", "belt"), 0 }, - { QT_TRANSLATE_NOOP("gettextFromC", "ankle"), 0 }, - { QT_TRANSLATE_NOOP("gettextFromC", "backplate"), 0 }, - { QT_TRANSLATE_NOOP("gettextFromC", "clip-on"), 0 }, - }; - ``` - Note that here, the texts will be scheduled for translation with the "gettextFromC" - context, but the array is only initialized with the original text. The actual - translation has to be performed later in code. For C-code, the `QT_TRANSLATE_NOOP` - macro is defined in the "core/gettext.h" header. - -* UI text style - These guidelines are designed to ensure consistency in presentation within - Subsurface. - Only the first word of multi-word text strings should be capitalized unless - a word would normally be capitalized mid-sentence, like Africa. This applies - to all UI text including menus, menu items, tool-tips, button text and label - text etc. e.g. "Check for updates" rather than "Check for Updates". - We also capitalize Subsurface (NOTE: not SubSurface) when referring to the - application itself. - Abbreviations should end with a period, e.g. "temp." not "temp" for - temperature - Numerals in chemical formulae should use subscript characters e.g. O₂ not O2 - Partial pressures in Subsurface are, by convention, abbreviated with a single - "p" rather than 2, as in pO₂ not ppO₂ - Where more than one term exists for something, please choose the one already - in use within Subsurface e.g. Cylinder vs. Tank. - - -* string manipulation - * user interface - In UI part of the code use of QString methods is preferred, see this pretty - good guide in [QString documentation][1] - * core components - In the core part of the code, C-string should be used. - C-string manipulation is not always straightforward specifically when - it comes to memory allocation, a set of helper functions has been developed - to help with this. Documentation and usage examples can be found in - [core/membuffer.h][2] - -## Sample Settings - -### Emacs - -These lines in your .emacs file should get you fairly close when it comes -to indentation - many of the other rules you have to follow manually - -``` -;; indentation -(defun c-lineup-arglist-tabs-only (ignored) - "Line up argument lists by tabs, not spaces" - (let* ((anchor (c-langelem-pos c-syntactic-element)) - (column (c-langelem-2nd-pos c-syntactic-element)) - (offset (- (1+ column) anchor)) - (steps (floor offset c-basic-offset))) - (* (max steps 1) - c-basic-offset))) - -(add-hook 'c-mode-common-hook - (lambda () - ;; Add kernel style - (c-add-style - "linux-tabs-only" - '("linux" (c-offsets-alist - (arglist-cont-nonempty - c-lineup-gcc-asm-reg - c-lineup-arglist-tabs-only)))))) - -(add-hook 'c-mode-hook - (lambda () - (let ((filename (buffer-file-name))) - ;; Enable kernel mode for the appropriate files - (setq indent-tabs-mode t) - (c-set-style "linux-tabs-only")))) - -(add-hook 'c++-mode-hook - (lambda () - (let ((filename (buffer-file-name))) - ;; Enable kernel mode for the appropriate files - (setq indent-tabs-mode t) - (c-set-style "linux-tabs-only")))) -``` - -### QtCreator - -These settings seem to get indentation right in QtCreator. Making TAB -always adjust indent makes it hard to add hard tabs before '\' when -creating continuing lines. Copying a tab with your mouse / ctrl-C and -inserting it with ctrl-V seems to work around that problem (use Command -instead of ctrl on your Mac) -Save this XML code below to a file, open Preferences (or Tools->Options) -in QtCreator, pick C++ in the left column and then click on Import... -to open the file you just created. Now you should have a "Subsurface" -style that you can select which should work well for our coding style. - -``` -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE QtCreatorCodeStyle> -<!-- Written by QtCreator 3.0.0, 2014-02-27T07:52:57. --> -<qtcreator> - <data> - <variable>CodeStyleData</variable> - <valuemap type="QVariantMap"> - <value type="bool" key="AlignAssignments">false</value> - <value type="bool" key="AutoSpacesForTabs">false</value> - <value type="bool" key="BindStarToIdentifier">true</value> - <value type="bool" key="BindStarToLeftSpecifier">false</value> - <value type="bool" key="BindStarToRightSpecifier">false</value> - <value type="bool" key="BindStarToTypeName">false</value> - <value type="bool" key="ExtraPaddingForConditionsIfConfusingAlign">false</value> - <value type="bool" key="IndentAccessSpecifiers">false</value> - <value type="bool" key="IndentBlockBody">true</value> - <value type="bool" key="IndentBlockBraces">false</value> - <value type="bool" key="IndentBlocksRelativeToSwitchLabels">false</value> - <value type="bool" key="IndentClassBraces">false</value> - <value type="bool" key="IndentControlFlowRelativeToSwitchLabels">true</value> - <value type="bool" key="IndentDeclarationsRelativeToAccessSpecifiers">true</value> - <value type="bool" key="IndentEnumBraces">false</value> - <value type="bool" key="IndentFunctionBody">true</value> - <value type="bool" key="IndentFunctionBraces">false</value> - <value type="bool" key="IndentNamespaceBody">false</value> - <value type="bool" key="IndentNamespaceBraces">false</value> - <value type="int" key="IndentSize">8</value> - <value type="bool" key="IndentStatementsRelativeToSwitchLabels">true</value> - <value type="bool" key="IndentSwitchLabels">false</value> - <value type="int" key="PaddingMode">2</value> - <value type="bool" key="SpacesForTabs">false</value> - <value type="int" key="TabSize">8</value> - </valuemap> - </data> - <data> - <variable>DisplayName</variable> - <value type="QString">Subsurface</value> - </data> -</qtcreator> -``` - -### Vim - -As everybody knows vim is a way better editor than emacs and thus needs to be -in this file too. Put this into your .vimrc and this should produce something -close to our coding standards. - -``` -" Subsurface coding style -filetype plugin indent on -filetype detect -set cindent tabstop=8 shiftwidth=8 cinoptions=l1,:0,(0,g0 -" TODO: extern "C" gets indented - -" And some sane defaults, optional, but quite nice -set nocompatible -syntax on -colorscheme default -set hls -set is - -" The default blue is just impossible to see on a black terminal -highlight Comment ctermfg=Brown - -" clearly point out when someone have trailing spaces -highlight ExtraWhitespace ctermbg=red guibg=red - -" Show trailing whitespace and spaces before a tab: -match ExtraWhitespace /\s\+$\| \+\ze\t/ -``` - -[1]: http://doc.qt.io/qt-5/qstring.html#manipulating-string-data -[2]: https://github.com/Subsurface-divelog/subsurface/blob/master/core/membuffer.h |