1 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
2 # vim: set filetype=python:
3 # This Source Code Form is subject to the terms of the Mozilla Public
4 # License, v. 2.0. If a copy of the MPL was not distributed with this
5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 from mozlint
import result
12 from mozlint
.pathutils
import expand_exclusions
14 # This simple linter checks for duplicates from
15 # modules/libpref/init/StaticPrefList.yaml against modules/libpref/init/all.js
17 # If for any reason a pref needs to appear in both files, add it to this set.
19 "devtools.console.stdout.chrome", # Uses the 'sticky' attribute.
20 "devtools.console.stdout.content", # Uses the 'sticky' attribute.
21 "fission.autostart", # Uses the 'locked' attribute.
22 "browser.dom.window.dump.enabled", # Uses the 'sticky' attribute.
23 "apz.fling_curve_function_y2", # This pref is a part of a series.
24 "dom.postMessage.sharedArrayBuffer.bypassCOOP_COEP.insecure.enabled", # NOQA: E501; Uses the 'locked' attribute.
25 "extensions.backgroundServiceWorkerEnabled.enabled", # NOQA: E501; Uses the 'locked' attribute.
27 PATTERN
= re
.compile(r
"\s*pref\(\s*\"(?P
<pref
>.+)\"\s
*,\s
*(?P
<val
>.+)\
)\s
*;.*")
30 def get_names(pref_list_filename):
32 # We want to transform patterns like 'foo: @VAR@' into valid yaml. This
33 # pattern does not happen in 'name', so it's fine to ignore these.
34 # We also want to evaluate all branches of #ifdefs for pref names, so we
35 # ignore anything else preprocessor related.
36 file = open(pref_list_filename, encoding="utf
-8").read().replace("@", "")
38 pref_list = yaml.safe_load(file)
39 except (IOError, ValueError) as e:
40 print("{}: error
:\n {}".format(pref_list_filename, e), file=sys.stderr)
43 for pref in pref_list:
44 if pref["name
"] not in IGNORE_PREFS:
45 pref_names[pref["name
"]] = pref["value
"]
50 # Check the names of prefs against each other, and if the pref is a duplicate
51 # that has not previously been noted, add that name to the list of errors.
52 def check_against(path, pref_names):
54 prefs = read_prefs(path)
56 if pref["name
"] in pref_names:
57 errors.extend(check_value_for_pref(pref, pref_names[pref["name
"]], path))
61 def check_value_for_pref(some_pref, some_value, path):
63 if some_pref["value
"] == some_value:
67 "message
": some_pref["raw
"],
68 "lineno
": some_pref["line
"],
69 "hint
": "Remove the duplicate pref
or add it to IGNORE_PREFS
.",
76 # The entries in the *.js pref files are regular enough to use simple pattern
77 # matching to load in prefs.
80 with open(path, encoding="utf
-8") as source:
81 for lineno, line in enumerate(source, start=1):
82 match = PATTERN.match(line)
86 "name
": match.group("pref
"),
87 "value
": evaluate_pref(match.group("val
")),
95 def evaluate_pref(value):
96 bools = {"true
": True, "false
": False}
104 def checkdupes(paths, config, **kwargs):
107 pref_names = get_names(config["support
-files
"][0])
108 files = list(expand_exclusions(paths, config, kwargs["root
"]))
110 errors.extend(check_against(file, pref_names))
112 results.append(result.from_config(config, **error))