mfbt/STYLE

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mfbt/STYLE	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,382 @@
     1.4 += mfbt style rules =
     1.5 +
     1.6 +== Line length ==
     1.7 +
     1.8 +The line limit is 80 characters, except that excessively long blocks of
     1.9 +preprocessor directives may exceed this if it makes the code more readable (e.g.
    1.10 +MOZ_STATIC_ASSERT in Assertions.h.), and unbreakable text in comments (e.g.
    1.11 +URLs) may exceed this as well.  Wrap expressions after binary operators.
    1.12 +
    1.13 +== Capitalization ==
    1.14 +
    1.15 +Standalone functions, classes, structs, and template parameters are named
    1.16 +InterCaps-style.  Member functions and fields in classes and structs are named
    1.17 +camelCaps-style.
    1.18 +
    1.19 +== Indentation ==
    1.20 +
    1.21 +Indentation is two spaces, never tabs.
    1.22 +
    1.23 +  if (x == 2)
    1.24 +    return 17;
    1.25 +
    1.26 +== Whitespace ==
    1.27 +
    1.28 +Surround binary operators with a single space on either side.
    1.29 +
    1.30 +  if (x == 2)
    1.31 +    return 17;
    1.32 +
    1.33 +When describing pointer types, the * shall be adjacent to the type name.  (Same
    1.34 +goes for references -- & goes by the type name.)
    1.35 +
    1.36 +  int
    1.37 +  Foo(int* p)
    1.38 +  {
    1.39 +    typedef void* VoidPtr;
    1.40 +    int& i = *p;
    1.41 +  }
    1.42 +
    1.43 +A corollary: don't mix declaration types by declaring a T and a T* (or a T**,
    1.44 +&c.) in the same declaration.
    1.45 +
    1.46 +  T* foo, bar; // BAD
    1.47 +
    1.48 +== Expressions ==
    1.49 +
    1.50 +Ternary expressions (a ? b : c) should use only one line if sufficiently short.
    1.51 +Longer ternary expressions should use multiple lines.  The condition,
    1.52 +consequent, and alternative should each be on separate lines (each part
    1.53 +overflowing to additional lines as necessary), and the ? and : should be aligned
    1.54 +with the start of the condition:
    1.55 +
    1.56 +  size_t
    1.57 +  BinaryTree::height()
    1.58 +  {
    1.59 +    return isLeaf()
    1.60 +           ? 0
    1.61 +           : 1 + std::max(left()->height(),
    1.62 +                          right()->height());
    1.63 +  }
    1.64 +
    1.65 +== Bracing ==
    1.66 +
    1.67 +Don't brace single statements.
    1.68 +
    1.69 +  if (y == 7)
    1.70 +    return 3;
    1.71 +  for (size_t i = 0; i < 5; i++)
    1.72 +    frob(i);
    1.73 +
    1.74 +But do brace them if the statement (or condition(s) or any additional
    1.75 +consequents, if the braces would be associated with an if statement) occupies
    1.76 +multiple lines.
    1.77 +
    1.78 +  if (cond1 ||
    1.79 +      cond2)
    1.80 +  {
    1.81 +    action();
    1.82 +  }
    1.83 +  if (cond1) {
    1.84 +    consequent();
    1.85 +  } else {
    1.86 +    alternative(arg1,
    1.87 +                arg2);
    1.88 +  }
    1.89 +  if (cond1 || cond2) {
    1.90 +    callMethod(arg1,
    1.91 +               arg2);
    1.92 +  }
    1.93 +  for (size_t j = 0;
    1.94 +       j < 17;
    1.95 +       j++)
    1.96 +  {
    1.97 +    action();
    1.98 +  }
    1.99 +
   1.100 +Braces in control flow go at the end of the line except when associated with an
   1.101 +|if| or loop-head where the condition covers multiple lines
   1.102 +
   1.103 +== Classes and structs ==
   1.104 +
   1.105 +Inside class and structure definitions, public/private consume one level of
   1.106 +indentation.
   1.107 +
   1.108 +  class Baz
   1.109 +  {
   1.110 +    public:
   1.111 +      Baz() { }
   1.112 +  };
   1.113 +
   1.114 +The absence of public/private in structs in which all members are public still
   1.115 +consumes a level.
   1.116 +
   1.117 +  struct Foo
   1.118 +  {
   1.119 +      int field;
   1.120 +  };
   1.121 +
   1.122 +Braces delimiting a class or struct go on their own lines.
   1.123 +
   1.124 +Member initialization in constructors should be formatted as follows:
   1.125 +
   1.126 +  class Fnord
   1.127 +  {
   1.128 +      size_t s1, s2, s3, s4, s5;
   1.129 +
   1.130 +    public:
   1.131 +      Fnord(size_t s) : s1(s), s2(s), s3(s), s4(s), s5(s) { }
   1.132 +      Fnord()
   1.133 +        : s1(0), /* member initialization can be compressed if desired */
   1.134 +          s2(0),
   1.135 +          s3(0),
   1.136 +          s4(0),
   1.137 +          s5(0)
   1.138 +      {
   1.139 +        ...
   1.140 +      }
   1.141 +  };
   1.142 +
   1.143 +Fields should go first in the class so that the basic structure is all in one
   1.144 +place, consistently.
   1.145 +
   1.146 +Use the inline keyword to annotate functions defined inline in a header.  (If
   1.147 +the function is defined inline in the class, don't bother adding it
   1.148 +redundantly.)
   1.149 +
   1.150 +Explicitly delete (using Attributes.h's MOZ_DELETE) the copy constructor and
   1.151 +assignment operator from classes not intended to be copied or assigned to avoid
   1.152 +mistakes.
   1.153 +
   1.154 +  class Funky
   1.155 +  {
   1.156 +    public:
   1.157 +      Funky() { }
   1.158 +
   1.159 +    private:
   1.160 +      Funky(const Funky& other) MOZ_DELETE;
   1.161 +      void operator=(const Funky& other) MOZ_DELETE;
   1.162 +  };
   1.163 +
   1.164 +Include a blank line between sections of structs and classes with different
   1.165 +access control.
   1.166 +
   1.167 +The "get" prefix is used when a method is fallible.  If it's infallible, don't
   1.168 +use it.
   1.169 +
   1.170 +  class String
   1.171 +  {
   1.172 +    public:
   1.173 +      size_t length() const; // not getLength()
   1.174 +  };
   1.175 +
   1.176 +== Templates ==
   1.177 +
   1.178 +Capitalize template parameter names to distinguish them from fields.
   1.179 +
   1.180 +  template<size_t KeySize, typename T>
   1.181 +  class BloomFilter
   1.182 +  {
   1.183 +  };
   1.184 +
   1.185 +Use single-letter names if it makes sense (T for an arbitrary type, K for key
   1.186 +type, V for value type, &c.).  Otherwise use InterCaps-style names.
   1.187 +
   1.188 +When declaring or defining a function, template<...> goes on one line, the
   1.189 +return type and other specifiers go on another line, and the function name and
   1.190 +argument list go on a third line.
   1.191 +
   1.192 +  template<typename T>
   1.193 +  inline bool
   1.194 +  Vector::add(T t)
   1.195 +  {
   1.196 +  }
   1.197 +
   1.198 +== Namespaces ==
   1.199 +
   1.200 +All C++ code shall be in the mozilla namespace, except that functionality only
   1.201 +used to implement external-facing API should be in the mozilla::detail
   1.202 +namespace, indicating that it should not be directly used.
   1.203 +
   1.204 +Namespace opening braces go on the same line as the namespace declaration.
   1.205 +Namespace closing braces shall be commented.  Namespace contents are not
   1.206 +indented.
   1.207 +
   1.208 +  namespace mozilla {
   1.209 +  ...
   1.210 +  } // namespace mozilla
   1.211 +
   1.212 +Don't use |using| in a header unless it's confined to a class or method.
   1.213 +Implementation files for out-of-line functionality may use |using|.
   1.214 +
   1.215 +Name data structures and methods which must be usable in C code with a Moz*
   1.216 +prefix, e.g. MozCustomStructure.  If the data structure is not meant to be used
   1.217 +outside of the header in which it is found (i.e. it would be in mozilla::detail
   1.218 +but for its being required to work in C code), add a corresponding comment to
   1.219 +highlight this.
   1.220 +
   1.221 +== #includes ==
   1.222 +
   1.223 +Headers that include mfbt headers use a fully-qualified include path, even if
   1.224 +full qualification is not strictly necessary.
   1.225 +
   1.226 +  #include "mozilla/Assertions.h"
   1.227 +
   1.228 +mfbt headers should be included first, alphabetically.  Standard includes should
   1.229 +follow, separated from mfbt includes by a blank line.
   1.230 +
   1.231 +  #include "mozilla/Assertions.h"
   1.232 +  #include "mozilla/Attributes.h"
   1.233 +  
   1.234 +  #include <string.h>
   1.235 +
   1.236 +If a header dependency is limited simply to the existence of a class,
   1.237 +forward-declare it rather than #include that header.
   1.238 +
   1.239 +  namespace mozilla {
   1.240 +  
   1.241 +  class BloomFilter;
   1.242 +  extern bool
   1.243 +  Test(BloomFilter* bf);
   1.244 +  
   1.245 +  } // namespace mozilla
   1.246 +
   1.247 +== Preprocessor ==
   1.248 +
   1.249 +Include guards should be named by determining the fully-qualified include path,
   1.250 +and substituting _ for / and . in it.  For example, "mozilla/Assertions.h"
   1.251 +becomes mozilla_Assertions_h.
   1.252 +
   1.253 +Nested preprocessor directives indent the directive name (but not the #) by two
   1.254 +spaces.
   1.255 +
   1.256 +  #ifdef __clang__
   1.257 +  #  define FOO ...
   1.258 +  #else
   1.259 +  #  define FOO ...
   1.260 +  #endif
   1.261 +
   1.262 +Comments within nested preprocessor directives align with directive names at
   1.263 +that nesting depth.
   1.264 +
   1.265 +  #if defined(__GNUC__)
   1.266 +     /* gcc supports C++11 override syntax. */
   1.267 +  #  define MOZ_OVERRIDE override
   1.268 +  #else
   1.269 +  #  define MOZ_OVERRIDE /* unsupported */
   1.270 +  #endif
   1.271 +
   1.272 +Feature-testing macros may be defined to nothing.  Macros intended to be
   1.273 +textually expanded should be defined to a comment indicating non-support, as
   1.274 +above or as appropriate to the situation.
   1.275 +
   1.276 +No particular preference is expressed between testing for a macro being defined
   1.277 +using defined(...) and using #ifdef.
   1.278 +
   1.279 +When defining a macro with different expansions for different compilers, the top
   1.280 +level of distinction should be the compiler, and the next nested level should be
   1.281 +the compiler version.  Clang seems likely to be around for awhile, so to reduce
   1.282 +confusion test for it separately from gcc even when it's not strictly necessary.
   1.283 +
   1.284 +  #if defined(__clang__)
   1.285 +  #elif defined(__GNUC__)
   1.286 +  #  if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
   1.287 +  #  else
   1.288 +  #  endif
   1.289 +  #elif defined(_MSC_VER)
   1.290 +  #endif
   1.291 +
   1.292 +But don't distinguish clang's feature support using version checks: use the
   1.293 +__has_feature() and __has_extension() macros instead, because vendors may
   1.294 +customize clang's version numbers.
   1.295 +
   1.296 +Use a MOZ_* prefix when defining macros (e.g. MOZ_OVERRIDE, MOZ_LIKELY, and so
   1.297 +on) that are part of the mfbt interface.  (C++ implementation files implementing
   1.298 +mfbt's interface but which are not directly part of that interface may ignore
   1.299 +this rule.)
   1.300 +
   1.301 +Prefer inline functions to macros whenever possible.
   1.302 +
   1.303 +== Comments ==
   1.304 +
   1.305 +Header files shall have a short descriptive comment underneath license
   1.306 +boilerplate indicating what functionality the file implements, to be picked up
   1.307 +by MXR and displayed in directory listings.  (But see bug 717196, which
   1.308 +currently prevents MXR from doing this if the MPL2 boilerplate is used.)
   1.309 +
   1.310 +  Assertions.h:
   1.311 +  ...license boilerplate...
   1.312 +  
   1.313 +  /* Implementations of runtime and static assertion macros for C and C++. */
   1.314 +
   1.315 +Classes intended for public use shall have interface comments explaining their
   1.316 +functionality from the user's perspective.  These comments shall include
   1.317 +examples of how the relevant functionality might be used.  These interface
   1.318 +comments use /** */ doxygen/Javadoc-style comments.
   1.319 +
   1.320 +  /**
   1.321 +   * The Frobber class simplifies the process of frobbing.
   1.322 +   */
   1.323 +  class Frobber
   1.324 +  {
   1.325 +  };
   1.326 +
   1.327 +Comments describing implementation details (tradeoffs considered, assumptions
   1.328 +made, mathematical background, &c.) occur separately from interface comments so
   1.329 +that users need not consider them.  They should go inside the class definition
   1.330 +or inside the appropriate method, depending on the specificity of the comment.
   1.331 +
   1.332 +Headers which are intended to be C-compatible shall use only /**/-style
   1.333 +comments.  (Code examples nested inside documentation comments may use //-style
   1.334 +comments.)  Headers which are C++-compatible may also use //-style comments.
   1.335 +
   1.336 +Non-interface comments that are /**/-style shall not also be doxygen-style.
   1.337 +
   1.338 +Use Python-style ** to denote exponentiation inside comments, not ^ (which can
   1.339 +be confused with C-style bitwise xor).  If you're writing sufficiently complex
   1.340 +math, feel free to descend into LaTeX math mode ;-) inside implementation
   1.341 +comments if you need to.  (But keep it out of interface comments, because most
   1.342 +people probably haven't seen LaTeX.)
   1.343 +
   1.344 +== Miscellaneous ==
   1.345 +
   1.346 +Enclose C-compatible code in |extern "C"| blocks, and #ifdef __cplusplus the
   1.347 +block start/end as needed.  The contents of these blocks should not be indented.
   1.348 +
   1.349 +Add new functionality to new headers unless an existing header makes sense.
   1.350 +Err on the side of more headers rather than fewer, as this helps to minimize
   1.351 +dependencies.
   1.352 +
   1.353 +Don't use bool for argument types unless the method is a "set" or "enable"-style
   1.354 +method where the method name and bool value together indicate the sense of its
   1.355 +effect.  Use well-named enums in all other places, so that the semantics of the
   1.356 +argument are clear at a glance and do not require knowing how the method
   1.357 +interprets that argument.
   1.358 +
   1.359 +  void
   1.360 +  setVisible(bool visible); // true clearly means visible, false clearly not
   1.361 +  enum Enumerability {
   1.362 +    Enumerable,
   1.363 +    NonEnumerable
   1.364 +  };
   1.365 +  bool
   1.366 +  DefineProperty(JSObject* obj, const char* name, Value v, Enumerability e);
   1.367 +
   1.368 +Use NULL for the null pointer constant.
   1.369 +
   1.370 +If a consequent in an if-statement ends with a return, don't specify an else.
   1.371 +The else would be redundant with the return, and not using it avoids excess
   1.372 +indentation.  If you feel the if-else alternation is important as a way to
   1.373 +think about the choice being made, consider a ternary expression instead.
   1.374 +
   1.375 +  // BAD
   1.376 +  if (f())
   1.377 +    return 2;
   1.378 +  else
   1.379 +    return 5;
   1.380 +  // GOOD
   1.381 +  if (f())
   1.382 +    return 2;
   1.383 +  return 5;
   1.384 +  // GOOD
   1.385 +  return f() ? 2 : 5

mercurial