Skip to content

Commit a91b040

Browse files
committed
checker: handle code-blocks from other files
Handle code-blocks from files being included by fetching and operating on the source of the included file as needed. Add a function to iterate through parent nodes until we get a source since there is a chance the code-block could be nested several layers below other directives. Signed-off-by: Randolph Sapp <rs@ti.com>
1 parent d50e1fe commit a91b040

1 file changed

Lines changed: 43 additions & 26 deletions

File tree

src/rstcheck_core/checker.py

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,20 @@ def _parse_and_filter_rst_errors(
293293
)
294294

295295

296+
def _get_source_path(node: docutils.nodes.Element):
297+
"""Iterate through all parent nodes until we get a valid source file
298+
299+
:param node: A docutils node
300+
:return: String with rst source path
301+
"""
302+
current_node = node
303+
source = current_node.source
304+
while current_node and not source:
305+
current_node = current_node.parent
306+
source = current_node.source
307+
return source
308+
309+
296310
class _CheckWriter(docutils.writers.Writer): # type: ignore[misc]
297311
"""Runs CheckTranslator on code blocks."""
298312

@@ -396,6 +410,34 @@ def visit_doctest_block(self, node: docutils.nodes.Element) -> None:
396410
is_code_node=False,
397411
)
398412

413+
def _get_code_block_directive_line(self, node: docutils.nodes.Element) -> int | None:
414+
"""Find line of code block directive.
415+
416+
:param node: The code block node
417+
:return: Line of code block directive or :py:obj:`None`
418+
"""
419+
line_number = node.line
420+
if line_number is None:
421+
try:
422+
line_number = _generate_directive_line(node)
423+
except IndexError:
424+
return None
425+
426+
if line_number is None:
427+
return None
428+
429+
node_source = _get_source_path(node)
430+
if node_source and node_source != str(self.source_origin):
431+
lines = _get_source(pathlib.Path(node_source)).splitlines()
432+
else:
433+
lines = self.source.splitlines()
434+
435+
for line_no in range(line_number, 1, -1):
436+
if CODE_BLOCK_RE.match(lines[line_no - 2].strip()) is not None:
437+
return line_no - 1
438+
439+
return None
440+
399441
def visit_literal_block(self, node: docutils.nodes.Element) -> None:
400442
"""Add check for syntax of code block.
401443
@@ -413,7 +455,7 @@ def visit_literal_block(self, node: docutils.nodes.Element) -> None:
413455
return
414456
language = classes[-1]
415457

416-
directive_line = _get_code_block_directive_line(node, self.source)
458+
directive_line = self._get_code_block_directive_line(node)
417459
if directive_line is None:
418460
logger.warning(
419461
"Could not find line for literal block directive. "
@@ -570,31 +612,6 @@ def _generate_directive_line(node: docutils.nodes.Element) -> int | None:
570612
return None
571613

572614

573-
def _get_code_block_directive_line(node: docutils.nodes.Element, full_contents: str) -> int | None:
574-
"""Find line of code block directive.
575-
576-
:param node: The code block node
577-
:param full_contents: The node's contents
578-
:return: Line of code block directive or :py:obj:`None`
579-
"""
580-
line_number = node.line
581-
if line_number is None:
582-
try:
583-
line_number = _generate_directive_line(node)
584-
except IndexError:
585-
return None
586-
587-
if line_number is None:
588-
return None
589-
590-
lines = full_contents.splitlines()
591-
for line_no in range(line_number, 1, -1):
592-
if CODE_BLOCK_RE.match(lines[line_no - 2].strip()) is not None:
593-
return line_no - 1
594-
595-
return None
596-
597-
598615
class CodeBlockChecker:
599616
"""Checker for code blocks with different languages."""
600617

0 commit comments

Comments
 (0)