feat(code-graph): type-flow resolution and ast-driven walking for ssa

What does this MR do and why?

Part of #456 (closed), #457 (closed). Depends on !887 (merged), Relates to orbit#3 (closed). Extends the v2 code graph pipeline with three major capabilities: AST-driven SSA construction per Braun et al., type-flow chain resolution for Java/Kotlin, and expression chain extraction/resolution for multi-hop method calls.


AST-driven SSA walker (Braun et al. CC 2013)

The DSL parser now retains the tree-sitter AST. The FileWalker walks it inline, creating SSA blocks for branches, loops, and scopes exactly as the paper describes:

  • Branch arms get separate blocks, merging at a join point with phi nodes
  • Loop headers are unsealed until the back-edge is added, then sealed
  • Nested branches propagate correctly (inner merges flow to outer merges)

This replaced an earlier flat walker (byte-range heuristics) with the paper's actual protocol — net negative lines.

Type-flow chain resolution

ChainMode::TypeFlow is now functional for Java/Kotlin. When a variable has a declared type or is assigned from a method with return_type metadata, member access chains resolve through the type hierarchy:

// 4-hop chain — each step resolves via return_type
pool.getConnection().getDb().execute().fetchAll();

// Implicit this — bare helper() resolves as this.helper()
helper();

// super — resolves through parent class
super.baseMethod();

// Return type propagation through binding
UserService svc = getService();  // getService returns UserService
svc.query();                     // resolves to UserService.query

ExpressionStep chain extraction

References with receivers produce structured ExpressionStep chains instead of flat name strings. The chain builder is fully language-agnostic — driven by per-language ChainConfig (ident node kinds, this/super kinds, field access patterns, constructor patterns). The resolver walks chains left-to-right, threading the resolved type through each step, with compound SSA key fallback for Python instance attributes.

What's new

  • MemberIndex with super_types BFS for inherited member lookup
  • ResolutionRules holds Option<LanguageSpec> — single source of truth, no config duplication
  • instance_attr_prefixes on BindingRuleself.X written to class scope
  • ReceiverExtract (Field / FieldChain) on ReferenceRule
  • ChainConfig on LanguageSpec for chain building
  • extract_rhs_name unwraps call expressions via language spec rules
  • Java: field_declaration, catch_formal_parameter, switch_statement, ternary_expression
  • Kotlin: companion_objectDefKind::Class, ChainConfig
  • Python: ChainConfig, receiver_chain for attribute calls

Test coverage — 38/38 suites passing

  • 9 conditional binding tests (if/else phi, try/except, trivial collapse, nested, elif, reassignment-kills-phi, no-else, false positives, no-duplicates invariant)
  • 10 Java type-flow tests (typed locals, inheritance, this, super, implicit this, return type propagation, chained calls, 4-hop deep chain, diamond inheritance, cross-contamination check)
  • 2 Java cross-file type-flow tests
  • 3 Python expression chain tests (value-flow alias, cross-file import chain)
  • All 35 original suites still passing
Edited by Michael Usachenko

Merge request reports

Loading