diff --git a/doc/CODING_STYLE.md b/doc/CODING_STYLE.md new file mode 100644 index 0000000000..614057737d --- /dev/null +++ b/doc/CODING_STYLE.md @@ -0,0 +1,200 @@ +Panda3D C++ Style Guide +======================= + +Rather than try to justify every decision made, this document attempts to be as +at-a-glance as possible. Examples provided where necessary to illustrate best +practices. + +Note that this style guide is, for the most part, not very strict, and there +are exceptions to every rule. However, this guide does serve to illustrate the +preferred style for the entire codebase. + +Naming conventions +------------------ + +- **Classes**: `CamelCaseFirstUpper` +- **Filenames**: `lowerCamelCase.h`, `lowerCamelCase.cxx` + - Note, every header file must have a unique filename. They are all + installed into the same path. +- **Functions**: `lower_snake_case_without_prefix` +- **Local variables**: `lower_snake_case_without_prefix` +- **Member variables**: `_lower_snake_case_with_initial_score` +- **Enum constants**: `SE_enum_value` (for an enum type named SomeEnum) +- **Enum class constants**: `ENUM_VALUE` + +Indentation +----------- + +Always use two spaces to indent. Tabs should never appear in a C++ file. + +Access modifiers (`public`/`private`/`protected`/`PUBLISHED`) are never +indented relative to the class they are in, and do not affect the indentation +of the surrounding lines. + +Spaces +------ + +Always put one space after a control keyword, before the condition's +parentheses. Don't pad the inside of parentheses with spaces unless there are +several nested parenthetical expressions and the extra spaces contribute +substantially to readability. + + if (x == y) { + +Don't place a space after a function name (declarations, definitions, or calls). + + void function_name(); + ... + function_name(); + +Always place a space after each comma in an arguments list. + + function_call(x, y, z); + +Always pad binary operators with a space on either side. + + a || b + +Never end a line with trailing whitespace. + +Function definitions +-------------------- + +The recipe for a function definition is: + +1. JavaDoc comment describing the purpose of the function +2. Function return value and class +3. **At the beginning of its own line,** the function's name, followed by the + parameter list and anything else necessary for the function's signature. +4. Opening brace on the same line, not its own line. +5. Single empty line before next definition. + +For example: + + /** + * String documenting the function, in JavaDoc style. + */ + void ClassName:: + function_name(int x, int y) const { + ... + } + + /** + * ... + */ + ... + +If the function is a constructor with an initializer list, the `:` goes on the +same line as the constructor name, and the initializers are listed *one per +line*, indented by two spaces. + + ClassName:: + ClassName() : + _a("a"), + _b("b"), + _c("c") + { + } + +Empty function bodies in a .cxx/.I file still contain a single line break (i.e. +to put `}` on its own line). In a .h file, an empty function can be given as +`{}` + +Braces +------ + +Always put an opening `{` on the same line as the statement that calls for the +brace. There is exactly one exception to this: constructors with initializer +lists. + + SomeClass:: + SomeClass() : + _one(1), + _two(2) + { + if (_one < _two) { + ... + } + } + +Comments +-------- + +Comments should be properly-formatted English, with proper capitalization and +punctuation rules. There are two spaces between sentences. + +Note that `//` is preferred over `/*` except in some special circumstances. + +Except for commented-out lines of code, there should be a space between the +first word and the `//`. + + // The following line is commented out. + //if (value == 0) { + +Line limits and continuations +----------------------------- + +Lines should be limited to 80 columns. This is not a hard limit, and lines +should not be wrapped if doing so hurts readability, except comments, which +should always be wrapped. + +Continuation lines shall be aligned to the same column as appropriate, or +indented two spaces otherwise: + + if ((a && + b) || + c) { + ... + } + +When choosing where to break a line, these are the preferred places, from best +to worst: + +1. If inside a comment, break the comment to as many lines as appropriate, but + only after moving the comment to its own line. +2. After a comma in an argument/parameter list. +3. After a binary operator (leaving the binary operator at the end of the line) +4. In a function declaration, after the function's return type but before the + function's name. (Indented by two spaces.) +5. In a log statement with `<<`, before a `<<`. (Avoid ending a line with `<<`) +6. Around a string literal, at a natural word boundary, with a space left on + the previous line (e.g. `"This is a "` / `"continued string literal."`) +7. After the `=` in an assignment operator. +8. As a last resort, after the opening `(` in a function call. + +If none of these rules can apply cleanly, it is okay to have lines extend past +the 80-column boundary. + +Alignment +--------- + +Avoid the temptation to align multiple assignments in consecutive lines of code. +While it may look neater, it decreases the maintainability of the code. + +Asterisks and ampersands indicating a pointer or reference type should always +be aligned against the name, and not the type: + + Type *x, &y; + +Grouping +-------- + +Try to group logically-similar lines, separating them with a single blank line. + +Modern language features +------------------------ + +Panda3D is a C++11 project. The use of the following modern language features +is greatly encouraged: + +1. `nullptr` over `NULL` +2. `std::move` and move semantics +3. Range-based for loops + +Using `auto` can be okay, such as when storing an iterator, but consider +creating a typedef for the container type instead. + +Avoid using `std::function` in cases where a lambda can be accepted directly +(using a template function), since it has extra overhead over lambdas. + +C++14 and C++17 features should be avoided for now.