| = mfbt style rules = | |
| == Line length == | |
| The line limit is 80 characters, except that excessively long blocks of | |
| preprocessor directives may exceed this if it makes the code more readable (e.g. | |
| MOZ_STATIC_ASSERT in Assertions.h.), and unbreakable text in comments (e.g. | |
| URLs) may exceed this as well. Wrap expressions after binary operators. | |
| == Capitalization == | |
| Standalone functions, classes, structs, and template parameters are named | |
| InterCaps-style. Member functions and fields in classes and structs are named | |
| camelCaps-style. | |
| == Indentation == | |
| Indentation is two spaces, never tabs. | |
| if (x == 2) | |
| return 17; | |
| == Whitespace == | |
| Surround binary operators with a single space on either side. | |
| if (x == 2) | |
| return 17; | |
| When describing pointer types, the * shall be adjacent to the type name. (Same | |
| goes for references -- & goes by the type name.) | |
| int | |
| Foo(int* p) | |
| { | |
| typedef void* VoidPtr; | |
| int& i = *p; | |
| } | |
| A corollary: don't mix declaration types by declaring a T and a T* (or a T**, | |
| &c.) in the same declaration. | |
| T* foo, bar; // BAD | |
| == Expressions == | |
| Ternary expressions (a ? b : c) should use only one line if sufficiently short. | |
| Longer ternary expressions should use multiple lines. The condition, | |
| consequent, and alternative should each be on separate lines (each part | |
| overflowing to additional lines as necessary), and the ? and : should be aligned | |
| with the start of the condition: | |
| size_t | |
| BinaryTree::height() | |
| { | |
| return isLeaf() | |
| ? 0 | |
| : 1 + std::max(left()->height(), | |
| right()->height()); | |
| } | |
| == Bracing == | |
| Don't brace single statements. | |
| if (y == 7) | |
| return 3; | |
| for (size_t i = 0; i < 5; i++) | |
| frob(i); | |
| But do brace them if the statement (or condition(s) or any additional | |
| consequents, if the braces would be associated with an if statement) occupies | |
| multiple lines. | |
| if (cond1 || | |
| cond2) | |
| { | |
| action(); | |
| } | |
| if (cond1) { | |
| consequent(); | |
| } else { | |
| alternative(arg1, | |
| arg2); | |
| } | |
| if (cond1 || cond2) { | |
| callMethod(arg1, | |
| arg2); | |
| } | |
| for (size_t j = 0; | |
| j < 17; | |
| j++) | |
| { | |
| action(); | |
| } | |
| Braces in control flow go at the end of the line except when associated with an | |
| |if| or loop-head where the condition covers multiple lines | |
| == Classes and structs == | |
| Inside class and structure definitions, public/private consume one level of | |
| indentation. | |
| class Baz | |
| { | |
| public: | |
| Baz() { } | |
| }; | |
| The absence of public/private in structs in which all members are public still | |
| consumes a level. | |
| struct Foo | |
| { | |
| int field; | |
| }; | |
| Braces delimiting a class or struct go on their own lines. | |
| Member initialization in constructors should be formatted as follows: | |
| class Fnord | |
| { | |
| size_t s1, s2, s3, s4, s5; | |
| public: | |
| Fnord(size_t s) : s1(s), s2(s), s3(s), s4(s), s5(s) { } | |
| Fnord() | |
| : s1(0), /* member initialization can be compressed if desired */ | |
| s2(0), | |
| s3(0), | |
| s4(0), | |
| s5(0) | |
| { | |
| ... | |
| } | |
| }; | |
| Fields should go first in the class so that the basic structure is all in one | |
| place, consistently. | |
| Use the inline keyword to annotate functions defined inline in a header. (If | |
| the function is defined inline in the class, don't bother adding it | |
| redundantly.) | |
| Explicitly delete (using Attributes.h's MOZ_DELETE) the copy constructor and | |
| assignment operator from classes not intended to be copied or assigned to avoid | |
| mistakes. | |
| class Funky | |
| { | |
| public: | |
| Funky() { } | |
| private: | |
| Funky(const Funky& other) MOZ_DELETE; | |
| void operator=(const Funky& other) MOZ_DELETE; | |
| }; | |
| Include a blank line between sections of structs and classes with different | |
| access control. | |
| The "get" prefix is used when a method is fallible. If it's infallible, don't | |
| use it. | |
| class String | |
| { | |
| public: | |
| size_t length() const; // not getLength() | |
| }; | |
| == Templates == | |
| Capitalize template parameter names to distinguish them from fields. | |
| template<size_t KeySize, typename T> | |
| class BloomFilter | |
| { | |
| }; | |
| Use single-letter names if it makes sense (T for an arbitrary type, K for key | |
| type, V for value type, &c.). Otherwise use InterCaps-style names. | |
| When declaring or defining a function, template<...> goes on one line, the | |
| return type and other specifiers go on another line, and the function name and | |
| argument list go on a third line. | |
| template<typename T> | |
| inline bool | |
| Vector::add(T t) | |
| { | |
| } | |
| == Namespaces == | |
| All C++ code shall be in the mozilla namespace, except that functionality only | |
| used to implement external-facing API should be in the mozilla::detail | |
| namespace, indicating that it should not be directly used. | |
| Namespace opening braces go on the same line as the namespace declaration. | |
| Namespace closing braces shall be commented. Namespace contents are not | |
| indented. | |
| namespace mozilla { | |
| ... | |
| } // namespace mozilla | |
| Don't use |using| in a header unless it's confined to a class or method. | |
| Implementation files for out-of-line functionality may use |using|. | |
| Name data structures and methods which must be usable in C code with a Moz* | |
| prefix, e.g. MozCustomStructure. If the data structure is not meant to be used | |
| outside of the header in which it is found (i.e. it would be in mozilla::detail | |
| but for its being required to work in C code), add a corresponding comment to | |
| highlight this. | |
| == #includes == | |
| Headers that include mfbt headers use a fully-qualified include path, even if | |
| full qualification is not strictly necessary. | |
| #include "mozilla/Assertions.h" | |
| mfbt headers should be included first, alphabetically. Standard includes should | |
| follow, separated from mfbt includes by a blank line. | |
| #include "mozilla/Assertions.h" | |
| #include "mozilla/Attributes.h" | |
| #include <string.h> | |
| If a header dependency is limited simply to the existence of a class, | |
| forward-declare it rather than #include that header. | |
| namespace mozilla { | |
| class BloomFilter; | |
| extern bool | |
| Test(BloomFilter* bf); | |
| } // namespace mozilla | |
| == Preprocessor == | |
| Include guards should be named by determining the fully-qualified include path, | |
| then substituting _ for / and . in it, and finally appending a trailing _. For | |
| example, "mozilla/Assertions.h" becomes mozilla_Assertions_h_. | |
| Nested preprocessor directives indent the directive name (but not the #) by two | |
| spaces. | |
| #ifdef __clang__ | |
| # define FOO ... | |
| #else | |
| # define FOO ... | |
| #endif | |
| Comments within nested preprocessor directives align with directive names at | |
| that nesting depth. | |
| #if defined(__GNUC__) | |
| /* gcc supports C++11 override syntax. */ | |
| # define MOZ_OVERRIDE override | |
| #else | |
| # define MOZ_OVERRIDE /* unsupported */ | |
| #endif | |
| Feature-testing macros may be defined to nothing. Macros intended to be | |
| textually expanded should be defined to a comment indicating non-support, as | |
| above or as appropriate to the situation. | |
| No particular preference is expressed between testing for a macro being defined | |
| using defined(...) and using #ifdef. | |
| When defining a macro with different expansions for different compilers, the top | |
| level of distinction should be the compiler, and the next nested level should be | |
| the compiler version. Clang seems likely to be around for awhile, so to reduce | |
| confusion test for it separately from gcc even when it's not strictly necessary. | |
| #if defined(__clang__) | |
| #elif defined(__GNUC__) | |
| # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) | |
| # else | |
| # endif | |
| #elif defined(_MSC_VER) | |
| #endif | |
| But don't distinguish clang's feature support using version checks: use the | |
| __has_feature() and __has_extension() macros instead, because vendors may | |
| customize clang's version numbers. | |
| Use a MOZ_* prefix when defining macros (e.g. MOZ_OVERRIDE, MOZ_LIKELY, and so | |
| on) that are part of the mfbt interface. (C++ implementation files implementing | |
| mfbt's interface but which are not directly part of that interface may ignore | |
| this rule.) | |
| Prefer inline functions to macros whenever possible. | |
| == Comments == | |
| Header files shall have a short descriptive comment underneath license | |
| boilerplate indicating what functionality the file implements, to be picked up | |
| by MXR and displayed in directory listings. (But see bug 717196, which | |
| currently prevents MXR from doing this if the MPL2 boilerplate is used.) | |
| Assertions.h: | |
| ...license boilerplate... | |
| /* Implementations of runtime and static assertion macros for C and C++. */ | |
| Classes intended for public use shall have interface comments explaining their | |
| functionality from the user's perspective. These comments shall include | |
| examples of how the relevant functionality might be used. These interface | |
| comments use /** */ doxygen/Javadoc-style comments. | |
| /** | |
| * The Frobber class simplifies the process of frobbing. | |
| */ | |
| class Frobber | |
| { | |
| }; | |
| Comments describing implementation details (tradeoffs considered, assumptions | |
| made, mathematical background, &c.) occur separately from interface comments so | |
| that users need not consider them. They should go inside the class definition | |
| or inside the appropriate method, depending on the specificity of the comment. | |
| Headers which are intended to be C-compatible shall use only /**/-style | |
| comments. (Code examples nested inside documentation comments may use //-style | |
| comments.) Headers which are C++-compatible may also use //-style comments. | |
| Non-interface comments that are /**/-style shall not also be doxygen-style. | |
| Use Python-style ** to denote exponentiation inside comments, not ^ (which can | |
| be confused with C-style bitwise xor). If you're writing sufficiently complex | |
| math, feel free to descend into LaTeX math mode ;-) inside implementation | |
| comments if you need to. (But keep it out of interface comments, because most | |
| people probably haven't seen LaTeX.) | |
| == Miscellaneous == | |
| Enclose C-compatible code in |extern "C"| blocks, and #ifdef __cplusplus the | |
| block start/end as needed. The contents of these blocks should not be indented. | |
| Add new functionality to new headers unless an existing header makes sense. | |
| Err on the side of more headers rather than fewer, as this helps to minimize | |
| dependencies. Don't add anything to Util.h, which will be split into multiple | |
| headers at some point (bug 713082). | |
| Don't use bool for argument types unless the method is a "set" or "enable"-style | |
| method where the method name and bool value together indicate the sense of its | |
| effect. Use well-named enums in all other places, so that the semantics of the | |
| argument are clear at a glance and do not require knowing how the method | |
| interprets that argument. | |
| void | |
| setVisible(bool visible); // true clearly means visible, false clearly not | |
| enum Enumerability { | |
| Enumerable, | |
| NonEnumerable | |
| }; | |
| bool | |
| DefineProperty(JSObject* obj, const char* name, Value v, Enumerability e); | |
| Use NULL for the null pointer constant. | |
| If a consequent in an if-statement ends with a return, don't specify an else. | |
| The else would be redundant with the return, and not using it avoids excess | |
| indentation. If you feel the if-else alternation is important as a way to | |
| think about the choice being made, consider a ternary expression instead. | |
| // BAD | |
| if (f()) | |
| return 2; | |
| else | |
| return 5; | |
| // GOOD | |
| if (f()) | |
| return 2; | |
| return 5; | |
| // GOOD | |
| return f() ? 2 : 5 |