Files
Colby Mchenry bd993b12fa fix(extraction): index Python body docstrings across backends (#1905) (#2004)
* feat(extraction): index Python docstrings, not just preceding comments (#1905)

getPrecedingDocstring only walks preceding comment siblings, so a Python
docstring — a bare string literal first in the body — never reached the
docstring column, never entered nodes_fts, and was never shown by
`codegraph node`. The identical sentence written as a leading `#` comment was
both. For a Python codebase that is most of the prose there is. (#1905)

Adds an optional getBodyDocstring() to LanguageExtractor, in the same shape as
getSignature(), and routes every docstring call site through one docstringFor()
helper that consults both sources. A node carrying a comment AND a docstring
keeps both, joined: they are two things the author wrote about the same symbol
and the column is free text.

The Python implementation reads the grammar`s string_content rather than
slicing quotes off the raw text, so r/u/b prefixes and both triple-quote forms
work without a regex per case; f-strings are skipped because an interpolated
string is code, not prose. Dedent follows PEP 257 (first line exempt).

Scoped to Python deliberately. Julia (a string sibling before the def) and
Elixir (@doc) fit the same hook and are left as follow-ups.

* fix(extraction): index Python body docstrings across backends (#1905)

Python extraction only consulted preceding comments, leaving body docstrings absent from search and rendered prose.
Extend the contributor's hook to module and definition docstrings, and mirror it in the native kernel.
Handle comments, concatenated literals, and indentation consistently while rejecting bytes, f-strings, and tuples.
Verify persistence, exact-name ranking, MCP/CLI rendering, and native/WASM parity.

Co-authored-by: Max Hsu <maxmilian@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Max Hsu <maxmilian@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 12:32:27 +00:00

103 lines
1.8 KiB
Python

# Module header is not the module docstring.
(u"Ledger module " r"documentation.")
# Legacy reconciliation path.
@decorator
async def reconcile_ledger():
# A comment before the docstring is allowed.
"""Settle the nightly discrepancy with the bank."""
return 1
# Settle the nightly discrepancy with the bank.
def audit_ledger():
return 1
# Ledger class comment.
@decorator
class Ledger:
# Class body comment.
'''Post entries.
Preserve relative indentation:
details here.
'''
# Method comment.
@staticmethod
async def settle():
# Method body comment.
(U"Settle " # Between concatenated strings.
R"the ledger.")
return 1
def raw_doc():
R'''Raw \d+ expression.'''
return 1
def empty_concat():
"" "Kept prose." ""
return 1
def empty_doc():
""
return 1
def bytes_doc():
b"Not documentation."
return 1
def raw_bytes_doc():
BR"Not documentation."
return 1
def formatted_doc():
F"Not documentation."
return 1
def interpolated_doc():
rf"Not {documentation}."
return 1
def concatenated_bytes():
b"Not " b"documentation."
return 1
def concatenated_format():
"Not " f"documentation."
return 1
def late_string():
value = 1
"Not documentation."
return value
def computed_string():
"Not " + "documentation."
return 1
def tuple_string():
("Not documentation.",)
return 1
def bare_tuple():
"Not documentation.", "Also not."
return 1
def singleton_tuple():
"Not documentation.",
return 1
#
def blank_comment():
(("Kept despite blank comment."))
return 1
def nested_string():
if True:
"Not documentation."
return 1
def ranked_decoy():
"""reconcile_ledger reconcile_ledger reconcile_ledger"""
return 1