pub static AST_SHORTHANDS: &[(&str, &str)] = &[
("loops", "for_expression,while_expression,loop_expression"),
("conditionals", "if_expression,match_expression,match_arm"),
(
"functions",
"function_item,closure_expression,async_function_item",
),
(
"declarations",
"struct_item,enum_item,let_declaration,const_item,static_item,type_alias_item",
),
("unsafe", "unsafe_block"),
("types", "struct_item,enum_item,type_alias_item,union_item"),
("macros", "macro_invocation,macro_definition,macro_rule"),
("mods", "mod_item"),
("traits", "trait_item,trait_impl_item"),
("impls", "impl_item"),
];
#[derive(Debug, Clone)]
pub struct LanguageNodeKinds {
pub language: &'static str,
pub loops: &'static [&'static str],
pub conditionals: &'static [&'static str],
pub functions: &'static [&'static str],
pub declarations: &'static [&'static str],
}
pub static PYTHON_NODE_KINDS: LanguageNodeKinds = LanguageNodeKinds {
language: "python",
loops: &["for_statement", "while_statement"],
conditionals: &["if_statement", "match_statement"],
functions: &["function_definition", "lambda", "async_function_definition"],
declarations: &["class_definition", "type_alias_statement"],
};
pub static JAVASCRIPT_NODE_KINDS: LanguageNodeKinds = LanguageNodeKinds {
language: "javascript",
loops: &[
"for_statement",
"for_in_statement",
"for_of_statement",
"while_statement",
"do_statement",
],
conditionals: &["if_statement", "switch_statement", "catch_clause"],
functions: &[
"function_declaration",
"function_expression",
"arrow_function",
"generator_function_declaration",
"generator_function_expression",
],
declarations: &[
"class_declaration",
"class_expression",
"variable_declaration",
"type_alias_declaration",
],
};
pub static TYPESCRIPT_NODE_KINDS: LanguageNodeKinds = LanguageNodeKinds {
language: "typescript",
loops: &[
"for_statement",
"for_in_statement",
"for_of_statement",
"while_statement",
"do_statement",
],
conditionals: &["if_statement", "switch_statement", "catch_clause"],
functions: &[
"function_declaration",
"function_expression",
"arrow_function",
"generator_function_declaration",
"generator_function_expression",
],
declarations: &[
"class_declaration",
"class_expression",
"variable_declaration",
"type_alias_declaration",
"interface_declaration",
"enum_declaration",
],
};
pub fn get_supported_languages() -> &'static [&'static str] {
&["rust", "python", "javascript", "typescript"]
}
pub fn get_node_kinds_for_language(language: &str, category: &str) -> Option<Vec<String>> {
let kinds = match language.to_lowercase().as_str() {
"python" => {
let mapping = &PYTHON_NODE_KINDS;
match category.to_lowercase().as_str() {
"loops" => mapping.loops,
"conditionals" => mapping.conditionals,
"functions" => mapping.functions,
"declarations" => mapping.declarations,
_ => return None,
}
}
"javascript" => {
let mapping = &JAVASCRIPT_NODE_KINDS;
match category.to_lowercase().as_str() {
"loops" => mapping.loops,
"conditionals" => mapping.conditionals,
"functions" => mapping.functions,
"declarations" => mapping.declarations,
_ => return None,
}
}
"typescript" => {
let mapping = &TYPESCRIPT_NODE_KINDS;
match category.to_lowercase().as_str() {
"loops" => mapping.loops,
"conditionals" => mapping.conditionals,
"functions" => mapping.functions,
"declarations" => mapping.declarations,
_ => return None,
}
}
_ => return None,
};
Some(kinds.iter().map(|s| s.to_string()).collect())
}
pub fn expand_shorthand(input: &str) -> String {
let normalized = input.trim().to_lowercase();
for &(shorthand, expansion) in AST_SHORTHANDS {
if normalized == shorthand {
return expansion.to_string();
}
}
input.to_string()
}
pub fn expand_shorthands(input: &str) -> Vec<String> {
let mut result = std::collections::HashSet::new();
for part in input.split(',') {
let part = part.trim();
if part.is_empty() {
continue;
}
let expanded = expand_shorthand(part);
for kind in expanded.split(',') {
let kind = kind.trim();
if !kind.is_empty() {
result.insert(kind.to_string());
}
}
}
let mut kinds: Vec<String> = result.into_iter().collect();
kinds.sort();
kinds
}
pub fn expand_shorthand_with_language(shorthand: &str, language: Option<&str>) -> Vec<String> {
let normalized = shorthand.trim().to_lowercase();
if let Some(lang) = language {
let lang_lower = lang.to_lowercase();
if let Some(kinds) = get_node_kinds_for_language(&lang_lower, &normalized) {
return kinds;
}
}
let expanded = expand_shorthand(&normalized);
expanded.split(',').map(|s| s.trim().to_string()).collect()
}