|
13 | 13 | - _format_header(classes: List[ClassInfo], functions: List[SignatureInfo], language: str, line_offset: int) -> str (line 242) |
14 | 14 | - get_preserved_header_end_line(lines: List[str], language: str) -> int (line 262) |
15 | 15 | - process_file(path: Path, verbose: bool = False) -> None (line 344) |
16 | | - - discover_and_process_files(directories: List[str], verbose: bool = False) -> None (line 414) |
| 16 | + - discover_and_process_files(directories: List[str], verbose: bool = False) -> None (line 468) |
17 | 17 | --- END AUTO-GENERATED DOCSTRING --- |
18 | 18 | """ |
19 | 19 | from __future__ import annotations |
@@ -390,15 +390,69 @@ def process_file(path: Path, verbose: bool = False) -> None: |
390 | 390 | # * Now create the final header with correct line numbers |
391 | 391 | final_header = _format_header(classes, functions, language, line_offset) |
392 | 392 |
|
393 | | - new_content_parts = [] |
394 | | - if file_prefix: |
395 | | - new_content_parts.append(file_prefix) |
396 | | - |
397 | | - new_content_parts.append(final_header) |
398 | | - new_content_parts.append(cleaned_body.strip()) |
399 | | - |
400 | | - # Use single newlines to test composition theory |
401 | | - new_content = "\n".join(filter(None, new_content_parts)) |
| 393 | + # Attempt to merge auto-generated header into existing manual docstring for Python |
| 394 | + merged_body = None |
| 395 | + if language == "python": |
| 396 | + # Split cleaned body into lines |
| 397 | + body_lines = cleaned_body.splitlines() |
| 398 | + # Find first non-empty line |
| 399 | + idx = 0 |
| 400 | + while idx < len(body_lines) and body_lines[idx].strip() == "": |
| 401 | + idx += 1 |
| 402 | + # Check for manual docstring start |
| 403 | + if idx < len(body_lines) and body_lines[idx].strip().startswith(('"""', "'''")): |
| 404 | + delim = body_lines[idx].strip() |
| 405 | + # Ensure it's not an existing auto-generated docstring |
| 406 | + marker_present = False |
| 407 | + for i in range(idx, min(idx + 5, len(body_lines))): |
| 408 | + if DOCSTRING_START_MARKER in body_lines[i]: |
| 409 | + marker_present = True |
| 410 | + break |
| 411 | + if not marker_present: |
| 412 | + # Find end of manual docstring |
| 413 | + end_idx = None |
| 414 | + for j in range(idx + 1, len(body_lines)): |
| 415 | + if body_lines[j].strip() == delim: |
| 416 | + end_idx = j |
| 417 | + break |
| 418 | + if end_idx is not None: |
| 419 | + manual_inner = body_lines[idx + 1:end_idx] |
| 420 | + # Compute auto header content lines with correct offset for merge |
| 421 | + # temp_header_lines holds the auto header lines including delimiters |
| 422 | + # content_lines length is temp_header_lines minus start/end markers |
| 423 | + offset_override = len(temp_header_lines) - 2 |
| 424 | + # Generate only the header content lines (without triple-quote delimiters) |
| 425 | + header_inner = _get_header_content_lines( |
| 426 | + classes, functions, language, offset_override |
| 427 | + ) |
| 428 | + merged_lines = [] |
| 429 | + # Preserve leading blank lines before manual docstring |
| 430 | + merged_lines.extend(body_lines[:idx]) |
| 431 | + # Start merged docstring with manual delimiter |
| 432 | + merged_lines.append(delim) |
| 433 | + # Insert auto-generated header content |
| 434 | + merged_lines.extend(header_inner) |
| 435 | + # Insert original manual docstring content |
| 436 | + merged_lines.extend(manual_inner) |
| 437 | + # Close merged docstring with manual delimiter |
| 438 | + merged_lines.append(delim) |
| 439 | + # Append rest of body after original docstring |
| 440 | + merged_lines.extend(body_lines[end_idx + 1:]) |
| 441 | + merged_body = "\n".join(merged_lines) |
| 442 | + if merged_body is not None: |
| 443 | + if file_prefix: |
| 444 | + new_content = file_prefix + "\n" + merged_body.lstrip("\n") |
| 445 | + else: |
| 446 | + new_content = merged_body.lstrip("\n") |
| 447 | + else: |
| 448 | + # Default behavior: insert separate docstring |
| 449 | + new_content_parts = [] |
| 450 | + if file_prefix: |
| 451 | + new_content_parts.append(file_prefix) |
| 452 | + new_content_parts.append(final_header) |
| 453 | + new_content_parts.append(cleaned_body.strip()) |
| 454 | + # Use single newlines to test composition theory |
| 455 | + new_content = "\n".join(filter(None, new_content_parts)) |
402 | 456 |
|
403 | 457 | if new_content.strip() != original_content.strip(): |
404 | 458 | path.write_text(new_content, encoding="utf-8", newline="\n") |
|
0 commit comments