Version: codebase-memory-mcp v0.8.1
Project: real-world repo, 93,315 nodes
Summary
The recursion detector appears to flag a function as self-recursive whenever its body contains a call whose bare name equals the function's own name — ignoring the receiver. This makes super().method() overrides and same-named delegating wrappers false positives. In our repo, every unguarded_recursion=true node also has self_recursive=true, and a large fraction are not recursive at all.
Repro
MATCH (f:Function) WHERE f.unguarded_recursion = true RETURN f.name, f.qualified_name, f.file_path, f.self_recursive
(and the same for :Method). Representative false positives:
| node |
actual body |
why it's not recursion |
ConsumerAddress.save, ProductPriceHistory.save, PurchaseOrderV2.save |
super().save(*args, **kwargs) |
calls the parent class method |
MPApiError.__init__, CloudAIExhausted.__init__ |
super().__init__(...) |
parent ctor |
StoreAdmin.get_queryset, MerchantCompanyAdmin.get_queryset |
super().get_queryset(...) |
parent method |
*.setUp, DecimalEncoder.default |
super().setUp() / super().default(o) |
parent method |
ApiClient.get/post/put (TS) |
return this.request('GET', …) / axios.get(…) |
different receiver |
console-style error/warn wrappers |
console.error(…) |
different receiver |
minified bundle ids e,Vo,Ii (lines=1) |
minified |
not analyzable |
Minimal example
class Order(models.Model):
def save(self, *a, **k):
self.full_clean()
super().save(*a, **k) # parent call — flagged as self-recursion today
class ApiClient {
get(url: string) { return axios.get(url); } // flagged as self-recursion today
}
Expected
- A call is self-recursion only when it resolves to the same function/method (same receiver / same class binding), not by bare name.
- Specifically:
super().X() is a parent-class call and must never count as recursion of X.
- Calls on a different object (
axios.get, this.request, console.error) must not count.
Bonus (likely same subsystem)
transitive_loop_depth saturates to an impossible 174 on many unrelated functions (e.g. whatsapp_webhook, several mains) — looks like the interprocedural propagation doesn't break cycles and saturates. Worth checking alongside the recursion resolver.
Impact
unguarded_recursion and transitive_loop_depth are currently unusable as-is for hot-path/risk triage on Python/TS codebases (super() overrides are everywhere).
Version: codebase-memory-mcp v0.8.1
Project: real-world repo, 93,315 nodes
Summary
The recursion detector appears to flag a function as self-recursive whenever its body contains a call whose bare name equals the function's own name — ignoring the receiver. This makes
super().method()overrides and same-named delegating wrappers false positives. In our repo, everyunguarded_recursion=truenode also hasself_recursive=true, and a large fraction are not recursive at all.Repro
MATCH (f:Function) WHERE f.unguarded_recursion = true RETURN f.name, f.qualified_name, f.file_path, f.self_recursive(and the same for
:Method). Representative false positives:ConsumerAddress.save,ProductPriceHistory.save,PurchaseOrderV2.savesuper().save(*args, **kwargs)MPApiError.__init__,CloudAIExhausted.__init__super().__init__(...)StoreAdmin.get_queryset,MerchantCompanyAdmin.get_querysetsuper().get_queryset(...)*.setUp,DecimalEncoder.defaultsuper().setUp()/super().default(o)ApiClient.get/post/put(TS)return this.request('GET', …)/axios.get(…)console-styleerror/warnwrappersconsole.error(…)e,Vo,Ii(lines=1)Minimal example
Expected
super().X()is a parent-class call and must never count as recursion ofX.axios.get,this.request,console.error) must not count.Bonus (likely same subsystem)
transitive_loop_depthsaturates to an impossible 174 on many unrelated functions (e.g.whatsapp_webhook, severalmains) — looks like the interprocedural propagation doesn't break cycles and saturates. Worth checking alongside the recursion resolver.Impact
unguarded_recursionandtransitive_loop_depthare currently unusable as-is for hot-path/risk triage on Python/TS codebases (super() overrides are everywhere).