Bug 1691763 - Add identifier length check for Fluent linter; r=gregtatum,fluent-reviewers,flod

Differential Revision: https://phabricator.services.mozilla.com/D106666
This commit is contained in:
Dan Minor 2021-03-01 16:18:26 +00:00
parent 81a29b7e6b
commit a685764079
12 changed files with 116 additions and 16 deletions

View File

@ -55,6 +55,8 @@ class Linter(visitor.Visitor):
self.double_quote_re = re.compile(r"\"")
self.ellipsis_re = re.compile(r"\.\.\.")
self.minimum_id_length = 9
self.state = {
# The resource comment should be at the top of the page after the license.
"node_can_be_resource_comment": True,
@ -81,7 +83,9 @@ class Linter(visitor.Visitor):
)
if self.debug_print_json:
print(node.to_json())
import json
print(json.dumps(node.to_json(), indent=2))
# Only debug print the root node.
self.debug_print_json = False
@ -101,6 +105,11 @@ class Linter(visitor.Visitor):
self.state["can_have_group_comment"] = True
super().generic_visit(node)
def visit_MessageReference(self, node):
# We don't recurse into message references, the identifiers are either
# checked elsewhere or are attributes and come from DOM.
pass
def visit_Identifier(self, node):
if (
self.path not in self.exclusions["ID01"]["files"]
@ -110,6 +119,16 @@ class Linter(visitor.Visitor):
self.add_error(
node, "ID01", "Identifiers may only contain lowercase characters and -"
)
if (
len(node.name) < self.minimum_id_length
and self.path not in self.exclusions["ID02"]["files"]
and node.name not in self.exclusions["ID02"]["messages"]
):
self.add_error(
node,
"ID02",
f"Identifiers must be at least {self.minimum_id_length} characters long",
)
def visit_TextElement(self, node):
parser = TextElementHTMLParser()
@ -182,6 +201,12 @@ class Linter(visitor.Visitor):
)
return
def visit_SelectExpression(self, node):
# We only want to visit the variant values, the identifiers in selectors
# and keys are allowed to be free form.
for variant in node.variants:
super().generic_visit(variant.value)
def visit_GroupComment(self, node):
# This node is a comment with: "##"

View File

@ -83,3 +83,60 @@ ID01:
# policies-descriptions.ftl: These IDs are generated programmatically
# from policy names.
- browser/locales/en-US/browser/policies/policies-descriptions.ftl
ID02:
messages:
# browser/components/ion/content/ion.ftl
- ion
# browser/locales/en-US/browser/aboutDialog.ftl
- helpus
# browser/locales/en-US/browser/aboutLogins.ftl
- menu
# browser/locales/en-US/browser/newInstallPage.ftl
- title
- heading
- lost
# browser/locales/en-US/browser/pageInfo.ftl
- copy
- perm-tab
# browser/locales/en-US/browser/tabContextMenu.ftl
- pin-tab
# browser/locales/en-US/browser/touchbar/touchbar.ftl
- back
- forward
- reload
- home
- find
- new-tab
- share
# security/manager/locales/en-US/security/certificates/deviceManager.ftl
- devmgr
# toolkit/locales/en-US/toolkit/about/aboutPerformance.ftl
- type-tab
- size-KB
- size-MB
- size-GB
- item
# toolkit/locales/en-US/toolkit/about/aboutPlugins.ftl
- file-dd
- path-dd
# toolkit/locales/en-US/toolkit/about/aboutServiceWorkers.ftl
- scope
- waiting
# toolkit/locales/en-US/toolkit/about/aboutSupport.ftl
# yaml interprets yes and no as booleans if quotes are not present.
- "yes"
- "no"
- unknown
- found
- missing
- gpu-ram
- apz-none
# toolkit/locales/en-US/toolkit/printing/printDialogs.ftl
- portrait
- scale
- print-bg
- hf-blank
- hf-title
- hf-url
- hf-page
files: []

View File

@ -27,3 +27,15 @@ good-function-call = Last modified: { DATETIME($timeChanged, day: "numeric", mon
# $engineName (String) - The engine name that will currently be used for the private window.
good-variable-identifier = { $engineName } is your default search engine in Private Windows
short-id = I am too short
identifiers-in-selectors-should-be-ignored =
.label = { $tabCount ->
[1] Send Tab to Device
[UPPERCASE] Send Tab to Device
*[other] Send { $tabCount } Tabs to Device
}
this-message-reference-is-ignored =
.label = { menu-quit.label }

View File

@ -4,32 +4,32 @@
### Test group comments.
fake1 = Fake text
fake-identifier-1 = Fake text
## Pass: This group comment has proper spacing.
fake2 = Fake text
fake-identifier-2 = Fake text
## Fail: (GC03) Group comments should have an empty line before them.
fake3 = Fake text
fake-identifier-3 = Fake text
## Fail: (GC02) Group comments should have an empty line after them.
fake4 = Fake text
fake-identifier-4 = Fake text
## Pass: A single comment is fine.
## Fail: (GC04) A group comment must be followed by at least one message.
fake5 = Fake text
fake-identifier-5 = Fake text
## Fail: (GC03) Only allow 1 line above.
fake6 = Fake text
fake-identifier-6 = Fake text
## Fail: (GC02) Only allow 1 line below.
fake6 = Fake text
fake-identifier-6 = Fake text
## Fail: (GC01) Group comments should not be at the end of a file.

View File

@ -6,6 +6,6 @@
## Pass: The last group comment is allowed to be an empty ##
fake1 = Fake text
fake-identifier-1 = Fake text
##

View File

@ -4,8 +4,8 @@
### Pass: This is a resource comment with proper spacing.
fake1 = Fake text
fake-identifier-1 = Fake text
### Fail: (RC01) There should not be more than one resource comment
fake2 = Fake text
fake-identifier-2 = Fake text

View File

@ -3,4 +3,4 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
### Fail: (RC03) There should be an empty line preceeding.
fake1 = Fake text
fake-identifier-1 = Fake text

View File

@ -3,4 +3,4 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
### Fail: (RC02) There should be an empty line following.
fake1 = Fake text
fake-identifier-1 = Fake text

View File

@ -5,4 +5,4 @@
### Fail: (RC03) There should be only one space above.
fake1 = Fake text
fake-identifier-1 = Fake text

View File

@ -5,4 +5,4 @@
### Fail: (RC02) There should be only one space below.
fake1 = Fake text
fake-identifier-1 = Fake text

View File

@ -7,3 +7,6 @@ ID01:
- Invalid_Id
files:
- excluded.ftl
ID02:
messages: []
files: []

View File

@ -16,7 +16,7 @@ def test_lint_exclusions(lint, paths):
def test_lint_single_file(lint, paths):
results = lint(paths("bad.ftl"))
assert len(results) == 9
assert len(results) == 10
assert results[0].rule == "ID01"
assert results[0].lineno == 1
assert results[0].column == 1
@ -44,6 +44,9 @@ def test_lint_single_file(lint, paths):
assert results[8].rule == "TE03"
assert results[8].lineno == 24
assert results[8].column == 18
assert results[9].rule == "ID02"
assert results[9].lineno == 31
assert results[9].column == 1
def test_comment_group(lint, paths):