Skip to content

Commit

Permalink
Separate modules and files listing of reformatting
Browse files Browse the repository at this point in the history
As suggested in #141
Closes #156
  • Loading branch information
cassiersg committed Aug 2, 2015
1 parent bc43b81 commit 0e10329
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 51 deletions.
4 changes: 0 additions & 4 deletions src/changes.rs
Expand Up @@ -216,10 +216,6 @@ impl<'a> ChangeSet<'a> {

Ok(None)
}

pub fn is_changed(&self, filename: &str) -> bool {
self.file_map.get(filename).expect("Unknown filename").len != 0
}
}

// Iterates over each file in the ChangSet. Yields the filename and the changed
Expand Down
6 changes: 4 additions & 2 deletions src/lib.rs
Expand Up @@ -37,7 +37,6 @@ use rustc_driver::{driver, CompilerCalls, Compilation};
use syntax::ast;
use syntax::codemap::CodeMap;
use syntax::diagnostics;
use syntax::visit;

use std::path::PathBuf;
use std::collections::HashMap;
Expand All @@ -64,6 +63,7 @@ mod issues;
mod rewrite;
mod string;
mod comment;
mod modules;

const MIN_STRING: usize = 10;
// When we get scoped annotations, we should have rustfmt::skip.
Expand Down Expand Up @@ -198,7 +198,9 @@ impl fmt::Display for FormatReport {
// Formatting which depends on the AST.
fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap, config: &'a Config) -> ChangeSet<'a> {
let mut visitor = FmtVisitor::from_codemap(codemap, config);
visit::walk_crate(&mut visitor, krate);
for (path, module) in modules::list_modules(krate, codemap) {
visitor.format_separate_mod(module, path.to_str().unwrap());
}
visitor.changes
}

Expand Down
73 changes: 73 additions & 0 deletions src/modules.rs
@@ -0,0 +1,73 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use utils;

use std::path::{Path, PathBuf};
use std::collections::HashMap;

use syntax::ast;
use syntax::codemap;
use syntax::parse::{parser, token};


/// List all the files containing modules of a crate.
/// If a file is used twice in a crate, it appears only once.
pub fn list_modules<'a>(krate: &'a ast::Crate,
codemap: &codemap::CodeMap)
-> HashMap<PathBuf, &'a ast::Mod> {
let mut result = HashMap::new();
let root_filename: PathBuf = codemap.span_to_filename(krate.span).into();
list_submodules(&krate.module, root_filename.parent().unwrap(), codemap, &mut result);
result.insert(root_filename, &krate.module);
result
}

/// Recursively list all external modules included in a module.
fn list_submodules<'a>(module: &'a ast::Mod,
search_dir: &Path,
codemap: &codemap::CodeMap,
result: &mut HashMap<PathBuf, &'a ast::Mod>) {
debug!("list_submodules: search_dir: {:?}", search_dir);
for item in module.items.iter() {
if let ast::ItemMod(ref sub_mod) = item.node {
if !utils::contains_skip(&item.attrs) {
let is_internal = codemap.span_to_filename(item.span) ==
codemap.span_to_filename(sub_mod.inner);
let dir_path = if is_internal {
let dir: &str = &token::get_ident(item.ident);
search_dir.join(dir)
} else {
let mod_path = module_file(item.ident, &item.attrs, search_dir, codemap);
let dir_path = mod_path.parent().unwrap().to_owned();
result.insert(mod_path, sub_mod);
dir_path
};
list_submodules(sub_mod, &dir_path, codemap, result);
}
}
}
}

/// Find the file corresponding to an external mod
fn module_file(id: ast::Ident,
attrs: &[ast::Attribute],
dir_path: &Path,
codemap: &codemap::CodeMap)
-> PathBuf {
if let Some(path) = parser::Parser::submod_path_from_attr(attrs, &dir_path) {
return path;
}

match parser::Parser::default_submod_path(id, &dir_path, codemap).result {
Ok(parser::ModulePathSuccess { path, .. }) => path,
Err(_) => panic!("Couldn't find module {}", token::get_ident(id))
}
}
48 changes: 3 additions & 45 deletions src/visitor.rs
Expand Up @@ -11,8 +11,6 @@
use syntax::ast;
use syntax::codemap::{self, CodeMap, Span, BytePos};
use syntax::visit;
use syntax::parse::parser;
use std::path::PathBuf;

