Skip to content

Commit

Permalink
DOCSP-6190: Add validation of 'doc' role links
Browse files Browse the repository at this point in the history
  • Loading branch information
rayangler authored and i80and committed Jul 30, 2019
1 parent ef2c9fc commit db74d16
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ __pycache__/
parser/snooty.py
*.dist/
node_modules/
.coverage
.coverage*
htmlcov/
.venv/
dist/
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Add validation for links under the `doc` role (DOCSP-6190).

- Add support for the following reStructuredText constructs:

- `datalakeconf` rstobject
Expand Down
16 changes: 15 additions & 1 deletion snooty/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ def dispatch_visit(self, node: docutils.nodes.Node) -> None:
doc["label"] = node["label"]
if "target" in node:
doc["target"] = node["target"]

if doc["name"] == "doc":
self.validate_doc_role(node)
elif node_name == "target":
doc["type"] = "target"
doc["ids"] = node["ids"]
Expand Down Expand Up @@ -402,7 +405,7 @@ def handle_directive(
):
pass
else:
msg = f'"{name}" could not open "{argument_text}: No such file exists"'
msg = f'"{name}" could not open "{argument_text}": No such file exists'
self.diagnostics.append(Diagnostic.error(msg, util.get_line(node)))

if options:
Expand All @@ -411,6 +414,17 @@ def handle_directive(
doc["children"] = []
return True

def validate_doc_role(self, node: docutils.nodes.Node) -> None:
"""Validate target for doc role"""
target = PurePath(node["target"]).with_suffix(".txt")
fileid, target_path = util.reroot_path(target, self.docpath, self.source_path)

if not target_path.is_file():
msg = (
f'"{node["name"]}" could not open "{target_path}": No such file exists'
)
self.diagnostics.append(Diagnostic.error(msg, util.get_line(node)))

def add_static_asset(self, path: Path, upload: bool) -> StaticAsset:
fileid, path = util.reroot_path(path, self.docpath, self.source_path)
static_asset = StaticAsset.load(fileid, path, upload)
Expand Down
85 changes: 85 additions & 0 deletions snooty/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,91 @@ def test_roles() -> None:
)


def test_doc_role() -> None:
project_root = ROOT_PATH.joinpath("test_project")
path = project_root.joinpath(Path("source/test.rst")).resolve()
project_config = ProjectConfig(project_root, "")
parser = rstparser.Parser(project_config, JSONVisitor)

# Test bad text
page, diagnostics = parse_rst(
parser,
path,
"""
* :doc:`Testing it <fake-text>`
* :doc:`Testing this </fake-text>`
* :doc:`Testing that <./fake-text>`
* :doc:`fake-text`
* :doc:`/fake-text`
* :doc:`./fake-text`
""",
)
page.finish(diagnostics)
assert len(diagnostics) == 6

# Test valid text
page, diagnostics = parse_rst(
parser,
path,
"""
* :doc:`Testing this </index>`
* :doc:`Testing that <./../source/index>`
* :doc:`index`
* :doc:`/index`
* :doc:`./../source/index`
* :doc:`/index/`
""",
)
page.finish(diagnostics)
print(ast_to_testing_string(page.ast))
assert diagnostics == []
assert ast_to_testing_string(page.ast) == "".join(
(
"<root>",
"<list>",
"<listItem>",
"<paragraph>",
'<role name="doc" label="',
"{'type': 'text', 'value': 'Testing this', 'position': {'start': {'line': 2}}}",
'" target="/index">',
"</role>",
"</paragraph>",
"</listItem>",
"<listItem>",
"<paragraph>",
'<role name="doc" label="',
"{'type': 'text', 'value': 'Testing that', 'position': {'start': {'line': 3}}}",
'" target="./../source/index">',
"</role>",
"</paragraph>",
"</listItem>",
"<listItem>",
"<paragraph>",
'<role name="doc" target="index"></role>',
"</paragraph>",
"</listItem>",
"<listItem>",
"<paragraph>",
'<role name="doc" target="/index"></role>',
"</paragraph>",
"</listItem>",
"<listItem>",
"<paragraph>",
'<role name="doc" target="./../source/index"></role>',
"</paragraph>",
"</listItem>",
"<listItem>",
"<paragraph>",
'<role name="doc" target="/index/">',
"</role>",
"</paragraph>",
"</listItem>",
"</list>",
"</root>",
)
)


def test_accidental_indentation() -> None:
path = ROOT_PATH.joinpath(Path("test.rst"))
project_config = ProjectConfig(ROOT_PATH, "", source="./")
Expand Down

0 comments on commit db74d16

Please sign in to comment.