From f3c05e9854f9913d1ddffcbf58dc02f7b354ba84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 3 Aug 2012 15:27:53 +0200 Subject: [PATCH] Coding style guide is now shared with Corrade. --- doc/coding-style.dox | 393 ++----------------------------------------- 1 file changed, 10 insertions(+), 383 deletions(-) diff --git a/doc/coding-style.dox b/doc/coding-style.dox index 5a06bdfbd..acab6dc81 100644 --- a/doc/coding-style.dox +++ b/doc/coding-style.dox @@ -9,377 +9,32 @@ Please note that if you have a good excuse to either break the rules or modify them, feel free to do it (and update this guide accordingly, if appropriate). Nothing is worse than rule that hurts productivity instead of improving it. -You can also take inspiration from other thorougly written coding style -guidelines of large projects: +This guide builds upon Corrade's coding style guide and extends it where +needed. You are encouraged to read it first: - - LLVM: http://llvm.org/docs/CodingStandards.html - - Qt: http://qt-project.org/wiki/Qt_Coding_Style - -@section cmake CMake code - -All cmake functions and macros (e.g. `add_executable()`, `set()`) are -lowercase, keywords (e.g. `FILES`, `DESTINATION`) are uppercase. Variables are -mostly uppercase with underscores between words, except for variables with -direct relation to any named target - then they have the target name as prefix -with no case change, followed with underscore, the rest of variable name is -uppercase, e.g. variable holding all sources for target `MagnuMeshTools` will -be named `MagnumMeshTools_SRCS`. - -Multi-line calls (i.e. `set()`) have trailing parenthesis on the same line as -last parameter, *not* on separate line: -@code -set(Magnum_SRCS - Object.cpp - Camera.cpp - Light.cpp) -@endcode + - @ref corrade-coding-style @section cpp C++ code -@subsection cpp-files File naming and directory structure - -All C++ header and source files are named after the class they contain with no -case change. Thus there should be only one class per file, but if the classes -are closely related and small enough, you can make an exception (see Query.h -or TypeTraits.h for example). - -Supporting headers (not relevant to end user), such as various `configure.h`, -`visibility.h` etc., which are used only internally and don't contain any -code, should have first letter of the name lowercased to distinguish them from -API headers. - -Code in the root Magnum namespace is in `src/` directory, each subnamespace is -in its own subdirectory. Unit tests are in `Test` subnamespace (and -subdirectory). Implementation details (helper classes etc.) which shouldn't be -visible to end users should be in `Implementation` subnamespace in the same -file as the class/function for which the implementation is. See @ref documentation -section below for guide how to hide it also from Doxygen documentation. - @subsection cpp-headers Headers -Headers have an strict structure. Include guards are basically include path -with slashes replaced with underscores to make refactoring as easy as possible. -Directly after them is license block, blank line, then file documentation, -blank line and after that the contents of the header. Include guard ending is -only `endif`, without any additional comments. - -It's probably common practice, but repeating won't hurt: headers shouldn't -have `using` declarations inside them (unless there is good excuse, see -Magnum.h). - -@subsection cpp-sources Source files - -Source file have similar structure as headers - first license block, then -blank line, then the includes, then contents of the file. - -Unlike headers, it's good to use `using` declaration in source files as much -as needed to make the code less verbose (unless the name is used only once). +Headers shouldn't have `using` declarations inside them (unless there is good +excuse, see Magnum.h). @subsection cpp-format Code format @subsubsection cpp-naming Naming -Namespaces, classes and structs, enums, type template names and static -constants should be named with `CamelCase`, i.e. first letter of the name and -each successive word uppercase, other lowercase. E.g. `%CubeMapTextureArray`. -Classes with pure virtual methods or base classes which are not meant to be -used directly should be prefixed with `Abstract`. If the class is not meant -to be instanced directly and doesn't have any pure virtual methods, consider -using pure virtual destructor (see AbstractTexture source for example). - -Functions, function parameters, non-type template names and variables should -be named with `camelCase`, i.e. first letter of the name lowercase, each -successive word starting with uppercase. E.g. `generateFlatNormals()`. - -Preprocessor macros should be written in uppercase with underscores between -words, e.g. `MAGNUM_EXPORTING`. - -Redundant information and abbrevations in names are not recommended (use -`determinant`, `inverse` and `attribute` instead of `det`, `inv` and `attr`). -Hungarian notation, `I` and `E` prefixes for interfaces and enums are -forbidden and cruelly punished, if found. Acronyms should be written with -first letter uppercase only to avoid visual collision with preprocessor macros -(`Http`, `Collada` and `Bptc` instead of `HTTP`, `COLLADA` and `BPTC`). When -writing wrappers for OpenGL functions and defines, try to match the original -name as closely as possible, although expanding abbrevations (and removing -redundant prefixes) is encouraged. - -Private variables clashing with (mostly getter) function names can have -one underscore before them, don't use two underscores, as they are reserved -for internal usage by the C++ standard. Underscores before the name shouldn't -be used in public API or function parameters, as it looks ugly in the -documentation. - -@subsubsection cpp-namespace Namespace declarations - -Namespace declaration is on one line, separated with blank lines on both -sides. The code inside the declaration is not indented to save horizontal -space. -@code -namespace Magnum { namespace Math { namespace Geometry { - -// ... - -}}} -@endcode - -The only exception is with forward declarations: use indentation where it -improves readability, e.g.: -@code -namespace Corrade { namespace PluginManager { - class AbstractPluginManager; -}} - -namespace Magnum { - -namespace Math { - class Matrix4; - - namespace Geometry { - class Distance; - } -} - -// the actual code... - -} -@endcode - -@subsubsection cpp-classes Class and structure declarations - -Class and structure protection levels are ordered as following: first friend -declarations, then deleted copy/move constructors and assignment operators, -then public members, then protected members and finally private members, so -class public interface is easy to spot at the top of the file. - -Members are ordered as following: first classes and enums, then static -functions, then non-static functions, then static variables, then non-static -variables. Again, classes and methods are more important for user than -variables, static members are more important than non-static. - -@subsubsection cpp-style Blocks, whitespace and indentation - -The goal is to preserve readability with minimal amount of wasted vertical -and horizontal space. - -Each file must have one blank line at the end (Git will warn you in the -diff if it's not the case), indentation is done exclusively with spaces (4 -spaces). Trailing whitespaces are not permitted (and you should set up your -Git installation to warn about that). - -The code should be wrapped around 80th column, exceptions for long single-line -statements are allowed unless it hurts readability. - -Indented is everything except namespace declarations (as specified above) - -blocks, class protection levels, `case` statements. Overlong line breaks are -indented also with 4 spaces or better where it makes more sense (e.g. for -aligning similar code), multiline comments are indented with three spaces for -the comment text block to be aligned. - -Whitespace is **not allowed** inside parentheses and between function name or -branch/loop statement and left parenthesis (or between constructed variable -name and left brace) and before semicolon. It **must be** around block braces -if the block is not empty. It **must not** be space before, but after the -comma. -@code -if ( statement ){foo (a ,b) ;} // awful! -if(statement) { foo(a, b); } // good -@endcode - -Whitespace should be around operators with low precedence (namely `+`, `-`, -`<<`, `>>` but not on unary `-`), around all boolean and comparison operators, -around `=` and related operators and around ternary operator. Whitespace is -should be around `/`, `*`, `%` to indicate they have precedence before -addition and substraction. Whitespace can or need not to be around binary -operators, whichever looks better in particular content. - -Block opening braces start on the same line as corresponding statement (class/ -function declaration, branch and loop statement), `else` and `else if` -statements have both braces on the same line too: -@code -if(expression) { - // ... -} else if(another || expression) { - // ... -} else { - // ... -} -@endcode - -If the block is only one statement and short enough, it can be on the same line: -@code -void setClearDepth(GLfloat depth) { clearDepth = depth; } -@endcode -@code -if(!initialized) return false; -@endcode - -@subsubsection cpp-switches Switch statements - -Switch statements are usually very verbose and thus they are often subject of -various shortening and whitespace tricks. The goal is to make them as readable -as possible without wasting too much vertical space, for example: -@code -switch(type) { - case Byte: size = 8; break; - case Short: size = 16; break; - case Int: size = 32; break; - case Long: size = 64; break; - case LongLong: size = 128; break; - - default: size = 0; -} -@endcode - -@subsubsection cpp-keywords Class member and function keywords - -Use keywords in this order: `template virtual inline constexpr static`. Only -base virtual functions should have `virtual` keyword, not the -reimplementations. - -@subsubsection cpp-includes Includes - -Includes should be organized into separate groups separated with blank line - -first header belonging to the particular source file (if the file is source -file), then system includes, then includes from the engine itself and then -internal includes used only in the particular file (e.g. `configure.h`). -Includes from system libraries and dependencies are in angle brackets, -includes from engine itself are in quotes. Includes should be sorted by -"level" (e.g. C includes (`<cstdlib>`) before C++ includes -(`<string>`) and those before dependencies (`<GL/gl.h>`)), then by -path name. - -@subsubsection cpp-macros Preprocessor macros - -Preprocessor macros should have the same indentation as surrounding code. If -the macro is long or contains code which should be spanned or multiple lines, -it should be wrapped on multiple lines, each successive line indented and the -line wrapping indicator `\` should be aligned around 80th column, preferably -on some tab-stop. - -@subsection cpp-constexpr Constant expressions and constants - -Use `constexpr` keyword as much as possible, mainly for getters and static -pure functions, e.g. Matrix4::translation(). If the function is not a single -return-statement, try hard to make it so. - -Traits class members and class constants which are not meant to be referenced -or pointed to should be defined as inline (constexpr) function, because -declaring them as static const variable will result in another (probably -unwanted) symbol. - -@subsection cpp-assert Assertions - -Use asserts as much as possible. %Corrade utility library has convenient -`CORRADE_ASSERT()` macro, which does everything needed - checks the statement, -prints given message to error output and exits immediately or returns default -value: - -@code -T operator[](size_t pos) const { - CORRADE_ASSERT(pos < size(), "Index out of range", T()) - return data[pos]; -} -@endcode - -@subsection cpp-forbidden Forbidden C/C++ features - -Don't use C-style casts, use C++-style `static_cast` and `reinterpret_cast` -instead. For numeric types (e.g. casting from int to float) you can use -"constructor cast": - -@code -int a = 22; -int b = 7; -float pi = ((float) a)/b; // bad! -float pi = static_cast(a)/b; // good -float pi = float(a)/b; // even better here -@endcode - -Don't use RTTI (`dynamic_cast` and `std::typeinfo`) and exceptions. They -violate C++ principle of "don't pay for what you don't use" and thus they are -disabled in the code (GCC/Clang option `-fno-rtti -fno-exceptions`). - -@section comments Comments - -All comments should be in C-style (i.e. slash and asterisk, not two slashes). -There should always be space after leading asterisk and before trailing -asterisk, this is also the case for C++-style comments, if are used somewhere -(mostly in the documentation, because nesting of C-style comments is -impossible). - -Multi-line comments should be done in a way which preserves block align (so -when first line starts with slash, asterisk and space, the second line should -be indented with three spaces to align the text). +When writing wrappers for OpenGL functions and defines, try to match the +original name as closely as possible, although expanding abbrevations (and +removing redundant prefixes) is encouraged. @section documentation Doxygen documentation -Doxygen documentation uses C-style comments with two asterisks, each -successive line should start with asterisk and space. However, documentation -block starting at beginning of the line (with no indentation) and spanning -more lines shouldn't have leading asterisks and use whole 80 column width to -avoid wasted space. - -Doxygen commands are prefixed with `@`. - -If the documentation comment is short enough, it can be on one line. If not, -the first line should contain only the slash and two asterisks. However, there -are exceptions for commands that can be on the first line of the multiline -documentation block - namely @c \@page, @c \@name, @c \@file, @c \@namespace -and other commands for "out-of-place" documentation. - -Doxygen documentation is mainly in header files, additional documentation -pages which doesn't belong to any particular class (e.g. namespaces, -overview...) is in `doc/` directory. In source file should be only @c \@todo -items related to particular lines of code. Documentation pages and additional -documentation files should be named in lowercase with dashes between words. -Additional documentation files use `*.dox` extension. - -File documentation block is after license block, it explains only in -@c \@brief what content given header contains. - -Namespace documentation is only in file `namespaces.dox` inside `doc/` -directory. - -Class and function documentation block nearly always starts with an @c \@brief -description (the only exception is enum value documentation). After that is -documentation of template parameters, function parameters and return value. -These are documented only if it's not obvious from the description or -function/parameter name (i.e. it's not needed for setters). - -Trivial function overloads (e.g. const overloads) are marked only with -@c \@overload keyword and are always *after* the original documented function. - -If the documentation is short enough, it can be placed after the documented -element only if it doesn't exceed 80 character limit too much (e.g. enum value -documentation). - -For hiding implementation details from documentation or for working around -Doxygen parsing issues (and false positive warnings), preprocessor define -`DOXYGEN_GENERATING_OUTPUT` can be used. It is defined only when doxygen -generates the documentation. If that works around some Doxygen parsing bug, -don't forget to mark it with @c \@todoc (see below). - @subsection documentation-commands Special documentation commands -@subsubsection documentation-commands-todoc Documentation-related TODOs - -TODOs about documentation (or about Doxygen workarounds) should be written -with @c \@todoc instead of @c \@todo. They will appear on @ref todoc -"separate page". - -@subsubsection documentation-commands-debugoperator Debugging operators - -Operators for printing types on Corrade's debug output should be marked with -@c \@debugoperator, e.g.: -@code -// @debugoperator{Matrix4} -template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Matrix4& value) { - // ... -} -@endcode -They will appear as related functions within documentation of class specified -as the parameter. +Additionally to @c \@todoc and @c \@debugoperator (same as in Corrade), these +are defined: @subsubsection documentation-commands-collisionoperator Physics collision operators @@ -425,33 +80,5 @@ noted in the description. All classes and functions using those commands are cross-referenced in page @ref required-extensions. -@section git Git commit messages, branch and tag format - -It is encouraged to follow best practices of git commit messages as explained -here: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html - -In short, each commit message should be in this format, each line at most 72 -characters long: - -~~~~ -Capitalized short summary - -More detailed explanation text, if necessary, wrapped on multiple lines. - - - Bullet points, indented with one space before (if there is preceeding - paragraph) and one space after the bullet, indented to have the text - aligned. Colons are allowed too, but not mixed. - - Bullet points are separated from surrounding text with blank lines. - -It is good to use *emphasise*, _underline_ or `code` as in Markdown, if -necessary, but they shouldn't be overused. - - Multi-line code examples are indented with four spaces, as in Markdown - syntax. -~~~~ - -Branches and tags should be named with lowercase names with words separated -with colons (`-`), e.g. `physics-performance-tweaks`. Version tags start with -`v`, followed by version number, e.g. `v1.0.3`. */ }