use utils;
use config::Config;
Expand Down Expand Up @@ -197,7 +195,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
}
ast::Item_::ItemMod(ref module) => {
self.format_missing_with_indent(item.span.lo);
self.format_mod(module, item.span, item.ident, &item.attrs);
self.format_mod(module, item.span, item.ident);
}
_ => {
visit::walk_item(self, item);
Expand Down Expand Up @@ -237,12 +235,6 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
fn visit_mac(&mut self, mac: &'v ast::Mac) {
visit::walk_mac(self, mac)
}

fn visit_mod(&mut self, m: &'v ast::Mod, s: Span, _: ast::NodeId) {
// This is only called for the root module
let filename = self.codemap.span_to_filename(s);
self.format_separate_mod(m, &filename);
}
}

impl<'a> FmtVisitor<'a> {
Expand Down Expand Up @@ -322,7 +314,7 @@ impl<'a> FmtVisitor<'a> {
result
}

fn format_mod(&mut self, m: &ast::Mod, s: Span, ident: ast::Ident, attrs: &[ast::Attribute]) {
fn format_mod(&mut self, m: &ast::Mod, s: Span, ident: ast::Ident) {
debug!("FmtVisitor::format_mod: ident: {:?}, span: {:?}", ident, s);

// Decide whether this is an inline mod or an external mod.
Expand All @@ -337,49 +329,15 @@ impl<'a> FmtVisitor<'a> {
visit::walk_mod(self, m);
debug!("... last_pos after: {:?}", self.last_pos);
self.block_indent -= self.config.tab_spaces;
} else {
debug!("FmtVisitor::format_mod: external mod");
let file_path = self.module_file(ident, attrs, local_file_name);
let filename = file_path.to_str().unwrap();
if self.changes.is_changed(filename) {
// The file has already been reformatted, do nothing
} else {
self.format_separate_mod(m, filename);
}
}

debug!("FmtVisitor::format_mod: exit");
}

/// Find the file corresponding to an external mod
fn module_file(&self, id: ast::Ident, attrs: &[ast::Attribute], filename: String) -> PathBuf {
let dir_path = {
let mut path = PathBuf::from(&filename);
path.pop();
path
};

if let Some(path) = parser::Parser::submod_path_from_attr(attrs, &dir_path) {
return path;
}

match parser::Parser::default_submod_path(id, &dir_path, &self.codemap).result {
Ok(parser::ModulePathSuccess { path, .. }) => path,
_ => panic!("Couldn't find module {}", id)
}
}

/// Format the content of a module into a separate file
fn format_separate_mod(&mut self, m: &ast::Mod, filename: &str) {
let last_pos = self.last_pos;
let block_indent = self.block_indent;
pub fn format_separate_mod(&mut self, m: &ast::Mod, filename: &str) {
let filemap = self.codemap.get_filemap(filename);
self.last_pos = filemap.start_pos;
self.block_indent = 0;
visit::walk_mod(self, m);
self.format_missing(filemap.end_pos);
self.last_pos = last_pos;
self.block_indent = block_indent;
}

fn format_import(&mut self, vis: ast::Visibility, vp: &ast::ViewPath, span: Span) {
Expand Down
1 change: 1 addition & 0 deletions tests/source/nestedmod/mod.rs
Expand Up @@ -4,6 +4,7 @@ mod mod2b;

mod mymod1 {
use mod2a::{Foo,Bar};
mod mod3a;
}

#[path="mod2c.rs"]
Expand Down
2 changes: 2 additions & 0 deletions tests/source/nestedmod/mymod1/mod3a.rs
@@ -0,0 +1,2 @@
// Another mod
fn a( ) { }
1 change: 1 addition & 0 deletions tests/target/nestedmod/mod.rs
Expand Up @@ -4,6 +4,7 @@ mod mod2b;

mod mymod1 {
use mod2a::{Foo, Bar};
mod mod3a;
}

#[path="mod2c.rs"]
Expand Down
3 changes: 3 additions & 0 deletions tests/target/nestedmod/mymod1/mod3a.rs
@@ -0,0 +1,3 @@
// Another mod
fn a() {
}

0 comments on commit 0e10329

Please sign in to comment.