|
32 | 32 | from mkdocstrings.loggers import get_logger
|
33 | 33 |
|
34 | 34 | if TYPE_CHECKING:
|
35 |
| - from collections.abc import Sequence |
| 35 | + from collections.abc import Iterator, Sequence |
36 | 36 |
|
37 | 37 | from griffe import Attribute, Class, Function, Module
|
38 | 38 | from jinja2 import Environment, Template
|
@@ -326,26 +326,47 @@ def repl(match: Match) -> str:
|
326 | 326 | return Markup(text).format(**variables)
|
327 | 327 |
|
328 | 328 |
|
329 |
| -def do_split_path(path: str, full_path: str) -> list[tuple[str, str]]: |
| 329 | +_split_path_re = re.compile(r"([.(]?)([\w]+)(\))?") |
| 330 | +_splitable_re = re.compile(r"[().]") |
| 331 | + |
| 332 | + |
| 333 | +def do_split_path(path: str, full_path: str) -> Iterator[tuple[str, str, str, str]]: |
330 | 334 | """Split object paths for building cross-references.
|
331 | 335 |
|
332 | 336 | Parameters:
|
333 | 337 | path: The path to split.
|
| 338 | + full_path: The full path, used to compute correct paths for each part of the path. |
334 | 339 |
|
335 |
| - Returns: |
336 |
| - A list of pairs (title, full path). |
| 340 | + Yields: |
| 341 | + 4-tuples: prefix, word, full path, suffix. |
337 | 342 | """
|
338 |
| - if "." not in path: |
339 |
| - return [(path, full_path)] |
340 |
| - pairs = [] |
341 |
| - full_path = "" |
342 |
| - for part in path.split("."): |
343 |
| - if full_path: |
344 |
| - full_path += f".{part}" |
345 |
| - else: |
346 |
| - full_path = part |
347 |
| - pairs.append((part, full_path)) |
348 |
| - return pairs |
| 343 | + # Path is a single word, yield full path directly. |
| 344 | + if not _splitable_re.search(path): |
| 345 | + yield ("", path, full_path, "") |
| 346 | + return |
| 347 | + |
| 348 | + current_path = "" |
| 349 | + if path == full_path: |
| 350 | + # Split full path and yield directly without storing data in a dict. |
| 351 | + for match in _split_path_re.finditer(full_path): |
| 352 | + prefix, word, suffix = match.groups() |
| 353 | + current_path = f"{current_path}{prefix}{word}{suffix or ''}" if current_path else word |
| 354 | + yield prefix or "", word, current_path, suffix or "" |
| 355 | + return |
| 356 | + |
| 357 | + # Split full path first to store tuples in a dict. |
| 358 | + elements = {} |
| 359 | + for match in _split_path_re.finditer(full_path): |
| 360 | + prefix, word, suffix = match.groups() |
| 361 | + current_path = f"{current_path}{prefix}{word}{suffix or ''}" if current_path else word |
| 362 | + elements[word] = (prefix or "", word, current_path, suffix or "") |
| 363 | + |
| 364 | + # Then split path and pick tuples from the dict. |
| 365 | + first = True |
| 366 | + for match in _split_path_re.finditer(path): |
| 367 | + prefix, word, current_path, suffix = elements[match.group(2)] |
| 368 | + yield "" if first else prefix, word, current_path, suffix |
| 369 | + first = False |
349 | 370 |
|
350 | 371 |
|
351 | 372 | def _keep_object(name: str, filters: Sequence[tuple[Pattern, bool]]) -> bool:
|
|
0 commit comments