Follow-ups from the automated review of the first commit:
- Two same-named nested types under different outers in one file share one
node id. That node took the first declaration's type_path and could join
the other outer's halves; it now gets no type_path and is not merged.
- The shadowed-base step drops only a placeholder spelled with the bare
name. A base written qualified (Other.IFoo), or through a using alias of
that name, can be a different type that only shares the simple name, and
keeps its edge.
- Pin that receiver-qualified calls (base.M(), this.M(), Type.M(), obj.M())
keep their targets: they leave the cross-file pass as member calls before
the own-type binding.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
(cherry picked from commit 37ec971f16)
The partial merge grouped halves by (namespace, label) and skipped nested
types, because nested ids omit the enclosing type. A nested partial type split
across files stayed split, and `Box` / `Box<T>` partials were folded into one
node although they are distinct types (#4249).
- The C# extractor records each partial type's path inside its namespace,
enclosing types first, each with its arity (`Outer`1.Inner`), as
metadata.type_path; the merge keys on (assembly, namespace, type_path).
- The cross-file call pass binds a C# unqualified call to the one candidate
that is a member of the caller's own type, so a call into another half of a
partial type is not lost to a same-named method elsewhere (#4252 does this
in-file only). Ties fall through unchanged.
- After C# type resolution, a merged partial type drops a placeholder base
that sits next to a real base of the same name; one half resolving a sibling
nested base and the other not left two bases, and base-chain lookups failed.
- _AST_CACHE_SCHEMA 8 -> 9, so cached C# results without type_path are
re-extracted.
Fixes#4363.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
(cherry picked from commit 92d9197787)
_merge_csharp_partial_class_nodes rewrote every edge in the corpus and
dropped every self-loop, so one partial class split across two files
erased recursive calls in every language of the repo. It also deduped
edges it never rewrote, on a key that ignores confidence and context.
Keep edges the merge does not remap verbatim (the Swift extension merge
rule, #2538) and drop a self-loop only when two distinct endpoints
collapse into one node (the deduplicate_entities rule, #3809), so a
pre-existing self-loop on a merged-away half is rewired, not lost.
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 5992044f32)
#2411 (thanks @JensD-git): key the C# partial-class merge on assembly
(nearest ancestor .csproj/.fsproj/.vbproj) in addition to namespace and
name, so same-name partial classes in different assemblies stay distinct
while genuine partial halves within one project still merge. Fixes a
0.9.32 regression from #2332.
#2437/#2438 (thanks @aryanbonigala, builds on PR #2439): incremental
rebuilds no longer drop member-call and indirect_call edges from a
changed file into an unchanged target. Re-resolution now sees the
unchanged corpus (nodes, contains/method edges, and _callable markers,
which now persist to graph.json like _origin); edges to a genuinely
removed target are still evicted.
#2444/#2445 (thanks @Baziar, builds on PRs #2461/#2458): a
BrokenProcessPool triggers the sequential fallback instead of being
swallowed per future, a failed worker file is retried sequentially
rather than merged as empty, and a whole-pass AST failure on a fresh
build exits non-zero instead of writing a zero-node graph
(--allow-partial opts into a best-effort partial graph).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- C# receivers declared inline via out-var / is / case / switch-arm patterns
are now typed into the per-method table, so their member calls resolve (#2346).
- partial class halves across files now merge to one class node (new
_merge_csharp_partial_class_nodes pass, mirroring the Swift-extension merge),
so cross-half member calls resolve instead of splitting the class (#2332).
- Kotlin anonymous-object (object : Foo {}) members now get nodes, contains/
implements edges, and their calls resolve (#2347).
All in-corpus only, never a wrong edge.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>