Skip to content

Commit

Permalink
config: Add field for restricting formating to specific lines
Browse files Browse the repository at this point in the history
This commit adds a `file_lines_map` field to `Config`. This is an
optional field that when present stores a map from file names to sets of
lines to format. The code to use this field will come in a later commit.

This includes code to parse a file name / line set specification that is
used for `Config::override_value()` and will be used to parse the
command line option.

Adding `nom` as a dependency for parsing increases the incremental
rustfmt build time by 0.96s on a machine where it takes ~23s to build
rustfmt.

Refs rust-lang#434
  • Loading branch information
kamalmarhubi committed Apr 21, 2016
1 parent 5a6df6b commit 365f794
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 1 deletion.
6 changes: 6 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -26,3 +26,4 @@ log = "0.3"
env_logger = "0.3"
getopts = "0.2"
itertools = "0.4"
nom = "1.2.1"
115 changes: 114 additions & 1 deletion src/config.rs
Expand Up @@ -10,7 +10,12 @@

extern crate toml;

use std::str;
use std::{iter, str};
use std::collections::HashMap;

use nom::IResult;

use codemap::LineSet;
use lists::{SeparatorTactic, ListTactic};
use std::io::Write;

Expand Down Expand Up @@ -111,6 +116,112 @@ configuration_option_enum! { TypeDensity:
Wide,
}

// Newtype needed to have impls for `create_config` macro.
#[derive(Clone, Debug, Default, RustcDecodable)]
pub struct FileLinesMap(pub HashMap<String, LineSet>);

impl ConfigType for Option<FileLinesMap> {
type ParseErr = String;

fn doc_hint() -> String {
unimplemented!();
}

fn parse(s: &str) -> Result<Self, String> {
let mut map = HashMap::new();
let (file, lines) = try!(parse_file_lines_spec(s));
map.insert(file, lines);

Ok(Some(FileLinesMap(map)))
}
}

pub fn parse_file_lines_spec(s: &str) -> Result<(String, LineSet), String> {
let err = || Err(format!("invalid experimental-file-lines argument: {}", s));

match file_lines_spec_parser::file_lines_spec(&s) {
IResult::Error(_) |
IResult::Incomplete(_) => return err(),
IResult::Done(remaining, _) if !remaining.is_empty() => return err(),
IResult::Done(_, (file, line_ranges)) => Ok((file, line_ranges)),
}
}

impl iter::FromIterator<(String, LineSet)> for FileLinesMap {
fn from_iter<I: IntoIterator<Item = (String, LineSet)>>(iter: I) -> FileLinesMap {
let mut ret = FileLinesMap(HashMap::new());
ret.extend(iter);
ret
}
}

impl Extend<(String, LineSet)> for FileLinesMap {
fn extend<I>(&mut self, iter: I)
where I: IntoIterator<Item = (String, LineSet)>
{
let map = &mut self.0;

for (file, line_set) in iter {
map.entry(file).or_insert(LineSet::new()).extend(line_set);
}
}
}

mod file_lines_spec_parser {
use std::iter::FromIterator;
use std::str::FromStr;

use nom::digit;

use codemap::{LineRange, LineSet};

named!(pub file_lines_spec<&str, (String, LineSet)>,
chain!(
file: map!(
is_not_s!(":"),
String::from
) ~
tag_s!(":") ~
line_set: line_set,
|| (file, line_set)
)
);

named!(usize_digit<&str, usize>,
map_res!(
digit,
usize::from_str
)
);

named!(line_range<&str, LineRange>,
map_res!(
separated_pair!(
usize_digit,
tag_s!("-"),
usize_digit
),
|pair| {
let (lo, hi) = pair;
if lo > hi {
return Err(format!("empty line range: {}-{}", lo, hi));
}
Ok(LineRange { lo: lo, hi: hi })
}
)
);

named!(line_set<&str, LineSet>,
map!(
separated_nonempty_list!(
tag_s!(","),
line_range
),
LineSet::from_iter
)
);
}

impl Density {
pub fn to_list_tactic(self) -> ListTactic {
match self {
Expand Down Expand Up @@ -356,6 +467,8 @@ macro_rules! create_config {
create_config! {
Doc verbose: bool, false, "Use verbose output";
Doc skip_children: bool, false, "Don't reformat out of line modules";
NoDoc file_lines_map: Option<FileLinesMap>, None::<FileLinesMap>,
"Lines to format for each file";
Doc max_width: usize, 100, "Maximum width of each line";
Doc ideal_width: usize, 80, "Ideal width of each line";
Doc tab_spaces: usize, 4, "Number of spaces per tab";
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Expand Up @@ -14,6 +14,8 @@

#[macro_use]
extern crate log;
#[macro_use]
extern crate nom;

extern crate syntex_syntax as syntax;
extern crate rustc_serialize;
Expand Down

0 comments on commit 365f794

Please sign in to comment.