use super::*;
const COMMENTS: &[&str] = &["comment"];
fn doc(ts: &TreeSitterAdapter, i: usize) -> Option<String> {
preceding_comments(ts, i, COMMENTS, &[], |_| true)
}
fn declarator_leaf(ts: &TreeSitterAdapter, start: usize) -> Option<usize> {
let mut i = field_child(ts, start, "declarator")?;
loop {
if matches!(
ts.nodes()[i].kind,
"identifier" | "field_identifier" | "type_identifier"
) {
return Some(i);
}
if let Some(d) = field_child(ts, i, "declarator") {
i = d;
} else if ts.nodes()[i].kind.ends_with("_declarator")
&& ts.nodes()[i].children.len() == 1
{
i = ts.nodes()[i].children[0].0 as usize;
} else {
return None;
}
}
}
fn chained_name(ts: &TreeSitterAdapter, i: usize) -> Option<String> {
declarator_leaf(ts, i).map(|l| ts.text(quarb::NodeId(l as u64)).to_string())
}
fn chained_params(ts: &TreeSitterAdapter, i: usize) -> Option<i64> {
let mut d = field_child(ts, i, "declarator")?;
loop {
if ts.nodes()[d].kind == "function_declarator" {
return field_child(ts, d, "parameters").map(|p| count_params(ts, p));
}
d = field_child(ts, d, "declarator")?;
}
}
fn specifier(ts: &TreeSitterAdapter, i: usize) -> Option<Lowered> {
let name = field_text(ts, i, "name")?;
field_child(ts, i, "body")?;
Some(Lowered {
construct: "type",
name: Some(name),
traits: TYPE,
signature: None,
doc: doc(ts, i),
callee: None,
n_params: None,
})
}
pub(crate) fn lower_node(ts: &TreeSitterAdapter, i: usize) -> Option<Lowered> {
match ts.nodes()[i].kind {
"function_definition" => Some(Lowered {
construct: "function",
name: chained_name(ts, i),
traits: FUNCTION,
signature: signature(ts, i),
doc: doc(ts, i),
callee: None,
n_params: chained_params(ts, i),
}),
"struct_specifier" | "enum_specifier" | "union_specifier" => specifier(ts, i),
"type_definition" => Some(Lowered {
construct: "type",
name: chained_name(ts, i),
traits: TYPE,
signature: None,
doc: doc(ts, i),
callee: None,
n_params: None,
}),
"enumerator" => Some(Lowered {
construct: "field",
name: field_text(ts, i, "name"),
traits: NONE,
signature: None,
doc: None,
callee: None,
n_params: None,
}),
"field_declaration" => Some(Lowered {
construct: "field",
name: chained_name(ts, i),
traits: NONE,
signature: None,
doc: doc(ts, i),
callee: None,
n_params: None,
}),
"preproc_def" | "preproc_function_def" => Some(Lowered {
construct: "constant",
name: field_text(ts, i, "name"),
traits: NONE,
signature: None,
doc: doc(ts, i),
callee: None,
n_params: None,
}),
"preproc_include" => Some(Lowered::anon("import", IMPORT)),
"if_statement" => Some(Lowered::anon("if", CONDITIONAL)),
"else_clause" => Some(Lowered::anon("else", NONE)),
"switch_statement" => Some(Lowered::anon("switch", CONDITIONAL)),
"for_statement" => Some(Lowered::anon("for", LOOP)),
"while_statement" | "do_statement" => Some(Lowered::anon("while", LOOP)),
"call_expression" => Some(Lowered {
callee: field_text(ts, i, "function"),
..Lowered::anon("call", CALL)
}),
_ => None,
}
}