Separate modules and files listing of reformatting

As suggested in #141
Closes #156
This commit is contained in:
Gaëtan Cassiers 2015-07-26 12:55:25 +02:00
parent bc43b81200
commit 0e10329dc7
8 changed files with 87 additions and 51 deletions

View File

@ -216,10 +216,6 @@ fn write_system_newlines<T>(mut writer: T,
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

View File

@ -37,7 +37,6 @@
use syntax::ast;
use syntax::codemap::CodeMap;
use syntax::diagnostics;
use syntax::visit;
use std::path::PathBuf;
use std::collections::HashMap;
@ -64,6 +63,7 @@
mod rewrite;
mod string;
mod comment;
mod modules;
const MIN_STRING: usize = 10;
// When we get scoped annotations, we should have rustfmt::skip.
@ -198,7 +198,9 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
// 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
}

73
src/modules.rs Normal file
View File

@ -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))
}
}

View File

@ -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;
@ -197,7 +195,7 @@ fn visit_item(&mut self, item: &'v ast::Item) {
}
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);
@ -237,12 +235,6 @@ fn visit_impl_item(&mut self, ii: &'v ast::ImplItem) {
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> {
@ -322,7 +314,7 @@ pub fn rewrite_attrs(&self, attrs: &[ast::Attribute], indent: usize) -> String {
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.
@ -337,49 +329,15 @@ fn format_mod(&mut self, m: &ast::Mod, s: Span, ident: ast::Ident, attrs: &[ast:
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) {

View File

@ -4,6 +4,7 @@
mod mymod1 {
use mod2a::{Foo,Bar};
mod mod3a;
}
#[path="mod2c.rs"]

View File

@ -0,0 +1,2 @@
// Another mod
fn a( ) { }

View File

@ -4,6 +4,7 @@
mod mymod1 {
use mod2a::{Foo, Bar};
mod mod3a;
}
#[path="mod2c.rs"]

View File

@ -0,0 +1,3 @@
// Another mod
fn a() {
}