diff --git a/apps/minds/changelog/mngr-inline-fn-ratchet-doublecount.md b/apps/minds/changelog/mngr-inline-fn-ratchet-doublecount.md new file mode 100644 index 0000000000..aa71714a3b --- /dev/null +++ b/apps/minds/changelog/mngr-inline-fn-ratchet-doublecount.md @@ -0,0 +1 @@ +Re-trimmed the inline-function ratchet count from 9 to 7 after a shared-checker bug fix stopped double-counting a doubly-nested function. No minds source changed; the two removed counts were the same function counted once per enclosing function. diff --git a/apps/minds/imbue/minds/test_ratchets.py b/apps/minds/imbue/minds/test_ratchets.py index 31f1d3f5a2..0fd3a2a2bb 100644 --- a/apps/minds/imbue/minds/test_ratchets.py +++ b/apps/minds/imbue/minds/test_ratchets.py @@ -365,7 +365,7 @@ def test_prevent_inline_functions() -> None: # ported Sentry HTTP transport's ``_send_request`` (it closes over the # envelope being sent). The recorded count reflects the actual finder count # for the current tree. - rc.check_inline_functions(_DIR, snapshot(9)) + rc.check_inline_functions(_DIR, snapshot(7)) def test_prevent_underscore_imports() -> None: diff --git a/libs/imbue_common/changelog/mngr-inline-fn-ratchet-doublecount.md b/libs/imbue_common/changelog/mngr-inline-fn-ratchet-doublecount.md new file mode 100644 index 0000000000..a273047d20 --- /dev/null +++ b/libs/imbue_common/changelog/mngr-inline-fn-ratchet-doublecount.md @@ -0,0 +1 @@ +Fixed the inline-function ratchet (`find_inline_functions`) double-counting a function nested two or more levels deep. It walked every `FunctionDef` in a file, including nested ones, and descended into all of each one's descendants, so a function with two enclosing functions was emitted once per ancestor. The recorded count therefore overstated the real number of inline functions. Nested defs are now collected keyed by source position and counted once. Only projects that actually nest functions two deep are affected; across the whole monorepo the sole recorded count that changes is `apps/minds` (from 9 to 7 before any code change). diff --git a/libs/imbue_common/imbue/imbue_common/ratchet_testing/ratchets.py b/libs/imbue_common/imbue/imbue_common/ratchet_testing/ratchets.py index 02639a02aa..bc40588cda 100644 --- a/libs/imbue_common/imbue/imbue_common/ratchet_testing/ratchets.py +++ b/libs/imbue_common/imbue/imbue_common/ratchet_testing/ratchets.py @@ -235,24 +235,29 @@ def find_inline_functions( for file_path in file_paths: func_def_nodes = get_ast_nodes_of_type(file_path, ast.FunctionDef) + # ast.walk from every FunctionDef reaches a function nested N deep once per + # ancestor, so collect the nested defs keyed by source position to count each once. + nested_by_position: dict[tuple[int, int], ast.FunctionDef] = {} for node in func_def_nodes: - # Walk within each FunctionDef to find nested functions for inner_node in ast.walk(node): if inner_node is not node and isinstance(inner_node, ast.FunctionDef): - # Skip decorator wrapper functions that use @functools.wraps - if _has_functools_wraps_decorator(inner_node): - continue + nested_by_position[(inner_node.lineno, inner_node.col_offset)] = inner_node - start_line = LineNumber(inner_node.lineno) - end_line = LineNumber(inner_node.end_lineno if inner_node.end_lineno else inner_node.lineno) + for inner_node in nested_by_position.values(): + # Skip decorator wrapper functions that use @functools.wraps + if _has_functools_wraps_decorator(inner_node): + continue - chunk = RatchetMatchChunk( - file_path=file_path, - matched_content=f"inline function '{inner_node.name}' at line {start_line}", - start_line=start_line, - end_line=end_line, - ) - chunks.append(chunk) + start_line = LineNumber(inner_node.lineno) + end_line = LineNumber(inner_node.end_lineno if inner_node.end_lineno else inner_node.lineno) + + chunk = RatchetMatchChunk( + file_path=file_path, + matched_content=f"inline function '{inner_node.name}' at line {start_line}", + start_line=start_line, + end_line=end_line, + ) + chunks.append(chunk) sorted_chunks = sorted(chunks, key=lambda c: (str(c.file_path), c.start_line)) return tuple(sorted_chunks)