summaryrefslogtreecommitdiffstats
path: root/docs/code-quality
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /docs/code-quality
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--docs/code-quality/coding-style/coding_style_cpp.rst867
-rw-r--r--docs/code-quality/coding-style/coding_style_general.rst18
-rw-r--r--docs/code-quality/coding-style/coding_style_java.rst68
-rw-r--r--docs/code-quality/coding-style/coding_style_js.rst150
-rw-r--r--docs/code-quality/coding-style/coding_style_other.rst11
-rw-r--r--docs/code-quality/coding-style/coding_style_python.rst71
-rw-r--r--docs/code-quality/coding-style/format_cpp_code_with_clang-format.rst272
-rw-r--r--docs/code-quality/coding-style/index.rst20
-rw-r--r--docs/code-quality/coding-style/using_cxx_in_firefox_code.rst1065
-rw-r--r--docs/code-quality/index.rst184
-rw-r--r--docs/code-quality/lint/create.rst329
-rw-r--r--docs/code-quality/lint/index.rst38
-rw-r--r--docs/code-quality/lint/linters/black.rst36
-rw-r--r--docs/code-quality/lint/linters/clang-format.rst35
-rw-r--r--docs/code-quality/lint/linters/clippy.rst42
-rw-r--r--docs/code-quality/lint/linters/codespell.rst36
-rw-r--r--docs/code-quality/lint/linters/cpp-virtual-final.rst30
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla.rst243
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-Date-timing.rst31
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/environment.rst33
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/no-define-cc-etc.rst24
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/no-throw-cr-literal.rst39
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-parameters.rst27
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-import.rst25
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-spidermonkey-js.rst15
-rw-r--r--docs/code-quality/lint/linters/eslint.rst60
-rw-r--r--docs/code-quality/lint/linters/file-perm.rst42
-rw-r--r--docs/code-quality/lint/linters/file-whitespace.rst38
-rw-r--r--docs/code-quality/lint/linters/flake8.rst46
-rw-r--r--docs/code-quality/lint/linters/l10n.rst45
-rw-r--r--docs/code-quality/lint/linters/license.rst39
-rw-r--r--docs/code-quality/lint/linters/lintpref.rst31
-rw-r--r--docs/code-quality/lint/linters/mingw-capitalization.rst28
-rw-r--r--docs/code-quality/lint/linters/perfdocs.rst84
-rw-r--r--docs/code-quality/lint/linters/pylint.rst33
-rw-r--r--docs/code-quality/lint/linters/rejected-words.rst27
-rw-r--r--docs/code-quality/lint/linters/rstlinter.rst32
-rw-r--r--docs/code-quality/lint/linters/rustfmt.rst33
-rw-r--r--docs/code-quality/lint/usage.rst117
-rw-r--r--docs/code-quality/static-analysis.rst251
40 files changed, 4615 insertions, 0 deletions
diff --git a/docs/code-quality/coding-style/coding_style_cpp.rst b/docs/code-quality/coding-style/coding_style_cpp.rst
new file mode 100644
index 0000000000..09319cfd12
--- /dev/null
+++ b/docs/code-quality/coding-style/coding_style_cpp.rst
@@ -0,0 +1,867 @@
+================
+C++ Coding style
+================
+
+
+This document attempts to explain the basic styles and patterns used in
+the Mozilla codebase. New code should try to conform to these standards,
+so it is as easy to maintain as existing code. There are exceptions, but
+it's still important to know the rules!
+
+This article is particularly for those new to the Mozilla codebase, and
+in the process of getting their code reviewed. Before requesting a
+review, please read over this document, making sure that your code
+conforms to recommendations.
+
+.. container:: blockIndicator warning
+
+ The Firefox code base adopts parts of the `Google Coding style for C++
+ code <https://google.github.io/styleguide/cppguide.html>`__, but not all of its rules.
+ A few rules are followed across the code base, others are intended to be
+ followed in new or significantly revised code. We may extend this list in the
+ future, when we evaluate the Google Coding Style for C++ Code further and/or update
+ our coding practices. However, the plan is not to adopt all rules of the Google Coding
+ Style for C++ Code. Some rules are explicitly unlikely to be adopted at any time.
+
+ Followed across the code base:
+
+ - `Formatting <https://google.github.io/styleguide/cppguide.html#Formatting>`__,
+ except for subsections noted here otherwise
+ - `Implicit Conversions <https://google.github.io/styleguide/cppguide.html#Implicit_Conversions>`__,
+ which is enforced by a custom clang-plugin check, unless explicitly overridden using
+ ``MOZ_IMPLICIT``
+
+ Followed in new/significantly revised code:
+
+ - `Include guards <https://google.github.io/styleguide/cppguide.html#The__define_Guard>`__
+
+ Unlikely to be ever adopted:
+
+ - `Forward declarations <https://google.github.io/styleguide/cppguide.html#Forward_Declarations>`__
+ - `Formatting/Conditionals <https://google.github.io/styleguide/cppguide.html#Conditionals>`__
+ w.r.t. curly braces around inner statements, we require them in all cases where the
+ Google style allows to leave them out for single-line conditional statements
+
+ This list reflects the state of the Google Google Coding Style for C++ Code as of
+ 2020-07-17. It may become invalid when the Google modifies its Coding Style.
+
+
+Formatting code
+---------------
+
+Formatting is done automatically via clang-format, and controlled via in-tree
+configuration files. See :ref:`Formatting C++ Code With clang-format`
+for more information.
+
+Unix-style linebreaks (``\n``), not Windows-style (``\r\n``). You can
+convert patches, with DOS newlines to Unix via the ``dos2unix`` utility,
+or your favorite text editor.
+
+Static analysis
+---------------
+
+Several of the rules in the Google C++ coding styles and the additions mentioned below
+can be checked via clang-tidy (some rules are from the upstream clang-tidy, some are
+provided via a mozilla-specific plugin). Some of these checks also allow fixes to
+be automatically applied.
+
+``mach static-analysis`` provides a convenient way to run these checks. For example,
+for the check called ``google-readability-braces-around-statements``, you can run:
+
+.. code-block:: shell
+
+ ./mach static-analysis check --checks="-*,google-readability-braces-around-statements" --fix <file>
+
+It may be necessary to reformat the files after automatically applying fixes, see
+:ref:`Formatting C++ Code With clang-format`.
+
+Additional rules
+----------------
+
+*The norms in this section should be followed for new code. For existing code,
+use the prevailing style in a file or module, ask the owner if you are
+in another team's codebase or it's not clear what style to use.*
+
+
+
+
+Control structures
+~~~~~~~~~~~~~~~~~~
+
+Always brace controlled statements, even a single-line consequent of
+``if else else``. This is redundant, typically, but it avoids dangling
+else bugs, so it's safer at scale than fine-tuning.
+
+Examples:
+
+.. code-block:: cpp
+
+ if (...) {
+ } else if (...) {
+ } else {
+ }
+
+ while (...) {
+ }
+
+ do {
+ } while (...);
+
+ for (...; ...; ...) {
+ }
+
+ switch (...) {
+ case 1: {
+ // When you need to declare a variable in a switch, put the block in braces.
+ int var;
+ break;
+ }
+ case 2:
+ ...
+ break;
+ default:
+ break;
+ }
+
+``else`` should only ever be followed by ``{`` or ``if``; i.e., other
+control keywords are not allowed and should be placed inside braces.
+
+.. note::
+
+ For this rule, clang-tidy provides the ``google-readability-braces-around-statements``
+ check with autofixes.
+
+
+C++ namespaces
+~~~~~~~~~~~~~~
+
+Mozilla project C++ declarations should be in the ``mozilla``
+namespace. Modules should avoid adding nested namespaces under
+``mozilla``, unless they are meant to contain names which have a high
+probability of colliding with other names in the code base. For example,
+``Point``, ``Path``, etc. Such symbols can be put under
+module-specific namespaces, under ``mozilla``, with short
+all-lowercase names. Other global namespaces besides ``mozilla`` are
+not allowed.
+
+No ``using`` directives are allowed in header files, except inside class
+definitions or functions. (We don't want to pollute the global scope of
+compilation units that use the header file.)
+
+.. note::
+
+ For parts of this rule, clang-tidy provides the ``google-global-names-in-headers``
+ check. It only detects ``using namespace`` directives in the global namespace.
+
+
+``using namespace ...;`` is only allowed in ``.cpp`` files after all
+``#include``\ s. Prefer to wrap code in ``namespace ... { ... };``
+instead, if possible. ``using namespace ...;``\ should always specify
+the fully qualified namespace. That is, to use ``Foo::Bar`` do not
+write ``using namespace Foo; using namespace Bar;``, write
+``using namespace Foo::Bar;``
+
+Use nested namespaces (ex: ``namespace mozilla::widget {``
+
+.. note::
+
+ clang-tidy provides the ``modernize-concat-nested-namespaces``
+ check with autofixes.
+
+
+Anonymous namespaces
+~~~~~~~~~~~~~~~~~~~~
+
+We prefer using ``static``, instead of anonymous C++ namespaces. This may
+change once there is better debugger support (especially on Windows) for
+placing breakpoints, etc. on code in anonymous namespaces. You may still
+use anonymous namespaces for things that can't be hidden with ``static``,
+such as types, or certain objects which need to be passed to template
+functions.
+
+
+C++ classes
+~~~~~~~~~~~~
+
+.. code-block:: cpp
+
+ namespace mozilla {
+
+ class MyClass : public A
+ {
+ ...
+ };
+
+ class MyClass
+ : public X
+ , public Y
+ {
+ public:
+ MyClass(int aVar, int aVar2)
+ : mVar(aVar)
+ , mVar2(aVar2)
+ {
+ ...
+ }
+
+ // Special member functions, like constructors, that have default bodies
+ // should use '= default' annotation instead.
+ MyClass() = default;
+
+ // Unless it's a copy or move constructor or you have a specific reason to allow
+ // implicit conversions, mark all single-argument constructors explicit.
+ explicit MyClass(OtherClass aArg)
+ {
+ ...
+ }
+
+ // This constructor can also take a single argument, so it also needs to be marked
+ // explicit.
+ explicit MyClass(OtherClass aArg, AnotherClass aArg2 = AnotherClass())
+ {
+ ...
+ }
+
+ int LargerFunction()
+ {
+ ...
+ ...
+ }
+
+ private:
+ int mVar;
+ };
+
+ } // namespace mozilla
+
+Define classes using the style given above.
+
+.. note::
+
+ For the rule on ``= default``, clang-tidy provides the ``modernize-use-default``
+ check with autofixes.
+
+ For the rule on explicit constructors and conversion operators, clang-tidy
+ provides the ``mozilla-implicit-constructor`` check.
+
+Existing classes in the global namespace are named with a short prefix
+(For example, ``ns``) as a pseudo-namespace.
+
+
+Methods and functions
+~~~~~~~~~~~~~~~~~~~~~
+
+
+C/C++
+^^^^^
+
+In C/C++, method names should use ``UpperCamelCase``.
+
+Getters that never fail, and never return null, are named ``Foo()``,
+while all other getters use ``GetFoo()``. Getters can return an object
+value, via a ``Foo** aResult`` outparam (typical for an XPCOM getter),
+or as an ``already_AddRefed<Foo>`` (typical for a WebIDL getter,
+possibly with an ``ErrorResult& rv`` parameter), or occasionally as a
+``Foo*`` (typical for an internal getter for an object with a known
+lifetime). See `the bug 223255 <https://bugzilla.mozilla.org/show_bug.cgi?id=223255>`_
+for more information.
+
+XPCOM getters always return primitive values via an outparam, while
+other getters normally use a return value.
+
+Method declarations must use, at most, one of the following keywords:
+``virtual``, ``override``, or ``final``. Use ``virtual`` to declare
+virtual methods, which do not override a base class method with the same
+signature. Use ``override`` to declare virtual methods which do
+override a base class method, with the same signature, but can be
+further overridden in derived classes. Use ``final`` to declare virtual
+methods which do override a base class method, with the same signature,
+but can NOT be further overridden in the derived classes. This should
+help the person reading the code fully understand what the declaration
+is doing, without needing to further examine base classes.
+
+.. note::
+
+ For the rule on ``virtual/override/final``, clang-tidy provides the
+ ``modernize-use-override`` check with autofixes.
+
+
+Operators
+~~~~~~~~~
+
+The unary keyword operator ``sizeof``, should have its operand parenthesized
+even if it is an expression; e.g. ``int8_t arr[64]; memset(arr, 42, sizeof(arr));``.
+
+
+Literals
+~~~~~~~~
+
+Use ``\uXXXX`` unicode escapes for non-ASCII characters. The character
+set for XUL, DTD, script, and properties files is UTF-8, which is not easily
+readable.
+
+
+Prefixes
+~~~~~~~~
+
+Follow these naming prefix conventions:
+
+
+Variable prefixes
+^^^^^^^^^^^^^^^^^
+
+- k=constant (e.g. ``kNC_child``). Not all code uses this style; some
+ uses ``ALL_CAPS`` for constants.
+- g=global (e.g. ``gPrefService``)
+- a=argument (e.g. ``aCount``)
+- C++ Specific Prefixes
+
+ - s=static member (e.g. ``sPrefChecked``)
+ - m=member (e.g. ``mLength``)
+ - e=enum variants (e.g. ``enum Foo { eBar, eBaz }``). Enum classes
+ should use ``CamelCase`` instead (e.g.
+ ``enum class Foo { Bar, Baz }``).
+
+
+Global functions/macros/etc
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- Macros begin with ``MOZ_``, and are all caps (e.g.
+ ``MOZ_WOW_GOODNESS``). Note that older code uses the ``NS_`` prefix;
+ while these aren't being changed, you should only use ``MOZ_`` for
+ new macros. The only exception is if you're creating a new macro,
+ which is part of a set of related macros still using the old ``NS_``
+ prefix. Then you should be consistent with the existing macros.
+
+
+Error Variables
+^^^^^^^^^^^^^^^
+
+- Local variables that are assigned ``nsresult`` result codes should be named ``rv``
+ (i.e., e.g., not ``res``, not ``result``, not ``foo``). `rv` should not be
+ used for bool or other result types.
+- Local variables that are assigned ``bool`` result codes should be named `ok`.
+
+
+C/C++ practices
+---------------
+
+- **Have you checked for compiler warnings?** Warnings often point to
+ real bugs. `Many of them <https://searchfox.org/mozilla-central/source/build/moz.configure/warnings.configure>`__
+ are enabled by default in the build system.
+- In C++ code, use ``nullptr`` for pointers. In C code, using ``NULL``
+ or ``0`` is allowed.
+
+.. note::
+
+ For the C++ rule, clang-tidy provides the ``modernize-use-nullptr`` check
+ with autofixes.
+
+- Don't use ``PRBool`` and ``PRPackedBool`` in C++, use ``bool``
+ instead.
+- For checking if a ``std`` container has no items, don't use
+ ``size()``, instead use ``empty()``.
+- When testing a pointer, use ``(!myPtr)`` or ``(myPtr)``;
+ don't use ``myPtr != nullptr`` or ``myPtr == nullptr``.
+- Do not compare ``x == true`` or ``x == false``. Use ``(x)`` or
+ ``(!x)`` instead. ``if (x == true)`` may have semantics different from
+ ``if (x)``!
+
+.. note::
+
+ clang-tidy provides the ``readability-simplify-boolean-expr`` check
+ with autofixes that checks for these and some other boolean expressions
+ that can be simplified.
+
+- In general, initialize variables with ``nsFoo aFoo = bFoo,`` and not
+ ``nsFoo aFoo(bFoo)``.
+
+ - For constructors, initialize member variables with : ``nsFoo
+ aFoo(bFoo)`` syntax.
+
+- To avoid warnings created by variables used only in debug builds, use
+ the
+ `DebugOnly<T> <https://developer.mozilla.org/docs/Mozilla/Debugging/DebugOnly%3CT%3E>`__
+ helper when declaring them.
+- You should `use the static preference
+ API <https://developer.mozilla.org/docs/Mozilla/Preferences/Using_preferences_from_application_code>`__ for
+ working with preferences.
+- One-argument constructors, that are not copy or move constructors,
+ should generally be marked explicit. Exceptions should be annotated
+ with ``MOZ_IMPLICIT``.
+- Use ``char32_t`` as the return type or argument type of a method that
+ returns or takes as argument a single Unicode scalar value. (Don't
+ use UTF-32 strings, though.)
+- Forward-declare classes in your header files, instead of including
+ them, whenever possible. For example, if you have an interface with a
+ ``void DoSomething(nsIContent* aContent)`` function, forward-declare
+ with ``class nsIContent;`` instead of ``#include "nsIContent.h"``
+- Include guards are named per the Google coding style and should not
+ include a leading ``MOZ_`` or ``MOZILLA_``. For example
+ ``dom/media/foo.h`` would use the guard ``DOM_MEDIA_FOO_H_``.
+- Avoid the usage of ``typedef``, instead, please use ``using`` instead.
+
+.. note::
+
+ For parts of this rule, clang-tidy provides the ``modernize-use-using``
+ check with autofixes.
+
+
+COM and pointers
+----------------
+
+- Use ``nsCOMPtr<>``
+ If you don't know how to use it, start looking in the code for
+ examples. The general rule, is that the very act of typing
+ ``NS_RELEASE`` should be a signal to you to question your code:
+ "Should I be using ``nsCOMPtr`` here?". Generally the only valid use
+ of ``NS_RELEASE`` is when you are storing refcounted pointers in a
+ long-lived datastructure.
+- Declare new XPCOM interfaces using `XPIDL <https://developer.mozilla.org/docs/Mozilla/Tech/XPIDL>`__, so they
+ will be scriptable.
+- Use `nsCOMPtr <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Reference/Glue_classes/nsCOMPtr>`__ for strong references, and
+ `nsWeakPtr <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Weak_reference>`__ for weak references.
+- Don't use ``QueryInterface`` directly. Use ``CallQueryInterface`` or
+ ``do_QueryInterface`` instead.
+- Use `Contract
+ IDs <news://news.mozilla.org/3994AE3E.D96EF810@netscape.com>`__,
+ instead of CIDs with ``do_CreateInstance``/``do_GetService``.
+- Use pointers, instead of references for function out parameters, even
+ for primitive types.
+
+
+IDL
+---
+
+
+Use leading-lowercase, or "interCaps"
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When defining a method or attribute in IDL, the first letter should be
+lowercase, and each following word should be capitalized. For example:
+
+.. code-block:: cpp
+
+ long updateStatusBar();
+
+
+Use attributes wherever possible
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Whenever you are retrieving or setting a single value, without any
+context, you should use attributes. Don't use two methods when you could
+use an attribute. Using attributes logically connects the getting and
+setting of a value, and makes scripted code look cleaner.
+
+This example has too many methods:
+
+.. code-block:: cpp
+
+ interface nsIFoo : nsISupports
+ {
+ long getLength();
+ void setLength(in long length);
+ long getColor();
+ };
+
+The code below will generate the exact same C++ signature, but is more
+script-friendly.
+
+.. code-block:: cpp
+
+ interface nsIFoo : nsISupports
+ {
+ attribute long length;
+ readonly attribute long color;
+ };
+
+
+Use Java-style constants
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+When defining scriptable constants in IDL, the name should be all
+uppercase, with underscores between words:
+
+.. code-block:: cpp
+
+ const long ERROR_UNDEFINED_VARIABLE = 1;
+
+
+See also
+~~~~~~~~
+
+For details on interface development, as well as more detailed style
+guides, see the `Interface development
+guide <https://developer.mozilla.org/docs/Mozilla/Developer_guide/Interface_development_guide>`__.
+
+
+Error handling
+--------------
+
+
+Check for errors early and often
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Every time you make a call into an XPCOM function, you should check for
+an error condition. You need to do this even if you know that call will
+never fail. Why?
+
+- Someone may change the callee in the future to return a failure
+ condition.
+- The object in question may live on another thread, another process,
+ or possibly even another machine. The proxy could have failed to make
+ your call in the first place.
+
+Also, when you make a new function which is failable (i.e. it will
+return a ``nsresult`` or a ``bool`` that may indicate an error), you should
+explicitly mark the return value should always be checked. For example:
+
+::
+
+ // for IDL.
+ [must_use] nsISupports
+ create();
+
+ // for C++, add this in *declaration*, do not add it again in implementation.
+ [[nodiscard]] nsresult
+ DoSomething();
+
+There are some exceptions:
+
+- Predicates or getters, which return ``bool`` or ``nsresult``.
+- IPC method implementation (For example, ``bool RecvSomeMessage()``).
+- Most callers will check the output parameter, see below.
+
+.. code-block:: cpp
+
+ nsresult
+ SomeMap::GetValue(const nsString& key, nsString& value);
+
+If most callers need to check the output value first, then adding
+``[[nodiscard]]`` might be too verbose. In this case, change the return value
+to void might be a reasonable choice.
+
+There is also a static analysis attribute ``MOZ_MUST_USE_TYPE``, which can
+be added to class declarations, to ensure that those declarations are
+always used when they are returned.
+
+
+Use the NS_WARN_IF macro when errors are unexpected.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``NS_WARN_IF`` macro can be used to issue a console warning, in debug
+builds if the condition fails. This should only be used when the failure
+is unexpected and cannot be caused by normal web content.
+
+If you are writing code which wants to issue warnings when methods fail,
+please either use ``NS_WARNING`` directly, or use the new ``NS_WARN_IF`` macro.
+
+.. code-block:: cpp
+
+ if (NS_WARN_IF(somethingthatshouldbefalse)) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+Previously, the ``NS_ENSURE_*`` macros were used for this purpose, but
+those macros hide return statements, and should not be used in new code.
+(This coding style rule isn't generally agreed, so use of ``NS_ENSURE_*``
+can be valid.)
+
+
+Return from errors immediately
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In most cases, your knee-jerk reaction should be to return from the
+current function, when an error condition occurs. Don't do this:
+
+.. code-block:: cpp
+
+ rv = foo->Call1();
+ if (NS_SUCCEEDED(rv)) {
+ rv = foo->Call2();
+ if (NS_SUCCEEDED(rv)) {
+ rv = foo->Call3();
+ }
+ }
+ return rv;
+
+Instead, do this:
+
+.. code-block:: cpp
+
+ rv = foo->Call1();
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = foo->Call2();
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = foo->Call3();
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+Why? Error handling should not obfuscate the logic of the code. The
+author's intent, in the first example, was to make 3 calls in
+succession. Wrapping the calls in nested if() statements, instead
+obscured the most likely behavior of the code.
+
+Consider a more complicated example to hide a bug:
+
+.. code-block:: cpp
+
+ bool val;
+ rv = foo->GetBooleanValue(&val);
+ if (NS_SUCCEEDED(rv) && val) {
+ foo->Call1();
+ } else {
+ foo->Call2();
+ }
+
+The intent of the author, may have been, that ``foo->Call2()`` would only
+happen when val had a false value. In fact, ``foo->Call2()`` will also be
+called, when ``foo->GetBooleanValue(&val)`` fails. This may, or may not,
+have been the author's intent. It is not clear from this code. Here is
+an updated version:
+
+.. code-block:: cpp
+
+ bool val;
+ rv = foo->GetBooleanValue(&val);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ if (val) {
+ foo->Call1();
+ } else {
+ foo->Call2();
+ }
+
+In this example, the author's intent is clear, and an error condition
+avoids both calls to ``foo->Call1()`` and ``foo->Call2();``
+
+*Possible exceptions:* Sometimes it is not fatal if a call fails. For
+instance, if you are notifying a series of observers that an event has
+fired, it might be trivial that one of these notifications failed:
+
+.. code-block:: cpp
+
+ for (size_t i = 0; i < length; ++i) {
+ // we don't care if any individual observer fails
+ observers[i]->Observe(foo, bar, baz);
+ }
+
+Another possibility, is you are not sure if a component exists or is
+installed, and you wish to continue normally, if the component is not
+found.
+
+.. code-block:: cpp
+
+ nsCOMPtr<nsIMyService> service = do_CreateInstance(NS_MYSERVICE_CID, &rv);
+ // if the service is installed, then we'll use it.
+ if (NS_SUCCEEDED(rv)) {
+ // non-fatal if this fails too, ignore this error.
+ service->DoSomething();
+
+ // this is important, handle this error!
+ rv = service->DoSomethingImportant();
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ }
+
+ // continue normally whether or not the service exists.
+
+
+Strings
+-------
+
+.. note::
+
+ This section overlaps with the more verbose advice given in
+ `Internal strings <https://wiki.developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Guide/Internal_strings>`__.
+ These should eventually be merged. For now, please refer to that guide for
+ more advice.
+
+- String arguments to functions should be declared as ``[const] nsA[C]String&``.
+- Prefer using string literals. In particular, use empty string literals,
+ i.e. ``u""_ns`` or ``""_ns``, instead of ``Empty[C]String()`` or
+ ``const nsAuto[C]String empty;``. Use ``Empty[C]String()`` only if you
+ specifically need a ``const ns[C]String&``, e.g. with the ternary operator
+ or when you need to return/bind to a reference or take the address of the
+ empty string.
+- For 16-bit literal strings, use ``u"..."_ns`` or, if necessary
+ ``NS_LITERAL_STRING_FROM_CSTRING(...)`` instead of ``nsAutoString()``
+ or other ways that would do a run-time conversion.
+ See :ref:`Avoid runtime conversion of string literals` below.
+- To compare a string with a literal, use ``.EqualsLiteral("...")``.
+- Use ``str.IsEmpty()`` instead of ``str.Length() == 0``.
+- Use ``str.Truncate()`` instead of ``str.SetLength(0)``,
+ ``str.Assign(""_ns)`` or ``str.AssignLiteral("")``.
+- Don't use functions from ``ctype.h`` (``isdigit()``, ``isalpha()``,
+ etc.) or from ``strings.h`` (``strcasecmp()``, ``strncasecmp()``).
+ These are locale-sensitive, which makes them inappropriate for
+ processing protocol text. At the same time, they are too limited to
+ work properly for processing natural-language text. Use the
+ alternatives in ``mozilla/TextUtils.h`` and in ``nsUnicharUtils.h``
+ in place of ``ctype.h``. In place of ``strings.h``, prefer the
+ ``nsStringComparator`` facilities for comparing strings or if you
+ have to work with zero-terminated strings, use ``nsCRT.h`` for
+ ASCII-case-insensitive comparison.
+
+
+Use the ``Auto`` form of strings for local values
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When declaring a local, short-lived ``nsString`` class, always use
+``nsAutoString`` or ``nsAutoCString``. These pre-allocate a 64-byte
+buffer on the stack, and avoid fragmenting the heap. Don't do this:
+
+.. code-block:: cpp
+
+ nsresult
+ foo()
+ {
+ nsCString bar;
+ ..
+ }
+
+instead:
+
+.. code-block:: cpp
+
+ nsresult
+ foo()
+ {
+ nsAutoCString bar;
+ ..
+ }
+
+
+Be wary of leaking values from non-XPCOM functions that return char\* or PRUnichar\*
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It is an easy trap to return an allocated string, from an internal
+helper function, and then using that function inline in your code,
+without freeing the value. Consider this code:
+
+.. code-block:: cpp
+
+ static char*
+ GetStringValue()
+ {
+ ..
+ return resultString.ToNewCString();
+ }
+
+ ..
+ WarnUser(GetStringValue());
+
+In the above example, ``WarnUser`` will get the string allocated from
+``resultString.ToNewCString()`` and throw away the pointer. The
+resulting value is never freed. Instead, either use the string classes,
+to make sure your string is automatically freed when it goes out of
+scope, or make sure that your string is freed.
+
+Automatic cleanup:
+
+.. code-block:: cpp
+
+ static void
+ GetStringValue(nsAWritableCString& aResult)
+ {
+ ..
+ aResult.Assign("resulting string");
+ }
+
+ ..
+ nsAutoCString warning;
+ GetStringValue(warning);
+ WarnUser(warning.get());
+
+Free the string manually:
+
+.. code-block:: cpp
+
+ static char*
+ GetStringValue()
+ {
+ ..
+ return resultString.ToNewCString();
+ }
+
+ ..
+ char* warning = GetStringValue();
+ WarnUser(warning);
+ nsMemory::Free(warning);
+
+
+Avoid runtime conversion of string literals
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It is very common to need to assign the value of a literal string, such
+as ``"Some String"``, into a unicode buffer. Instead of using ``nsString``'s
+``AssignLiteral`` and ``AppendLiteral``, use a user-defined literal like `u"foo"_ns`
+instead. On most platforms, this will force the compiler to compile in a
+raw unicode string, and assign it directly. In cases where the literal is defined
+via a macro that is used in both 8-bit and 16-bit ways, you can use
+`NS_LITERAL_STRING_FROM_CSTRING` to do the conversion at compile time.
+
+Incorrect:
+
+.. code-block:: cpp
+
+ nsAutoString warning;
+ warning.AssignLiteral("danger will robinson!");
+ ...
+ foo->SetStringValue(warning);
+ ...
+ bar->SetUnicodeValue(warning.get());
+
+Correct:
+
+.. code-block:: cpp
+
+ constexpr auto warning = u"danger will robinson!"_ns;
+ ...
+ // if you'll be using the 'warning' string, you can still use it as before:
+ foo->SetStringValue(warning);
+ ...
+ bar->SetUnicodeValue(warning.get());
+
+ // alternatively, use the wide string directly:
+ foo->SetStringValue(u"danger will robinson!"_ns);
+ ...
+
+ // if a macro is the source of a 8-bit literal and you cannot change it, use
+ // NS_LITERAL_STRING_FROM_CSTRING, but only if necessary.
+ #define MY_MACRO_LITERAL "danger will robinson!"
+ foo->SetStringValue(NS_LITERAL_STRING_FROM_CSTRING(MY_MACRO_LITERAL));
+
+ // If you need to pass to a raw const char16_t *, there's no benefit to
+ // go through our string classes at all, just do...
+ bar->SetUnicodeValue(u"danger will robinson!");
+
+ // .. or, again, if a macro is the source of a 8-bit literal
+ bar->SetUnicodeValue(u"" MY_MACRO_LITERAL);
+
+
+Usage of PR_(MAX|MIN|ABS|ROUNDUP) macro calls
+---------------------------------------------
+
+Use the standard-library functions (``std::max``), instead of
+``PR_(MAX|MIN|ABS|ROUNDUP)``.
+
+Use ``mozilla::Abs`` instead of ``PR_ABS``. All ``PR_ABS`` calls in C++ code have
+been replaced with ``mozilla::Abs`` calls, in `bug
+847480 <https://bugzilla.mozilla.org/show_bug.cgi?id=847480>`__. All new
+code in ``Firefox/core/toolkit`` needs to ``#include "nsAlgorithm.h"`` and
+use the ``NS_foo`` variants instead of ``PR_foo``, or
+``#include "mozilla/MathAlgorithms.h"`` for ``mozilla::Abs``.
diff --git a/docs/code-quality/coding-style/coding_style_general.rst b/docs/code-quality/coding-style/coding_style_general.rst
new file mode 100644
index 0000000000..950cd6ccd3
--- /dev/null
+++ b/docs/code-quality/coding-style/coding_style_general.rst
@@ -0,0 +1,18 @@
+
+Mode line
+~~~~~~~~~
+
+Files should have Emacs and vim mode line comments as the first two
+lines of the file, which should set ``indent-tabs-mode`` to ``nil``. For new
+files, use the following, specifying two-space indentation:
+
+.. code-block:: cpp
+
+ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+ /* vim: set ts=2 et sw=2 tw=80: */
+ /* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+Be sure to use the correct ``Mode`` in the first line, don't use ``C++`` in
+JavaScript files.
diff --git a/docs/code-quality/coding-style/coding_style_java.rst b/docs/code-quality/coding-style/coding_style_java.rst
new file mode 100644
index 0000000000..f2206d8e2d
--- /dev/null
+++ b/docs/code-quality/coding-style/coding_style_java.rst
@@ -0,0 +1,68 @@
+=================
+Java Coding style
+=================
+
+- We use the `Java Coding
+ Style <https://www.oracle.com/technetwork/java/codeconvtoc-136057.html>`__.
+ Quick summary:
+
+ - FirstLetterUpperCase for class names.
+ - camelCase for method and variable names.
+ - One declaration per line:
+
+ .. code-block:: java
+
+ int x, y; // this is BAD!
+ int a; // split it over
+ int b; // two lines
+
+- Braces should be placed like so (generally, opening braces on same
+ line, closing braces on a new line):
+
+ .. code-block:: java
+
+ public void func(int arg) {
+ if (arg != 0) {
+ while (arg > 0) {
+ arg--;
+ }
+ } else {
+ arg++;
+ }
+ }
+
+- Places we differ from the Java coding style:
+
+ - Start class variable names with 'm' prefix (e.g.
+ mSomeClassVariable) and static variables with 's' prefix (e.g.
+ sSomeStaticVariable)
+ - ``import`` statements:
+
+ - Do not use wildcard imports like \`import java.util.*;\`
+ - Organize imports by blocks separated by empty line:
+ org.mozilla.*, android.*, com.*, net.*, org.*, then java.\*
+ This is basically what Android Studio does by default, except
+ that we place org.mozilla.\* at the front - please adjust
+ Settings -> Editor -> Code Style -> Java -> Imports
+ accordingly.
+ - Within each import block, alphabetize import names with
+ uppercase before lowercase. For example, ``com.example.Foo`` is
+ before ``com.example.bar``
+
+ - 4-space indents.
+ - Spaces, not tabs.
+ - Don't restrict yourself to 80-character lines. Google's Android
+ style guide suggests 100-character lines, which is also the
+ default setting in Android Studio. Java code tends to be long
+ horizontally, so use appropriate judgement when wrapping. Avoid
+ deep indents on wrapping. Note that aligning the wrapped part of a
+ line, with some previous part of the line (rather than just using
+ a fixed indent), may require shifting the code every time the line
+ changes, resulting in spurious whitespace changes.
+
+- For additional specifics on Firefox for Android, see the `Coding
+ Style guide for Firefox on
+ Android <https://wiki.mozilla.org/Mobile/Fennec/Android#Coding_Style>`__.
+- The `Android Coding
+ Style <https://source.android.com/source/code-style.html>`__ has some
+ useful guidelines too.
diff --git a/docs/code-quality/coding-style/coding_style_js.rst b/docs/code-quality/coding-style/coding_style_js.rst
new file mode 100644
index 0000000000..46ec1dd8a6
--- /dev/null
+++ b/docs/code-quality/coding-style/coding_style_js.rst
@@ -0,0 +1,150 @@
+=======================
+JavaScript Coding style
+=======================
+
+Coding style
+~~~~~~~~~~~~
+
+`prettier <https://prettier.io/>`_ is the tool used to reformat the JavaScript code.
+
+
+Methods and functions
+~~~~~~~~~~~~~~~~~~~~~
+
+In JavaScript, functions should use camelCase, but should not capitalize
+the first letter. Methods should not use the named function expression
+syntax, because our tools understand method names:
+
+.. code-block:: cpp
+
+ doSomething: function (aFoo, aBar) {
+ ...
+ }
+
+In-line functions should have spaces around braces, except before commas
+or semicolons:
+
+.. code-block:: cpp
+
+ function valueObject(aValue) { return { value: aValue }; }
+
+
+JavaScript objects
+~~~~~~~~~~~~~~~~~~
+
+.. code-block:: cpp
+
+ var foo = { prop1: "value1" };
+
+ var bar = {
+ prop1: "value1",
+ prop2: "value2"
+ };
+
+Constructors for objects should be capitalized and use Pascal Case:
+
+.. code-block:: cpp
+
+ function ObjectConstructor() {
+ this.foo = "bar";
+ }
+
+
+Operators
+~~~~~~~~~
+
+In JavaScript, overlong expressions not joined by ``&&`` and
+``||`` should break so the operator starts on the second line and
+starting in the same column as the beginning of the expression in the
+first line. This applies to ``?:``, binary arithmetic operators
+including ``+``, and member-of operators. Rationale: an operator at the
+front of the continuation line makes for faster visual scanning, as
+there is no need to read to the end of line. Also there exists a
+context-sensitive keyword hazard in JavaScript; see {{bug(442099, "bug",
+19)}}, which can be avoided by putting . at the start of a continuation
+line, in long member expression.
+
+In JavaScript, ``==`` is preferred to ``===``.
+
+Unary keyword operators, such as ``typeof``, should have their operand
+parenthesized; e.g. ``typeof("foo") == "string"``.
+
+Literals
+~~~~~~~~
+
+Double-quoted strings (e.g. ``"foo"``) are preferred to single-quoted
+strings (e.g. ``'foo'``), in JavaScript, except to avoid escaping
+embedded double quotes, or when assigning inline event handlers.
+
+
+Prefixes
+~~~~~~~~
+
+- k=constant (e.g. ``kNC_child``). Not all code uses this style; some
+ uses ``ALL_CAPS`` for constants.
+- g=global (e.g. ``gPrefService``)
+- a=argument (e.g. ``aCount``)
+
+- JavaScript Specific Prefixes
+
+ - \_=member (variable or function) (e.g. ``_length`` or
+ ``_setType(aType)``)
+ - k=enumeration value (e.g. ``const kDisplayModeNormal = 0``)
+ - on=event handler (e.g. ``function onLoad()``)
+ - Convenience constants for interface names should be prefixed with
+ ``nsI``:
+
+ .. code-block:: javascript
+
+ const nsISupports = Components.interfaces.nsISupports;
+ const nsIWBN = Components.interfaces.nsIWebBrowserNavigation;
+
+
+
+Other advices
+~~~~~~~~~~~~~
+
+- Make sure you are aware of the `JavaScript
+ Tips <https://developer.mozilla.org/docs/Mozilla/JavaScript_Tips>`__.
+- Do not compare ``x == true`` or ``x == false``. Use ``(x)`` or
+ ``(!x)`` instead. ``x == true``, is certainly different from if
+ ``(x)``! Compare objects to ``null``, numbers to ``0`` or strings to
+ ``""``, if there is chance for confusion.
+- Make sure that your code doesn't generate any strict JavaScript
+ warnings, such as:
+
+ - Duplicate variable declaration.
+ - Mixing ``return;`` with ``return value;``
+ - Undeclared variables or members. If you are unsure if an array
+ value exists, compare the index to the array's length. If you are
+ unsure if an object member exists, use ``"name"`` in ``aObject``,
+ or if you are expecting a particular type you may use
+ ``typeof(aObject.name) == "function"`` (or whichever type you are
+ expecting).
+
+- Use ``['value1, value2']`` to create a JavaScript array in preference
+ to using
+ ``new {{JSxRef("Array", "Array", "Syntax", 1)}}(value1, value2)``
+ which can be confusing, as ``new Array(length)`` will actually create
+ a physically empty array with the given logical length, while
+ ``[value]`` will always create a 1-element array. You cannot actually
+ guarantee to be able to preallocate memory for an array.
+- Use ``{ member: value, ... }`` to create a JavaScript object; a
+ useful advantage over ``new {{JSxRef("Object", "Object", "", 1)}}()``
+ is the ability to create initial properties and use extended
+ JavaScript syntax, to define getters and setters.
+- If having defined a constructor you need to assign default
+ properties, it is preferred to assign an object literal to the
+ prototype property.
+- Use regular expressions, but use wisely. For instance, to check that
+ ``aString`` is not completely whitespace use
+ ``/\S/.{{JSxRef("RegExp.test", "test(aString)", "", 1)}}``. Only use
+ {{JSxRef("String.search", "aString.search()")}} if you need to know
+ the position of the result, or {{JSxRef("String.match",
+ "aString.match()")}} if you need to collect matching substrings
+ (delimited by parentheses in the regular expression). Regular
+ expressions are less useful if the match is unknown in advance, or to
+ extract substrings in known positions in the string. For instance,
+ {{JSxRef("String.slice", "aString.slice(-1)")}} returns the last
+ letter in ``aString``, or the empty string if ``aString`` is empty.
+
diff --git a/docs/code-quality/coding-style/coding_style_other.rst b/docs/code-quality/coding-style/coding_style_other.rst
new file mode 100644
index 0000000000..2c82cc4a76
--- /dev/null
+++ b/docs/code-quality/coding-style/coding_style_other.rst
@@ -0,0 +1,11 @@
+==================
+Other coding style
+==================
+
+SVG practices
+-------------
+
+Check `SVG
+Guidelines <https://developer.mozilla.org/docs/Mozilla/Developer_guide/SVG_Guidelines>`__ for
+more details.
+
diff --git a/docs/code-quality/coding-style/coding_style_python.rst b/docs/code-quality/coding-style/coding_style_python.rst
new file mode 100644
index 0000000000..3a818fcfd4
--- /dev/null
+++ b/docs/code-quality/coding-style/coding_style_python.rst
@@ -0,0 +1,71 @@
+===================
+Python Coding style
+===================
+
+Coding style
+~~~~~~~~~~~~
+
+ :ref:`black` is the tool used to reformat the Python code.
+
+Linting
+~~~~~~~
+
+The Python linting is done by :ref:`Flake8` and :ref:`pylint`
+They are executed by mozlint both at review phase and in the CI.
+
+Indentation
+~~~~~~~~~~~
+
+Four spaces in Python code.
+
+
+Makefile/moz.build practices
+----------------------------
+
+- Changes to makefile and moz.build variables do not require
+ build-config peer review. Any other build system changes, such as
+ adding new scripts or rules, require review from the build-config
+ team.
+- Suffix long ``if``/``endif`` conditionals with #{ & #}, so editors
+ can display matched tokens enclosing a block of statements.
+
+ ::
+
+ ifdef CHECK_TYPE #{
+ ifneq ($(flavor var_type),recursive) #{
+ $(warning var should be expandable but detected var_type=$(flavor var_type))
+ endif #}
+ endif #}
+
+- moz.build are python and follow normal Python style.
+- List assignments should be written with one element per line. Align
+ closing square brace with start of variable assignment. If ordering
+ is not important, variables should be in alphabetical order.
+
+ .. code-block:: python
+
+ var += [
+ 'foo',
+ 'bar'
+ ]
+
+- Use ``CONFIG['CPU_ARCH'] {=arm}`` to test for generic classes of
+ architecture rather than ``CONFIG['OS_TEST'] {=armv7}`` (re: bug 886689).
+
+
+Other advices
+~~~~~~~~~~~~~
+
+- Install the
+ `mozext <https://hg.mozilla.org/hgcustom/version-control-tools/file/default/hgext/mozext>`__
+ Mercurial extension, and address every issue reported on commit
+ or the output of ``hg critic``.
+- Follow `PEP 8 <https://www.python.org/dev/peps/pep-0008/>`__. Please run :ref:`black` for this.
+- Do not place statements on the same line as ``if/elif/else``
+ conditionals to form a one-liner.
+- Global vars, please avoid them at all cost.
+- Exclude outer parenthesis from conditionals.Use
+ ``if x > 5:,``\ rather than ``if (x > 5):``
+- Use string formatters, rather than var + str(val).
+ ``var = 'Type %s value is %d'% ('int', 5).``
+- Testing/Unit tests, please write them and make sure that they are executed in the CI.
diff --git a/docs/code-quality/coding-style/format_cpp_code_with_clang-format.rst b/docs/code-quality/coding-style/format_cpp_code_with_clang-format.rst
new file mode 100644
index 0000000000..10d2bc00fc
--- /dev/null
+++ b/docs/code-quality/coding-style/format_cpp_code_with_clang-format.rst
@@ -0,0 +1,272 @@
+=====================================
+Formatting C++ Code With clang-format
+=====================================
+
+Mozilla uses the Google coding style for whitespace, which is enforced
+using `clang-format <https://clang.llvm.org/docs/ClangFormat.html>`__. A
+specific version of the binary will be installed when
+``./mach clang-format`` or ``./mach bootstrap`` are run. We build our
+own binaries and update them as needed.
+
+Options are explicitly defined `in clang-format
+itself <https://github.com/llvm-mirror/clang/blob/e8a55f98df6bda77ee2eaa7f7247bd655f79ae0e/lib/Format/Format.cpp#L856>`__.
+If the options are changed in clang upstream, this might cause some
+changes in the Firefox tree. For this reason, it is best to use the
+mozilla-provided binaries.
+
+Manual formatting
+-----------------
+
+We provide a mach subcommand for running clang-format from the
+command-line. This wrapper handles ensuring the correct version of
+clang-format is installed and run.
+
+If clang-format isn’t installed, the binaries will be automatically
+downloaded from taskcluster and installed into ~/.mozbuild. We build our
+own clang-format binaries.
+
+
+Formatting local changes
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ $ ./mach clang-format
+
+When run without arguments, it will run on a local diff. This could miss
+some reformatting (for example, when blocks are touched).
+(`searchfox <https://searchfox.org/mozilla-central/rev/501eb4718d73870892d28f31a99b46f4783efaa0/python/mozbuild/mozbuild/code-analysis/mach_commands.py#1620>`__)
+
+
+Formatting specific paths
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ $ ./mach clang-format -p <path> # Format <path> in-place
+ $ ./mach clang-format -p <path> -s # Show changes
+
+The command also accepts a ``-p`` argument to reformat a specific
+directory or file, and a ``-s`` flag to show the changes instead of
+applying them to the working directory
+(`searchfox <https://searchfox.org/mozilla-central/rev/501eb4718d73870892d28f31a99b46f4783efaa0/python/mozbuild/mozbuild/code-analysis/mach_commands.py#1633>`__)
+
+
+Formatting specific commits / revisions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ $ ./mach clang-format -c HEAD # Format a single git commit
+ $ ./mach clang-format -c HEAD~~..HEAD # Format a range of git commits
+ $ ./mach clang-format -c . # Format a single mercurial revision
+
+The command accepts a ``-c`` argument that takes a revision number or
+commit range, and will format the lines modified by those commits.
+(`searchfox <https://searchfox.org/mozilla-central/rev/501eb4718d73870892d28f31a99b46f4783efaa0/python/mozbuild/mozbuild/code-analysis/mach_commands.py#1635>`__)
+
+
+Scripting Clang-Format
+~~~~~~~~~~~~~~~~~~~~~~
+
+Clang format expects that the path being passed to it is the path
+on-disk. If this is not the case, for example when formatting a
+temporary file, the "real" path must be specified. This can be done with
+the ``--assume-filename <path>`` argument.
+
+
+Configuring the clang-format commit hook
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To run clang-format at commit phase, run ``mach boostrap`` or just add
+the following line in the ``hgrc`` file:
+
+.. code:: ini
+
+ [extensions]
+ clang-format = ~/.mozbuild/version-control-tools/hgext/clang-format
+
+We use a hg extension as they are more flexible than hooks.
+
+With git, the configuration is the following:
+
+::
+
+ # From the root git directory:
+ $ ln -s $(pwd)/tools/lint/hooks_clang_format.py .git/hooks/pre-commit
+
+You'll likely need to install the ``python-hglib`` package for your OS,
+or else you may get errors like ``abort: No module named hglib.client!``
+when you try to commit.
+
+
+Editor integration
+------------------
+
+It is possible to configure many editors to support running
+``clang-format`` automatically on save, or when run from within the
+editor.
+
+
+Editor plugins
+~~~~~~~~~~~~~~
+
+- `Atom <https://atom.io/packages/clang-format>`__
+- `BBEdit <http://clang.llvm.org/docs/ClangFormat.html#bbedit-integration>`__
+
+ - `clang-format-bbedit.applescript <https://raw.githubusercontent.com/llvm-mirror/clang/master/tools/clang-format/clang-format-bbedit.applescript>`__
+
+- Eclipse
+
+ - Install the
+ `CppStyle <https://marketplace.eclipse.org/content/cppstyle>`__
+ plugin
+ - In Preferences -> C/C++ -> CppStyle, set the clang-format path to
+ ~/.mozbuild/clang-tools/clang-tidy/bin/clang-format
+ - (Optional) check "Run clang-format on file save"
+
+- `Emacs <http://clang.llvm.org/docs/ClangFormat.html#emacs-integration>`__
+
+ - `clang-format.el <https://raw.githubusercontent.com/llvm-mirror/clang/master/tools/clang-format/clang-format.el>`__
+ (Or install
+ `clang-format <http://melpa.org/#/clang-format>`__ from MELPA)
+ - `google-c-style <http://melpa.org/#/google-c-style>`__ from MELPA
+
+- `Sublime Text <https://packagecontrol.io/packages/Clang%20Format>`__
+
+ - `alternative
+ tool <https://github.com/rosshemsley/SublimeClangFormat>`__
+
+- `Vim <http://clang.llvm.org/docs/ClangFormat.html#vim-integration>`__
+
+ - `clang-format.py <https://raw.githubusercontent.com/llvm-mirror/clang/master/tools/clang-format/clang-format.py>`__
+ - `vim-clang-format <https://github.com/rhysd/vim-clang-format>`__
+
+- `Visual
+ Studio <https://marketplace.visualstudio.com/items?itemName=LLVMExtensions.ClangFormat>`__
+
+ - `llvm.org plugin <http://llvm.org/builds/>`__
+ - `Integrated support in Visual Studio
+ 2017 <https://blogs.msdn.microsoft.com/vcblog/2018/03/13/clangformat-support-in-visual-studio-2017-15-7-preview-1/>`__
+
+- `Visual Studio
+ Code <https://marketplace.visualstudio.com/items?itemName=xaver.clang-format>`__
+- `XCode <https://github.com/travisjeffery/ClangFormat-Xcode>`__
+- `Script for patch
+ reformatting <http://clang.llvm.org/docs/ClangFormat.html#script-for-patch-reformatting>`__
+
+ - `clang-format-diff.py <https://raw.githubusercontent.com/llvm-mirror/clang/master/tools/clang-format/clang-format-diff.py>`__
+
+
+Configuration
+~~~~~~~~~~~~~
+
+These tools generally run clang-format themselves, and won't use
+``./mach clang-format``. The binary installed by our tooling will be
+located at ``~/.mozbuild/clang-tools/clang-tidy/bin/clang-format``.
+
+You typically shouldn't need to specify any other special configuration
+in your editor besides the clang-format binary. Most of the
+configuration that clang-format relies on for formatting is stored
+inside our source tree. More specifically, using the .clang-format file
+located in the root of the repository. Please note that this doesn't
+include the list of ignored files and directories (provided by
+.clang-format-ignore which is a feature provided by the mach command
+wrapper).
+
+Coding style configuration is done within clang-format itself. When we
+change the configuration (incorrect configuration, new feature in clang,
+etc), we use `local
+overrides <https://searchfox.org/mozilla-central/rev/501eb4718d73870892d28f31a99b46f4783efaa0/.clang-format>`__.
+
+
+Ignored files & directories
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+We maintain a `list of ignored directories and
+files <https://searchfox.org/mozilla-central/rev/501eb4718d73870892d28f31a99b46f4783efaa0/.clang-format-ignore>`__,
+which is used by ``./mach clang-format``. This is generally only used
+for code broken by clang-format, and third-party code.
+
+
+Ignored code hunks
+~~~~~~~~~~~~~~~~~~
+
+Sections of code may have formatting disabled using comments. If a
+section must not be formatted, the following comments will disable the
+reformat:
+
+::
+
+ // clang-format off
+ my code which should not be reformated
+ // clang-format on
+
+You can find an `example of code not
+formatted <https://searchfox.org/mozilla-central/rev/501eb4718d73870892d28f31a99b46f4783efaa0/xpcom/io/nsEscape.cpp#22>`__.
+
+
+Merging formatted and unformatted code
+--------------------------------------
+
+During the transition to using chromium style enforced by clang-format
+for all code in tree, it will often be necessary to rebase non-formatted
+code onto a formatted tree.
+
+
+Mercurial
+~~~~~~~~~
+
+The ``format-source`` extension, now bundled with
+``version-control-tools``, and installed by ``./mach bootstrap``, may be
+used to seamlessly handle this situation. More details may be found in
+this
+`document <https://docs.google.com/document/d/13AwAsvKMhH0mflDlfatBqn6LmZHiQih76oxM4zfrPl4/edit>`__.
+
+The parent changeset of the reformat has been tagged as
+``PRE_TREEWIDE_CLANG_FORMAT``.
+
+
+Git
+~~~
+
+To perform a rebase onto mozilla-central after the merge, a handy merge
+driver, ``clang-format-merge``, has been written:
+
+.. code:: shell
+
+ $ git clone https://github.com/emilio/clang-format-merge
+ $ /path/to/clang-format-merge/git-wrapper rebase <upstream>
+
+The wrapper should clean up after itself, and the clone may be deleted
+after the rebase is complete.
+
+
+Ignore lists
+------------
+
+To make sure that the blame/annotate features of Mercurial or git aren't
+affected. Two files are maintained to keep track of the reformatting
+commits.
+
+
+With Mercurial
+~~~~~~~~~~~~~~
+
+| The list is stored in
+ `https://searchfox.org/mozilla-central/source/.hg-annotate-ignore-revs </en-US/docs/>`__
+| Commit messages should also contain the string ``# ignore-this-changeset``
+
+The syntax in this file is generated using the following syntax:
+
+::
+
+ $ hg log --template '{node} - {author|person} - {desc|strip|firstline}\n'
+
+With git
+~~~~~~~~
+
+The list is stored in
+`https://searchfox.org/mozilla-central/source/.git-blame-ignore-revs </en-US/docs/>`__
+and contains git revisions for both gecko-dev and the git cinnabar
+repository.
diff --git a/docs/code-quality/coding-style/index.rst b/docs/code-quality/coding-style/index.rst
new file mode 100644
index 0000000000..e62ce910ca
--- /dev/null
+++ b/docs/code-quality/coding-style/index.rst
@@ -0,0 +1,20 @@
+Coding style
+============
+
+Firefox code is using different programming languages.
+For each language, we are enforcing a specific coding style.
+
+Getting Help
+------------
+
+If you need help or have questions, please don’t hesitate to contact us via Matrix
+in the "Lint and Formatting" room
+(`#lint:mozilla.org <https://chat.mozilla.org/#/room/#lint:mozilla.org>`_).
+
+
+.. toctree::
+ :caption: Coding Style User Guide
+ :maxdepth: 2
+ :glob:
+
+ *
diff --git a/docs/code-quality/coding-style/using_cxx_in_firefox_code.rst b/docs/code-quality/coding-style/using_cxx_in_firefox_code.rst
new file mode 100644
index 0000000000..513098855a
--- /dev/null
+++ b/docs/code-quality/coding-style/using_cxx_in_firefox_code.rst
@@ -0,0 +1,1065 @@
+Using C++ in Mozilla code
+=========================
+
+C++ language features
+---------------------
+
+Mozilla code only uses a subset of C++. Runtime type information (RTTI)
+is disabled, as it tends to cause a very large increase in codesize.
+This means that ``dynamic_cast``, ``typeid()`` and ``<typeinfo>`` cannot
+be used in Mozilla code. Also disabled are exceptions; do not use
+``try``/``catch`` or throw any exceptions. Libraries that throw
+exceptions may be used if you are willing to have the throw instead be
+treated as an abort.
+
+On the side of extending C++, we compile with ``-fno-strict-aliasing``.
+This means that when reinterpreting a pointer as a differently-typed
+pointer, you don't need to adhere to the "effective type" (of the
+pointee) rule from the standard (aka. "the strict aliasing rule") when
+dereferencing the reinterpreted pointer. You still need make sure that
+you don't violate alignment requirements and need to make sure that the
+data at the memory location pointed to forms a valid value when
+interpreted according to the type of the pointer when dereferencing the
+pointer for reading. Likewise, if you write by dereferencing the
+reinterpreted pointer and the originally-typed pointer might still be
+dereferenced for reading, you need to make sure that the values you
+write are valid according to the original type. This value validity
+issue is moot for e.g. primitive integers for which all bit patterns of
+their size are valid values.
+
+- As of Mozilla 59, C++14 mode is required to build Mozilla.
+- As of Mozilla 67, MSVC can no longer be used to build Mozilla.
+- As of Mozilla 73, C++17 mode is required to build Mozilla.
+
+This means that C++17 can be used where supported on all platforms. The
+list of acceptable features is given below:
+
+.. list-table::
+ :widths: 25 25 25 25
+ :header-rows: 3
+
+ * -
+ - GCC
+ - Clang
+ -
+ * - Current minimal requirement
+ - 7.1
+ - 5.0
+ -
+ * - Feature
+ - GCC
+ - Clang
+ - Can be used in code
+ * - ``type_t &&``
+ - 4.3
+ - 2.9
+ - Yes (see notes)
+ * - ref qualifiers on methods
+ - 4.8.1
+ - 2.9
+ - Yes
+ * - default member - initializers (except for bit-fields)
+ - 4.7
+ - 3.0
+ - Yes
+ * - default member - initializers (for bit-fields)
+ - 8
+ - 6
+ - **No**
+ * - variadic templates
+ - 4.3
+ - 2.9
+ - Yes
+ * - Initializer lists
+ - 4.4
+ - 3.1
+ - Yes
+ * - ``static_assert``
+ - 4.3
+ - 2.9
+ - Yes
+ * - ``auto``
+ - 4.4
+ - 2.9
+ - Yes
+ * - lambdas
+ - 4.5
+ - 3.1
+ - Yes
+ * - ``decltype``
+ - 4.3
+ - 2.9
+ - Yes
+ * - ``Foo<Bar<T>>``
+ - 4.3
+ - 2.9
+ - Yes
+ * - ``auto func() -> int``
+ - 4.4
+ - 3.1
+ - Yes
+ * - Templated aliasing
+ - 4.7
+ - 3.0
+ - Yes
+ * - ``nullptr``
+ - 4.6
+ - 3.0
+ - Yes
+ * - ``enum foo : int16_t`` {};
+ - 4.4
+ - 2.9
+ - Yes
+ * - ``enum class foo {}``;
+ - 4.4
+ - 2.9
+ - Yes
+ * - ``enum foo;``
+ - 4.6
+ - 3.1
+ - Yes
+ * - ``[[attributes]]``
+ - 4.8
+ - 3.3
+ - **No** (see notes)
+ * - ``constexpr``
+ - 4.6
+ - 3.1
+ - Yes
+ * - ``alignas``
+ - 4.8
+ - 3.3
+ - Yes
+ * - ``alignof``
+ - 4.8
+ - 3.3
+ - Yes, but see notes ; only clang 3.6 claims as_feature(cxx_alignof)
+ * - Delegated constructors
+ - 4.7
+ - 3.0
+ - Yes
+ * - Inherited constructors
+ - 4.8
+ - 3.3
+ - Yes
+ * - ``explicit operator bool()``
+ - 4.5
+ - 3.0
+ - Yes
+ * - ``char16_t/u"string"``
+ - 4.4
+ - 3.0
+ - Yes
+ * - ``R"(string)"``
+ - 4.5
+ - 3.0
+ - Yes
+ * - ``operator""()``
+ - 4.7
+ - 3.1
+ - Yes
+ * - ``=delete``
+ - 4.4
+ - 2.9
+ - Yes
+ * - ``=default``
+ - 4.4
+ - 3.0
+ - Yes
+ * - unrestricted unions
+ - 4.6
+ - 3.1
+ - Yes
+ * - ``for (auto x : vec)`` (`be careful about the type of the iterator <https://stackoverflow.com/questions/15176104/c11-range-based-loop-get-item-by-value-or-reference-to-const>`__)
+ - 4.6
+ - 3.0
+ - Yes
+ * - ``override``/``final``
+ - 4.7
+ - 3.0
+ - Yes
+ * - ``thread_local``
+ - 4.8
+ - 3.3
+ - **No** (see notes)
+ * - function template default arguments
+ - 4.3
+ - 2.9
+ - Yes
+ * - local structs as template parameters
+ - 4.5
+ - 2.9
+ - Yes
+ * - extended friend declarations
+ - 4.7
+ - 2.9
+ - Yes
+ * - ``0b100`` (C++14)
+ - 4.9
+ - 2.9
+ - Yes
+ * - `Tweaks to some C++ contextual conversions` (C++14)
+ - 4.9
+ - 3.4
+ - Yes
+ * - Return type deduction (C++14)
+ - 4.9
+ - 3.4
+ - Yes (but only in template code when you would have used ``decltype (complex-expression)``)
+ * - Generic lambdas (C++14)
+ - 4.9
+ - 3.4
+ - Yes
+ * - Initialized lambda captures (C++14)
+ - 4.9
+ - 3.4
+ - Yes
+ * - Digit separator (C++14)
+ - 4.9
+ - 3.4
+ - Yes
+ * - Variable templates (C++14)
+ - 5.0
+ - 3.4
+ - Yes
+ * - Relaxed constexpr (C++14)
+ - 5.0
+ - 3.4
+ - Yes
+ * - Aggregate member initialization (C++14)
+ - 5.0
+ - 3.3
+ - Yes
+ * - Clarifying memory allocation (C++14)
+ - 5.0
+ - 3.4
+ - Yes
+ * - [[deprecated]] attribute (C++14)
+ - 4.9
+ - 3.4
+ - **No** (see notes)
+ * - Sized deallocation (C++14)
+ - 5.0
+ - 3.4
+ - **No** (see notes)
+ * - Concepts (Concepts TS)
+ - 6.0
+ - —
+ - **No**
+ * - Inline variables (C++17)
+ - 7.0
+ - 3.9
+ - **No** (clang 5 has bugs with inline variables)
+ * - constexpr_if (C++17)
+ - 7.0
+ - 3.9
+ - Yes
+ * - constexpr lambdas (C++17)
+ - —
+ - —
+ - **No**
+ * - Structured bindings (C++17)
+ - 7.0
+ - 4.0
+ - Yes
+ * - Separated declaration and condition in ``if``, ``switch`` (C++17)
+ - 7.0
+ - 3.9
+ - Yes
+ * - `Fold expressions <https://en.cppreference.com/w/cpp/language/fold>`__ (C++17)
+ - 6.0
+ - 3.9
+ - Yes
+ * - [[fallthrough]], [[maybe_unused]], [[nodiscard]] (C++17)
+ - 7.0
+ - 3.9
+ - Yes
+ * - Aligned allocation/deallocation (C++17)
+ - 7.0
+ - 4.0
+ - **No** (see notes)
+ * - #pragma once
+ - 3.4
+ - Yes
+ - **Not** until we `normalize headers <https://groups.google.com/d/msg/mozilla.dev.platform/PgDjWw3xp8k/eqCFlP4Kz1MJ>`__
+ * - `Source code information capture <https://en.cppreference.com/w/cpp/experimental/lib_extensions_2#Source_code_information_capture>`__
+ - 8.0
+ - —
+ - **No**
+
+Sources
+~~~~~~~
+
+* GCC: https://gcc.gnu.org/projects/cxx-status.html
+* Clang: https://clang.llvm.org/cxx_status.html
+
+Notes
+~~~~~
+
+rvalue references: Implicit move method generation cannot be used.
+
+Attributes: Several common attributes are defined in
+`mozilla/Attributes.h <https://searchfox.org/mozilla-central/source/mfbt/Attributes.h>`__
+or nscore.h.
+
+Alignment: Some alignment utilities are defined in
+`mozilla/Alignment.h <https://searchfox.org/mozilla-central/source/mfbt/Alignment.h>`__.
+/!\\ MOZ_ALIGNOF and alignof don't have the same semantics. Be careful
+of what you expect from them.
+
+``[[deprecated]]``: If we have deprecated code, we should be removing it
+rather than marking it as such. Marking things as ``[[deprecated]]``
+also means the compiler will warn if you use the deprecated API, which
+turns into a fatal error in our automation builds, which is not helpful.
+
+Sized deallocation: Our compilers all support this (custom flags are
+required for GCC and Clang), but turning it on breaks some classes'
+``operator new`` methods, and `some
+work <https://bugzilla.mozilla.org/show_bug.cgi?id=1250998>`__ would
+need to be done to make it an efficiency win with our custom memory
+allocator.
+
+Aligned allocation/deallocation: Our custom memory allocator doesn't
+have support for these functions.
+
+Thread locals: ``thread_local`` is not supported on Android.
+
+
+C++ and Mozilla standard libraries
+----------------------------------
+
+The Mozilla codebase contains within it several subprojects which follow
+different rules for which libraries can and can't be used it. The rules
+listed here apply to normal platform code, and assume unrestricted
+usability of MFBT or XPCOM APIs.
+
+.. warning::
+
+ The rest of this section is a draft for expository and exploratory
+ purposes. Do not trust the information listed here.
+
+What follows is a list of standard library components provided by
+Mozilla or the C++ standard. If an API is not listed here, then it is
+not permissible to use it in Mozilla code. Deprecated APIs are not
+listed here. In general, prefer Mozilla variants of data structures to
+standard C++ ones, even when permitted to use the latter, since Mozilla
+variants tend to have features not found in the standard library (e.g.,
+memory size tracking) or have more controllable performance
+characteristics.
+
+A list of approved standard library headers is maintained in
+`config/stl-headers.mozbuild <https://searchfox.org/mozilla-central/source/config/stl-headers.mozbuild>`__.
+
+
+Data structures
+~~~~~~~~~~~~~~~
+
+.. list-table::
+ :widths: 25 25 25 25
+ :header-rows: 1
+
+ * - Name
+ - Header
+ - STL equivalent
+ - Notes
+ * - ``nsAutoTArray``
+ - ``nsTArray.h``
+ -
+ - Like ``nsTArray``, but will store a small amount as stack storage
+ * - ``nsAutoTObserverArray``
+ - ``nsTObserverArray.h``
+ -
+ - Like ``nsTObserverArray``, but will store a small amount as stack storage
+ * - ``mozilla::BloomFilter``
+ - ``mozilla/BloomFilter.h``
+ -
+ - Probabilistic set membership (see `Wikipedia <https://en.wikipedia.org/wiki/Bloom_filter#Counting_filters>`__)
+ * - ``nsClassHashtable``
+ - ``nsClassHashtable.h``
+ -
+ - Adaptation of nsTHashtable, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
+ * - ``nsCOMArray``
+ - ``nsCOMArray.h``
+ -
+ - Like ``nsTArray<nsCOMPtr<T>>``
+ * - ``nsDataHashtable``
+ - ``nsClassHashtable.h``
+ - ``std::unordered_map``
+ - Adaptation of ``nsTHashtable``, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
+ * - ``nsDeque``
+ - ``nsDeque.h``
+ - ``std::deque<void *>``
+ -
+ * - ``mozilla::EnumSet``
+ - ``mozilla/EnumSet.h``
+ -
+ - Like ``std::set``, but for enum classes.
+ * - ``mozilla::Hash{Map,Set}``
+ - `mozilla/HashTable.h <https://searchfox.org/mozilla-central/source/mfbt/HashTable.h>`__
+ - ``std::unordered_{map,set}``
+ - A general purpose hash map and hash set.
+ * - ``nsInterfaceHashtable``
+ - ``nsInterfaceHashtable.h``
+ - ``std::unordered_map``
+ - Adaptation of ``nsTHashtable``, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
+ * - ``nsJSThingHashtable``
+ - ``nsJSThingHashtable.h``
+ -
+ - Adaptation of ``nsTHashtable``, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
+ * - ``mozilla::LinkedList``
+ - ``mozilla/LinkedList.h``
+ - ``std::list``
+ - Doubly-linked list
+ * - ``nsRef PtrHashtable``
+ - ``nsRefPtrHashtable.h``
+ - ``std::unordered_map``
+ - Adaptation of ``nsTHashtable``, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
+ * - ``mozilla::SegmentedVector``
+ - ``mozilla/SegmentedVector.h``
+ - ``std::deque`` w/o O(1) pop_front
+ - Doubly-linked list of vector elements
+ * - ``mozilla::SplayTree``
+ - ``mozilla/SplayTree.h``
+ -
+ - Quick access to recently-accessed elements (see `Wikipedia <https://en.wikipedia.org/wiki/Splay_tree>`__)
+ * - ``nsTArray``
+ - ``nsTArray.h``
+ - ``std::vector``
+ -
+ * - ``nsTHashtable``
+ - ``nsTHashtable.h``
+ - ``std::unordered_{map,set}``
+ - See `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__, you probably want a subclass
+ * - ``nsTObserverArray``
+ - ``nsTObserverArray.h``
+ -
+ - Like ``nsTArray``, but iteration is stable even through mutation
+ * - ``nsTPriorityQueue``
+ - ``nsTPriorityQueue.h``
+ - ``std::priority_queue``
+ - Unlike the STL class, not a container adapter
+ * - ``mozilla::Vector``
+ - ``mozilla/Vector.h``
+ - ``std::vector``
+ -
+ * - ``mozilla::Buffer``
+ - ``mozilla/Buffer.h``
+ -
+ - Unlike ``Array``, has a run-time variable length. Unlike ``Vector``, does not have capacity and growth mechanism. Unlike ``Span``, owns its buffer.
+
+
+Safety utilities
+~~~~~~~~~~~~~~~~
+
+.. list-table::
+ :widths: 25 25 25 25
+ :header-rows: 1
+
+ * - Name
+ - Header
+ - STL equivalent
+ - Notes
+ * - ``mozilla::Array``
+ - ``mfbt/Array.h``
+ -
+ - safe array index
+ * - ``mozilla::AssertedCast``
+ - ``mfbt/Casting.h``
+ -
+ - casts
+ * - ``mozilla::CheckedInt``
+ - ``mfbt/CheckedInt.h``
+ -
+ - avoids overflow
+ * - ``nsCOMPtr``
+ - ``xpcom/base/nsCOMPtr.h``
+ - ``std::shared_ptr``
+ -
+ * - ``mozilla::EnumeratedArray``
+ - ``mfbt/EnumeratedArray.h``
+ - ``mozilla::Array``
+ -
+ * - ``mozilla::Maybe``
+ - ``mfbt/Maybe.h``
+ - ``std::optional``
+ -
+ * - ``mozilla::RangedPtr``
+ - ``mfbt/RangedPtr.h``
+ -
+ - like ``mozilla::Span`` but with two pointers instead of pointer and length
+ * - ``mozilla::RefPtr``
+ - ``mfbt/RefPtr.h``
+ - ``std::shared_ptr``
+ -
+ * - ``mozilla::Span``
+ - ``mozilla/Span.h``
+ - ``gsl::span``, ``absl::Span``, ``std::string_view``, ``std::u16string_view``
+ - Rust's slice concept for C++ (without borrow checking)
+ * - ``StaticRefPtr``
+ - ``xpcom/base/StaticPtr.h``
+ -
+ - ``nsRefPtr`` w/o static constructor
+ * - ``mozilla::UniquePtr``
+ - ``mfbt/UniquePtr.h``
+ - ``std::unique_ptr``
+ -
+ * - ``mozilla::WeakPtr``
+ - ``mfbt/WeakPtr.h``
+ - ``std::weak_ptr``
+ -
+ * - ``nsWeakPtr``
+ - ``xpcom/base/nsWeakPtr.h``
+ - ``std::weak_ptr``
+ -
+
+
+Strings
+~~~~~~~
+
+See the `Mozilla internal string
+guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Internal_strings>`__ for
+usage of ``nsAString`` (our copy-on-write replacement for
+``std::u16string``) and ``nsACString`` (our copy-on-write replacement
+for ``std::string``).
+
+Be sure not to introduce further uses of ``std::wstring``, which is not
+portable! (Some uses exist in the IPC code.)
+
+
+Algorithms
+~~~~~~~~~~
+
+.. list-table::
+ :widths: 25 25
+
+ * - ``mozilla::BinarySearch``
+ - ``mfbt/BinarySearch.h``
+ * - ``mozilla::BitwiseCast``
+ - ``mfbt/Casting.h`` (strict aliasing-safe cast)
+ * - ``mozilla/MathAlgorithms.h``
+ - (rotate, ctlz, popcount, gcd, abs, lcm)
+ * - ``mozilla::RollingMean``
+ - ``mfbt/RollingMean.h`` ()
+
+
+Concurrency
+~~~~~~~~~~~
+
+.. list-table::
+ :widths: 25 25 25 25
+ :header-rows: 1
+
+ * - Name
+ - Header
+ - STL/boost equivalent
+ - Notes
+ * - ``mozilla::Atomic``
+ - mfbt/Atomic.h
+ - ``std::atomic``
+ -
+ * - ``mozilla::CondVar``
+ - xpcom/threads/CondVar.h
+ - ``std::condition_variable``
+ -
+ * - ``mozilla::DataMutex``
+ - xpcom/threads/DataMutex.h
+ - ``boost::synchronized_value``
+ -
+ * - ``mozilla::Monitor``
+ - xpcom/threads/Monitor.h
+ -
+ -
+ * - ``mozilla::Mutex``
+ - xpcom/threads/Mutex.h
+ - ``std::mutex``
+ -
+ * - ``mozilla::ReentrantMonitor``
+ - xpcom/threads/ReentrantMonitor.h
+ -
+ -
+ * - ``mozilla::StaticMutex``
+ - xpcom/base/StaticMutex.h
+ - ``std::mutex``
+ - Mutex that can (and in fact, must) be used as a global/static variable.
+
+
+Miscellaneous
+~~~~~~~~~~~~~
+
+.. list-table::
+ :widths: 25 25 25 25
+ :header-rows: 1
+
+ * - Name
+ - Header
+ - STL/boost equivalent
+ - Notes
+ * - ``mozilla::AlignedStorage``
+ - mfbt/Alignment.h
+ - ``std::aligned_storage``
+ -
+ * - ``mozilla::MaybeOneOf``
+ - mfbt/MaybeOneOf.h
+ - ``std::optional<std::variant<T1, T2>>``
+ - ~ ``mozilla::Maybe<union {T1, T2}>``
+ * - ``mozilla::Pair``
+ - mfbt/Pair.h
+ - ``std::tuple<T1, T2>``
+ - minimal space!
+ * - ``mozilla::TimeStamp``
+ - xpcom/ds/TimeStamp.h
+ - ``std::chrono::time_point``
+ -
+ * -
+ - mozilla/TypeTraits.h
+ - ``<type_traits>``
+ -
+ * -
+ - mozilla/PodOperations.h
+ -
+ - C++ versions of ``memset``, ``memcpy``, etc.
+ * -
+ - mozilla/ArrayUtils.h
+ -
+ -
+ * -
+ - mozilla/Compression.h
+ -
+ -
+ * -
+ - mozilla/Endian.h
+ -
+ -
+ * -
+ - mozilla/FloatingPoint.h
+ -
+ -
+ * -
+ - mozilla/HashFunctions.h
+ - ``std::hash``
+ -
+ * -
+ - mozilla/Move.h
+ - ``std::move``, ``std::swap``, ``std::forward``
+ -
+
+
+Mozilla data structures and standard C++ ranges and iterators
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Some Mozilla-defined data structures provide STL-style
+`iterators <https://en.cppreference.com/w/cpp/named_req/Iterator>`__ and
+are usable in `range-based for
+loops <https://en.cppreference.com/w/cpp/language/range-for>`__ as well
+as STL `algorithms <https://en.cppreference.com/w/cpp/algorithm>`__.
+
+Currently, these include:
+
+.. list-table::
+ :widths: 16 16 16 16 16
+ :header-rows: 1
+
+ * - Name
+ - Header
+ - Bug(s)
+ - Iterator category
+ - Notes
+ * - ``nsTArray``
+ - ``xpcom/ds/n sTArray.h``
+ - `1126552 <https://bugzilla.mozilla.org/show_bug.cgi?id=1126552>`__
+ - Random-access
+ - Also reverse-iterable. Also supports remove-erase pattern via RemoveElementsAt method. Also supports back-inserting output iterators via ``MakeBackInserter`` function.
+ * - ``nsBaseHashtable`` and subclasses: ``nsClassHashtable`` ``nsDataHashtable`` ``nsInterfaceHashtable`` ``nsJSThingHashtable`` ``nsRefPtrHashtable``
+ - ``xpcom/ds/nsBaseHashtable.h`` ``xpcom/ds/nsClassHashtable.h`` ``xpcom/ds/nsDataHashtable.h`` ``xpcom/ds/nsInterfaceHashtable.h`` ``xpcom/ds/nsJSThingHashtable.h`` ``xpcom/ds/nsRefPtrHashtable.h``
+ - `1575479 <https://bugzilla.mozilla.org/show_bug.cgi?id=1575479>`__
+ - Forward
+ -
+ * - ``nsCOMArray``
+ - ``xpcom/ds/nsCOMArray.h``
+ - `1342303 <https://bugzilla.mozilla.org/show_bug.cgi?id=1342303>`__
+ - Random-access
+ - Also reverse-iterable.
+ * - ``Array`` ``EnumerationArray`` ``RangedArray``
+ - ``mfbt/Array.h`` ``mfbt/EnumerationArray.h`` ``mfbt/RangedArray.h``
+ - `1216041 <https://bugzilla.mozilla.org/show_bug.cgi?id=1216041>`__
+ - Random-access
+ - Also reverse-iterable.
+ * - ``Buffer``
+ - ``mfbt/Buffer.h``
+ - `1512155 <https://bugzilla.mozilla.org/show_bug.cgi?id=1512155>`__
+ - Random-access
+ - Also reverse-iterable.
+ * - ``DoublyLinkedList``
+ - ``mfbt/DoublyLinkedList.h``
+ - `1277725 <https://bugzilla.mozilla.org/show_bug.cgi?id=1277725>`__
+ - Forward
+ -
+ * - ``EnumeratedRange``
+ - ``mfbt/EnumeratedRange.h``
+ - `1142999 <https://bugzilla.mozilla.org/show_bug.cgi?id=1142999>`__
+ - *Missing*
+ - Also reverse-iterable.
+ * - ``IntegerRange``
+ - ``mfbt/IntegerRange.h``
+ - `1126701 <https://bugzilla.mozilla.org/show_bug.cgi?id=1126701>`__
+ - *Missing*
+ - Also reverse-iterable.
+ * - ``SmallPointerArray``
+ - ``mfbt/SmallPointerArray.h``
+ - `1331718 <https://bugzilla.mozilla.org/show_bug.cgi?id=1331718>`__
+ - Random-access
+ -
+ * - ``Span``
+ - ``mfbt/Span.h``
+ - `1295611 <https://bugzilla.mozilla.org/show_bug.cgi?id=1295611>`__
+ - Random-access
+ - Also reverse-iterable.
+
+Note that if the iterator category is stated as "missing", the type is
+probably only usable in range-based for. This is most likely just an
+omission, which could be easily fixed.
+
+Useful in this context are also the class template ``IteratorRange``
+(which can be used to construct a range from any pair of iterators) and
+function template ``Reversed`` (which can be used to reverse any range),
+both defined in ``mfbt/ReverseIterator.h``
+
+
+Further C++ rules
+-----------------
+
+
+Don't use static constructors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+(You probably shouldn't be using global variables to begin with. Quite
+apart from the weighty software-engineering arguments against them,
+globals affect startup time! But sometimes we have to do ugly things.)
+
+Non-portable example:
+
+.. code-block:: c++
+
+ FooBarClass static_object(87, 92);
+
+ void
+ bar()
+ {
+ if (static_object.count > 15) {
+ ...
+ }
+ }
+
+Once upon a time, there were compiler bugs that could result in
+constructors not being called for global objects. Those bugs are
+probably long gone by now, but even with the feature working correctly,
+there are so many problems with correctly ordering C++ constructors that
+it's easier to just have an init function:
+
+.. code-block:: c++
+
+ static FooBarClass* static_object;
+
+ FooBarClass*
+ getStaticObject()
+ {
+ if (!static_object)
+ static_object =
+ new FooBarClass(87, 92);
+ return static_object;
+ }
+
+ void
+ bar()
+ {
+ if (getStaticObject()->count > 15) {
+ ...
+ }
+ }
+
+
+Don't use exceptions
+~~~~~~~~~~~~~~~~~~~~
+
+See the introduction to the "C++ language features" section at the start
+of this document.
+
+
+Don't use Run-time Type Information
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+See the introduction to the "C++ language features" section at the start
+of this document.
+
+If you need runtime typing, you can achieve a similar result by adding a
+``classOf()`` virtual member function to the base class of your
+hierarchy and overriding that member function in each subclass. If
+``classOf()`` returns a unique value for each class in the hierarchy,
+you'll be able to do type comparisons at runtime.
+
+
+Don't use the C++ standard library (including iostream and locale)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+See the section "C++ and Mozilla standard libraries".
+
+
+Use C++ lambdas, but with care
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+C++ lambdas are supported across all our compilers now. Rejoice! We
+recommend explicitly listing out the variables that you capture in the
+lambda, both for documentation purposes, and to double-check that you're
+only capturing what you expect to capture.
+
+
+Use namespaces
+~~~~~~~~~~~~~~
+
+Namespaces may be used according to the style guidelines in :ref:`C++ Coding style`.
+
+
+Don't mix varargs and inlines
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+What? Why are you using varargs to begin with?! Stop that at once!
+
+
+Make header files compatible with C and C++
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Non-portable example:
+
+.. code-block:: c++
+
+ /*oldCheader.h*/
+ int existingCfunction(char*);
+ int anotherExistingCfunction(char*);
+
+ /* oldCfile.c */
+ #include "oldCheader.h"
+ ...
+
+ // new file.cpp
+ extern "C" {
+ #include "oldCheader.h"
+ };
+ ...
+
+If you make new header files with exposed C interfaces, make the header
+files work correctly when they are included by both C and C++ files.
+
+(If you need to include a C header in new C++ files, that should just
+work. If not, it's the C header maintainer's fault, so fix the header if
+you can, and if not, whatever hack you come up with will probably be
+fine.)
+
+Portable example:
+
+.. code-block:: c++
+
+ /* oldCheader.h*/
+ PR_BEGIN_EXTERN_C
+ int existingCfunction(char*);
+ int anotherExistingCfunction(char*);
+ PR_END_EXTERN_C
+
+ /* oldCfile.c */
+ #include "oldCheader.h"
+ ...
+
+ // new file.cpp
+ #include "oldCheader.h"
+ ...
+
+There are number of reasons for doing this, other than just good style.
+For one thing, you are making life easier for everyone else, doing the
+work in one common place (the header file) instead of all the C++ files
+that include it. Also, by making the C header safe for C++, you document
+that "hey, this file is now being included in C++". That's a good thing.
+You also avoid a big portability nightmare that is nasty to fix...
+
+
+Use override on subclass virtual member functions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``override`` keyword is supported in C++11 and in all our supported
+compilers, and it catches bugs.
+
+
+Always declare a copy constructor and assignment operator
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Many classes shouldn't be copied or assigned. If you're writing one of
+these, the way to enforce your policy is to declare a deleted copy
+constructor as private and not supply a definition. While you're at it,
+do the same for the assignment operator used for assignment of objects
+of the same class. Example:
+
+.. code-block:: c++
+
+ class Foo {
+ ...
+ private:
+ Foo(const Foo& x) = delete;
+ Foo& operator=(const Foo& x) = delete;
+ };
+
+Any code that implicitly calls the copy constructor will hit a
+compile-time error. That way nothing happens in the dark. When a user's
+code won't compile, they'll see that they were passing by value, when
+they meant to pass by reference (oops).
+
+
+Be careful of overloaded methods with like signatures
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It's best to avoid overloading methods when the type signature of the
+methods differs only by one "abstract" type (e.g. ``PR_Int32`` or
+``int32``). What you will find as you move that code to different
+platforms, is suddenly on the Foo2000 compiler your overloaded methods
+will have the same type-signature.
+
+
+Type scalar constants to avoid unexpected ambiguities
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Non-portable code:
+
+.. code-block:: c++
+
+ class FooClass {
+ // having such similar signatures
+ // is a bad idea in the first place.
+ void doit(long);
+ void doit(short);
+ };
+
+ void
+ B::foo(FooClass* xyz)
+ {
+ xyz->doit(45);
+ }
+
+Be sure to type your scalar constants, e.g., ``uint32_t(10)`` or
+``10L``. Otherwise, you can produce ambiguous function calls which
+potentially could resolve to multiple methods, particularly if you
+haven't followed (2) above. Not all of the compilers will flag ambiguous
+method calls.
+
+Portable code:
+
+.. code-block:: c++
+
+ class FooClass {
+ // having such similar signatures
+ // is a bad idea in the first place.
+ void doit(long);
+ void doit(short);
+ };
+
+ void
+ B::foo(FooClass* xyz)
+ {
+ xyz->doit(45L);
+ }
+
+
+Use nsCOMPtr in XPCOM code
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+See the ``nsCOMPtr`` `User
+Manual <https://developer.mozilla.org/en-US/docs/Using_nsCOMPtr>`__ for
+usage details.
+
+
+Don't use identifiers that start with an underscore
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This rule occasionally surprises people who've been hacking C++ for
+decades. But it comes directly from the C++ standard!
+
+According to the C++ Standard, 17.4.3.1.2 Global Names
+[lib.global.names], paragraph 1:
+
+Certain sets of names and function signatures are always reserved to the
+implementation:
+
+- Each name that contains a double underscore (__) or begins with an
+ underscore followed by an uppercase letter (2.11) is reserved to the
+ implementation for any use.
+- **Each name that begins with an underscore is reserved to the
+ implementation** for use as a name in the global namespace.
+
+
+Stuff that is good to do for C or C++
+-------------------------------------
+
+
+Avoid conditional #includes when possible
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Don't write an ``#include`` inside an ``#ifdef`` if you could instead
+put it outside. Unconditional includes are better because they make the
+compilation more similar across all platforms and configurations, so
+you're less likely to cause stupid compiler errors on someone else's
+favorite platform that you never use.
+
+Bad code example:
+
+.. code-block:: c++
+
+ #ifdef MOZ_ENABLE_JPEG_FOUR_BILLION
+ #include <stdlib.h> // <--- don't do this
+ #include "jpeg4e9.h" // <--- only do this if the header really might not be there
+ #endif
+
+Of course when you're including different system files for different
+machines, you don't have much choice. That's different.
+
+
+Every .cpp source file should have a unique name
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Every object file linked into libxul needs to have a unique name. Avoid
+generic names like nsModule.cpp and instead use nsPlacesModule.cpp.
+
+
+Turn on warnings for your compiler, and then write warning free code
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+What generates a warning on one platform will generate errors on
+another. Turn warnings on. Write warning-free code. It's good for you.
+Treat warnings as errors by adding
+``ac_add_options --enable-warnings-as-errors`` to your mozconfig file.
+
+
+Use the same type for all bitfields in a ``struct`` or ``class``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Some compilers do not pack the bits when different bitfields are given
+different types. For example, the following struct might have a size of
+8 bytes, even though it would fit in 1:
+
+.. code-block:: c++
+
+ struct {
+ char ch: 1;
+ int i: 1;
+ };
+
+
+Don't use an enum type for a bitfield
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The classic example of this is using ``PRBool`` for a boolean bitfield.
+Don't do that. ``PRBool`` is a signed integer type, so the bitfield's
+value when set will be ``-1`` instead of ``+1``, which---I know,
+*crazy*, right? The things C++ hackers used to have to put up with...
+
+You shouldn't be using ``PRBool`` anyway. Use ``bool``. Bitfields of
+type ``bool`` are fine.
+
+Enums are signed on some platforms (in some configurations) and unsigned
+on others and therefore unsuitable for writing portable code when every
+bit counts, even if they happen to work on your system.
diff --git a/docs/code-quality/index.rst b/docs/code-quality/index.rst
new file mode 100644
index 0000000000..97939211df
--- /dev/null
+++ b/docs/code-quality/index.rst
@@ -0,0 +1,184 @@
+Code quality
+============
+
+Because Firefox is a complex piece of software, a lot of tools are
+executed to identify issues at development phase.
+In this document, we try to list these all tools.
+
+
+.. toctree::
+ :maxdepth: 1
+ :glob:
+
+ static-analysis.rst
+ lint/index.rst
+ coding-style/index.rst
+
+.. list-table:: C/C++
+ :header-rows: 1
+ :widths: 20 20 20 20 20
+
+ * - Tools
+ - Has autofixes
+ - Meta bug
+ - More info
+ - Upstream
+ * - Custom clang checker
+ -
+ -
+ - `Source <https://searchfox.org/mozilla-central/source/build/clang-plugin>`_
+ -
+ * - Clang-Tidy
+ - Yes
+ - `bug 712350 <https://bugzilla.mozilla.org/show_bug.cgi?id=712350>`__
+ - :ref:`Static analysis <Mach static analysis>`
+ - https://clang.llvm.org/extra/clang-tidy/checks/list.html
+ * - Clang analyzer
+ -
+ - `bug 712350 <https://bugzilla.mozilla.org/show_bug.cgi?id=712350>`__
+ -
+ - https://clang-analyzer.llvm.org/
+ * - Coverity
+ -
+ - `bug 1230156 <https://bugzilla.mozilla.org/show_bug.cgi?id=1230156>`__
+ -
+ -
+ * - cpp virtual final
+ -
+ -
+ - :ref:`cpp virtual final`
+ -
+ * - Semmle/LGTM
+ -
+ - `bug 1458117 <https://bugzilla.mozilla.org/show_bug.cgi?id=1458117>`__
+ -
+ -
+ * - clang-format
+ - Yes
+ - `bug 1188202 <https://bugzilla.mozilla.org/show_bug.cgi?id=1188202>`__
+ - :ref:`Formatting C++ Code With clang-format`
+ - https://clang.llvm.org/docs/ClangFormat.html
+
+.. list-table:: JavaScript
+ :widths: 20 20 20 20 20
+ :header-rows: 1
+
+ * - Tools
+ - Has autofixes
+ - Meta bug
+ - More info
+ - Upstream
+ * - Eslint
+ - Yes
+ - `bug 1229856 <https://bugzilla.mozilla.org/show_bug.cgi?id=1229856>`__
+ - :ref:`ESLint`
+ - https://eslint.org/
+ * - Mozilla ESLint
+ -
+ - `bug 1229856 <https://bugzilla.mozilla.org/show_bug.cgi?id=1229856>`__
+ - :ref:`Mozilla ESLint Plugin`
+ -
+ * - Prettier
+ - Yes
+ - `bug 1558517 <https://bugzilla.mozilla.org/show_bug.cgi?id=1558517>`__
+ - :ref:`JavaScript Coding style`
+ - https://prettier.io/
+
+
+
+.. list-table:: Python
+ :widths: 20 20 20 20 20
+ :header-rows: 1
+
+ * - Tools
+ - Has autofixes
+ - Meta bug
+ - More info
+ - Upstream
+ * - Flake8
+ - Yes (with `autopep8 <https://github.com/hhatto/autopep8>`_)
+ - `bug 1155970 <https://bugzilla.mozilla.org/show_bug.cgi?id=1155970>`__
+ - :ref:`Flake8`
+ - http://flake8.pycqa.org/
+ * - black
+ - Yes
+ - `bug 1555560 <https://bugzilla.mozilla.org/show_bug.cgi?id=1555560>`__
+ - :ref:`black`
+ - https://black.readthedocs.io/en/stable
+ * - pylint
+ -
+ - `bug 1623024 <https://bugzilla.mozilla.org/show_bug.cgi?id=1623024>`__
+ - :ref:`pylint`
+ - https://www.pylint.org/
+ * - Python 2/3 compatibility check
+ -
+ - `bug 1496527 <https://bugzilla.mozilla.org/show_bug.cgi?id=1496527>`__
+ - :ref:`Python 2/3 compatibility check`
+ -
+
+
+.. list-table:: Rust
+ :widths: 20 20 20 20 20
+ :header-rows: 1
+
+ * - Tools
+ - Has autofixes
+ - Meta bug
+ - More info
+ - Upstream
+ * - Rustfmt
+ - Yes
+ - `bug 1454764 <https://bugzilla.mozilla.org/show_bug.cgi?id=1454764>`__
+ - :ref:`Rustfmt`
+ - https://github.com/rust-lang/rustfmt
+ * - Clippy
+ -
+ - `bug 1361342 <https://bugzilla.mozilla.org/show_bug.cgi?id=1361342>`__
+ - :ref:`clippy`
+ - https://github.com/rust-lang/rust-clippy
+
+.. list-table:: Java
+ :widths: 20 20 20 20 20
+ :header-rows: 1
+
+ * - Tools
+ - Has autofixes
+ - Meta bug
+ - More info
+ - Upstream
+ * - Infer
+ -
+ - `bug 1175203 <https://bugzilla.mozilla.org/show_bug.cgi?id=1175203>`__
+ -
+ - https://github.com/facebook/infer
+
+.. list-table:: Others
+ :widths: 20 20 20 20 20
+ :header-rows: 1
+
+ * - Tools
+ - Has autofixes
+ - Meta bug
+ - More info
+ - Upstream
+ * - shellcheck
+ -
+ -
+ -
+ - https://www.shellcheck.net/
+ * - rstchecker
+ -
+ -
+ - :ref:`RST Linter`
+ - https://github.com/myint/rstcheck
+ * - Typo detection
+ - Yes
+ -
+ - :ref:`Codespell`
+ - https://github.com/codespell-project/codespell
+ * - YAML linter
+ -
+ -
+ -
+ - https://github.com/adrienverge/yamllint
+
diff --git a/docs/code-quality/lint/create.rst b/docs/code-quality/lint/create.rst
new file mode 100644
index 0000000000..066cb5eeef
--- /dev/null
+++ b/docs/code-quality/lint/create.rst
@@ -0,0 +1,329 @@
+Adding a New Linter to the Tree
+===============================
+
+Linter Requirements
+-------------------
+
+For a linter to be integrated into the mozilla-central tree, it needs to have:
+
+* Any required dependencies should be installed as part of ``./mach bootstrap``
+* A ``./mach lint`` interface
+* Running ``./mach lint`` command must pass (note, linters can be disabled for individual directories)
+* Taskcluster/Treeherder integration
+* In tree documentation (under ``docs/code-quality/lint``) to give a basic summary, links and any other useful information
+* Unit tests (under ``tools/lint/test``) to make sure that the linter works as expected and we don't regress.
+
+The review group in Phabricator is ``#linter-reviewers``.
+
+Linter Basics
+-------------
+
+A linter is a yaml file with a ``.yml`` extension. Depending on how the type of linter, there may
+be python code alongside the definition, pointed to by the 'payload' attribute.
+
+Here's a trivial example:
+
+no-eval.yml
+
+.. code-block:: yaml
+
+ EvalLinter:
+ description: Ensures the string eval doesn't show up.
+ extensions: ['js']
+ type: string
+ payload: eval
+
+Now ``no-eval.yml`` gets passed into :func:`LintRoller.read`.
+
+
+Linter Types
+------------
+
+There are four types of linters, though more may be added in the future.
+
+1. string - fails if substring is found
+2. regex - fails if regex matches
+3. external - fails if a python function returns a non-empty result list
+4. structured_log - fails if a mozlog logger emits any lint_error or lint_warning log messages
+
+As seen from the example above, string and regex linters are very easy to create, but they
+should be avoided if possible. It is much better to use a context aware linter for the language you
+are trying to lint. For example, use eslint to lint JavaScript files, use flake8 to lint python
+files, etc.
+
+Which brings us to the third and most interesting type of linter,
+external. External linters call an arbitrary python function which is
+responsible for not only running the linter, but ensuring the results
+are structured properly. For example, an external type could shell out
+to a 3rd party linter, collect the output and format it into a list of
+:class:`Issue` objects. The signature for this python
+function is ``lint(files, config, **kwargs)``, where ``files`` is a list of
+files to lint and ``config`` is the linter definition defined in the ``.yml``
+file.
+
+Structured log linters are much like external linters, but suitable
+for cases where the linter code is using mozlog and emits
+``lint_error`` or ``lint_warning`` logging messages when the lint
+fails. This is recommended for writing novel gecko-specific lints. In
+this case the signature for lint functions is ``lint(files, config, logger,
+**kwargs)``.
+
+
+Linter Definition
+-----------------
+
+Each ``.yml`` file must have at least one linter defined in it. Here are the supported keys:
+
+* description - A brief description of the linter's purpose (required)
+* type - One of 'string', 'regex' or 'external' (required)
+* payload - The actual linting logic, depends on the type (required)
+* include - A list of file paths that will be considered (optional)
+* exclude - A list of file paths or glob patterns that must not be matched (optional)
+* extensions - A list of file extensions to be considered (optional)
+* setup - A function that sets up external dependencies (optional)
+* support-files - A list of glob patterns matching configuration files (optional)
+* find-dotfiles - If set to ``true``, run on dot files (.*) (optional)
+* ignore-case - If set to ``true`` and ``type`` is regex, ignore the case (optional)
+
+In addition to the above, some ``.yml`` files correspond to a single lint rule. For these, the
+following additional keys may be specified:
+
+* message - A string to print on infraction (optional)
+* hint - A string with a clue on how to fix the infraction (optional)
+* rule - An id string for the lint rule (optional)
+* level - The severity of the infraction, either 'error' or 'warning' (optional)
+
+For structured_log lints the following additional keys apply:
+
+* logger - A StructuredLog object to use for logging. If not supplied
+ one will be created (optional)
+
+
+Example
+-------
+
+Here is an example of an external linter that shells out to the python flake8 linter,
+let's call the file ``flake8_lint.py`` (`in-tree version <https://searchfox.org/mozilla-central/source/tools/lint/python/flake8.py>`_):
+
+.. code-block:: python
+
+ import json
+ import os
+ import subprocess
+ from collections import defaultdict
+
+ from mozlint import result
+
+ try:
+ from shutil import which
+ except ImportError:
+ from shutil_which import which
+
+
+ FLAKE8_NOT_FOUND = """
+ Could not find flake8! Install flake8 and try again.
+ """.strip()
+
+
+ def lint(files, config, **lintargs):
+ binary = os.environ.get('FLAKE8')
+ if not binary:
+ binary = which('flake8')
+ if not binary:
+ print(FLAKE8_NOT_FOUND)
+ return 1
+
+ # Flake8 allows passing in a custom format string. We use
+ # this to help mold the default flake8 format into what
+ # mozlint's Issue object expects.
+ cmdargs = [
+ binary,
+ '--format',
+ '{"path":"%(path)s","lineno":%(row)s,"column":%(col)s,"rule":"%(code)s","message":"%(text)s"}',
+ ] + files
+
+ proc = subprocess.Popen(cmdargs, stdout=subprocess.PIPE, env=os.environ)
+ output = proc.communicate()[0]
+
+ # all passed
+ if not output:
+ return []
+
+ results = []
+ for line in output.splitlines():
+ # res is a dict of the form specified by --format above
+ res = json.loads(line)
+
+ # parse level out of the id string
+ if 'code' in res and res['code'].startswith('W'):
+ res['level'] = 'warning'
+
+ # result.from_linter is a convenience method that
+ # creates a Issue using a LINTER definition
+ # to populate some defaults.
+ results.append(result.from_config(config, **res))
+
+ return results
+
+Now here is the linter definition that would call it:
+
+.. code-block:: yaml
+
+ flake8:
+ description: Python linter
+ include: ['.']
+ extensions: ['py']
+ type: external
+ payload: py.flake8:lint
+ support-files:
+ - '**/.flake8'
+
+Notice the payload has two parts, delimited by ':'. The first is the module
+path, which ``mozlint`` will attempt to import. The second is the object path
+within that module (e.g, the name of a function to call). It is up to consumers
+of ``mozlint`` to ensure the module is in ``sys.path``. Structured log linters
+use the same import mechanism.
+
+The ``support-files`` key is used to list configuration files or files related
+to the running of the linter itself. If using ``--outgoing`` or ``--workdir``
+and one of these files was modified, the entire tree will be linted instead of
+just the modified files.
+
+Result definition
+-----------------
+
+When generating the list of results, the following values are available.
+
+.. csv-table::
+ :header: "Name", "Description", "Optional"
+ :widths: 20, 40, 10
+
+ "linter", "Name of the linter that flagged this error", ""
+ "path", "Path to the file containing the error", ""
+ "message", "Text describing the error", ""
+ "lineno", "Line number that contains the error", ""
+ "column", "Column containing the error", ""
+ "level", "Severity of the error, either 'warning' or 'error' (default 'error')", "Yes"
+ "hint", "Suggestion for fixing the error", "Yes"
+ "source", "Source code context of the error", "Yes"
+ "rule", "Name of the rule that was violated", "Yes"
+ "lineoffset", "Denotes an error spans multiple lines, of the form (<lineno offset>, <num lines>)", "Yes"
+ "diff", "A diff describing the changes that need to be made to the code", "Yes"
+
+
+Automated testing
+-----------------
+
+Every new checker must have tests associated.
+
+They should be pretty easy to write as most of the work is managed by the Mozlint
+framework. The key declaration is the ``LINTER`` variable which must match
+the linker declaration.
+
+As an example, the `Flake8 test <https://searchfox.org/mozilla-central/source/tools/lint/test/test_flake8.py>`_ looks like the following snippet:
+
+.. code-block:: python
+
+ import mozunit
+ LINTER = 'flake8'
+
+ def test_lint_single_file(lint, paths):
+ results = lint(paths('bad.py'))
+ assert len(results) == 2
+ assert results[0].rule == 'F401'
+ assert results[1].rule == 'E501'
+ assert results[1].lineno == 5
+
+ if __name__ == '__main__':
+ mozunit.main()
+
+As always with tests, please make sure that enough positive and negative cases are covered.
+
+To run the tests:
+
+.. code-block:: shell
+
+ $ ./mach python-test --python 3 --subsuite mozlint
+
+
+More tests can be `found in-tree <https://searchfox.org/mozilla-central/source/tools/lint/test>`_.
+
+
+
+Bootstrapping Dependencies
+--------------------------
+
+Many linters, especially 3rd party ones, will require a set of dependencies. It
+could be as simple as installing a binary from a package manager, or as
+complicated as pulling a whole graph of tools, plugins and their dependencies.
+
+Either way, to reduce the burden on users, linters should strive to provide
+automated bootstrapping of all their dependencies. To help with this,
+``mozlint`` allows linters to define a ``setup`` config, which has the same
+path object format as an external payload. For example (`in-tree version <https://searchfox.org/mozilla-central/source/tools/lint/flake8.yml>`_):
+
+.. code-block:: yaml
+
+ flake8:
+ description: Python linter
+ include: ['.']
+ extensions: ['py']
+ type: external
+ payload: py.flake8:lint
+ setup: py.flake8:setup
+
+The setup function takes a single argument, the root of the repository being
+linted. In the case of ``flake8``, it might look like:
+
+.. code-block:: python
+
+ import subprocess
+ from distutils.spawn import find_executable
+
+ def setup(root, **lintargs):
+ # This is a simple example. Please look at the actual source for better examples.
+ if not find_executable('flake8'):
+ subprocess.call(['pip', 'install', 'flake8'])
+
+The setup function will be called implicitly before running the linter. This
+means it should return fast and not produce any output if there is no setup to
+be performed.
+
+The setup functions can also be called explicitly by running ``mach lint
+--setup``. This will only perform setup and not perform any linting. It is
+mainly useful for other tools like ``mach bootstrap`` to call into.
+
+
+Adding the linter to the CI
+---------------------------
+
+First, the job will have to be declared in Taskcluster.
+
+This should be done in the `mozlint Taskcluster configuration <https://searchfox.org/mozilla-central/source/taskcluster/ci/source-test/mozlint.yml>`_.
+You will need to define a symbol, how it is executed and on what kind of change.
+
+For example, for flake8, the configuration is the following:
+
+.. code-block:: yaml
+
+ py-flake8:
+ description: flake8 run over the gecko codebase
+ treeherder:
+ symbol: py(f8)
+ run:
+ mach: lint -l flake8 -f treeherder -f json:/builds/worker/mozlint.json
+ when:
+ files-changed:
+ - '**/*.py'
+ - '**/.flake8'
+ # moz.configure files are also Python files.
+ - '**/*.configure'
+
+If the linter requires an external program, you will have to install it in the `setup script <https://searchfox.org/mozilla-central/source/taskcluster/docker/lint/system-setup.sh>`_
+and maybe install the necessary files in the `Docker configuration <https://searchfox.org/mozilla-central/source/taskcluster/docker/lint/Dockerfile>`_.
+
+.. note::
+
+ If the defect found by the linter is minor, make sure that it is run as `tier 2 <https://wiki.mozilla.org/Sheriffing/Job_Visibility_Policy#Overview_of_the_Job_Visibility_Tiers>`_.
+ This prevents the tree from closing because of a tiny issue.
+ For example, the typo detection is run as tier-2.
diff --git a/docs/code-quality/lint/index.rst b/docs/code-quality/lint/index.rst
new file mode 100644
index 0000000000..1c282f60b4
--- /dev/null
+++ b/docs/code-quality/lint/index.rst
@@ -0,0 +1,38 @@
+Linting
+=======
+
+Linters are used in mozilla-central to help enforce coding style and avoid bad practices. Due to the
+wide variety of languages in use, this is not always an easy task. In addition, linters should be runnable from editors, from the command line, from review tools
+and from continuous integration. It's easy to see how the complexity of running all of these
+different kinds of linters in all of these different places could quickly balloon out of control.
+
+``Mozlint`` is a library that accomplishes several goals:
+
+1. It provides a standard method for adding new linters to the tree, which can be as easy as
+ defining a config object in a ``.yml`` file. This helps keep lint related code localized, and
+ prevents different teams from coming up with their own unique lint implementations.
+2. It provides a streamlined interface for running all linters at once. Instead of running N
+ different lint commands to test your patch, a single ``mach lint`` command will automatically run
+ all applicable linters. This means there is a single API surface that other tools can use to
+ invoke linters.
+3. With a simple taskcluster configuration, Mozlint provides an easy way to execute all these jobs
+ at review phase.
+
+``Mozlint`` isn't designed to be used directly by end users. Instead, it can be consumed by things
+like mach, phabricator and taskcluster.
+
+Getting Help
+------------
+
+If you need help or have questions, please don’t hesitate to contact us via Matrix
+in the "Lint and Formatting" room
+(`#lint:mozilla.org <https://chat.mozilla.org/#/room/#lint:mozilla.org>`_).
+
+.. toctree::
+ :caption: Linting User Guide
+ :maxdepth: 1
+ :glob:
+
+ usage
+ create
+ linters/*
diff --git a/docs/code-quality/lint/linters/black.rst b/docs/code-quality/lint/linters/black.rst
new file mode 100644
index 0000000000..da4c1a52a2
--- /dev/null
+++ b/docs/code-quality/lint/linters/black.rst
@@ -0,0 +1,36 @@
+Black
+=====
+
+`Black <https://black.readthedocs.io/en/stable/>`__ is a opinionated python code formatter.
+
+
+Run Locally
+-----------
+
+The mozlint integration of black can be run using mach:
+
+.. parsed-literal::
+
+ $ mach lint --linter black <file paths>
+
+Alternatively, omit the ``--linter black`` and run all configured linters, which will include
+black.
+
+
+Configuration
+-------------
+
+To enable black on new directory, add the path to the include
+section in the `black.yml <https://searchfox.org/mozilla-central/source/tools/lint/black.yml>`_ file.
+
+Autofix
+-------
+
+The black linter provides a ``--fix`` option.
+
+
+Sources
+-------
+
+* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/black.yml>`_
+* `Source <https://searchfox.org/mozilla-central/source/tools/lint/python/black.py>`_
diff --git a/docs/code-quality/lint/linters/clang-format.rst b/docs/code-quality/lint/linters/clang-format.rst
new file mode 100644
index 0000000000..2913c7440e
--- /dev/null
+++ b/docs/code-quality/lint/linters/clang-format.rst
@@ -0,0 +1,35 @@
+clang-format
+============
+
+`clang-format <https://clang.llvm.org/docs/ClangFormat.html>`__ is a tool to reformat C/C++ to the right coding style.
+
+Run Locally
+-----------
+
+The mozlint integration of clang-format can be run using mach:
+
+.. parsed-literal::
+
+ $ mach lint --linter clang-format <file paths>
+
+
+Configuration
+-------------
+
+To enable clang-format on new directory, add the path to the include
+section in the `clang-format.yml <https://searchfox.org/mozilla-central/source/tools/lint/clang-format.yml>`_ file.
+
+While excludes: will work, this linter will read the ignore list from `.clang-format-ignore file <https://searchfox.org/mozilla-central/source/.clang-format-ignore>`_
+at the root directory. This because it is also used by the ./mach clang-format -p command.
+
+Autofix
+-------
+
+clang-format can reformat the code with the option `--fix` (based on the upstream option `-i`).
+To highlight the results, we are using the ``--dry-run`` option (from clang-format 10).
+
+Sources
+-------
+
+* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/clang-format.yml>`_
+* `Source <https://searchfox.org/mozilla-central/source/tools/lint/clang-format/__init__.py>`_
diff --git a/docs/code-quality/lint/linters/clippy.rst b/docs/code-quality/lint/linters/clippy.rst
new file mode 100644
index 0000000000..728b38b6b4
--- /dev/null
+++ b/docs/code-quality/lint/linters/clippy.rst
@@ -0,0 +1,42 @@
+clippy
+======
+
+`clippy`_ is the tool for Rust static analysis.
+
+Run Locally
+-----------
+
+The mozlint integration of clippy can be run using mach:
+
+.. parsed-literal::
+
+ $ mach lint --linter clippy <file paths>
+
+.. note::
+
+ clippy expects a path or a .rs file. It doesn't accept Cargo.toml
+ as it would break the mozlint workflow.
+
+Configuration
+-------------
+
+To enable clippy on new directory, add the path to the include
+section in the `clippy.yml <https://searchfox.org/mozilla-central/source/tools/lint/clippy.yml>`_ file.
+
+Autofix
+-------
+
+This linter provides a ``--fix`` option. It requires using nightly
+which can be installed with:
+
+.. code-block:: shell
+
+ $ rustup component add clippy --toolchain nightly-x86_64-unknown-linux-gnu
+
+
+
+Sources
+-------
+
+* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/clippy.yml>`_
+* `Source <https://searchfox.org/mozilla-central/source/tools/lint/clippy/__init__.py>`_
diff --git a/docs/code-quality/lint/linters/codespell.rst b/docs/code-quality/lint/linters/codespell.rst
new file mode 100644
index 0000000000..e5804d30bb
--- /dev/null
+++ b/docs/code-quality/lint/linters/codespell.rst
@@ -0,0 +1,36 @@
+Codespell
+=========
+
+`codespell <https://github.com/codespell-project/codespell/>`__ is a popular tool to look for typical typos in the source code.
+
+It is enabled mostly for the documentation and English locale files.
+
+Run Locally
+-----------
+
+The mozlint integration of codespell can be run using mach:
+
+.. parsed-literal::
+
+ $ mach lint --linter codespell <file paths>
+
+
+Configuration
+-------------
+
+To enable codespell on new directory, add the path to the include
+section in the `codespell.yml <https://searchfox.org/mozilla-central/source/tools/lint/codespell.yml>`_ file.
+
+This job is configured as `tier 2 <https://wiki.mozilla.org/Sheriffing/Job_Visibility_Policy#Overview_of_the_Job_Visibility_Tiers>`_.
+
+Autofix
+-------
+
+Codespell provides a ``--fix`` option. It is based on the ``-w`` option provided by upstream.
+
+
+Sources
+-------
+
+* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/codespell.yml>`_
+* `Source <https://searchfox.org/mozilla-central/source/tools/lint/spell/__init__.py>`_
diff --git a/docs/code-quality/lint/linters/cpp-virtual-final.rst b/docs/code-quality/lint/linters/cpp-virtual-final.rst
new file mode 100644
index 0000000000..5353b6b4fe
--- /dev/null
+++ b/docs/code-quality/lint/linters/cpp-virtual-final.rst
@@ -0,0 +1,30 @@
+cpp virtual final
+=================
+
+This linter detects the virtual function declarations with multiple specifiers.
+
+It matches our coding style:
+Method declarations must use at most one of the following keywords: virtual, override, or final.
+
+As this linter uses some simple regular expression, it can miss some declarations.
+
+Run Locally
+-----------
+
+This linter can be run using mach:
+
+.. parsed-literal::
+
+ $ mach lint --linter cpp-virtual-final <file paths>
+
+
+Configuration
+-------------
+
+This linter is enabled on all C family files.
+
+Sources
+-------
+
+* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/cpp-virtual-final.yml>`_
+
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla.rst
new file mode 100644
index 0000000000..bd844f752a
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla.rst
@@ -0,0 +1,243 @@
+=====================
+Mozilla ESLint Plugin
+=====================
+
+This is the documentation of Mozilla ESLint PLugin.
+
+Environments
+============
+
+The plugin implements the following environments:
+
+
+.. toctree::
+ :maxdepth: 2
+
+ eslint-plugin-mozilla/environment
+
+Rules
+=====
+
+The plugin implements the following rules:
+
+.. toctree::
+ :maxdepth: 1
+
+ eslint-plugin-mozilla/avoid-Date-timing
+ eslint-plugin-mozilla/no-define-cc-etc
+ eslint-plugin-mozilla/no-throw-cr-literal
+ eslint-plugin-mozilla/no-useless-parameters
+ eslint-plugin-mozilla/use-chromeutils-import
+
+avoid-removeChild
+-----------------
+
+Rejects using element.parentNode.removeChild(element) when element.remove()
+can be used instead.
+
+balanced-listeners
+------------------
+
+Checks that for every occurrence of 'addEventListener' or 'on' there is an
+occurrence of 'removeEventListener' or 'off' with the same event name.
+
+consistent-if-bracing
+---------------------
+
+Checks that if/elseif/else bodies are braced consistently, so either all bodies
+are braced or unbraced. Doesn't enforce either of those styles though.
+
+import-browser-window-globals
+-----------------------------
+
+For scripts included in browser-window, this will automatically inject the
+browser-window global scopes into the file.
+
+import-content-task-globals
+---------------------------
+
+For files containing ContentTask.spawn calls, this will automatically declare
+the frame script variables in the global scope. ContentTask is only available
+to test files, so by default the configs only specify it for the mochitest based
+configurations.
+
+This saves setting the file as a mozilla/frame-script environment.
+
+Note: due to the way ESLint works, it appears it is only easy to declare these
+variables on a file global scope, rather than function global. This may mean that
+they are incorrectly allowed, but given they are test files, this should be
+detected during testing.
+
+import-globals
+--------------
+
+Checks the filename of imported files e.g. ``Cu.import("some/path/Blah.jsm")``
+adds Blah to the global scope.
+
+Note: uses modules.json for a list of globals listed in each file.
+
+
+import-globals-from
+-------------------
+
+Parses a file for globals defined in various unique Mozilla ways.
+
+When a "import-globals-from <path>" comment is found in a file, then all globals
+from the file at <path> will be imported in the current scope. This will also
+operate recursively.
+
+This is useful for scripts that are loaded as <script> tag in a window and rely
+on each other's globals.
+
+If <path> is a relative path, then it must be relative to the file being
+checked by the rule.
+
+
+import-headjs-globals
+---------------------
+
+Import globals from head.js and from any files that were imported by
+head.js (as far as we can correctly resolve the path).
+
+The following file import patterns are supported:
+
+- ``Services.scriptloader.loadSubScript(path)``
+- ``loader.loadSubScript(path)``
+- ``loadSubScript(path)``
+- ``loadHelperScript(path)``
+- ``import-globals-from path``
+
+If path does not exist because it is generated e.g.
+``testdir + "/somefile.js"`` we do our best to resolve it.
+
+The following patterns are supported:
+
+- ``Cu.import("resource://devtools/client/shared/widgets/ViewHelpers.jsm");``
+- ``loader.lazyImporter(this, "name1");``
+- ``loader.lazyRequireGetter(this, "name2"``
+- ``loader.lazyServiceGetter(this, "name3"``
+- ``XPCOMUtils.defineLazyModuleGetter(this, "setNamedTimeout", ...)``
+- ``loader.lazyGetter(this, "toolboxStrings"``
+- ``XPCOMUtils.defineLazyGetter(this, "clipboardHelper"``
+
+
+mark-test-function-used
+-----------------------
+
+Simply marks `test` (the test method) or `run_test` as used when in mochitests
+or xpcshell tests respectively. This avoids ESLint telling us that the function
+is never called.
+
+
+no-aArgs
+--------
+
+Checks that function argument names don't start with lowercase 'a' followed by
+a capital letter. This is to prevent the use of Hungarian notation whereby the
+first letter is a prefix that indicates the type or intended use of a variable.
+
+no-compare-against-boolean-literals
+-----------------------------------
+
+Checks that boolean expressions do not compare against literal values
+of `true` or `false`. This is to prevent overly verbose code such as
+`if (isEnabled == true)` when `if (isEnabled)` would suffice.
+
+no-useless-removeEventListener
+------------------------------
+
+Reject calls to removeEventListener where {once: true} could be used instead.
+
+no-useless-run-test
+-------------------
+
+Designed for xpcshell-tests. Rejects definitions of ``run_test()`` where the
+function only contains a single call to ``run_next_test()``. xpcshell's head.js
+already defines a utility function so there is no need for duplication.
+
+reject-importGlobalProperties
+-----------------------------
+
+Rejects calls to ``Cu.importGlobalProperties``. Use of this function is
+undesirable in some parts of the tree.
+
+
+reject-some-requires
+--------------------
+
+This takes an option, a regular expression. Invocations of
+``require`` with a string literal argument are matched against this
+regexp; and if it matches, the ``require`` use is flagged.
+
+
+use-cc-etc
+----------
+
+This requires using ``Cc`` rather than ``Components.classes``, and the same for
+``Components.interfaces``, ``Components.results`` and ``Components.utils``. This has
+a slight performance advantage by avoiding the use of the dot.
+
+use-default-preference-values
+-----------------------------
+
+Require providing a second parameter to get*Pref methods instead of
+using a try/catch block.
+
+use-ownerGlobal
+---------------
+
+Require .ownerGlobal instead of .ownerDocument.defaultView.
+
+use-includes-instead-of-indexOf
+-------------------------------
+
+Use .includes instead of .indexOf to check if something is in an array or string.
+
+use-returnValue
+---------------
+
+Warn when idempotent methods are called and their return value is unused.
+
+use-services
+------------
+
+Requires the use of Services.jsm rather than Cc[].getService() where a service
+is already defined in Services.jsm.
+
+var-only-at-top-level
+---------------------
+
+Marks all var declarations that are not at the top level invalid.
+
+Tests
+=====
+
+The tests for eslint-plugin-mozilla are run via `mochajs`_ on top of node. Most
+of the tests use the `ESLint Rule Unit Test framework`_.
+
+.. _mochajs: https://mochajs.org/
+.. _ESLint Rule Unit Test Framework: http://eslint.org/docs/developer-guide/working-with-rules#rule-unit-tests
+
+Running Tests
+-------------
+
+The tests for eslint-plugin-mozilla are run via `mochajs`_ on top of node. Most
+of the tests use the `ESLint Rule Unit Test framework`_.
+
+The rules have some self tests, these can be run via:
+
+.. code-block:: shell
+
+ $ cd tools/lint/eslint/eslint-plugin-mozilla
+ $ npm install
+ $ npm run test
+
+Disabling tests
+---------------
+
+In the unlikely event of needing to disable a test, currently the only way is
+by commenting-out. Please file a bug if you have to do this. Bugs should be filed
+in the *Testing* product under *Lint*.
+
+.. _mochajs: https://mochajs.org/
+.. _ESLint Rule Unit Test Framework: http://eslint.org/docs/developer-guide/working-with-rules#rule-unit-tests
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-Date-timing.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-Date-timing.rst
new file mode 100644
index 0000000000..378b153f03
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-Date-timing.rst
@@ -0,0 +1,31 @@
+=================
+avoid-Date-timing
+=================
+
+Rejects grabbing the current time via Date.now() or new Date() for timing
+purposes when the less problematic performance.now() can be used instead.
+
+The performance.now() function returns milliseconds since page load. To
+convert that to milliseconds since the epoch, use:
+
+.. code-block:: js
+
+ performance.timing.navigationStart + performance.now()
+
+Often timing relative to the page load is adequate and that conversion may not
+be necessary.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ Date.now()
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ new Date('2017-07-11');
+ performance.now()
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/environment.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/environment.rst
new file mode 100644
index 0000000000..34c4b20343
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/environment.rst
@@ -0,0 +1,33 @@
+===========
+Environment
+===========
+
+These environments are available by specifying a comment at the top of the file,
+e.g.
+
+.. code-block:: js
+
+ /* eslint-env mozilla/chrome-worker */
+
+There are also built-in ESLint environments available as well. Find them here: http://eslint.org/docs/user-guide/configuring#specifying-environments
+
+browser-window
+--------------
+
+Defines the environment for scripts that are in the main browser.xhtml scope.
+
+chrome-worker
+-------------
+
+Defines the environment for chrome workers. This differs from normal workers by
+the fact that `ctypes` can be accessed as well.
+
+frame-script
+------------
+
+Defines the environment for frame scripts.
+
+jsm
+---
+
+Defines the environment for jsm files (javascript modules).
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-define-cc-etc.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-define-cc-etc.rst
new file mode 100644
index 0000000000..cb55dabac0
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-define-cc-etc.rst
@@ -0,0 +1,24 @@
+================
+no-define-cc-etc
+================
+
+Disallows old-style definitions for Cc/Ci/Cu/Cr. These are now defined globally
+for all chrome contexts.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ var Cc = Components.classes;
+ var Ci = Components.interfaces;
+ var {Ci: interfaces, Cc: classes, Cu: utils} = Components;
+ var Cr = Components.results;
+
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ const CC = Components.Constructor;
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-throw-cr-literal.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-throw-cr-literal.rst
new file mode 100644
index 0000000000..ce73c72b36
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-throw-cr-literal.rst
@@ -0,0 +1,39 @@
+===================
+no-throw-cr-literal
+===================
+
+This is similar to the ESLint built-in rule no-throw-literal. It disallows
+throwing Components.results code directly.
+
+Throwing bare literals is inferior to throwing Exception objects, which provide
+stack information. Cr.ERRORs should be be passed as the second argument to
+``Components.Exception()`` to create an Exception object with stack info, and
+the correct result property corresponding to the NS_ERROR that other code
+expects.
+Using a regular ``new Error()`` to wrap just turns it into a string and doesn't
+set the result property, so the errors can't be recognised.
+
+This option can be autofixed (``--fix``).
+
+.. code-block:: js
+
+ performance.timing.navigationStart + performance.now()
+
+Often timing relative to the page load is adequate and that conversion may not
+be necessary.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ throw Cr.NS_ERROR_UNEXPECTED;
+ throw Components.results.NS_ERROR_ABORT;
+ throw new Error(Cr.NS_ERROR_NO_INTERFACE);
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ throw Components.Exception("Not implemented", Cr.NS_ERROR_NOT_IMPLEMENTED);
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-parameters.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-parameters.rst
new file mode 100644
index 0000000000..2783746198
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-parameters.rst
@@ -0,0 +1,27 @@
+=====================
+no-useless-parameters
+=====================
+
+Reject common XPCOM methods called with useless optional parameters (eg.
+``Services.io.newURI(url, null, null)``, or non-existent parameters (eg.
+``Services.obs.removeObserver(name, observer, false)``).
+
+This option can be autofixed (``--fix``).
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ elt.addEventListener('click', handler, false);
+ Services.io.newURI('http://example.com', null, null);
+ Services.obs.notifyObservers(obj, 'topic', null);
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ elt.addEventListener('click', handler);
+ Services.io.newURI('http://example.com');
+ Services.obs.notifyObservers(obj, 'topic');
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-import.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-import.rst
new file mode 100644
index 0000000000..7cef9d19ad
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-import.rst
@@ -0,0 +1,25 @@
+======================
+use-chromeutils-import
+======================
+
+Require use of ``ChromeUtils.import`` and ``ChromeUtils.defineModuleGetter``
+rather than ``Components.utils.import`` and
+``XPCOMUtils.defineLazyModuleGetter``.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ Components.utils.import("resource://gre/modules/Services.jsm", this);
+ XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm");
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ ChromeUtils.import("resource://gre/modules/Services.jsm", this);
+ ChromeUtils.defineModuleGetter(this, "Services", "resource://gre/modules/Services.jsm");
+ // 4 argument version of defineLazyModuleGetter is allowed.
+ XPCOMUtils.defineLazyModuleGetter(this, "Services","resource://gre/modules/Service.jsm","Foo");
diff --git a/docs/code-quality/lint/linters/eslint-plugin-spidermonkey-js.rst b/docs/code-quality/lint/linters/eslint-plugin-spidermonkey-js.rst
new file mode 100644
index 0000000000..35ff88dd59
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-spidermonkey-js.rst
@@ -0,0 +1,15 @@
+==============================
+Mozilla ESLint SpiderMonkey JS
+==============================
+
+This plugin only creates one item at the moment - a processor for the SpiderMonkey
+JS code.
+
+Processors
+==========
+
+The processor is used to pre-process all `*.js` files and deals with the macros
+that SpiderMonkey uses.
+
+Note: Currently the ESLint option --fix is disabled when the preprocessor is
+enabled.
diff --git a/docs/code-quality/lint/linters/eslint.rst b/docs/code-quality/lint/linters/eslint.rst
new file mode 100644
index 0000000000..5803163751
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint.rst
@@ -0,0 +1,60 @@
+ESLint
+======
+
+`ESLint <http://eslint.org/>`__ is a popular linter for JavaScript.
+
+Run Locally
+-----------
+
+The mozlint integration of `ESLint <http://eslint.org/>`__ can be run using mach:
+
+.. parsed-literal::
+
+ $ mach lint --linter eslint <file paths>
+
+Alternatively, omit the ``--linter eslint`` and run all configured linters, which will include
+ESLint.
+
+
+Configuration
+-------------
+
+The ESLint mozilla-central integration uses a skip list to exclude certain directories from being
+linted. This lives in ``topsrcdir/.eslintignore``. If you don't wish your directory to be linted, it
+must be added here.
+
+The global configuration file lives in ``topsrcdir/.eslintrc``. This global configuration can be
+overridden by including an ``.eslintrc`` in the appropriate subdirectory. For an overview of the
+supported configuration, see `ESLint's documentation <http://eslint.org/docs/user-guide/configuring>`__.
+
+
+Autofix
+-------
+
+The eslint linter provides a ``--fix`` option. It is based on the upstream option.
+
+Sources
+-------
+
+* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/eslint.yml>`_
+* `Source <https://searchfox.org/mozilla-central/source/tools/lint/eslint/__init__.py>`_
+
+
+ESLint Plugin Mozilla
+---------------------
+
+In addition to default ESLint rules, there are several Mozilla-specific rules that are defined in
+the :doc:`Mozilla ESLint Plugin <eslint-plugin-mozilla>`.
+
+ESLint Plugin SpiderMonkey JS
+-----------------------------
+
+In addition to default ESLint rules, there is an extra processor for SpiderMonkey
+code :doc:`Mozilla ESLint SpiderMonkey JS <eslint-plugin-spidermonkey-js>`.
+
+
+.. toctree::
+ :hidden:
+
+ eslint-plugin-mozilla
+ eslint-plugin-spidermonkey-js
diff --git a/docs/code-quality/lint/linters/file-perm.rst b/docs/code-quality/lint/linters/file-perm.rst
new file mode 100644
index 0000000000..5c3a02fa1b
--- /dev/null
+++ b/docs/code-quality/lint/linters/file-perm.rst
@@ -0,0 +1,42 @@
+File permission
+===============
+
+This linter verifies if a file has unnecessary permissions.
+If a file has execution permissions (+x), file-perm will
+generate a warning.
+
+It will ignore files starting with ``#!`` for types of files
+that typically have shebang lines (such as python, node or
+shell scripts).
+
+This linter does not have any affect on Windows.
+
+
+Run Locally
+-----------
+
+This mozlint linter can be run using mach:
+
+.. parsed-literal::
+
+ $ mach lint --linter file-perm <file paths>
+
+
+Configuration
+-------------
+
+This linter is enabled on the whole code base.
+
+This job is configured as `tier 2 <https://wiki.mozilla.org/Sheriffing/Job_Visibility_Policy#Overview_of_the_Job_Visibility_Tiers>`_.
+
+Autofix
+-------
+
+This linter provides a ``--fix`` option. The python script is doing the change itself.
+
+
+Sources
+-------
+
+* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/file-perm.yml>`_
+* `Source <https://searchfox.org/mozilla-central/source/tools/lint/file-perm/__init__.py>`_
diff --git a/docs/code-quality/lint/linters/file-whitespace.rst b/docs/code-quality/lint/linters/file-whitespace.rst
new file mode 100644
index 0000000000..fd134b32ef
--- /dev/null
+++ b/docs/code-quality/lint/linters/file-whitespace.rst
@@ -0,0 +1,38 @@
+Trailing whitespaces
+====================
+
+This linter verifies if a file has:
+
+* unnecessary trailing whitespaces,
+* Windows carriage return,
+* empty lines at the end of file,
+* if file ends with a newline or not
+
+
+Run Locally
+-----------
+
+This mozlint linter can be run using mach:
+
+.. parsed-literal::
+
+ $ mach lint --linter file-whitespace <file paths>
+
+
+Configuration
+-------------
+
+This linter is enabled on most of the code base.
+
+This job is configured as `tier 2 <https://wiki.mozilla.org/Sheriffing/Job_Visibility_Policy#Overview_of_the_Job_Visibility_Tiers>`_.
+
+Autofix
+-------
+
+This linter provides a ``--fix`` option. The python script is doing the change itself.
+
+Sources
+-------
+
+* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/file-whitespace.yml>`_
+* `Source <https://searchfox.org/mozilla-central/source/tools/lint/file-whitespace/__init__.py>`_
diff --git a/docs/code-quality/lint/linters/flake8.rst b/docs/code-quality/lint/linters/flake8.rst
new file mode 100644
index 0000000000..0e46d33ab0
--- /dev/null
+++ b/docs/code-quality/lint/linters/flake8.rst
@@ -0,0 +1,46 @@
+Flake8
+======
+
+`Flake8 <https://flake8.pycqa.org/en/latest/index.html>`__ is a popular lint wrapper for python. Under the hood, it runs three other tools and
+combines their results:
+
+* `pep8 <http://pep8.readthedocs.io/en/latest/>`__ for checking style
+* `pyflakes <https://github.com/pyflakes/pyflakes>`__ for checking syntax
+* `mccabe <https://github.com/pycqa/mccabe>`__ for checking complexity
+
+
+Run Locally
+-----------
+
+The mozlint integration of flake8 can be run using mach:
+
+.. parsed-literal::
+
+ $ mach lint --linter flake8 <file paths>
+
+Alternatively, omit the ``--linter flake8`` and run all configured linters, which will include
+flake8.
+
+
+Configuration
+-------------
+
+Path configuration is defined in the root `.flake8`_ file. Please update this file rather than
+``tools/lint/flake8.yml`` if you need to exclude a new path. For an overview of the supported
+configuration, see `flake8's documentation`_.
+
+.. _.flake8: https://searchfox.org/mozilla-central/source/.flake8
+.. _flake8's documentation: https://flake8.pycqa.org/en/latest/user/configuration.html
+
+Autofix
+-------
+
+The flake8 linter provides a ``--fix`` option. It is based on `autopep8 <https://github.com/hhatto/autopep8>`__.
+Please note that autopep8 does NOT fix all issues reported by flake8.
+
+
+Sources
+-------
+
+* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/flake8.yml>`_
+* `Source <https://searchfox.org/mozilla-central/source/tools/lint/python/flake8.py>`_
diff --git a/docs/code-quality/lint/linters/l10n.rst b/docs/code-quality/lint/linters/l10n.rst
new file mode 100644
index 0000000000..f8beb246d1
--- /dev/null
+++ b/docs/code-quality/lint/linters/l10n.rst
@@ -0,0 +1,45 @@
+L10n
+====
+
+The l10n linter checks for mistakes and problems in the localizable files.
+Most of the code lives inside the
+`compare-locales <https://pypi.org/project/compare-locales/>`_
+package, and is shipping as the ``moz-l10n-lint`` command.
+
+The linter checks for fundamental issues like parsing errors, but it also
+finds more subtle mistakes like duplicated messages. It also warns if you're
+trying to change a string without changing the ID, or to add a string that's
+still in use in a stable channel with a different value.
+
+The warnings on string ID changes get reported on phabricator, but they're
+not making the build fail. To find out when to change IDs and when not to,
+read the :ref:`Lifecycle & Workflow <Localization>` section in the
+localization documentation.
+
+Run Locally
+-----------
+
+The can be run using mach:
+
+.. parsed-literal::
+
+ $ mach lint --linter l10n <file paths>
+
+Alternatively, omit the ``--linter l10n`` and run all configured linters, which
+will include the l10n linter.
+
+
+Updating the Reference
+----------------------
+
+The linter checks out the cross-channel localization files into your
+``.mozbuild`` state directory. By default this is updated automatically after
+48 hours. There might be new strings anyway, if you want to ensure an
+updated clone, remove the marker file in
+``~/.mozbuild/gecko-strings/.hg/l10n_pull_marker``.
+
+Sources
+-------
+
+* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/l10n.yml>`_
+* `Source <https://searchfox.org/mozilla-central/source/tools/lint/python/l10n_lint.py>`_
diff --git a/docs/code-quality/lint/linters/license.rst b/docs/code-quality/lint/linters/license.rst
new file mode 100644
index 0000000000..0533333218
--- /dev/null
+++ b/docs/code-quality/lint/linters/license.rst
@@ -0,0 +1,39 @@
+License
+=======
+
+This linter verifies if a file has a known license header.
+
+By default, Firefox uses MPL-2 license with the `appropriate headers <https://www.mozilla.org/en-US/MPL/headers/>`_.
+In some cases (thirdpardy code), a file might have a different header file.
+If this is the case, one of the significant line of the header should be listed in the list `of valid licenses
+<https://searchfox.org/mozilla-central/source/tools/lint/license/valid-licenses.txt>`_.
+
+Run Locally
+-----------
+
+This mozlint linter can be run using mach:
+
+.. parsed-literal::
+
+ $ mach lint --linter license <file paths>
+
+
+Configuration
+-------------
+
+This linter is enabled on most of the whole code base.
+
+Autofix
+-------
+
+This linter provides a ``--fix`` option. The python script is doing the change itself
+and will use the right header MPL-2 header depending on the language.
+It will add the license at the right place in case the file is a script (ie starting with ``!#``
+or a XML file ``<?xml>``).
+
+
+Sources
+-------
+
+* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/license.yml>`_
+* `Source <https://searchfox.org/mozilla-central/source/tools/lint/license/__init__.py>`_
diff --git a/docs/code-quality/lint/linters/lintpref.rst b/docs/code-quality/lint/linters/lintpref.rst
new file mode 100644
index 0000000000..1b2236e10a
--- /dev/null
+++ b/docs/code-quality/lint/linters/lintpref.rst
@@ -0,0 +1,31 @@
+Lintpref
+========
+
+The lintpref linter is a simple linter for libpref files to check for duplicate
+entries between ``modules/libpref/init/all.js`` and ``modules/libpref/init/StaticPrefList.yaml``.
+If a duplicate is found, lintpref will raise an error and emit the ``all.js`` line
+where you can find the duplicate entry.
+
+
+Running Locally
+---------------
+
+The linter can be run using mach:
+
+ .. parsed-literal::
+
+ $ mach lint --linter lintpref
+
+
+Fixing Lintpref Errors
+----------------------
+
+In most cases, duplicate entries should be avoided and the duplicate removed
+from ``all.js``. If for any reason a pref should exist in both files, the pref
+should be added to ``IGNORE_PREFS`` in ``tools/lint/libpref/__init__.py``.
+
+Sources
+-------
+
+* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/lintpref.yml>`_
+* `Source <https://searchfox.org/mozilla-central/source/tools/lint/libpref/__init__.py>`_
diff --git a/docs/code-quality/lint/linters/mingw-capitalization.rst b/docs/code-quality/lint/linters/mingw-capitalization.rst
new file mode 100644
index 0000000000..df82a9c59d
--- /dev/null
+++ b/docs/code-quality/lint/linters/mingw-capitalization.rst
@@ -0,0 +1,28 @@
+MinGW capitalization
+====================
+
+This linter verifies that Windows include file are lowercase.
+It might break the mingw build otherwise.
+
+
+Run Locally
+-----------
+
+This mozlint linter can be run using mach:
+
+.. parsed-literal::
+
+ $ mach lint --linter mingw-capitalization <file paths>
+
+
+Configuration
+-------------
+
+This linter is enabled on the whole code base except WebRTC
+
+
+Sources
+-------
+
+* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/mingw-capitalization.yml>`_
+* `Source <https://searchfox.org/mozilla-central/source/tools/lint/cpp/mingw-capitalization.py>`_
diff --git a/docs/code-quality/lint/linters/perfdocs.rst b/docs/code-quality/lint/linters/perfdocs.rst
new file mode 100644
index 0000000000..851c920987
--- /dev/null
+++ b/docs/code-quality/lint/linters/perfdocs.rst
@@ -0,0 +1,84 @@
+PerfDocs
+========
+
+`PerfDocs`_ is a tool that checks to make sure all performance tests are documented in tree.
+
+At the moment, it is only used for this documentation verification, but in the future it will also auto-generate documentation from these descriptions that will be displayed in the source-docs documentation page (rather than the wiki, which is where they currently reside).
+
+Run Locally
+-----------
+
+The mozlint integration of PerfDocs can be run using mach:
+
+.. parsed-literal::
+
+ $ mach lint --linter perfdocs
+
+
+Configuration
+-------------
+
+There are no configuration options available for this linter. It scans the full source tree under ``testing``, looking for folders named ``perfdocs`` and then validates their content. This has only been implemented for Raptor so far, but Talos will be added in the future. We also hope to expand this to search outside the ``testing`` directory.
+
+The ``perfdocs`` folders, there needs to be an ``index.rst`` file and it needs to contain the string ``{documentation}`` in some location in the file which is where the test documentation will be placed. The folders must also have a ``config.yml`` file following this schema:
+
+.. code-block:: python
+
+ CONFIG_SCHEMA = {
+ "type": "object",
+ "properties": {
+ "name": {"type": "string"},
+ "manifest": {"type": "string"},
+ "suites": {
+ "type": "object",
+ "properties": {
+ "suite_name": {
+ "type": "object",
+ "properties": {
+ "tests": {
+ "type": "object",
+ "properties": {
+ "test_name": {"type": "string"},
+ }
+ },
+ "description": {"type": "string"},
+ },
+ "required": [
+ "description"
+ ]
+ }
+ }
+ }
+ },
+ "required": [
+ "name",
+ "manifest",
+ "suites"
+ ]
+ }
+
+Here is an example of a configuration file for the Raptor framework:
+
+.. parsed-literal::
+
+ name: raptor
+ manifest: testing/raptor/raptor/raptor.ini
+ suites:
+ desktop:
+ description: "Desktop tests."
+ tests:
+ raptor-tp6: "Raptor TP6 tests."
+ mobile:
+ description: "Mobile tests"
+ benchmarks:
+ description: "Benchmark tests."
+ tests:
+ wasm: "All wasm tests."
+
+Note that there needs to be a FrameworkGatherer implemented for the framework being documented since each of them may have different ways of parsing test manifests for the tests. See `RaptorGatherer <https://searchfox.org/mozilla-central/source/tools/lint/perfdocs/framework_gatherers.py>`_ for an example gatherer that was implemented for Raptor.
+
+Sources
+-------
+
+* `Configuration <https://searchfox.org/mozilla-central/source/tools/lint/perfdocs.yml>`__
+* `Source <https://searchfox.org/mozilla-central/source/tools/lint/perfdocs>`__
diff --git a/docs/code-quality/lint/linters/pylint.rst b/docs/code-quality/lint/linters/pylint.rst
new file mode 100644
index 0000000000..603f80516a
--- /dev/null
+++ b/docs/code-quality/lint/linters/pylint.rst
@@ -0,0 +1,33 @@
+pylint
+======
+
+`pylint <https://www.pylint.org/>`__ is a popular linter for python. It is now the default python
+linter in VS Code.
+
+Please note that we also have :ref:`Flake8` available as a linter.
+
+Run Locally
+-----------
+
+The mozlint integration of pylint can be run using mach:
+
+.. parsed-literal::
+
+ $ mach lint --linter pylint <file paths>
+
+
+
+Configuration
+-------------
+
+To enable pylint on new directory, add the path to the include
+section in the `pylint.yml <https://searchfox.org/mozilla-central/source/tools/lint/pylint.yml>`_ file.
+
+We enabled the same Pylint rules as `VS Code <https://code.visualstudio.com/docs/python/linting#_pylint>`_.
+See in `pylint.py <https://searchfox.org/mozilla-central/source/tools/lint/python/pylint.py>`_ for the full list
+
+Sources
+-------
+
+* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/pylint.yml>`_
+* `Source <https://searchfox.org/mozilla-central/source/tools/lint/python/pylint.py>`_
diff --git a/docs/code-quality/lint/linters/rejected-words.rst b/docs/code-quality/lint/linters/rejected-words.rst
new file mode 100644
index 0000000000..c952b420da
--- /dev/null
+++ b/docs/code-quality/lint/linters/rejected-words.rst
@@ -0,0 +1,27 @@
+Rejected words
+==============
+
+Reject some words we don't want to use in the code base for various reasons.
+
+Run Locally
+-----------
+
+The mozlint integration of codespell can be run using mach:
+
+.. parsed-literal::
+
+ $ mach lint --linter rejected-words <file paths>
+
+
+Configuration
+-------------
+
+This linter is enabled on the whole code base. Issues existing in the code base are listed in the exclude list in
+ the `rejected-words.yml <https://searchfox.org/mozilla-central/source/tools/lint/rejected-words.yml>`_ file.
+
+New words can be added in the `payload` section.
+
+Sources
+-------
+
+* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/rejected-words.yml>`_
diff --git a/docs/code-quality/lint/linters/rstlinter.rst b/docs/code-quality/lint/linters/rstlinter.rst
new file mode 100644
index 0000000000..6ed4f1befe
--- /dev/null
+++ b/docs/code-quality/lint/linters/rstlinter.rst
@@ -0,0 +1,32 @@
+RST Linter
+==========
+
+`rstcheck`_ is a popular linter for restructuredtext.
+
+
+Run Locally
+-----------
+
+The mozlint integration of rst linter can be run using mach:
+
+.. parsed-literal::
+
+ $ mach lint --linter rst <file paths>
+
+
+Configuration
+-------------
+
+All directories will have rst linter run against them.
+If you wish to exclude a subdirectory of an included one, you can add it to the ``exclude``
+directive.
+
+
+.. _rstcheck: https://github.com/myint/rstcheck
+
+
+Sources
+-------
+
+* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/rst.yml>`_
+* `Source <https://searchfox.org/mozilla-central/source/tools/lint/rst/__init__.py>`_
diff --git a/docs/code-quality/lint/linters/rustfmt.rst b/docs/code-quality/lint/linters/rustfmt.rst
new file mode 100644
index 0000000000..7ba3cd6c34
--- /dev/null
+++ b/docs/code-quality/lint/linters/rustfmt.rst
@@ -0,0 +1,33 @@
+Rustfmt
+=======
+
+`rustfmt <https://github.com/rust-lang/rustfmt>`__ is the tool for Rust coding style.
+
+Run Locally
+-----------
+
+The mozlint integration of rustfmt can be run using mach:
+
+.. parsed-literal::
+
+ $ mach lint --linter rustfmt <file paths>
+
+
+Configuration
+-------------
+
+To enable rustfmt on new directory, add the path to the include
+section in the `rustfmt.yml <https://searchfox.org/mozilla-central/source/tools/lint/rustfmt.yml>`_ file.
+
+
+Autofix
+-------
+
+Rustfmt is reformatting the code by default. To highlight the results, we are using
+the ``--check`` option.
+
+Sources
+-------
+
+* `Configuration (YAML) <https://searchfox.org/mozilla-central/source/tools/lint/rustfmt.yml>`_
+* `Source <https://searchfox.org/mozilla-central/source/tools/lint/rustfmt/__init__.py>`_
diff --git a/docs/code-quality/lint/usage.rst b/docs/code-quality/lint/usage.rst
new file mode 100644
index 0000000000..9c128383c1
--- /dev/null
+++ b/docs/code-quality/lint/usage.rst
@@ -0,0 +1,117 @@
+Running Linters Locally
+=======================
+
+Using the Command Line
+----------------------
+
+You can run all the various linters in the tree using the ``mach lint`` command. Simply pass in the
+directory or file you wish to lint (defaults to current working directory):
+
+.. parsed-literal::
+
+ ./mach lint path/to/files
+
+Multiple paths are allowed:
+
+.. parsed-literal::
+
+ ./mach lint path/to/foo.js path/to/bar.py path/to/dir
+
+To force execution on a directory that would otherwise be excluded:
+
+.. parsed-literal::
+
+ ./mach lint -n path/in/the/exclude/list
+
+``Mozlint`` will automatically determine which types of files exist, and which linters need to be run
+against them. For example, if the directory contains both JavaScript and Python files then mozlint
+will automatically run both ESLint and Flake8 against those files respectively.
+
+To restrict which linters are invoked manually, pass in ``-l/--linter``:
+
+.. parsed-literal::
+
+ ./mach lint -l eslint path/to/files
+
+You can see a list of the available linters by running:
+
+.. parsed-literal::
+
+ ./mach lint --list
+
+Finally, ``mozlint`` can lint the files touched by outgoing revisions or the working directory using
+the ``-o/--outgoing`` and ``-w/--workdir`` arguments respectively. These work both with mercurial and
+git. In the case of ``--outgoing``, the default remote repository the changes would be pushed to is
+used as the comparison. If desired, a remote can be specified manually. In git, you may only want to
+lint staged commits from the working directory, this can be accomplished with ``--workdir=staged``.
+Examples:
+
+.. parsed-literal::
+
+ ./mach lint --workdir
+ ./mach lint --workdir=staged
+ ./mach lint --outgoing
+ ./mach lint --outgoing origin/master
+ ./mach lint -wo
+
+
+Using a VCS Hook
+----------------
+
+There are also both pre-commit and pre-push version control hooks that work in
+either hg or git. To enable a pre-push hg hook, add the following to hgrc:
+
+.. parsed-literal::
+
+ [hooks]
+ pre-push.lint = python:./tools/lint/hooks.py:hg
+
+
+To enable a pre-commit hg hook, add the following to hgrc:
+
+.. parsed-literal::
+
+ [hooks]
+ pretxncommit.lint = python:./tools/lint/hooks.py:hg
+
+
+To enable a pre-push git hook, run the following command:
+
+.. parsed-literal::
+
+ $ ln -s /path/to/gecko/tools/lint/hooks.py .git/hooks/pre-push
+
+
+To enable a pre-commit git hook, run the following command:
+
+.. parsed-literal::
+
+ $ ln -s /path/to/gecko/tools/lint/hooks.py .git/hooks/pre-commit
+
+
+Fixing Lint Errors
+==================
+
+``Mozlint`` has a best-effort ability to fix lint errors:
+
+.. parsed-literal::
+
+ $ ./mach lint --fix
+
+Not all linters support fixing, and even the ones that do can not usually fix
+all types of errors. Any errors that cannot be automatically fixed, will be
+printed to stdout like normal. In that case, you can also fix errors manually:
+
+.. parsed-literal::
+
+ $ ./mach lint --edit
+
+This requires the $EDITOR environment variable be defined. For most editors,
+this will simply open each file containing errors one at a time. For vim (or
+neovim), this will populate the `quickfix list`_ with the errors.
+
+The ``--fix`` and ``--edit`` arguments can be combined, in which case any
+errors that can be fixed automatically will be, and the rest will be opened
+with your $EDITOR.
+
+.. _quickfix list: http://vimdoc.sourceforge.net/htmldoc/quickfix.html
diff --git a/docs/code-quality/static-analysis.rst b/docs/code-quality/static-analysis.rst
new file mode 100644
index 0000000000..21565e6969
--- /dev/null
+++ b/docs/code-quality/static-analysis.rst
@@ -0,0 +1,251 @@
+Static analysis
+===============
+
+This document is split in two parts. The first part will focus on the
+modern and robust way of static-analysis and the second part will
+present the build-time static-analysis.
+
+For linting, please see the `linting documentation </code-quality/lint/>`_.
+
+For reviews, use the `#static-analysis-reviewers review group <https://phabricator.services.mozilla.com/project/view/120/>`__.
+Ask questions on `#static-analysis:mozilla.org <https://chat.mozilla.org/#/room/#static-analysis:mozilla.org>`__.
+
+
+Clang-Tidy static analysis
+--------------------------
+
+Our current static-analysis infrastructure is based on
+`clang-tidy <http://clang.llvm.org/extra/clang-tidy/>`__. It uses
+checkers in order to assert different programming errors present in the
+code. The checkers that we use are split into 3 categories:
+
+#. `Firefox specific checkers <https://searchfox.org/mozilla-central/source/build/clang-plugin>`_. They detect incorrect Gecko programming
+ patterns which could lead to bugs or security issues.
+#. `Clang-tidy checkers <https://clang.llvm.org/extra/clang-tidy/checks/list.html>`_. They aim to suggest better programming practices
+ and to improve memory efficiency and performance.
+#. `Clang-analyzer checkers <https://clang-analyzer.llvm.org/>`_. These checks are more advanced, for example
+ some of them can detect dead code or memory leaks, but as a typical
+ side effect they have false positives. Because of that, we have
+ disabled them for now, but will enable some of them in the near
+ future.
+
+In order to simplify the process of static-analysis we have focused on
+integrating this process with Phabricator and mach. A list of some
+checkers that are used during automated scan can be found
+`here <https://searchfox.org/mozilla-central/source/tools/clang-tidy/config.yaml>`__.
+
+We are also running Coverity at review phase and a few times per day
+(when autoland is merged into mozilla-central).
+
+Static analysis at review phase
+-------------------------------
+
+We created a TaskCluster bot that runs clang static analysis on every
+patch submitted to Phabricator. It then quickly reports any code defects
+directly on the review platform, thus preventing bad patches from
+landing until all their defects are fixed. Currently, its feedback is
+posted in about 10 minutes after a patch series is published on the
+review platform.
+
+As part of the process, the various linting jobs are also executed
+using try. This can be also used to add new jobs, see: :ref:`attach-job-review`.
+An example of automated review can be found `on
+phabricator <https://phabricator.services.mozilla.com/D2066>`__.
+
+
+Mach static analysis
+--------------------
+
+It is supported on all Firefox built platforms. During the first run it
+automatically installs all of its dependencies like clang-tidy
+executable in the .mozbuild folder thus making it very easy to use. The
+resources that are used are provided by toolchain artifacts clang-tidy
+target.
+
+This is used through ``mach static-analysis`` command that has the
+following parameters:
+
+- ``check`` - Runs the checks using the installed helper tool from
+ ~/.mozbuild.
+- ``--checks, -c`` - Checks to enabled during the scan. The checks
+ enabled
+ `in the yaml file <https://searchfox.org/mozilla-central/source/tools/clang-tidy/config.yaml>`__
+ are used by default.
+- ``--fix, -f`` - Try to autofix errors detected by the checkers.
+ Depending on the checker, this option might not do anything.
+ The list of checkers with autofix can be found on the `clang-tidy website <https://clang.llvm.org/extra/clang-tidy/checks/list.html>`__.
+- ``--header-filter, -h-f`` - Regular expression matching the names of
+ the headers to output diagnostic from.Diagnostic from the main file
+ of each translation unit are always displayed.
+
+As an example we run static-analysis through mach on
+``dom/presentation/Presentation.cpp`` with
+``google-readability-braces-around-statements`` check and autofix we
+would have:
+
+.. code-block:: shell
+
+ ./mach static-analysis check --checks="-*, google-readability-braces-around-statements" --fix dom/presentation/Presentation.cpp
+
+If you want to use a custom clang-tidy binary this can be done by using
+the ``install`` subcommand of ``mach static-analysis``, but please note
+that the archive that is going to be used must be compatible with the
+directory structure clang-tidy from toolchain artifacts.
+
+.. code-block:: shell
+
+ ./mach static-analysis install clang.tar.gz
+
+
+Regression Testing
+------------------
+
+In order to prevent regressions in our clang-tidy based static analysis,
+we have created a
+`task <https://searchfox.org/mozilla-central/source/taskcluster/ci/static-analysis-autotest/kind.yml>`__
+on automation. This task runs on each commit and launches a test suite
+that is integrated into mach.
+
+The test suite implements the following:
+
+- Downloads the necessary clang-tidy artifacts.
+- Reads the
+ `configuration <https://searchfox.org/mozilla-central/source/tools/clang-tidy/config.yaml>`__
+ file.
+- For each checker reads the test file plus the expected result. A
+ sample of test and expected result can be found
+ `in the test file <https://searchfox.org/mozilla-central/source/tools/clang-tidy/test/clang-analyzer-deadcode.DeadStores.cpp>`__
+ and
+ `the json file <https://searchfox.org/mozilla-central/source/tools/clang-tidy/test/clang-analyzer-deadcode.DeadStores.json>`__.
+
+This testing suit can be run locally by doing the following:
+
+.. code-block:: shell
+
+ ./mach static-analysis autotest
+
+If we want to test only a specific checker, let's say
+modernize-raw-string-literal, we can run:
+
+.. code-block:: shell
+
+ ./mach static-analysis autotest modernize-raw-string-literal
+
+If we want to add a new checker we need to generated the expected result
+file, by doing:
+
+.. code-block:: shell
+
+ ./mach static-analysis autotest modernize-raw-string-literal -d
+
+
+Build-time static-analysis
+--------------------------
+
+If you want to build with the Firefox Clang plug-in
+(located in ``/build/clang-plugin`` and associated with
+``MOZ_CLANG_PLUGIN`` and the attributes in ``/mfbt/Attributes.h``)
+just add ``--enable-clang-plugin`` to your mozconfig!
+If you want to also have our experimental checkers that will produce ``warnings`` as
+diagnostic messages also add ``--enable-clang-plugin-alpha``.
+This requires to build Firefox using Clang.
+
+Configuring the build environment
+---------------------------------
+
+Once you have your Clang build in place, you will need to set up tools
+to use it.
+A full working .mozconfig for the desktop browser is:
+
+.. code-block:: shell
+
+ . $topsrcdir/browser/config/mozconfig
+ mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-ff-dbg
+
+ ac_add_options --enable-debug
+
+Attempts to use ``ccache`` will likely result in failure to compile. It
+is also necessary to avoid optimized builds, as these will modify macros
+which will result in many false positives.
+
+At this point, your Firefox build environment should be configured to
+compile via the Clang static analyzer!
+
+
+Performing scanning builds
+--------------------------
+
+It is not enough to simply start the build like normal. Instead, you
+need to run the build through a Clang utility script which will keep
+track of all produced analysis and consolidate it automatically.
+
+Reports are published daily on
+`https://sylvestre.ledru.info/reports/fx-scan-build/ <http://sylvestre.ledru.info/reports/fx-scan-build/>`__
+Many of the defects reported as sources for Good First Bug.
+
+That script is scan-build. You can find it in
+``$clang_source/tools/scan-build/scan-build``.
+
+Try running your build through ``scan-build``:
+
+.. code-block:: shell
+
+ $ cd /path/to/mozilla/source
+
+ # Blow away your object directory because incremental builds don't make sense
+ $ rm -rf obj-dir
+
+ # To start the build:
+ scan-build --show-description ./mach build -v
+
+ # The above should execute without any errors. However, it should take longer than
+ # normal because all compilation will be executing through Clang's static analyzer,
+ # which adds overhead.
+
+If things are working properly, you should see a bunch of console spew,
+just like any build.
+
+The first time you run scan-build, CTRL+C after a few files are
+compiled. You should see output like:
+
+.. code-block:: shell
+
+ scan-build: 3 bugs found.
+ scan-build: Run 'scan-view /Users/gps/tmp/mcsb/2011-12-15-3' to examine bug reports.
+
+If you see a message like:
+
+.. code-block:: shell
+
+ scan-build: Removing directory '/var/folders/s2/zc78dpsx2rz6cpc_21r9g5hr0000gn/T/scan-build-2011-12-15-1' because it contains no reports.
+
+either no static analysis results were available yet or your environment
+is not configured properly.
+
+By default, ``scan-build`` writes results to a folder in a
+pseudo-temporary location. You can control where results go by passing
+the ``-o /path/to/output`` arguments to ``scan-build``.
+
+You may also want to run ``scan-build --help`` to see all the options
+available. For example, it is possible to selectively enable and disable
+individual analyzers.
+
+
+Analyzing the output
+--------------------
+
+Once the build has completed, ``scan-build`` will produce a report
+summarizing all the findings. This is called ``index.html`` in the
+output directory. You can run ``scan-view`` (from
+``$clang_source/tools/scan-view/scan-view``) as ``scan-build's`` output
+suggests; this merely fires up a local HTTP server. Or you should be
+able to open the ``index.html`` directly with your browser.
+
+
+False positives
+---------------
+
+By definition, there are currently false positives in the static
+analyzer. A lot of these are due to the analyzer having difficulties
+following the relatively complicated error handling in various
+preprocessor macros.