mun_hir/code_model/
module.rs1use super::{Function, Package, Struct, TypeAlias};
2use crate::ids::{ItemDefinitionId, ModuleId};
3use crate::primitive_type::PrimitiveType;
4use crate::{DiagnosticSink, FileId, HirDatabase, Name};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
7pub struct Module {
8 pub(crate) id: ModuleId,
9}
10
11impl From<ModuleId> for Module {
12 fn from(id: ModuleId) -> Self {
13 Module { id }
14 }
15}
16
17impl Module {
18 pub fn from_file(db: &dyn HirDatabase, file: FileId) -> Option<Module> {
20 Package::all(db)
21 .iter()
22 .flat_map(|package| package.modules(db))
23 .find(|m| m.file_id(db) == Some(file))
24 }
25
26 pub fn parent(self, db: &dyn HirDatabase) -> Option<Module> {
28 let module_tree = db.module_tree(self.id.package);
29 let parent_id = module_tree[self.id.local_id].parent?;
30 Some(Module {
31 id: ModuleId {
32 package: self.id.package,
33 local_id: parent_id,
34 },
35 })
36 }
37
38 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
40 let module_tree = db.module_tree(self.id.package);
41 let parent = module_tree[self.id.local_id].parent?;
42 module_tree[parent]
43 .children
44 .iter()
45 .find_map(|(name, module_id)| {
46 if *module_id == self.id.local_id {
47 Some(name.clone())
48 } else {
49 None
50 }
51 })
52 }
53
54 pub fn file_id(self, db: &dyn HirDatabase) -> Option<FileId> {
56 db.module_tree(self.id.package).modules[self.id.local_id].file
57 }
58
59 pub fn declarations(self, db: &dyn HirDatabase) -> Vec<ModuleDef> {
61 let package_defs = db.package_defs(self.id.package);
62 package_defs.modules[self.id.local_id]
63 .declarations()
64 .map(ModuleDef::from)
65 .collect()
66 }
67
68 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
70 let package_defs = db.package_defs(self.id.package);
72 package_defs.add_diagnostics(db.upcast(), self.id.local_id, sink);
73
74 if let Some(file_id) = self.file_id(db) {
76 let item_tree = db.item_tree(file_id);
77 for diagnostics in item_tree.diagnostics.iter() {
78 diagnostics.add_to(db, &item_tree, sink);
79 }
80 }
81
82 for decl in self.declarations(db) {
84 match decl {
85 ModuleDef::Function(f) => f.diagnostics(db, sink),
86 ModuleDef::Struct(s) => s.diagnostics(db, sink),
87 ModuleDef::TypeAlias(t) => t.diagnostics(db, sink),
88 _ => (),
89 }
90 }
91 }
92
93 pub fn children(self, db: &dyn HirDatabase) -> Vec<Module> {
95 let module_tree = db.module_tree(self.id.package);
96 module_tree[self.id.local_id]
97 .children
98 .iter()
99 .map(|(_, local_id)| Module {
100 id: ModuleId {
101 package: self.id.package,
102 local_id: *local_id,
103 },
104 })
105 .collect()
106 }
107
108 pub fn path_to_root(self, db: &dyn HirDatabase) -> Vec<Module> {
110 let mut res = vec![self];
111 let mut curr = self;
112 while let Some(next) = curr.parent(db) {
113 res.push(next);
114 curr = next
115 }
116 res
117 }
118
119 pub fn full_name(self, db: &dyn HirDatabase) -> String {
121 itertools::Itertools::intersperse(
122 self.path_to_root(db)
123 .iter()
124 .filter_map(|&module| module.name(db))
125 .map(|name| name.to_string()),
126 String::from("::"),
127 )
128 .collect()
129 }
130}
131
132#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
133pub enum ModuleDef {
134 Module(Module),
135 Function(Function),
136 PrimitiveType(PrimitiveType),
137 Struct(Struct),
138 TypeAlias(TypeAlias),
139}
140
141impl From<Function> for ModuleDef {
142 fn from(t: Function) -> Self {
143 ModuleDef::Function(t)
144 }
145}
146
147impl From<PrimitiveType> for ModuleDef {
148 fn from(t: PrimitiveType) -> Self {
149 ModuleDef::PrimitiveType(t)
150 }
151}
152
153impl From<Struct> for ModuleDef {
154 fn from(t: Struct) -> Self {
155 ModuleDef::Struct(t)
156 }
157}
158
159impl From<TypeAlias> for ModuleDef {
160 fn from(t: TypeAlias) -> Self {
161 ModuleDef::TypeAlias(t)
162 }
163}
164
165impl From<Module> for ModuleDef {
166 fn from(m: Module) -> Self {
167 ModuleDef::Module(m)
168 }
169}
170
171impl From<ItemDefinitionId> for ModuleDef {
172 fn from(id: ItemDefinitionId) -> Self {
173 match id {
174 ItemDefinitionId::ModuleId(id) => Module { id }.into(),
175 ItemDefinitionId::FunctionId(id) => Function { id }.into(),
176 ItemDefinitionId::StructId(id) => Struct { id }.into(),
177 ItemDefinitionId::TypeAliasId(id) => TypeAlias { id }.into(),
178 ItemDefinitionId::PrimitiveType(id) => id.into(),
179 }
180 }
181}