Skip to content

fix(csharp): emit INHERITS edges from base_list clause#582

Draft
Saeed-Nourizadeh wants to merge 3 commits into
tirth8205:mainfrom
Saeed-Nourizadeh:fix/csharp-inherits-base-list
Draft

fix(csharp): emit INHERITS edges from base_list clause#582
Saeed-Nourizadeh wants to merge 3 commits into
tirth8205:mainfrom
Saeed-Nourizadeh:fix/csharp-inherits-base-list

Conversation

@Saeed-Nourizadeh

Copy link
Copy Markdown

Problem

C# classes produce zero INHERITS edges. _get_bases() handles C# in the shared java/kotlin/csharp branch, which only looks for superclass / super_interfaces / delegation_specifier nodes. The tree-sitter-csharp grammar emits none of those — it wraps a class's : Base, IFace clause in a single base_list node. So the branch never matches and C# inheritance is lost: inheritors_of / get_impact_radius return empty for .cs files.

Reproduced on a real 1,527-file / 440K-LoC C# codebase (SplendidCRM): 0 INHERITS edges before, 1,373 after this fix (top bases that were previously invisible: framework base classes like SplendidControl with 440 subclasses, page bases, System.Web.Services.WebService, etc.).

Fix

Give C# its own branch in _get_bases() that drills into base_list for the named base-type children — identifier, qualified_name, generic_name — and stores the bare type name (skipping the leading : and commas). Kotlin keeps its existing handling; Java is unaffected. This mirrors the approach in #278 (Java) and the C++ base_class_clause branch.

public class CachedRepo : InMemoryRepo, IRepository   ->  INHERITS: InMemoryRepo, IRepository
public class DisposableService : System.IDisposable   ->  INHERITS: System.IDisposable  (qualified_name preserved)
public class UserList : List<User>                     ->  INHERITS: List<User>          (generic_name preserved)

Tests

  • Extends tests/fixtures/Sample.cs with extends + implements, a qualified base (System.IDisposable) and a generic base (List<User>).
  • Adds test_finds_inheritance and test_inheritance_target_is_bare_name to TestCSharpParsing (asserts targets are bare type names — no leading :, no comma-joined clauses).
  • pytest tests/test_multilang.py -k "CSharp or Java or Kotlin" → 23 passed (no regression). ruff check clean.

tree-sitter-csharp wraps a class's `: Base, IFace` clause in a base_list
node. _get_bases() handled C# in the shared java/kotlin branch, which only
looks for superclass/super_interfaces nodes the C# grammar never emits, so
every C# class produced zero INHERITS edges and inheritors_of /
get_impact_radius returned empty for .cs files.

Adds a csharp-specific branch that drills into base_list for the named
base-type children (identifier / qualified_name / generic_name), extracting
bare type names. Kotlin retains its existing handling.

Extends tests/fixtures/Sample.cs with extends + implements, a qualified base
(System.IDisposable) and a generic base (List<User>), and adds inheritance
assertions to TestCSharpParsing.
@Saeed-Nourizadeh Saeed-Nourizadeh marked this pull request as draft June 25, 2026 16:29
…raint safety

- Parse record_declaration / record_struct_declaration as C# class-like nodes
  so record inheritance reaches _get_bases().
- Broaden the csharp base_list extraction to iterate *named* base entries
  (robust across grammar versions: identifier / qualified_name / generic_name /
  alias_qualified_name / type), and handle positional-record
  primary_constructor_base_type by taking its type (dropping the (args)).
  Generic constraints (where T : Base) live outside base_list and are never
  captured.
- Tests: add record + interface, positional record, struct, nested-qualified
  generic base, and a constraint-non-capture assertion.
…ng types

- Skip argument_list children of base_list: `class C(int x) : Base(x)` lists the
  ctor args `(x)` as a named sibling of the base type; it must not become an
  INHERITS target.
- Return no bases for enum_declaration: `enum E : byte` carries the underlying
  storage type in base_list, which is not inheritance.
- Tests: primary-constructor class (assert base only, no '(args)') and enum
  underlying type (assert no edge).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant