1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
use std::{
path::{PathBuf},
};
use libsyntax2::{
ast::{self, AstNode, NameOwner},
SyntaxNode, ParsedFile, SmolStr,
};
use {FileId, FileResolver};
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct ModuleId(FileId);
#[derive(Clone, Debug, Default)]
pub struct ModuleMap {
links: Vec<Link>,
}
#[derive(Clone, Debug)]
struct Link {
owner: ModuleId,
syntax: SyntaxNode,
points_to: Vec<ModuleId>,
}
impl ModuleMap {
pub fn update_file(
&mut self,
file_id: FileId,
syntax: Option<&ParsedFile>,
file_resolver: &FileResolver,
) {
let mod_id = ModuleId(file_id);
self.links.retain(|link| link.owner != mod_id);
match syntax {
None => {
for link in self.links.iter_mut() {
link.points_to.retain(|&x| x != mod_id);
}
}
Some(syntax) => {
self.links.extend(
syntax.ast().modules().filter_map(|it| {
Link::new(mod_id, it)
})
)
}
}
self.links.iter_mut().for_each(|link| {
link.resolve(file_resolver)
})
}
pub fn module2file(&self, m: ModuleId) -> FileId {
m.0
}
pub fn file2module(&self, file_id: FileId) -> ModuleId {
ModuleId(file_id)
}
pub fn child_module_by_name(&self, parent_mod: ModuleId, child_mod: &str) -> Vec<ModuleId> {
self.links
.iter()
.filter(|link| link.owner == parent_mod)
.filter(|link| link.name() == child_mod)
.filter_map(|it| it.points_to.first())
.map(|&it| it)
.collect()
}
pub fn parent_modules<'a>(&'a self, m: ModuleId) -> impl Iterator<Item=(ModuleId, ast::Module<'a>)> + 'a {
self.links
.iter()
.filter(move |link| link.points_to.iter().any(|&it| it == m))
.map(|link| {
(link.owner, link.ast())
})
}
}
impl Link {
fn new(owner: ModuleId, module: ast::Module) -> Option<Link> {
if module.name().is_none() {
return None;
}
let link = Link {
owner,
syntax: module.syntax().owned(),
points_to: Vec::new(),
};
Some(link)
}
fn name(&self) -> SmolStr {
self.ast().name()
.unwrap()
.text()
}
fn ast(&self) -> ast::Module {
ast::Module::cast(self.syntax.borrowed())
.unwrap()
}
fn resolve(&mut self, file_resolver: &FileResolver) {
let name = self.name();
let paths = &[
PathBuf::from(format!("../{}.rs", name)),
PathBuf::from(format!("../{}/mod.rs", name)),
];
self.points_to = paths.iter()
.filter_map(|path| file_resolver(self.owner.0, path))
.map(ModuleId)
.collect();
}
}
|