Problem
Two of the four function-slicing strategies in gitgalaxy/core/detector.py contain identical guards that cause nested/inner functions to be silently dropped:
Mode B (brace languages) — _slice_by_braces at line 1564:
start_idx = match.start()
if start_idx < last_end_idx:
continue
Mode C (indentation languages) — _slice_by_indentation at line 1693:
start_idx = match.start()
if start_idx < last_end_idx:
continue
last_end_idx tracks the end index of the previously accepted function match (set at line 1640 for braces, line 1733 for indentation).
Bug
A nested/inner function declaration (e.g. a Python function defined inside another function, or a JavaScript function expression assigned inside another function's body) necessarily starts before its enclosing function's end index. This guard causes it to always be skipped — it never becomes its own FunctionNode.
Consequence:
- The source text of the nested function is still included as part of the parent function's
block (so its complexity signals bleed into the parent's aggregate hit_vector/branch_count/etc.)
- But it is never counted, named, or reported as a distinct function
function_count is undercounted for any file using nested functions/closures
- Per-function complexity for the true innermost logic is invisible (merged into the outer function's numbers instead)
- Any future per-method analysis (e.g. LCOM within a class whose methods contain nested helper functions) would misattribute the nested function's behavior to the outer method
Example
def outer():
def inner(): # SILENTLY DROPPED — never becomes its own FunctionNode
return 42
return inner()
Detector sees:
- 1 function total (outer)
- Inner's branch/logic complexity merged into outer's hit_vector
Should see:
- 2 functions (outer, inner)
- Inner's metrics separate from outer
Fix Location
- Mode B (braces):
gitgalaxy/core/detector.py line 1564 guard + line 1640 last_end_idx update
- Mode C (indentation):
gitgalaxy/core/detector.py line 1693 guard + line 1733 last_end_idx update
- Mode A (labels/assembly) at line 1775+ does NOT have this guard and is not affected the same way
Fix Direction
The fix needs a proper nesting-depth-aware or stack-based scope tracker rather than the current flat "skip if inside previous match's span" approach. The guard exists specifically to prevent double-counting, but has the side effect of dropping real nested definitions entirely instead of counting them as their own (nested) function.
A correct approach would:
- Track the full nesting depth of each function's scope boundaries (not just flat "did it start after the previous one ended")
- Allow nested functions to be counted as distinct FunctionNodes with their own metrics
- Preserve the flat-scanning property (regex-based, no AST) while adding depth awareness
Affects
Mode B (C-family/brace languages): C, C++, C#, Java, JavaScript, TypeScript, Kotlin, Scala, Go, Rust, Swift, Objective-C, Groovy, etc.
Mode C (Python/YAML indentation languages): Python, Python embedded, YAML, etc.
These are the two most common parsing modes by volume of covered languages.
Problem
Two of the four function-slicing strategies in
gitgalaxy/core/detector.pycontain identical guards that cause nested/inner functions to be silently dropped:Mode B (brace languages) —
_slice_by_bracesat line 1564:Mode C (indentation languages) —
_slice_by_indentationat line 1693:last_end_idxtracks the end index of the previously accepted function match (set at line 1640 for braces, line 1733 for indentation).Bug
A nested/inner function declaration (e.g. a Python function defined inside another function, or a JavaScript function expression assigned inside another function's body) necessarily starts before its enclosing function's end index. This guard causes it to always be skipped — it never becomes its own
FunctionNode.Consequence:
block(so its complexity signals bleed into the parent's aggregatehit_vector/branch_count/etc.)function_countis undercounted for any file using nested functions/closuresExample
Detector sees:
Should see:
Fix Location
gitgalaxy/core/detector.pyline 1564 guard + line 1640last_end_idxupdategitgalaxy/core/detector.pyline 1693 guard + line 1733last_end_idxupdateFix Direction
The fix needs a proper nesting-depth-aware or stack-based scope tracker rather than the current flat "skip if inside previous match's span" approach. The guard exists specifically to prevent double-counting, but has the side effect of dropping real nested definitions entirely instead of counting them as their own (nested) function.
A correct approach would:
Affects
Mode B (C-family/brace languages): C, C++, C#, Java, JavaScript, TypeScript, Kotlin, Scala, Go, Rust, Swift, Objective-C, Groovy, etc.
Mode C (Python/YAML indentation languages): Python, Python embedded, YAML, etc.
These are the two most common parsing modes by volume of covered languages.