use syn::visit::{self, Visit};
use crate::classify::AbsVisEdit;
struct PathFixer {
mod_depth: usize,
edits: Vec<AbsVisEdit>,
}
impl<'ast> Visit<'ast> for PathFixer {
fn visit_item_mod(&mut self, m: &'ast syn::ItemMod) {
self.mod_depth += 1;
visit::visit_item_mod(self, m);
self.mod_depth -= 1;
}
fn visit_visibility(&mut self, _v: &'ast syn::Visibility) {}
fn visit_attribute(&mut self, _a: &'ast syn::Attribute) {}
fn visit_item_use(&mut self, u: &'ast syn::ItemUse) {
if self.mod_depth == 0 {
if let syn::UseTree::Path(p) = &u.tree {
let range = p.ident.span().byte_range();
match p.ident.to_string().as_str() {
"super" => self.edits.push(AbsVisEdit {
start: range.start,
end: range.start,
text: "super::".into(),
}),
"self" => self.edits.push(AbsVisEdit {
start: range.start,
end: range.end,
text: "super".into(),
}),
_ => {}
}
}
}
visit::visit_item_use(self, u);
}
fn visit_path(&mut self, p: &'ast syn::Path) {
if self.mod_depth == 0 && p.leading_colon.is_none() && p.segments.len() >= 2 {
let first = &p.segments[0].ident;
let range = first.span().byte_range();
match first.to_string().as_str() {
"super" => self.edits.push(AbsVisEdit {
start: range.start,
end: range.start,
text: "super::".into(),
}),
"self" => self.edits.push(AbsVisEdit {
start: range.start,
end: range.end,
text: "super".into(),
}),
_ => {}
}
}
visit::visit_path(self, p);
}
}
pub fn relative_path_edits(item: &syn::Item) -> Vec<AbsVisEdit> {
let mut fixer = PathFixer { mod_depth: 0, edits: Vec::new() };
fixer.visit_item(item);
fixer.edits
}