use tree_sitter::{Node, Tree};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ImportedName {
Default,
Namespace,
Named(String),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BindingKind {
Const,
Let,
Var,
Param,
Function,
Class,
CatchParam,
Assignment,
Loop,
ContextManager,
Comprehension,
}
impl BindingKind {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::Const => "const",
Self::Let => "let",
Self::Var => "var",
Self::Param => "param",
Self::Function => "function",
Self::Class => "class",
Self::CatchParam => "catch-param",
Self::Assignment => "assignment",
Self::Loop => "loop",
Self::ContextManager => "context-manager",
Self::Comprehension => "comprehension",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Binding {
Import {
module: String,
name: ImportedName,
},
Local(BindingKind),
}
impl Binding {
#[must_use]
pub const fn kind_str(&self) -> &'static str {
match self {
Self::Import { .. } => "import",
Self::Local(kind) => kind.as_str(),
}
}
}
pub trait BindingResolver: Send + Sync {
fn resolve(&self, tree: &Tree, source: &str, node: Node<'_>) -> Option<Binding>;
fn is_shadowed(&self, tree: &Tree, source: &str, node: Node<'_>) -> bool;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn binding_kinds_render_as_rules_write_them() {
assert_eq!(BindingKind::Const.as_str(), "const");
assert_eq!(BindingKind::Param.as_str(), "param");
assert_eq!(BindingKind::CatchParam.as_str(), "catch-param");
}
#[test]
fn imports_report_as_import_regardless_of_which_export() {
for name in [
ImportedName::Default,
ImportedName::Namespace,
ImportedName::Named("a".to_owned()),
] {
let binding = Binding::Import {
module: "m".to_owned(),
name,
};
assert_eq!(binding.kind_str(), "import");
}
}
#[test]
fn local_bindings_report_their_own_kind() {
assert_eq!(Binding::Local(BindingKind::Const).kind_str(), "const");
assert_eq!(Binding::Local(BindingKind::Function).kind_str(), "function");
}
}