#![allow(clippy::no_effect_underscore_binding)]
use ascent::ascent;
use log::{debug, info};
use rustdoc_types::Crate;
use super::item::{is_enum, is_relevant, is_struct, is_struct_unit};
use super::node::{CrateNode, ItemNode, SummaryNode};
ascent! {
#![measure_rule_times]
pub struct Filter;
relation item(ItemNode);
relation summary(SummaryNode);
relation ext_crate(CrateNode);
relation has_summary(ItemNode, SummaryNode);
has_summary(i, s) <-- item(i), summary(s), if i.has_summary(s);
relation is_struct(ItemNode);
is_struct(s) <-- item(s) if is_struct(&s.item);
relation is_enum(ItemNode);
is_enum(e) <-- item(e) if is_enum(&e.item);
relation variant(ItemNode, ItemNode);
variant(e, v) <-- is_enum(e), item(v) if e.has_variant(v);
relation field(ItemNode, ItemNode);
field(s, f) <-- is_struct(s), item(f) if s.has_field(f);
field(v, f) <-- variant(e, v), item(f) if v.has_field(f);
relation local_type_of(ItemNode, ItemNode);
local_type_of(f, t) <-- item(f), item(t) if f.is_of_local_type(t);
relation remote_type_of(ItemNode, SummaryNode);
remote_type_of(f, t) <-- item(f), summary(t) if f.is_of_remote_type(t);
relation app(ItemNode, ItemNode);
app(imp, app) <--
is_struct(app),
item(imp),
if imp.is_impl_for(app, "App");
relation parent(ItemNode, ItemNode);
parent(parent, child) <--
app(_, parent),
app(_, child),
field(parent, field),
local_type_of(field, child);
relation root_app(ItemNode, ItemNode);
root_app(impl_, app) <--
app(impl_, app),
!parent(_, app);
relation view_model(ItemNode, ItemNode);
view_model(app, view_model) <--
root_app(impl_, app),
local_type_of(item, view_model),
if impl_.has_associated_item(item, "ViewModel");
relation event(ItemNode, ItemNode);
event(app, event) <--
root_app(impl_, app),
local_type_of(item, event),
if impl_.has_associated_item(item, "Event");
relation effect(ItemNode, ItemNode);
effect(app, effect_ffi) <--
root_app(app_impl, app),
is_enum(effect),
item(effect_impl),
if effect_impl.is_impl_for(effect, "Effect"),
has_summary(app, app_summary),
has_summary(effect, effect_summary),
if app_summary.in_same_module_as(effect_summary),
local_type_of(effect_ffi_item, effect_ffi),
if effect_impl.has_associated_item(effect_ffi_item, "Ffi");
relation operation(ItemNode, ItemNode);
operation(op_impl, op) <--
is_struct(op),
item(op_impl),
if op_impl.is_impl_for(op, "Operation");
operation(op_impl, op) <--
is_enum(op),
item(op_impl),
if op_impl.is_impl_for(op, "Operation");
relation output(ItemNode);
output(out) <--
operation(op_impl, op),
local_type_of(item, out),
if op_impl.has_associated_item(item, "Output");
relation root(ItemNode);
root(x) <-- view_model(app, x);
root(x) <-- event(app, x);
root(x) <-- effect(app, x);
root(x) <-- operation(op_impl, x);
root(x) <-- output(x);
relation edge(ItemNode, ItemNode);
edge(root, root) <--
root(root),
is_struct(root), if is_struct_unit(&root.item);
edge(root, field) <--
root(root),
field(root, field);
edge(root, variant) <--
root(root),
variant(root, variant);
edge(type_, field) <--
edge(_, type_),
field(type_, field);
edge(type_, variant) <--
edge(_, type_),
variant(type_, variant);
edge(field, type_) <--
edge(_, field),
local_type_of(field, type_);
relation crates(String);
crates(n) <--
ext_crate(c),
edge(a, b),
remote_type_of(b, s),
if s.points_to_crate(c),
let n = &c.crate_.name;
}
impl Filter {
pub fn process(&mut self, crate_name: &str, crate_: &Crate) {
info!("Updating filter for {crate_name}");
self.summary = crate_
.paths
.iter()
.map(|(id, summary)| {
(SummaryNode::new(
crate_name.to_string(),
id.0,
summary.clone(),
),)
})
.collect::<Vec<_>>();
self.item = crate_
.index
.values()
.filter_map(|item| {
if is_relevant(item) {
Some((ItemNode::new(crate_name.to_string(), item.clone()),))
} else {
None
}
})
.collect::<Vec<_>>();
self.ext_crate = crate_
.external_crates
.iter()
.map(|(id, crate_)| (CrateNode::new(crate_name.to_string(), *id, crate_.clone()),))
.collect::<Vec<_>>();
self.run();
debug!("{}", self.scc_times_summary());
}
pub fn get_crates(&self) -> Vec<String> {
self.crates.iter().map(|(crate_,)| crate_.clone()).collect()
}
}
#[cfg(test)]
#[path = "filter_tests.rs"]
mod filter_tests;