Skip to content

Commit 4735edf

Browse files
committed
Format modules into separate files
1 parent 83290f1 commit 4735edf

File tree

17 files changed

+164
-12
lines changed

17 files changed

+164
-12
lines changed

src/changes.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@ impl<'a> ChangeSet<'a> {
213213

214214
Ok(None)
215215
}
216+
217+
pub fn is_changed(&self, filename: &str) -> bool {
218+
self.file_map.get(filename).expect("Unknown filename").len != 0
219+
}
216220
}
217221

218222
// Iterates over each file in the ChangSet. Yields the filename and the changed

src/lib.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,6 @@ impl fmt::Display for FormatReport {
167167
fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap, config: &'a Config) -> ChangeSet<'a> {
168168
let mut visitor = FmtVisitor::from_codemap(codemap, config);
169169
visit::walk_crate(&mut visitor, krate);
170-
let files = codemap.files.borrow();
171-
if let Some(last) = files.last() {
172-
visitor.format_missing(last.end_pos);
173-
}
174-
175170
visitor.changes
176171
}
177172

src/visitor.rs

Lines changed: 86 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@
1111
use syntax::ast;
1212
use syntax::codemap::{self, CodeMap, Span, BytePos};
1313
use syntax::visit;
14+
use syntax::parse::token;
15+
use syntax::attr;
16+
use std::path::PathBuf;
1417

1518
use utils;
1619
use config::Config;
20+
use comment::FindUncommented;
1721

1822
use changes::ChangeSet;
1923
use rewrite::{Rewrite, RewriteContext};
@@ -197,7 +201,6 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
197201
visit::walk_item(self, item);
198202
}
199203
ast::Item_::ItemImpl(..) |
200-
ast::Item_::ItemMod(_) |
201204
ast::Item_::ItemTrait(..) => {
202205
self.block_indent += self.config.tab_spaces;
203206
visit::walk_item(self, item);
@@ -227,6 +230,10 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
227230
item.span);
228231
self.last_pos = item.span.hi;
229232
}
233+
ast::Item_::ItemMod(ref module) => {
234+
self.format_missing_with_indent(item.span.lo);
235+
self.format_mod(module, item.span, item.ident, &item.attrs);
236+
}
230237
_ => {
231238
visit::walk_item(self, item);
232239
}
@@ -267,12 +274,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
267274
}
268275

269276
fn visit_mod(&mut self, m: &'v ast::Mod, s: Span, _: ast::NodeId) {
270-
// Only visit inline mods here.
271-
if self.codemap.lookup_char_pos(s.lo).file.name !=
272-
self.codemap.lookup_char_pos(m.inner.lo).file.name {
273-
return;
274-
}
275-
visit::walk_mod(self, m);
277+
// This is only called for the root module
278+
let filename = self.codemap.span_to_filename(s);
279+
self.format_separate_mod(m, &filename);
276280
}
277281
}
278282

