diff options
Diffstat (limited to 'mfbt/STYLE')
-rw-r--r-- | mfbt/STYLE | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/mfbt/STYLE b/mfbt/STYLE new file mode 100644 index 0000000..2d94c3a --- /dev/null +++ b/mfbt/STYLE @@ -0,0 +1,383 @@ += 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 |