Skip to content

Commit c7df450

Browse files
committed
Refactor ModResolver.directory
Make it so the field is only modified through a with_directory function so that it is easier to follow.
1 parent 21f353a commit c7df450

File tree

1 file changed

+44
-27
lines changed

1 file changed

+44
-27
lines changed

src/modules.rs

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,11 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
225225
item: &'c ast::Item,
226226
sub_mod: Module<'ast>,
227227
) -> Result<(), ModuleResolutionError> {
228-
let old_directory = self.directory.clone();
229228
let sub_mod_kind = self.peek_sub_mod(item, &sub_mod)?;
230229
if let Some(sub_mod_kind) = sub_mod_kind {
231230
self.insert_sub_mod(sub_mod_kind.clone())?;
232231
self.visit_sub_mod_inner(sub_mod, sub_mod_kind)?;
233232
}
234-
self.directory = old_directory;
235233
Ok(())
236234
}
237235

@@ -288,33 +286,35 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
288286
path: mod_path.parent().unwrap().to_path_buf(),
289287
ownership: directory_ownership,
290288
};
291-
self.visit_sub_mod_after_directory_update(sub_mod, Some(directory))
289+
self.with_directory(directory, |this| {
290+
this.visit_sub_mod_after_directory_update(sub_mod)
291+
})?;
292292
}
293293
SubModKind::Internal(item) => {
294-
self.push_inline_mod_directory(item.ident, &item.attrs);
295-
self.visit_sub_mod_after_directory_update(sub_mod, None)
294+
let directory = self.inline_mod_directory(item.ident, &item.attrs);
295+
self.with_directory(directory, |this| {
296+
this.visit_sub_mod_after_directory_update(sub_mod)
297+
})?;
296298
}
297299
SubModKind::MultiExternal(mods) => {
298300
for (mod_path, directory_ownership, sub_mod) in mods {
299301
let directory = Directory {
300302
path: mod_path.parent().unwrap().to_path_buf(),
301303
ownership: directory_ownership,
302304
};
303-
self.visit_sub_mod_after_directory_update(sub_mod, Some(directory))?;
305+
self.with_directory(directory, |this| {
306+
this.visit_sub_mod_after_directory_update(sub_mod)
307+
})?;
304308
}
305-
Ok(())
306309
}
307310
}
311+
Ok(())
308312
}
309313

310314
fn visit_sub_mod_after_directory_update(
311315
&mut self,
312316
sub_mod: Module<'ast>,
313-
directory: Option<Directory>,
314317
) -> Result<(), ModuleResolutionError> {
315-
if let Some(directory) = directory {
316-
self.directory = directory;
317-
}
318318
match (sub_mod.ast_mod_kind, sub_mod.items) {
319319
(Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _))), _) => {
320320
self.visit_mod_from_ast(items)
@@ -470,10 +470,12 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
470470
}
471471
}
472472

473-
fn push_inline_mod_directory(&mut self, id: symbol::Ident, attrs: &[ast::Attribute]) {
473+
fn inline_mod_directory(&mut self, id: symbol::Ident, attrs: &[ast::Attribute]) -> Directory {
474474
if let Some(path) = find_path_value(attrs) {
475-
self.directory.path.push(path.as_str());
476-
self.directory.ownership = DirectoryOwnership::Owned { relative: None };
475+
Directory {
476+
path: self.directory.path.join(path.as_str()),
477+
ownership: DirectoryOwnership::Owned { relative: None },
478+
}
477479
} else {
478480
let id = id.as_str();
479481
// We have to push on the current module name in the case of relative
@@ -482,19 +484,28 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
482484
//
483485
// For example, a `mod z { ... }` inside `x/y.rs` should set the current
484486
// directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
485-
if let DirectoryOwnership::Owned { relative } = &mut self.directory.ownership {
486-
if let Some(ident) = relative.take() {
487-
// remove the relative offset
488-
self.directory.path.push(ident.as_str());
489-
490-
// In the case where there is an x.rs and an ./x directory we want
491-
// to prevent adding x twice. For example, ./x/x
492-
if self.directory.path.exists() && !self.directory.path.join(id).exists() {
493-
return;
494-
}
487+
let new_path = if let DirectoryOwnership::Owned {
488+
relative: Some(ident),
489+
} = self.directory.ownership
490+
{
491+
// remove the relative offset
492+
let relative = self.directory.path.join(ident.as_str());
493+
let nested = relative.join(id);
494+
495+
// In the case where there is an x.rs and an ./x directory we want
496+
// to prevent adding x twice. For example, ./x/x
497+
if relative.exists() && !nested.exists() {
498+
relative
499+
} else {
500+
nested
495501
}
502+
} else {
503+
self.directory.path.join(id)
504+
};
505+
Directory {
506+
path: new_path,
507+
ownership: self.directory.ownership,
496508
}
497-
self.directory.path.push(id);
498509
}
499510
}
500511

@@ -512,8 +523,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
512523
}
513524
let mut result = vec![];
514525
for path in path_visitor.paths() {
515-
let mut actual_path = self.directory.path.clone();
516-
actual_path.push(&path);
526+
let actual_path = self.directory.path.join(path);
517527
if !actual_path.exists() {
518528
continue;
519529
}
@@ -546,6 +556,13 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
546556
}
547557
result
548558
}
559+
560+
fn with_directory<T>(&mut self, directory: Directory, f: impl FnOnce(&mut Self) -> T) -> T {
561+
let old = std::mem::replace(&mut self.directory, directory);
562+
let out = f(self);
563+
self.directory = old;
564+
out
565+
}
549566
}
550567

551568
fn path_value(attr: &ast::Attribute) -> Option<Symbol> {

0 commit comments

Comments
 (0)