use tree_sitter::Node;
use crate::core::signatures::{compact_params, Signature};
use super::super::helpers::{clean_return_type, field_text, has_named_child, strip_parens};
pub(crate) fn kotlin_function(node: &Node, name: &str, source: &[u8]) -> Signature {
let mut params = String::new();
let mut ret = String::new();
let mut seen_params = false;
let mut cursor = node.walk();
for child in node.children(&mut cursor) {
if child.kind() == "function_value_parameters" {
params = child.utf8_text(source).unwrap_or("").to_string();
seen_params = true;
} else if seen_params && child.kind() == "type" {
ret = child.utf8_text(source).unwrap_or("").to_string();
ret = ret.trim_start_matches(':').trim().to_string();
break;
}
}
let is_method = node.start_position().column > 0;
let exported = kotlin_modifiers_text(node, source).is_none_or(|t| !t.contains("private"));
Signature {
kind: if is_method { "method" } else { "fn" },
name: name.to_string(),
params: compact_params(&strip_parens(¶ms)),
return_type: clean_return_type(&ret),
is_async: false,
is_exported: exported,
indent: if is_method { 2 } else { 0 },
..Signature::no_span()
}
}
fn kotlin_modifiers_text<'a>(node: &Node, source: &'a [u8]) -> Option<&'a str> {
let mut cursor = node.walk();
for c in node.children(&mut cursor) {
if c.kind() == "modifiers" {
return c.utf8_text(source).ok();
}
}
None
}
pub(crate) fn kotlin_declaration_exported(node: &Node, source: &[u8]) -> bool {
kotlin_modifiers_text(node, source).is_none_or(|t| !t.contains("private"))
}
pub(crate) fn swift_function(node: &Node, name: &str, source: &[u8]) -> Signature {
let ret = field_text(node, "return_type", source);
let params = swift_parameters_before_body(node, source);
let is_async = has_named_child(node, "async");
let is_method = node.start_position().column > 0;
Signature {
kind: if is_method { "method" } else { "fn" },
name: name.to_string(),
params: compact_params(&strip_parens(¶ms)),
return_type: clean_return_type(&ret),
is_async,
is_exported: true,
indent: if is_method { 2 } else { 0 },
..Signature::no_span()
}
}
pub(crate) fn swift_protocol_function(node: &Node, name: &str, source: &[u8]) -> Signature {
let ret = field_text(node, "return_type", source);
Signature {
kind: "fn",
name: name.to_string(),
params: String::new(),
return_type: clean_return_type(&ret),
is_async: has_named_child(node, "async"),
is_exported: true,
indent: 2,
..Signature::no_span()
}
}
pub(crate) fn swift_class_declaration(node: &Node, name: &str, source: &[u8]) -> Signature {
let kind = node
.child_by_field_name("declaration_kind")
.and_then(|n| n.utf8_text(source).ok())
.unwrap_or("class");
let kind_static: &'static str = match kind {
"struct" => "struct",
"enum" => "enum",
_ => "class",
};
Signature {
kind: kind_static,
name: name.to_string(),
params: String::new(),
return_type: String::new(),
is_async: false,
is_exported: true,
indent: 0,
..Signature::no_span()
}
}
fn swift_parameters_before_body(node: &Node, source: &[u8]) -> String {
let end_byte = node
.child_by_field_name("body")
.map_or(usize::MAX, |b| b.start_byte());
let mut parts: Vec<String> = Vec::new();
fn walk(n: &Node, end_byte: usize, source: &[u8], parts: &mut Vec<String>) {
if n.start_byte() >= end_byte {
return;
}
if n.kind() == "parameter" {
if let Ok(t) = n.utf8_text(source) {
parts.push(t.to_string());
}
}
let mut c = n.walk();
for child in n.children(&mut c) {
if child.start_byte() < end_byte {
walk(&child, end_byte, source, parts);
}
}
}
walk(node, end_byte, source, &mut parts);
if parts.is_empty() {
String::new()
} else {
format!("({})", parts.join(", "))
}
}
pub(crate) fn csharp_has_modifier_text(node: &Node, needle: &str, source: &[u8]) -> bool {
let mut cursor = node.walk();
for c in node.children(&mut cursor) {
if c.kind() == "modifier" {
if let Ok(t) = c.utf8_text(source) {
if t.contains(needle) {
return true;
}
}
}
}
false
}