Skip to content

Commit 61a764f

Browse files
committed
Refactor ModResolver.directory
Prefer replacing with a new function with_directory rather than modifying in place.
1 parent b213f3b commit 61a764f

File tree

1 file changed

+46
-43
lines changed

1 file changed

+46
-43
lines changed

src/modules.rs

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -182,13 +182,11 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
182182
item: &'c ast::Item,
183183
sub_mod: Module<'_>,
184184
) -> Result<(), ModuleResolutionError> {
185-
let old_directory = self.directory.clone();
186185
let sub_mod_kind = self.peek_sub_mod(item, &sub_mod)?;
187186
if let Some(sub_mod_kind) = sub_mod_kind {
188187
self.insert_sub_mod(sub_mod_kind.clone())?;
189188
self.visit_sub_mod_inner(sub_mod, sub_mod_kind)?;
190189
}
191-
self.directory = old_directory;
192190
Ok(())
193191
}
194192

@@ -245,34 +243,23 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
245243
path: mod_path.parent().unwrap().to_path_buf(),
246244
ownership: directory_ownership,
247245
};
248-
self.visit_sub_mod_after_directory_update(sub_mod, Some(directory))
246+
self.with_directory(directory, |this| this.visit_mod(&sub_mod.items))?;
249247
}
250248
SubModKind::Internal(item) => {
251-
self.push_inline_mod_directory(item.ident, &item.attrs);
252-
self.visit_sub_mod_after_directory_update(sub_mod, None)
249+
let directory = self.inline_mod_directory(item.ident, &item.attrs);
250+
self.with_directory(directory, |this| this.visit_mod(&sub_mod.items))?;
253251
}
254252
SubModKind::MultiExternal(mods) => {
255253
for (mod_path, directory_ownership, sub_mod) in mods {
256254
let directory = Directory {
257255
path: mod_path.parent().unwrap().to_path_buf(),
258256
ownership: directory_ownership,
259257
};
260-
self.visit_sub_mod_after_directory_update(sub_mod, Some(directory))?;
258+
self.with_directory(directory, |this| this.visit_mod(&sub_mod.items))?;
261259
}
262-
Ok(())
263260
}
264261
}
265-
}
266-
267-
fn visit_sub_mod_after_directory_update(
268-
&mut self,
269-
sub_mod: Module<'_>,
270-
directory: Option<Directory>,
271-
) -> Result<(), ModuleResolutionError> {
272-
if let Some(directory) = directory {
273-
self.directory = directory;
274-
}
275-
self.visit_mod(&sub_mod.items)
262+
Ok(())
276263
}
277264

278265
/// Find a file path in the filesystem which corresponds to the given module.
@@ -404,31 +391,41 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
404391
}
405392
}
406393

407-
fn push_inline_mod_directory(&mut self, id: symbol::Ident, attrs: &[ast::Attribute]) {
394+
fn inline_mod_directory(&mut self, id: symbol::Ident, attrs: &[ast::Attribute]) -> Directory {
408395
if let Some(path) = find_path_value(attrs) {
409-
self.directory.path.push(path.as_str());
410-
self.directory.ownership = DirectoryOwnership::Owned { relative: None };
411-
} else {
412-
let id = id.as_str();
413-
// We have to push on the current module name in the case of relative
414-
// paths in order to ensure that any additional module paths from inline
415-
// `mod x { ... }` come after the relative extension.
416-
//
417-
// For example, a `mod z { ... }` inside `x/y.rs` should set the current
418-
// directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
419-
if let DirectoryOwnership::Owned { relative } = &mut self.directory.ownership {
420-
if let Some(ident) = relative.take() {
421-
// remove the relative offset
422-
self.directory.path.push(ident.as_str());
423-
424-
// In the case where there is an x.rs and an ./x directory we want
425-
// to prevent adding x twice. For example, ./x/x
426-
if self.directory.path.exists() && !self.directory.path.join(id).exists() {
427-
return;
428-
}
429-
}
396+
return Directory {
397+
path: self.directory.path.join(path.as_str()),
398+
ownership: DirectoryOwnership::Owned { relative: None },
399+
};
400+
}
401+
let id = id.as_str();
402+
// We have to push on the current module name in the case of relative
403+
// paths in order to ensure that any additional module paths from inline
404+
// `mod x { ... }` come after the relative extension.
405+
//
406+
// For example, a `mod z { ... }` inside `x/y.rs` should set the current
407+
// directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
408+
let new_path = if let DirectoryOwnership::Owned {
409+
relative: Some(ident),
410+
} = self.directory.ownership
411+
{
412+
// remove the relative offset
413+
let relative = self.directory.path.join(ident.as_str());
414+
let nested = relative.join(id);
415+
416+
// In the case where there is an x.rs and an ./x directory we want
417+
// to prevent adding x twice. For example, ./x/x
418+
if relative.exists() && !nested.exists() {
419+
relative
420+
} else {
421+
nested
430422
}
431-
self.directory.path.push(id);
423+
} else {
424+
self.directory.path.join(id)
425+
};
426+
Directory {
427+
path: new_path,
428+
ownership: self.directory.ownership,
432429
}
433430
}
434431

@@ -446,8 +443,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
446443
}
447444
let mut result = vec![];
448445
for path in path_visitor.paths() {
449-
let mut actual_path = self.directory.path.clone();
450-
actual_path.push(&path);
446+
let actual_path = self.directory.path.join(path);
451447
if !actual_path.exists() {
452448
continue;
453449
}
@@ -475,6 +471,13 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
475471
}
476472
result
477473
}
474+
475+
fn with_directory<T>(&mut self, directory: Directory, f: impl FnOnce(&mut Self) -> T) -> T {
476+
let old = std::mem::replace(&mut self.directory, directory);
477+
let out = f(self);
478+
self.directory = old;
479+
out
480+
}
478481
}
479482

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

0 commit comments

Comments
 (0)