use std::collections::BTreeSet;
use linkrs_core::types::expr::visitor::ExpressionVisitor;
use linkrs_core::Expression;
#[derive(Debug, Clone, Default)]
pub struct CollectedRefs {
pub props: Vec<(String, String)>,
pub full_vars: BTreeSet<String>,
}
impl CollectedRefs {
pub fn visit(expr: &Expression) -> Self {
let mut collector = RefCollector::default();
collector.visit(expr);
collector.into()
}
}
#[derive(Debug, Default)]
struct RefCollector {
props: Vec<(String, String)>,
full_vars: BTreeSet<String>,
}
impl ExpressionVisitor for RefCollector {
fn visit_property(&mut self, object: &Expression, property: &str) {
match object {
Expression::Variable(var) => {
self.props.push((var.clone(), property.to_string()));
}
other => self.visit(other),
}
}
fn visit_struct_field(&mut self, base: &Expression, field: &str) {
match base {
Expression::Variable(var) => {
self.props.push((var.clone(), field.to_string()));
}
other => self.visit(other),
}
}
fn visit_tag_property(&mut self, tag_name: &str, property: &str) {
self.props
.push((tag_name.to_string(), property.to_string()));
}
fn visit_edge_property(&mut self, edge_name: &str, property: &str) {
self.props
.push((edge_name.to_string(), property.to_string()));
}
fn visit_variable(&mut self, name: &str) {
self.full_vars.insert(name.to_string());
}
}
impl From<RefCollector> for CollectedRefs {
fn from(collector: RefCollector) -> Self {
Self {
props: collector.props,
full_vars: collector.full_vars,
}
}
}