use tree_sitter::Language;
pub trait SupportedLanguage: Send + Sync {
fn name(&self) -> &'static str;
fn file_exts(&self) -> &'static [&'static str];
fn language(&self) -> Language;
fn query(&self, name: &str) -> String;
}
#[macro_export]
macro_rules! construct_language {
($name:ident($tslang:expr).[$($ext:ident)+]?=$query_name:ident->$query:literal ) => {
#[derive(Debug, Clone, Copy)]
pub struct $name;
impl SupportedLanguage for $name {
fn query(&self, $query_name: &str) -> String {
format!($query)
}
fn name(&self) -> &'static str {
stringify!($name)
}
fn file_exts(&self) -> &'static [&'static str] {
&[$(stringify!($ext)),+]
}
fn language(&self) -> Language {
$tslang
}
}
};
}
#[cfg(feature = "c")]
construct_language!(C(tree_sitter_c::language()).[c h]?=
name -> "((function_definition
declarator:
(function_declarator declarator: (identifier) @method-name))
@method-definition
(#eq? @method-name {name}))
((declaration declarator:
(function_declarator declarator: (identifier) @method-name))
@method-definition
(#eq? @method-name {name}))"
);
#[cfg(feature = "rust")]
construct_language!(Rust(tree_sitter_rust::language()).[rs]?=name->
"((function_item
name: (identifier) @method-name)
@method-definition
(#eq? @method-name {name}))
((let_declaration
pattern: (identifier) @method-name
value: (closure_expression)) @method-definition
(#eq? @method-name {name}))
((const_item
name: (identifier) @method-name
value: (closure_expression)) @method-definition
(#eq? @method-name {name}))
((static_item
name: (identifier) @method-name
value: (closure_expression)) @method-definition
(#eq? @method-name {name}))"
);
#[cfg(feature = "python")]
construct_language!(Python(tree_sitter_python::language()).[py]?=name->
"((function_definition
name: (identifier) @method-name)
@method-definition
(#eq? @method-name {name}))
((assignment
left: ((identifier) @method-name)
right: (lambda)) @method-definition
(#eq? @method-name {name}))
"
);
#[cfg(feature = "java")]
construct_language!(Java(tree_sitter_java::language()).[java]?=name->
"((method_declaration
name: (identifier) @method-name)
@method-definition
(#eq? @method-name {name}))
((local_variable_declaration
declarator: (variable_declarator
name: (identifier) @method-name
value: (lambda_expression)))
@method-definition
(#eq? @method-name {name}))
((field_declaration
declarator: (variable_declarator
name: (identifier) @method-name
value: (lambda_expression)))
@method-definition
(#eq? @method-name {name}))"
);
#[cfg(feature = "ocaml")]
construct_language!(OCaml(tree_sitter_ocaml::language_ocaml()).[ml]?=name->
"((value_definition
(let_binding pattern: (value_name) @method-name (parameter)))
@method-defintion
(#eq? @method-name {name}))
((value_definition
(let_binding pattern: (parenthesized_operator) @method-name (parameter)))
@method-defintion
(#eq? @method-name {name}))
((value_definition
(let_binding pattern: (value_name) @method-name body: (function_expression)))
@method-defintion
(#eq? @method-name {name}))
((value_definition
(let_binding pattern: (value_name) @method-name body: (fun_expression)))
@method-defintion
(#eq? @method-name {name}))");
#[must_use]
pub fn predefined_languages() -> &'static [&'static dyn SupportedLanguage] {
&[
#[cfg(feature = "rust")]
&Rust,
#[cfg(feature = "c")]
&C,
#[cfg(feature = "python")]
&Python,
#[cfg(feature = "java")]
&Java,
#[cfg(feature = "ocaml")]
&OCaml,
]
}