3131 * C++ — extraction is correct (regression guards).
3232 * Rust — impl_traits array (not base_classes) is the capture point; Rust
3333 * rows verify impl_traits entries for `impl Trait for Struct`.
34+ * Ruby — green as of the fix that accompanies these rows: the
35+ * `superclass` wrapper's `constant` / `scope_resolution` child is
36+ * now matched, so `class C < Base` no longer falls through to the
37+ * raw-text fallback and stores "< Base".
3438 *
3539 * STRUCTURE
3640 * ─────────
@@ -1658,6 +1662,69 @@ TEST(inherit_rust_impls) {
16581662 PASS ();
16591663}
16601664
1665+ /* ═══════════════════════════════════════════════════════════════════
1666+ * RUBY (expected: GREEN — regression guards for the fix in this PR)
1667+ *
1668+ * Root cause fixed here: tree-sitter-ruby wraps `class C < Base` in a
1669+ * `superclass` node whose child is a `constant` (or `scope_resolution`
1670+ * for `A::B`). collect_bases_from_field() matched neither, so the
1671+ * raw-text fallback stored the whole field text "< Base" — operator
1672+ * included — and a base name spelled that way never resolves, so Ruby
1673+ * subclasses produced zero INHERITS edges.
1674+ *
1675+ * Every row therefore also asserts "<" never appears inside a captured
1676+ * base name: that substring IS the bug's signature.
1677+ * ═══════════════════════════════════════════════════════════════════ */
1678+
1679+ static const inherit_case_t ruby_cases [] = {
1680+ /* ── single bare-constant superclass ────────────────────────── */
1681+ {CBM_LANG_RUBY ,
1682+ "m.rb" ,
1683+ "class Animal\nend\n\nclass Dog < Animal\nend\n" ,
1684+ "Dog" ,
1685+ {"Animal" , NULL },
1686+ {"<" , NULL },
1687+ 1 },
1688+ /* ── scope-resolved superclass (A::B) ───────────────────────── */
1689+ {CBM_LANG_RUBY ,
1690+ "m.rb" ,
1691+ "class ApplicationRecord < ActiveRecord::Base\nend\n" ,
1692+ "ApplicationRecord" ,
1693+ {"ActiveRecord::Base" , NULL },
1694+ {"<" , NULL },
1695+ 1 },
1696+ /* ── the Rails chain's second link (bare, resolves to the above) ─ */
1697+ {CBM_LANG_RUBY ,
1698+ "m.rb" ,
1699+ "class ApplicationRecord < ActiveRecord::Base\nend\n"
1700+ "class User < ApplicationRecord\nend\n" ,
1701+ "User" ,
1702+ {"ApplicationRecord" , NULL },
1703+ {"<" , NULL },
1704+ 1 },
1705+ /* ── subclass declared inside a module body ─────────────────── */
1706+ {CBM_LANG_RUBY ,
1707+ "m.rb" ,
1708+ "class Base\nend\n\nmodule Admin\n class Panel < Base\n end\nend\n" ,
1709+ "Panel" ,
1710+ {"Base" , NULL },
1711+ {"<" , NULL },
1712+ 1 },
1713+ /* ── exception subclass (stdlib superclass) ─────────────────── */
1714+ {CBM_LANG_RUBY ,
1715+ "m.rb" ,
1716+ "class AppError < StandardError\nend\n" ,
1717+ "AppError" ,
1718+ {"StandardError" , NULL },
1719+ {"<" , NULL },
1720+ 1 },
1721+ };
1722+
1723+ TEST (inherit_ruby ) {
1724+ RUN_CASES (ruby_cases );
1725+ PASS ();
1726+ }
1727+
16611728/* ═══════════════════════════════════════════════════════════════════
16621729 * SUITE declaration
16631730 * ═══════════════════════════════════════════════════════════════════ */
@@ -1668,6 +1735,7 @@ SUITE(extraction_inheritance) {
16681735 RUN_TEST (inherit_csharp );
16691736 RUN_TEST (inherit_cpp );
16701737 RUN_TEST (inherit_rust_impls );
1738+ RUN_TEST (inherit_ruby );
16711739
16721740 /* Languages expected RED (broken extractors — reproduce-first) */
16731741 RUN_TEST (inherit_python ); /* RED: identifier-node not matched in collect_bases_from_field */
0 commit comments