@@ -352,4 +356,79 @@ impl<'a> FmtVisitor<'a> {
352356

353357
result
354358
}
359+
360+
fn format_mod(&mut self, m: &ast::Mod, s: Span, ident: ast::Ident, attrs: &[ast::Attribute]) {
361+
debug!("FmtVisitor::format_mod: ident: {:?}, span: {:?}", ident, s);
362+
// Decide whether this is an inline mod or an external mod.
363+
// There isn't any difference between inline and external mod in AST,
364+
// so we use the trick of searching for an opening brace. (Tricks based
365+
// on inner span doesn't work in case of mod with no items.)
366+
let open_brace = self.codemap.span_to_snippet(s).unwrap().find_uncommented("{");
367+
match open_brace {
368+
None => {
369+
debug!("FmtVisitor::format_mod: external mod");
370+
let file_path = self.module_file(ident, attrs, s);
371+
let filename = file_path.to_str().unwrap();
372+
if self.changes.is_changed(filename) {
373+
// The file has already been reformatted, do nothing
374+
} else {
375+
self.format_separate_mod(m, filename);
376+
}
377+
// TODO Should rewrite properly `mod X;`
378+
}
379+
Some(open_brace) => {
380+
debug!("FmtVisitor::format_mod: internal mod");
381+
debug!("... open_brace: {}, str: {:?}", open_brace, self.codemap.span_to_snippet(s));
382+
// Format everything until opening brace
383+
// TODO Shoud rewrite properly
384+
self.format_missing(s.lo + BytePos(open_brace as u32));
385+
self.block_indent += self.config.tab_spaces;
386+
visit::walk_mod(self, m);
387+
debug!("... last_pos after: {:?}", self.last_pos);
388+
self.block_indent -= self.config.tab_spaces;
389+
}
390+
}
391+
self.format_missing(s.hi);
392+
debug!("FmtVisitor::format_mod: exit");
393+
}
394+
395+
/// Find the file corresponding to an external mod
396+
/// Same algorithm as syntax::parse::eval_src_mod
397+
fn module_file(&self, id: ast::Ident, outer_attrs: &[ast::Attribute], id_sp: Span) -> PathBuf {
398+
let mut prefix = PathBuf::from(&self.codemap.span_to_filename(id_sp));
399+
prefix.pop();
400+
let mod_string = token::get_ident(id);
401+
match attr::first_attr_value_str_by_name(outer_attrs, "path") {
402+
Some(d) => prefix.join(&*d),
403+
None => {
404+
let default_path_str = format!("{}.rs", mod_string);
405+
let secondary_path_str = format!("{}/mod.rs", mod_string);
406+
let default_path = prefix.join(&default_path_str);
407+
let secondary_path = prefix.join(&secondary_path_str);
408+
let default_exists = self.codemap.file_exists(&default_path);
409+
let secondary_exists = self.codemap.file_exists(&secondary_path);
410+
if default_exists {
411+
default_path
412+
} else if secondary_exists {
413+
secondary_path
414+
} else {
415+
// Should never appens since rustc parsed everything sucessfully
416+
panic!("Didn't found module {}", mod_string);
417+
}
418+
}
419+
}
420+
}
421+
422+
/// Format the content of a module into a separate file
423+
fn format_separate_mod(&mut self, m: &ast::Mod, filename: &str) {
424+
let last_pos = self.last_pos;
425+
let block_indent = self.block_indent;
426+
let filemap = self.codemap.get_filemap(filename);
427+
self.last_pos = filemap.start_pos;
428+
self.block_indent = 0;
429+
visit::walk_mod(self, m);
430+
self.format_missing(filemap.end_pos);
431+
self.last_pos = last_pos;
432+
self.block_indent = block_indent;
433+
}
355434
}

tests/source/mod-2.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Some nested mods
2+
3+
mod nestedmod;

tests/source/nestedmod/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
mod mod2a;
3+
mod mod2b;
4+
5+
mod mymod1 {
6+
use mod2a::{Foo,Bar};
7+
}
8+
9+
#[path="mod2c.rs"]
10+
mod mymod2;
11+
12+
mod submod2;

tests/source/nestedmod/mod2a.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// This is an empty file containing only
2+
// comments
3+
4+
// ...................

tests/source/nestedmod/mod2b.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
#[path="mod2a.rs"]
3+
mod c;

tests/source/nestedmod/mod2c.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// A standard mod
2+
3+
fn a( ) {}

tests/source/nestedmod/submod2/a.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Yet Another mod
2+
// Nested
3+
4+
use c::a;
5+
6+
fn foo( ) { }

tests/source/nestedmod/submod2/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Another mod
2+
3+
mod a;
4+
5+
use a::a;

tests/target/mod-2.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Some nested mods
2+
3+
mod nestedmod;

tests/target/nestedmod/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
mod mod2a;
3+
mod mod2b;
4+
5+
mod mymod1 {
6+
use mod2a::{Foo, Bar};
7+
}
8+
9+
#[path="mod2c.rs"]
10+
mod mymod2;
11+
12+
mod submod2;

tests/target/nestedmod/mod2a.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// This is an empty file containing only
2+
// comments
3+
4+
// ...................

tests/target/nestedmod/mod2b.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
#[path="mod2a.rs"]
3+
mod c;

tests/target/nestedmod/mod2c.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// A standard mod
2+
3+
fn a() {
4+
}

tests/target/nestedmod/submod2/a.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Yet Another mod
2+
// Nested
3+
4+
use c::a;
5+
6+
fn foo() {
7+
}

tests/target/nestedmod/submod2/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Another mod
2+
3+
mod a;
4+
5+
use a::a;

0 commit comments

Comments
 (0)