Bug 1825507 - Separate out prettier and ESLint to run as different processes. r=linter-reviewers,devtools-reviewers,ahal

This is enough to allow ESLint and Prettier to be run as different processes within the same lint command.
It does not fix all the failures with those two separate - that will be handled in follow-up bugs.

Differential Revision: https://phabricator.services.mozilla.com/D174133
This commit is contained in:
Mark Banner
2023-04-04 19:02:13 +00:00
parent 7398567220
commit 781ac41b6a
4 changed files with 162 additions and 8 deletions

View File

@@ -2,6 +2,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
let prettierRules = { "prettier/prettier": "error" };
if (process.env.MOZ_SEPARATE_PRETTIER) {
prettierRules = { "prettier/prettier": "off" };
}
module.exports = {
// When adding items to this file please check for effects on sub-directories.
parserOptions: {
@@ -25,7 +31,6 @@ module.exports = {
"eslint:recommended",
"plugin:jsx-a11y/recommended", // require("eslint-plugin-jsx-a11y")
"plugin:mozilla/recommended", // require("eslint-plugin-mozilla") require("eslint-plugin-fetch-options") require("eslint-plugin-html") require("eslint-plugin-no-unsanitized")
"plugin:prettier/recommended", // require("eslint-plugin-prettier")
"prettier", // require("eslint-config-prettier")
],
overrides: [
@@ -113,6 +118,8 @@ module.exports = {
},
],
rules: {
...prettierRules,
"fetch-options/no-fetch-credentials": "error",
"react/jsx-boolean-value": ["error", "always"],

View File

@@ -2,6 +2,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
let prettierRules = { "prettier/prettier": "error" };
if (process.env.MOZ_SEPARATE_PRETTIER) {
prettierRules = { "prettier/prettier": "off" };
}
module.exports = {
plugins: ["react", "mozilla", "@babel", "prettier", "import", "file-header"],
globals: {
@@ -47,6 +53,8 @@ module.exports = {
jest: true,
},
rules: {
...prettierRules,
// These are the rules that have been configured so far to match the
// devtools coding style.
@@ -358,9 +366,6 @@ module.exports = {
// entirely
"operator-assignment": 0,
// Rules from the prettier plugin
"prettier/prettier": "error",
"file-header/file-header": [
"error",
[

View File

@@ -32,6 +32,14 @@ mach eslint --setup
and try again.
""".strip()
PRETTIER_ERROR_MESSAGE = """
An error occurred running prettier. Please check the following error messages:
{}
""".strip()
PRETTIER_FORMATTING_MESSAGE = "This file needs formatting with prettier."
def setup(root, **lintargs):
setup_helper.set_project_root(root)
@@ -70,6 +78,7 @@ def lint(paths, config, binary=None, fix=None, rules=[], setup=None, **lintargs)
for rule in rules:
extra_args.extend(["--rule", rule])
# First run ESLint
cmd_args = (
[
binary,
@@ -86,13 +95,56 @@ def lint(paths, config, binary=None, fix=None, rules=[], setup=None, **lintargs)
+ exclude_args
+ paths
)
log.debug("Command: {}".format(" ".join(cmd_args)))
if fix:
# eslint requires that --fix be set before the --ext argument.
cmd_args.insert(2, "--fix")
return run(cmd_args, config)
log.debug("ESLint command: {}".format(" ".join(cmd_args)))
result = run(cmd_args, config)
if result == 1:
return result
# Then run Prettier
if "MOZ_SEPARATE_PRETTIER" in os.environ:
patterns = []
for p in paths:
filename, file_extension = os.path.splitext(p)
if file_extension:
patterns.append(p)
else:
patterns.append(
p + "/**/*.+({})".format("|".join(config["extensions"]))
)
cmd_args = (
[
binary,
os.path.join(
module_path, "node_modules", "prettier", "bin-prettier.js"
),
"--list-different",
]
+ extra_args
# Prettier does not support exclude arguments.
# + exclude_args
# Prettier only supports this from 2.3 and above (bug 1826062).
# + "--no-error-on-unmatched-pattern",
+ patterns
)
log.debug("Prettier command: {}".format(" ".join(cmd_args)))
if fix:
cmd_args.append("--write")
prettier_result = run_prettier(cmd_args, config, fix)
if prettier_result == 1:
return prettier_result
result["results"].extend(prettier_result["results"])
result["fixed"] = result["fixed"] + prettier_result["fixed"]
return result
def run(cmd_args, config):
@@ -156,3 +208,77 @@ def run(cmd_args, config):
results.append(result.from_config(config, **err))
return {"results": results, "fixed": fixed}
def run_prettier(cmd_args, config, fix):
shell = False
if (
os.environ.get("MSYSTEM") in ("MINGW32", "MINGW64")
or "MOZILLABUILD" in os.environ
):
# The eslint binary needs to be run from a shell with msys
shell = True
encoding = "utf-8"
orig = signal.signal(signal.SIGINT, signal.SIG_IGN)
proc = subprocess.Popen(
cmd_args, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
signal.signal(signal.SIGINT, orig)
try:
output, errors = proc.communicate()
except KeyboardInterrupt:
proc.kill()
return {"results": [], "fixed": 0}
if errors:
errors = errors.decode(encoding, "replace")
# --no-error-on-unmatched-pattern was only added in Prettier 2.3,
# when we upgrade to the latest version (bug 1826062), we can pass in
# that argument and remove this check.
if "No matching files." in errors:
return {"results": [], "fixed": 0}
print(PRETTIER_ERROR_MESSAGE.format(errors))
if proc.returncode >= 2:
return 1
if not output:
return {"results": [], "fixed": 0} # no output means success
output = output.decode(encoding, "replace").splitlines()
results = []
fixed = 0
if fix:
# When Prettier is running in fix mode, it outputs the list of files
# that have been fixed, so sum them up here.
# If it can't fix files, it will throw an error, which will be handled
# above.
fixed = len(output)
else:
# When in "check" mode, Prettier will output the list of files that
# need changing, so we'll wrap them in our result structure here.
for file in output:
if not file:
continue
results.append(
result.from_config(
config,
**{
"name": "eslint",
"path": file,
"message": PRETTIER_FORMATTING_MESSAGE,
"level": "error",
"rule": "prettier",
"lineno": 0,
"column": 0,
}
)
)
return {"results": results, "fixed": fixed}

View File

@@ -4,6 +4,12 @@
"use strict";
let prettierRules = { "prettier/prettier": "error" };
if (process.env.MOZ_SEPARATE_PRETTIER) {
prettierRules = { "prettier/prettier": "off" };
}
/**
* The configuration is based on eslint:recommended config. The details for all
* the ESLint rules, and which ones are in the recommended configuration can
@@ -19,7 +25,9 @@ module.exports = {
"mozilla/specific": true,
},
extends: ["eslint:recommended", "plugin:prettier/recommended"],
// The prettier configuration here comes from eslint-config-prettier and
// turns off all of ESLint's rules related to formatting.
extends: ["eslint:recommended", "prettier"],
overrides: [
{
@@ -111,11 +119,16 @@ module.exports = {
},
// When adding items to this file please check for effects on sub-directories.
plugins: ["html", "fetch-options", "no-unsanitized"],
plugins: ["html", "fetch-options", "prettier", "no-unsanitized"],
// When adding items to this file please check for effects on all of toolkit
// and browser
rules: {
...prettierRules,
// This may conflict with prettier, so we turn it off.
"arrow-body-style": "off",
// Warn about cyclomatic complexity in functions.
// XXX Get this down to 20?
complexity: ["error", 34],
@@ -331,6 +344,9 @@ module.exports = {
// Require object-literal shorthand with ES6 method syntax
"object-shorthand": ["error", "always", { avoidQuotes: true }],
// This may conflict with prettier, so turn it off.
"prefer-arrow-callback": "off",
// This generates too many false positives that are not easy to work around,
// and false positives seem to be inherent in the rule.
"require-atomic-updates": "off",