From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- docs/code-quality/lint/create.rst | 368 +++++++++++++++++++++ docs/code-quality/lint/index.rst | 33 ++ docs/code-quality/lint/linters/android-format.rst | 31 ++ docs/code-quality/lint/linters/black.rst | 36 ++ docs/code-quality/lint/linters/clang-format.rst | 35 ++ docs/code-quality/lint/linters/clippy.rst | 36 ++ docs/code-quality/lint/linters/codespell.rst | 36 ++ .../lint/linters/eslint-plugin-mozilla.rst | 114 +++++++ .../eslint-plugin-mozilla/avoid-Date-timing.rst | 30 ++ .../eslint-plugin-mozilla/avoid-removeChild.rst | 20 ++ .../eslint-plugin-mozilla/balanced-listeners.rst | 20 ++ .../eslint-plugin-mozilla/balanced-observers.rst | 20 ++ .../consistent-if-bracing.rst | 23 ++ .../linters/eslint-plugin-mozilla/environment.rst | 76 +++++ .../import-browser-window-globals.rst | 8 + .../import-content-task-globals.rst | 14 + .../eslint-plugin-mozilla/import-globals-from.rst | 18 + .../eslint-plugin-mozilla/import-globals.rst | 5 + .../import-headjs-globals.rst | 28 ++ .../lazy-getter-object-name.rst | 25 ++ .../mark-exported-symbols-as-used.rst | 23 ++ .../mark-test-function-used.rst | 8 + .../linters/eslint-plugin-mozilla/no-aArgs.rst | 22 ++ .../eslint-plugin-mozilla/no-addtask-setup.rst | 27 ++ .../no-arbitrary-setTimeout.rst | 23 ++ .../no-compare-against-boolean-literals.rst | 23 ++ .../eslint-plugin-mozilla/no-cu-reportError.rst | 23 ++ .../eslint-plugin-mozilla/no-define-cc-etc.rst | 23 ++ .../no-redeclare-with-import-autofix.rst | 21 ++ .../eslint-plugin-mozilla/no-throw-cr-literal.rst | 38 +++ .../no-useless-parameters.rst | 26 ++ .../no-useless-removeEventListener.rst | 20 ++ .../eslint-plugin-mozilla/no-useless-run-test.rst | 6 + .../prefer-boolean-length-check.rst | 24 ++ .../eslint-plugin-mozilla/prefer-formatValues.rst | 23 ++ .../eslint-plugin-mozilla/reject-addtask-only.rst | 6 + .../reject-chromeutils-import-params.rst | 22 ++ .../reject-eager-module-in-lazy-getter.rst | 35 ++ .../eslint-plugin-mozilla/reject-global-this.rst | 29 ++ .../reject-globalThis-modification.rst | 19 ++ ...reject-import-system-module-from-non-system.rst | 36 ++ .../reject-importGlobalProperties.rst | 45 +++ .../reject-lazy-imports-into-globals.rst | 36 ++ .../reject-mixing-eager-and-lazy.rst | 22 ++ .../reject-multiple-getters-calls.rst | 27 ++ .../reject-relative-requires.rst | 22 ++ .../reject-requires-await.rst | 20 ++ .../reject-scriptableunicodeconverter.rst | 13 + .../eslint-plugin-mozilla/reject-some-requires.rst | 6 + .../reject-top-level-await.rst | 26 ++ .../linters/eslint-plugin-mozilla/use-cc-etc.rst | 26 ++ .../use-chromeutils-generateqi.rst | 33 ++ .../use-chromeutils-import.rst | 24 ++ .../use-default-preference-values.rst | 19 ++ .../use-includes-instead-of-indexOf.rst | 21 ++ .../eslint-plugin-mozilla/use-isInstance.rst | 42 +++ .../eslint-plugin-mozilla/use-ownerGlobal.rst | 20 ++ .../eslint-plugin-mozilla/use-returnValue.rst | 20 ++ .../linters/eslint-plugin-mozilla/use-services.rst | 21 ++ .../eslint-plugin-mozilla/use-static-import.rst | 21 ++ .../eslint-plugin-mozilla/valid-ci-uses.rst | 42 +++ .../linters/eslint-plugin-mozilla/valid-lazy.rst | 55 +++ .../valid-services-property.rst | 30 ++ .../eslint-plugin-mozilla/valid-services.rst | 24 ++ .../var-only-at-top-level.rst | 21 ++ .../lint/linters/eslint-plugin-spidermonkey-js.rst | 18 + docs/code-quality/lint/linters/eslint.rst | 211 ++++++++++++ docs/code-quality/lint/linters/file-perm.rst | 42 +++ docs/code-quality/lint/linters/file-whitespace.rst | 38 +++ docs/code-quality/lint/linters/fluent-lint.rst | 47 +++ docs/code-quality/lint/linters/l10n.rst | 45 +++ docs/code-quality/lint/linters/license.rst | 39 +++ docs/code-quality/lint/linters/lintpref.rst | 32 ++ .../lint/linters/mingw-capitalization.rst | 28 ++ docs/code-quality/lint/linters/perfdocs.rst | 84 +++++ docs/code-quality/lint/linters/rejected-words.rst | 28 ++ docs/code-quality/lint/linters/rstlinter.rst | 32 ++ docs/code-quality/lint/linters/ruff.rst | 44 +++ docs/code-quality/lint/linters/rustfmt.rst | 33 ++ docs/code-quality/lint/linters/stylelint.rst | 77 +++++ docs/code-quality/lint/linters/trojan-source.rst | 34 ++ docs/code-quality/lint/linters/yamllint.rst | 31 ++ docs/code-quality/lint/mozlint.rst | 23 ++ docs/code-quality/lint/usage.rst | 133 ++++++++ 84 files changed, 3108 insertions(+) create mode 100644 docs/code-quality/lint/create.rst create mode 100644 docs/code-quality/lint/index.rst create mode 100644 docs/code-quality/lint/linters/android-format.rst create mode 100644 docs/code-quality/lint/linters/black.rst create mode 100644 docs/code-quality/lint/linters/clang-format.rst create mode 100644 docs/code-quality/lint/linters/clippy.rst create mode 100644 docs/code-quality/lint/linters/codespell.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-Date-timing.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-removeChild.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-listeners.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-observers.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/consistent-if-bracing.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/environment.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/import-browser-window-globals.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/import-content-task-globals.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals-from.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/import-headjs-globals.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/lazy-getter-object-name.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-exported-symbols-as-used.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-test-function-used.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-aArgs.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-addtask-setup.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-arbitrary-setTimeout.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-compare-against-boolean-literals.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-cu-reportError.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-define-cc-etc.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-redeclare-with-import-autofix.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-throw-cr-literal.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-parameters.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-removeEventListener.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-run-test.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-boolean-length-check.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-formatValues.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-addtask-only.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-chromeutils-import-params.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-eager-module-in-lazy-getter.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-global-this.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-globalThis-modification.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-import-system-module-from-non-system.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-importGlobalProperties.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-lazy-imports-into-globals.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-mixing-eager-and-lazy.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-multiple-getters-calls.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-relative-requires.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-requires-await.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-scriptableunicodeconverter.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-some-requires.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-top-level-await.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-cc-etc.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-generateqi.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-import.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-default-preference-values.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-includes-instead-of-indexOf.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-isInstance.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-ownerGlobal.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-returnValue.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-services.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/use-static-import.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-ci-uses.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-lazy.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services-property.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-mozilla/var-only-at-top-level.rst create mode 100644 docs/code-quality/lint/linters/eslint-plugin-spidermonkey-js.rst create mode 100644 docs/code-quality/lint/linters/eslint.rst create mode 100644 docs/code-quality/lint/linters/file-perm.rst create mode 100644 docs/code-quality/lint/linters/file-whitespace.rst create mode 100644 docs/code-quality/lint/linters/fluent-lint.rst create mode 100644 docs/code-quality/lint/linters/l10n.rst create mode 100644 docs/code-quality/lint/linters/license.rst create mode 100644 docs/code-quality/lint/linters/lintpref.rst create mode 100644 docs/code-quality/lint/linters/mingw-capitalization.rst create mode 100644 docs/code-quality/lint/linters/perfdocs.rst create mode 100644 docs/code-quality/lint/linters/rejected-words.rst create mode 100644 docs/code-quality/lint/linters/rstlinter.rst create mode 100644 docs/code-quality/lint/linters/ruff.rst create mode 100644 docs/code-quality/lint/linters/rustfmt.rst create mode 100644 docs/code-quality/lint/linters/stylelint.rst create mode 100644 docs/code-quality/lint/linters/trojan-source.rst create mode 100644 docs/code-quality/lint/linters/yamllint.rst create mode 100644 docs/code-quality/lint/mozlint.rst create mode 100644 docs/code-quality/lint/usage.rst (limited to 'docs/code-quality/lint') diff --git a/docs/code-quality/lint/create.rst b/docs/code-quality/lint/create.rst new file mode 100644 index 0000000000..2efdf742f5 --- /dev/null +++ b/docs/code-quality/lint/create.rst @@ -0,0 +1,368 @@ +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 `__): + +.. code-block:: python + + import json + import os + import subprocess + from collections import defaultdict + from shutil import which + + from mozlint import result + + + 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 (, )", "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 `_ 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 --subsuite mozlint + +To run a specific test: + +.. code-block:: shell + + ./mach python-test --subsuite mozlint tools/lint/test/test_black.py + +More tests can be `found in-tree `_. + +Tracking fixed issues +--------------------- + +All the linters that provide ``fix support`` returns a dictionary instead of a list. + +``{"results":result,"fixed":fixed}`` + +* results - All the linting errors it was not able to fix +* fixed - Count of fixed errors (for ``fix=False`` this is 0) + +Some linters (example: `codespell `_) might require two passes to count the number of fixed issues. +Others might just need `some tuning `_. + +For adding tests to check your fixed count, add a global variable ``fixed = 0`` +and write a function to add your test as mentioned under ``Automated testing`` section. + + +Here's an example + +.. code-block:: python + + fixed = 0 + + + def test_lint_codespell_fix(lint, create_temp_file): + # Typo has been fixed in the contents to avoid triggering warning + # 'informations' ----> 'information' + contents = """This is a file with some typos and information. + But also testing false positive like optin (because this isn't always option) + or stuff related to our coding style like: + aparent (aParent). + but detects mistakes like mozilla + """.lstrip() + + path = create_temp_file(contents, "ignore.rst") + lint([path], fix=True) + + assert fixed == 2 + + +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 `__): + +.. 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 `_. +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 `_ +and maybe install the necessary files in the `Docker configuration `_. + +.. note:: + + If the defect found by the linter is minor, make sure that it is run as `tier 2 `_. + 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..2b2cfdefbd --- /dev/null +++ b/docs/code-quality/lint/index.rst @@ -0,0 +1,33 @@ +Linting +======= + +Linters are used in mozilla-central to help enforce coding style and avoid bad practices. +They cover a wide variety of languages and checks. + +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 `_). + + +.. toctree:: + :caption: Getting Started + :maxdepth: 2 + + usage + +.. toctree:: + :caption: Linter Implementations + :maxdepth: 1 + :glob: + + linters/* + +.. toctree:: + :caption: Linter Specifics + :maxdepth: 1 + + mozlint + create diff --git a/docs/code-quality/lint/linters/android-format.rst b/docs/code-quality/lint/linters/android-format.rst new file mode 100644 index 0000000000..ed23ac64de --- /dev/null +++ b/docs/code-quality/lint/linters/android-format.rst @@ -0,0 +1,31 @@ +Spotless +======== + +`Spotless `__ is a pluggable formatter +for Gradle and Android. + +In our current configuration, Spotless includes the +`Google Java Format plug-in `__ +which formats all our Java code using the Google Java coding style guidelines, +and `ktlint `__ which formats all +our Kotlin code using the official Kotlin coding convention and Android Kotlin +Style Guide. + + +Run Locally +----------- + +The mozlint integration of spotless can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter android-format + +Alternatively, omit the ``--linter android-format`` and run all configured linters, which will include +spotless. + + +Autofix +------- + +The spotless linter provides a ``--fix`` option. diff --git a/docs/code-quality/lint/linters/black.rst b/docs/code-quality/lint/linters/black.rst new file mode 100644 index 0000000000..60a06ce95b --- /dev/null +++ b/docs/code-quality/lint/linters/black.rst @@ -0,0 +1,36 @@ +Black +===== + +`Black `__ is a opinionated python code formatter. + + +Run Locally +----------- + +The mozlint integration of black can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter black + +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 :searchfox:`black.yml ` file. + +Autofix +------- + +The black linter provides a ``--fix`` option. + + +Sources +------- + +* :searchfox:`Configuration (YAML) ` +* :searchfox:`Source ` 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..a528af4358 --- /dev/null +++ b/docs/code-quality/lint/linters/clang-format.rst @@ -0,0 +1,35 @@ +clang-format +============ + +`clang-format `__ 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 + + +Configuration +------------- + +To enable clang-format on new directory, add the path to the include +section in the :searchfox:`clang-format.yml ` file. + +While excludes: will work, this linter will read the ignore list from :searchfox:`.clang-format-ignore file <.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 +------- + +* :searchfox:`Configuration (YAML) ` +* :searchfox:`Source ` diff --git a/docs/code-quality/lint/linters/clippy.rst b/docs/code-quality/lint/linters/clippy.rst new file mode 100644 index 0000000000..40db532b88 --- /dev/null +++ b/docs/code-quality/lint/linters/clippy.rst @@ -0,0 +1,36 @@ +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 + +.. 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 `_ file. + +Autofix +------- + +This linter provides a ``--fix`` option. +Please note that this option does not fix all detected issues. + +Sources +------- + +* `Configuration (YAML) `_ +* `Source `_ diff --git a/docs/code-quality/lint/linters/codespell.rst b/docs/code-quality/lint/linters/codespell.rst new file mode 100644 index 0000000000..9299a81b6e --- /dev/null +++ b/docs/code-quality/lint/linters/codespell.rst @@ -0,0 +1,36 @@ +Codespell +========= + +`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 + + +Configuration +------------- + +To enable codespell on new directory, add the path to the include +section in the :searchfox:`codespell.yml ` file. + +This job is configured as `tier 2 `_. + +Autofix +------- + +Codespell provides a ``--fix`` option. It is based on the ``-w`` option provided by upstream. + + +Sources +------- + +* :searchfox:`Configuration (YAML) ` +* :searchfox:`Source ` 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..d1d60c963c --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla.rst @@ -0,0 +1,114 @@ +===================== +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/avoid-removeChild + eslint-plugin-mozilla/balanced-listeners + eslint-plugin-mozilla/balanced-observers + eslint-plugin-mozilla/consistent-if-bracing + eslint-plugin-mozilla/import-browser-window-globals + eslint-plugin-mozilla/import-content-task-globals + eslint-plugin-mozilla/import-globals + eslint-plugin-mozilla/import-globals-from + eslint-plugin-mozilla/import-headjs-globals + eslint-plugin-mozilla/lazy-getter-object-name + eslint-plugin-mozilla/mark-exported-symbols-as-used + eslint-plugin-mozilla/mark-test-function-used + eslint-plugin-mozilla/no-aArgs + eslint-plugin-mozilla/no-addtask-setup + eslint-plugin-mozilla/no-arbitrary-setTimeout + eslint-plugin-mozilla/no-compare-against-boolean-literals + eslint-plugin-mozilla/no-cu-reportError + eslint-plugin-mozilla/no-define-cc-etc + eslint-plugin-mozilla/no-redeclare-with-import-autofix + eslint-plugin-mozilla/no-throw-cr-literal + eslint-plugin-mozilla/no-useless-parameters + eslint-plugin-mozilla/no-useless-removeEventListener + eslint-plugin-mozilla/no-useless-run-test + eslint-plugin-mozilla/prefer-boolean-length-check + eslint-plugin-mozilla/prefer-formatValues + eslint-plugin-mozilla/reject-addtask-only + eslint-plugin-mozilla/reject-chromeutils-import-params + eslint-plugin-mozilla/reject-eager-module-in-lazy-getter + eslint-plugin-mozilla/reject-global-this + eslint-plugin-mozilla/reject-globalThis-modification + eslint-plugin-mozilla/reject-importGlobalProperties + eslint-plugin-mozilla/reject-lazy-imports-into-globals + eslint-plugin-mozilla/reject-mixing-eager-and-lazy + eslint-plugin-mozilla/reject-multiple-getters-calls + eslint-plugin-mozilla/reject-relative-requires + eslint-plugin-mozilla/reject-requires-await + eslint-plugin-mozilla/reject-scriptableunicodeconverter + eslint-plugin-mozilla/reject-some-requires + eslint-plugin-mozilla/reject-top-level-await + eslint-plugin-mozilla/reject-import-system-module-from-non-system + eslint-plugin-mozilla/use-cc-etc + eslint-plugin-mozilla/use-chromeutils-generateqi + eslint-plugin-mozilla/use-chromeutils-import + eslint-plugin-mozilla/use-default-preference-values + eslint-plugin-mozilla/use-includes-instead-of-indexOf + eslint-plugin-mozilla/use-isInstance + eslint-plugin-mozilla/use-ownerGlobal + eslint-plugin-mozilla/use-returnValue + eslint-plugin-mozilla/use-services + eslint-plugin-mozilla/use-static-import + eslint-plugin-mozilla/valid-ci-uses + eslint-plugin-mozilla/valid-lazy + eslint-plugin-mozilla/valid-services + eslint-plugin-mozilla/valid-services-property + eslint-plugin-mozilla/var-only-at-top-level + +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..b01b568a28 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-Date-timing.rst @@ -0,0 +1,30 @@ +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/avoid-removeChild.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-removeChild.rst new file mode 100644 index 0000000000..15ece94d0d --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-removeChild.rst @@ -0,0 +1,20 @@ +avoid-removeChild +================= + +Rejects using ``element.parentNode.removeChild(element)`` when ``element.remove()`` +can be used instead. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + elt.parentNode.removeChild(elt); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + elt.remove(); + elt.parentNode.removeChild(elt2); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-listeners.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-listeners.rst new file mode 100644 index 0000000000..f53c11e7aa --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-listeners.rst @@ -0,0 +1,20 @@ +balanced-listeners +================== + +Checks that for every occurrence of 'addEventListener' or 'on' there is an +occurrence of 'removeEventListener' or 'off' with the same event name. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + elt.addEventListener('click', handler, false); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + elt.addEventListener('event', handler); + elt.removeEventListener('event', handler); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-observers.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-observers.rst new file mode 100644 index 0000000000..b169a520a3 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-observers.rst @@ -0,0 +1,20 @@ +balanced-observers +================== + +Checks that for every occurrence of ``addObserver`` there is an +occurrence of ``removeObserver`` with the same topic. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + Services.obs.addObserver(observer, 'observable'); + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + Services.obs.addObserver(observer, 'observable'); + Services.obs.removeObserver(observer, 'observable'); diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/consistent-if-bracing.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/consistent-if-bracing.rst new file mode 100644 index 0000000000..7bf6b796ef --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/consistent-if-bracing.rst @@ -0,0 +1,23 @@ +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. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: js + + if (true) {1} else 0 + if (true) 1; else {0} + if (true) {1} else if (true) 2; else {0} + +Examples of correct code for this rule: +--------------------------------------- + +.. code-block:: js + + if (true) {1} else {0} + if (false) 1; else 0 + if (true) {1} else if (true) {2} else {0} 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..2c779410d6 --- /dev/null +++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/environment.rst @@ -0,0 +1,76 @@ +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-script +------------- + +Defines the environment for scripts loaded by +``SpecialPowers.loadChromeScript``. + +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 scripts loaded by ``Services.mm.loadFrameScript``. + +jsm +--- + +Defines the environment for jsm files (javascript modules). + +privileged +---------- + +Defines the environment for privileged JS files. + +process-script +-------------- + +Defines the environment for scripts loaded by +``Services.ppmm.loadProcessScript``. + +remote-page +----------- + +Defines the environment for scripts loaded with ``