mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-27 10:50:35 +00:00
f9aac6fb1e
--HG-- extra : rebase_source : 0c11adc6052878710300eea87520345ca7e9143f
384 lines
11 KiB
Plaintext
384 lines
11 KiB
Plaintext
= 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
|