@@ -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+
296310class _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-
598615class CodeBlockChecker :
599616 """Checker for code blocks with different languages."""
600617
0 commit comments