feat(kernel): R7b Ruby walker — ruby module, tree-sitter-ruby 0.23.1 bump, ref-flag wire slot, ruby default-routed (#1379)
Third R7b port, checklist-first recipe (docs/design/ruby-kernel-port-checklist.md). Grammar bump first, validated standalone (the rust pattern): tree-sitter-ruby ^0.20.1 (tree-sitter-wasms, 2024-02) → v0.23.1 — crate pinned =0.23.1, wasm built from tag 71bd32f's checked-in parser.c/scanner.c (both sha-matched against the crates.io tarball; content bump, ABI stays 14). Old-vs-new full-init dumps: sinatra/jekyll byte-identical; rails = exactly the one classified hunk (the `recv&.!=` safe-nav operator misparse fix, `table_name.!` → `table_name.!=`, precision-positive). Walker (python.rs chassis + the six ruby divergences) preserves bug-for-bug: the importTypes:['call'] funnel (class-body DSL — attr_accessor, has_many, define_method incl. its block, sinatra route blocks — emits NOTHING at non-body scope), hook-handled module multiply-capture (nested modules re-scan their subtree per level after popping — `this.hooked` fn-refs from class AND module AND file), the sibling-scan visibility trio (bare `private` invisible; `private :sym`/`private def` poison all later defs; the inner def stays public), bare-call statements (do…end body_statement emits, brace-block block_body doesn't), `.new` instantiates with last-`::`-segment names, constant-receiver references refs, require/require_relative path refs (posix-normalized, `.rb`-suffixed, `Kernel.require` and interpolated-path quirks included), `=begin` docstring marker survival, and the reverse-order value-ref DFS. Wire v2: the hook's mixin `implements` refs carry `filePath: ctx.filePath` — the ONE extraction-ref denormalized field (php's trait-use refs share the shape). RefRow's first pad byte becomes a flags slot (REF_FLAG_FILE_PATH); decode re-attaches its own filePath parameter; KERNEL_ABI_VERSION 1→2 on both sides (mismatched dist/.node pairs degrade to wasm, as designed). Gates: sweeps 0-diff sinatra 147/147, jekyll 164/164, rails 3452/3452 (3,763 files, 0 deferrals — ruby error incidence 0.00%, any deferral = walker bug); full-init dumps byte-identical ×3 (7.2k/9.4k/375.6k lines); kernel-ruby-parity suite (torture + CRLF + wire-flag pin + defer) + ruby grammar-parity row; full suite 2,613 green ×2 under CODEGRAPH_KERNEL_EXPECT=1 (one unrelated mcp-initialize timing flake under parallel load, passes solo 3/3 ×3). DEFAULT_ROUTED += ruby (12 langs). Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
286e9ccc2d
commit
1909931238
@@ -57,14 +57,18 @@
|
||||
//! ref row (40 bytes):
|
||||
//! 0 u32 fromNode row index (NONE → use fromNodeIdStr)
|
||||
//! 4 u8 ReferenceKind (EDGE_KINDS index, or 200 = function_ref)
|
||||
//! 5 [3] pad
|
||||
//! 5 u8 flags — bit 0: ref carries the extracting file's path (v2; the
|
||||
//! ruby/php visitNode hooks set `filePath: ctx.filePath` on their
|
||||
//! mixin/trait `implements` refs — decode re-attaches the decode
|
||||
//! call's own filePath, which is byte-identical)
|
||||
//! 6 [2] pad
|
||||
//! 8 u32 line (1-based)
|
||||
//! 12 u32 column (0-based)
|
||||
//! 16 str referenceName
|
||||
//! 24 str candidates (NUL-joined list)
|
||||
//! 32 str fromNodeIdStr
|
||||
|
||||
pub const KERNEL_ABI_VERSION: u8 = 1;
|
||||
pub const KERNEL_ABI_VERSION: u8 = 2;
|
||||
pub const NONE: u32 = 0xFFFF_FFFF;
|
||||
|
||||
pub const META_SIZE: usize = 36;
|
||||
@@ -117,6 +121,9 @@ pub const EDGE_KINDS: [&str; 12] = [
|
||||
/// ReferenceKind code for the internal-only `function_ref` (#756).
|
||||
pub const FUNCTION_REF_CODE: u8 = 200;
|
||||
|
||||
/// Ref-row flag bit 0: the ref carries `filePath` = the extracted file.
|
||||
pub const REF_FLAG_FILE_PATH: u8 = 1;
|
||||
|
||||
pub fn node_kind_index(kind: &str) -> Option<u8> {
|
||||
NODE_KINDS.iter().position(|k| *k == kind).map(|i| i as u8)
|
||||
}
|
||||
@@ -303,10 +310,15 @@ impl Tables {
|
||||
}
|
||||
|
||||
pub fn push_ref(&mut self, r: &RefRow) {
|
||||
self.push_ref_flagged(r, 0);
|
||||
}
|
||||
|
||||
pub fn push_ref_flagged(&mut self, r: &RefRow, flags: u8) {
|
||||
let buf = &mut self.refs;
|
||||
buf.extend_from_slice(&r.from_idx.to_le_bytes());
|
||||
buf.push(r.kind);
|
||||
buf.extend_from_slice(&[0u8; 3]); // pad
|
||||
buf.push(flags);
|
||||
buf.extend_from_slice(&[0u8; 2]); // pad
|
||||
buf.extend_from_slice(&r.line.to_le_bytes());
|
||||
buf.extend_from_slice(&r.column.to_le_bytes());
|
||||
push_str_ref(buf, r.reference_name);
|
||||
|
||||
@@ -15,8 +15,10 @@ use tree_sitter::Language;
|
||||
|
||||
/// Languages this kernel binary can extract (reported by contractInfo;
|
||||
/// TS-side routing policy decides what actually routes).
|
||||
pub const LANGUAGES: [&str; 11] =
|
||||
["typescript", "tsx", "javascript", "jsx", "java", "python", "go", "c", "cpp", "rust", "csharp"];
|
||||
pub const LANGUAGES: [&str; 12] = [
|
||||
"typescript", "tsx", "javascript", "jsx", "java", "python", "go", "c", "cpp", "rust",
|
||||
"csharp", "ruby",
|
||||
];
|
||||
|
||||
pub fn grammar_for(language: &str) -> Option<Language> {
|
||||
match language {
|
||||
@@ -36,6 +38,9 @@ pub fn grammar_for(language: &str) -> Option<Language> {
|
||||
// R7b: 0.23.5, table-identical to the vendored ABI-15 wasm (#717;
|
||||
// verified against the crates.io tarball — csharp checklist header).
|
||||
"csharp" => Some(tree_sitter_c_sharp::LANGUAGE.into()),
|
||||
// R7b: v0.23.1, sha-matched with the vendored wasm (grammars.ts).
|
||||
// Content bump only — the tag's parser.c is still ABI 14.
|
||||
"ruby" => Some(tree_sitter_ruby::LANGUAGE.into()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ mod ids;
|
||||
mod go;
|
||||
mod java;
|
||||
mod langs;
|
||||
mod ruby;
|
||||
mod rustlang;
|
||||
mod textutil;
|
||||
mod python;
|
||||
@@ -215,6 +216,7 @@ pub fn extract_file(file_path: String, content: String, language: String) -> Res
|
||||
"c" | "cpp" => ccpp::extract(&file_path, &content, &language).map_err(Error::from_reason)?,
|
||||
"rust" => rustlang::extract(&file_path, &content).map_err(Error::from_reason)?,
|
||||
"csharp" => csharp::extract(&file_path, &content).map_err(Error::from_reason)?,
|
||||
"ruby" => ruby::extract(&file_path, &content).map_err(Error::from_reason)?,
|
||||
_ => tsjs::extract(&file_path, &content, &language).map_err(Error::from_reason)?,
|
||||
};
|
||||
Ok(ExtractBuffers {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user