gecko-dev/testing/web-platform/tests/docs/wpt_lint_rules.py
jugglinmike ddf4d4c288 Bug 1557103 [wpt PR 17189] - [docs] Generate linting docs from source, a=testonly
Automatic update from web-platform-tests
[docs] Generate linting docs from source (#17189)

When new rules have been added to WPT's "lint" tool, the corresponding
documentation has not always been updated [1] [2] [3]. The static list
of rules currently describes only 22 of the 53 available rules.
Automatically generating documentation from source code helps avoid this
state and the confusion it can cause contributors.

Rely on the previously-implemented source code structure [4] during
documentation generation to automatically create a listing of all
available linting rules.

Although the Sphinx documentation generator includes a built-in
extension for generating documentation from Python source code, the
output of that extension is designed to document Python primitives such
as functions and classes. Such a format is inappropriate for this case
because the users of the linting tool do not interact with the internals
in this way. Define a custom docutils directive to tailor the
documentation to the needs of its audience.

[1] https://github.com/web-platform-tests/wpt/issues/5299
[2] https://github.com/web-platform-tests/wpt/issues/10501
[3] https://github.com/web-platform-tests/wpt/issues/11479
[4] https://github.com/web-platform-tests/wpt/pull/16268
--

wpt-commits: 204072e843f69e3a13628c01a928ea99aebed978
wpt-pr: 17189
2019-11-29 10:56:26 +00:00

78 lines
2.6 KiB
Python

from docutils.parsers.rst import Directive, nodes
from docutils.utils import new_document
from recommonmark.parser import CommonMarkParser
import importlib
import textwrap
class WPTLintRules(Directive):
"""A docutils directive to generate documentation for the
web-platform-test-test's linting tool from its source code. Requires a
single argument: a Python module specifier for a file which declares
linting rules."""
has_content = True
required_arguments = 1
optional_arguments = 0
_md_parser = CommonMarkParser()
@staticmethod
def _parse_markdown(markdown):
WPTLintRules._md_parser.parse(markdown, new_document("<string>"))
return WPTLintRules._md_parser.document.children[0]
@property
def module_specifier(self):
return self.arguments[0]
def _get_rules(self):
try:
module = importlib.import_module(self.module_specifier)
except ImportError:
raise ImportError(
"""wpt-lint-rules: unable to resolve the module at "{}".""".format(self.module_specifier)
)
for binding_name, value in module.__dict__.iteritems():
if hasattr(value, "__abstractmethods__") and len(value.__abstractmethods__):
continue
description = getattr(value, "description", None)
name = getattr(value, "name", None)
to_fix = getattr(value, "to_fix", None)
if description is None:
continue
if to_fix is not None:
to_fix = textwrap.dedent(to_fix)
yield {
"name": name,
"description": textwrap.dedent(description),
"to_fix": to_fix
}
def run(self):
definition_list = nodes.definition_list()
for rule in sorted(self._get_rules(), key=lambda rule: rule['name']):
item = nodes.definition_list_item()
definition = nodes.definition()
term = nodes.term()
item += term
item += definition
definition_list += item
term += nodes.literal(text=rule["name"])
definition += WPTLintRules._parse_markdown(rule["description"])
if rule["to_fix"]:
definition += nodes.strong(text="To fix:")
definition += WPTLintRules._parse_markdown(rule["to_fix"])
if len(definition_list.children) == 0:
raise Exception(
"""wpt-lint-rules: no linting rules found at "{}".""".format(self.module_specifier)
)
return [definition_list]