Files
oh-my-pi/crates/pi-natives/src/chunk/ast_ruby_lua.rs
T
can1357 79cbd1ed47 refactor(chunk): migrated chunk naming to type-safe ChunkKind enum
- Replaced string-based chunk naming with type-safe ChunkKind enum across 35+ AST classifier modules.
- Refactored ChunkNode to use optional identifier and ChunkKind instead of name string for semantic clarity.
- Created new kind.rs module with ChunkKind enum (150+ variants) and trait-based metadata system.
- Removed string prefix-based chunk type detection and replaced with ChunkKind enum matching throughout.
- Updated chunk API signatures to accept ChunkKind and optional identifier instead of formatted names.
2026-04-08 11:49:12 +02:00

139 lines
3.9 KiB
Rust

//! Language-specific chunk classifiers for Ruby and Lua.
use tree_sitter::Node;
use super::{classify::LangClassifier, common::*, kind::ChunkKind};
pub struct RubyLuaClassifier;
impl LangClassifier for RubyLuaClassifier {
fn preserve_root_wrapper(&self, kind: &str) -> bool {
kind == "module"
}
fn classify_root<'t>(&self, node: Node<'t>, source: &str) -> Option<RawChunkCandidate<'t>> {
Some(match node.kind() {
// ── Imports ──
"command" | "call" => {
// Ruby `require`/`require_relative` appear as call/command nodes.
// Check if the target is an import keyword.
let target = extract_identifier(node, source);
match target.as_deref() {
Some("require" | "require_relative" | "load" | "autoload") => {
group_candidate(node, ChunkKind::Imports, source)
},
_ => group_candidate(node, ChunkKind::Statements, source),
}
},
// ── Functions ──
"function_definition" => named_candidate(
node,
ChunkKind::Function,
source,
recurse_body(node, ChunkContext::FunctionBody),
),
"method" | "singleton_method" => named_candidate(
node,
ChunkKind::Function,
source,
recurse_body(node, ChunkContext::FunctionBody),
),
// ── Containers ──
"class" => container_candidate(node, ChunkKind::Class, source, recurse_class(node)),
"module" => container_candidate(node, ChunkKind::Module, source, recurse_class(node)),
// ── Control flow (top-level scripts) ──
"if_statement" | "unless" | "while_statement" | "for_statement" => {
return Some(
self
.classify_function(node, source)
.unwrap_or_else(|| group_candidate(node, ChunkKind::Statements, source)),
);
},
// ── Assignments ──
"assignment" => group_candidate(node, ChunkKind::Declarations, source),
// ── Statements ──
"expression_statement" | "function_call" => {
group_candidate(node, ChunkKind::Statements, source)
},
_ => return None,
})
}
fn classify_class<'t>(&self, node: Node<'t>, source: &str) -> Option<RawChunkCandidate<'t>> {
Some(match node.kind() {
// ── Methods ──
"method" | "singleton_method" => {
let name = extract_identifier(node, source).unwrap_or_else(|| "anonymous".to_string());
if name == "initialize" {
make_kind_chunk(
node,
ChunkKind::Constructor,
None,
source,
recurse_body(node, ChunkContext::FunctionBody),
)
} else {
make_kind_chunk(
node,
ChunkKind::Function,
Some(name),
source,
recurse_body(node, ChunkContext::FunctionBody),
)
}
},
// ── Nested containers ──
"class" => container_candidate(node, ChunkKind::Class, source, recurse_class(node)),
"module" => container_candidate(node, ChunkKind::Module, source, recurse_class(node)),
// ── Fields / constants ──
"assignment" => group_candidate(node, ChunkKind::Fields, source),
// ── Calls (include, attr_reader, etc.) and bare identifiers (private) ──
"call" | "command" | "identifier" => group_candidate(node, ChunkKind::Statements, source),
_ => return None,
})
}
fn classify_function<'t>(&self, node: Node<'t>, source: &str) -> Option<RawChunkCandidate<'t>> {
let fn_recurse = || recurse_body(node, ChunkContext::FunctionBody);
Some(match node.kind() {
// ── Control flow ──
"if_statement" | "unless" => {
make_candidate(node, ChunkKind::If, None, NameStyle::Named, None, fn_recurse(), source)
},
"case_statement" | "case_match" => make_candidate(
node,
ChunkKind::Switch,
None,
NameStyle::Named,
None,
fn_recurse(),
source,
),
"while_statement" | "for_statement" => make_candidate(
node,
ChunkKind::Loop,
None,
NameStyle::Named,
None,
fn_recurse(),
source,
),
// ── Variables ──
"assignment" => group_candidate(node, ChunkKind::Statements, source),
_ => return None,
})
}
}