Skip to content

Commit bb8a4a0

Browse files
committed
Format modules into separate files
1 parent a1b7912 commit bb8a4a0

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
@@ -166,11 +166,6 @@ impl fmt::Display for FormatReport {
166166
fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap, config: &'a Config) -> ChangeSet<'a> {
167167
let mut visitor = FmtVisitor::from_codemap(codemap, config);
168168
visit::walk_crate(&mut visitor, krate);
169-
let files = codemap.files.borrow();
170-
if let Some(last) = files.last() {
171-
visitor.format_missing(last.end_pos);
172-
}
173-
174169
visitor.changes
175170
}
176171

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};
@@ -193,7 +197,6 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
193197
visit::walk_item(self, item);
194198
}
195199
ast::Item_::ItemImpl(..) |
196-
ast::Item_::ItemMod(_) |
197200
ast::Item_::ItemTrait(..) => {
198201
self.block_indent += self.config.tab_spaces;
199202
visit::walk_item(self, item);
@@ -223,6 +226,10 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
223226
item.span);
224227
self.last_pos = item.span.hi;
225228
}
229+
ast::Item_::ItemMod(ref module) => {
230+
self.format_missing_with_indent(item.span.lo);
231+
self.format_mod(module, item.span, item.ident, &item.attrs);
232+
}
226233
_ => {
227234
visit::walk_item(self, item);
228235
}
@@ -263,12 +270,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
263270
}
264271

265272
fn visit_mod(&mut self, m: &'v ast::Mod, s: Span, _: ast::NodeId) {
266-
// Only visit inline mods here.
267-
if self.codemap.lookup_char_pos(s.lo).file.name !=
268-
self.codemap.lookup_char_pos(m.inner.lo).file.name {
269-
return;
270-
}
271-
visit::walk_mod(self, m);
273+
// This is only called for the root module
274+
let filename = self.codemap.span_to_filename(s);
275+
self.format_separate_mod(m, &filename);
272276
}
273277
}
274278

@@ -348,4 +352,79 @@ impl<'a> FmtVisitor<'a> {
348352

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

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)