Use config file for constants

This commit is contained in:
Nick Cameron 2015-05-23 17:02:59 +12:00
parent aa6f7e8d3c
commit 1a09a6d00a
11 changed files with 115 additions and 56 deletions

View file

@ -15,10 +15,18 @@ extern crate rustfmt;
use rustfmt::{WriteMode, run};
use std::fs::File;
use std::io::Read;
fn main() {
let args: Vec<_> = std::env::args().collect();
//run(args, WriteMode::Display);
run(args, WriteMode::Overwrite);
let mut def_config_file = File::open("default.toml").unwrap();
let mut def_config = String::new();
def_config_file.read_to_string(&mut def_config).unwrap();
//run(args, WriteMode::Display, &def_config);
run(args, WriteMode::Overwrite, &def_config);
std::env::set_exit_status(0);
// TODO unit tests

View file

@ -20,7 +20,6 @@ use std::fmt;
use std::fs::File;
use std::io::{Write, stdout};
use WriteMode;
use NEWLINE_STYLE;
use NewlineStyle;
// This is basically a wrapper around a bunch of Ropes which makes it convenient
@ -157,7 +156,7 @@ impl<'a> ChangeSet<'a> {
-> Result<(), ::std::io::Error>
where T: Write,
{
match NEWLINE_STYLE {
match config!(newline_style) {
NewlineStyle::Unix => write!(writer, "{}", text),
NewlineStyle::Windows => {
for (c, _) in text.chars() {

View file

@ -1,2 +1,7 @@
max-width = 100
ideal-width = 80
max_width = 100
ideal_width = 80
leeway = 5
tab_spaces = 4
newline_style = "Unix"
fn_brace_style = "SameLineWhere"
fn_return_indent = "WithArgs"

View file

@ -15,7 +15,7 @@ use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic};
use syntax::{ast, ptr};
use syntax::codemap::{Span, Pos};
use {MAX_WIDTH, MIN_STRING};
use MIN_STRING;
impl<'a> FmtVisitor<'a> {
// TODO NEEDS TESTS
@ -26,7 +26,7 @@ impl<'a> FmtVisitor<'a> {
// strings, or if the string is too long for the line.
let l_loc = self.codemap.lookup_char_pos(span.lo);
let r_loc = self.codemap.lookup_char_pos(span.hi);
if l_loc.line == r_loc.line && r_loc.col.to_usize() <= MAX_WIDTH {
if l_loc.line == r_loc.line && r_loc.col.to_usize() <= config!(max_width) {
return self.snippet(span);
}

View file

@ -8,8 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use {ReturnIndent, MAX_WIDTH, BraceStyle,
IDEAL_WIDTH, LEEWAY, FN_BRACE_STYLE, FN_RETURN_INDENT};
use {ReturnIndent, BraceStyle};
use utils::make_indent;
use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic};
use visitor::FmtVisitor;
@ -149,8 +148,8 @@ impl<'a> FmtVisitor<'a> {
// If we've already gone multi-line, or the return type would push
// over the max width, then put the return type on a new line.
if result.contains("\n") ||
result.len() + indent + ret_str.len() > MAX_WIDTH {
let indent = match FN_RETURN_INDENT {
result.len() + indent + ret_str.len() > config!(max_width) {
let indent = match config!(fn_return_indent) {
ReturnIndent::WithWhereClause => indent + 4,
// TODO we might want to check that using the arg indent doesn't
// blow our budget, and if it does, then fallback to the where
@ -344,15 +343,15 @@ impl<'a> FmtVisitor<'a> {
if !newline_brace {
used_space += 2;
}
let one_line_budget = if used_space > MAX_WIDTH {
let one_line_budget = if used_space > config!(max_width) {
0
} else {
MAX_WIDTH - used_space
config!(max_width) - used_space
};
// 2 = `()`
let used_space = indent + result.len() + 2;
let max_space = IDEAL_WIDTH + LEEWAY;
let max_space = config!(ideal_width) + config!(leeway);
debug!("compute_budgets_for_args: used_space: {}, max_space: {}",
used_space, max_space);
if used_space < max_space {
@ -368,7 +367,7 @@ impl<'a> FmtVisitor<'a> {
result.push_str(&make_indent(indent + 4));
// 6 = new indent + `()`
let used_space = indent + 6;
let max_space = IDEAL_WIDTH + LEEWAY;
let max_space = config!(ideal_width) + config!(leeway);
if used_space > max_space {
// Whoops! bankrupt.
// TODO take evasive action, perhaps kill the indent or something.
@ -382,7 +381,7 @@ impl<'a> FmtVisitor<'a> {
}
fn newline_for_brace(&self, where_clause: &ast::WhereClause) -> bool {
match FN_BRACE_STYLE {
match config!(fn_brace_style) {
BraceStyle::AlwaysNextLine => true,
BraceStyle::SameLineWhere if where_clause.predicates.len() > 0 => true,
_ => false,
@ -399,7 +398,7 @@ impl<'a> FmtVisitor<'a> {
return result;
}
let budget = MAX_WIDTH - indent - 2;
let budget = config!(max_width) - indent - 2;
// TODO might need to insert a newline if the generics are really long
result.push('<');
@ -475,7 +474,7 @@ impl<'a> FmtVisitor<'a> {
.zip(comments.into_iter())
.collect();
let budget = IDEAL_WIDTH + LEEWAY - indent - 10;
let budget = config!(ideal_width) + config!(leeway) - indent - 10;
let fmt = ListFormatting {
tactic: ListTactic::Vertical,
separator: ",",

View file

@ -24,13 +24,17 @@ extern crate getopts;
extern crate rustc;
extern crate rustc_driver;
extern crate syntax;
extern crate rustc_serialize;
extern crate strings;
use rustc::session::Session;
use rustc::session::config::{self, Input};
use rustc::session::config as rustc_config;
use rustc::session::config::Input;
use rustc_driver::{driver, CompilerCalls, Compilation};
use rustc_serialize::{Decodable, Decoder};
use syntax::ast;
use syntax::codemap::CodeMap;
use syntax::diagnostics;
@ -42,6 +46,8 @@ use std::collections::HashMap;
use changes::ChangeSet;
use visitor::FmtVisitor;
#[macro_use]
mod config;
mod changes;
mod visitor;
mod functions;
@ -52,17 +58,12 @@ mod types;
mod expr;
mod imports;
const IDEAL_WIDTH: usize = 80;
const LEEWAY: usize = 5;
const MAX_WIDTH: usize = 100;
const MIN_STRING: usize = 10;
const TAB_SPACES: usize = 4;
const NEWLINE_STYLE: NewlineStyle = NewlineStyle::Unix;
const FN_BRACE_STYLE: BraceStyle = BraceStyle::SameLineWhere;
const FN_RETURN_INDENT: ReturnIndent = ReturnIndent::WithArgs;
// When we get scoped annotations, we should have rustfmt::skip.
const SKIP_ANNOTATION: &'static str = "rustfmt_skip";
static mut CONFIG: Option<config::Config> = None;
#[derive(Copy, Clone)]
pub enum WriteMode {
Overwrite,
@ -75,13 +76,24 @@ pub enum WriteMode {
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
enum NewlineStyle {
pub enum NewlineStyle {
Windows, // \r\n
Unix, // \n
}
impl Decodable for NewlineStyle {
fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
let s = try!(d.read_str());
match &*s {
"Windows" => Ok(NewlineStyle::Windows),
"Unix" => Ok(NewlineStyle::Unix),
_ => Err(d.error("Bad variant")),
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
enum BraceStyle {
pub enum BraceStyle {
AlwaysNextLine,
PreferSameLine,
// Prefer same line except where there is a where clause, in which case force
@ -89,15 +101,39 @@ enum BraceStyle {
SameLineWhere,
}
impl Decodable for BraceStyle {
fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
let s = try!(d.read_str());
match &*s {
"AlwaysNextLine" => Ok(BraceStyle::AlwaysNextLine),
"PreferSameLine" => Ok(BraceStyle::PreferSameLine),
"SameLineWhere" => Ok(BraceStyle::SameLineWhere),
_ => Err(d.error("Bad variant")),
}
}
}
// How to indent a function's return type.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
enum ReturnIndent {
pub enum ReturnIndent {
// Aligned with the arguments
WithArgs,
// Aligned with the where clause
WithWhereClause,
}
// TODO could use a macro for all these Decodable impls.
impl Decodable for ReturnIndent {
fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
let s = try!(d.read_str());
match &*s {
"WithArgs" => Ok(ReturnIndent::WithArgs),
"WithWhereClause" => Ok(ReturnIndent::WithWhereClause),
_ => Err(d.error("Bad variant")),
}
}
}
// Formatting which depends on the AST.
fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> {
let mut visitor = FmtVisitor::from_codemap(codemap);
@ -133,10 +169,10 @@ fn fmt_lines(changes: &mut ChangeSet) {
line_len -= b - lw;
}
// Check for any line width errors we couldn't correct.
if line_len > MAX_WIDTH {
if line_len > config!(max_width) {
// TODO store the error rather than reporting immediately.
println!("Rustfmt couldn't fix (sorry). {}:{}: line longer than {} characters",
f, cur_line, MAX_WIDTH);
f, cur_line, config!(max_width));
}
line_len = 0;
cur_line += 1;
@ -200,7 +236,7 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls {
fn no_input(&mut self,
_: &getopts::Matches,
_: &config::Options,
_: &rustc_config::Options,
_: &Option<PathBuf>,
_: &Option<PathBuf>,
_: &diagnostics::registry::Registry)
@ -248,7 +284,14 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls {
}
}
pub fn run(args: Vec<String>, write_mode: WriteMode) {
// args are the arguments passed on the command line, generally passed through
// to the compiler.
// write_mode determines what happens to the result of running rustfmt, see
// WriteMode.
// default_config is a string of toml data to be used to configure rustfmt.
pub fn run(args: Vec<String>, write_mode: WriteMode, default_config: &str) {
config::set_config(default_config);
let mut call_ctxt = RustFmtCalls { input_path: None, write_mode: write_mode };
rustc_driver::run_compiler(&args, &mut call_ctxt);
}

View file

@ -14,7 +14,7 @@ use syntax::visit;
use utils;
use {IDEAL_WIDTH, MAX_WIDTH, TAB_SPACES, SKIP_ANNOTATION};
use SKIP_ANNOTATION;
use changes::ChangeSet;
pub struct FmtVisitor<'a> {
@ -32,7 +32,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
self.codemap.lookup_char_pos(ex.span.hi));
self.format_missing(ex.span.lo);
let offset = self.changes.cur_offset_span(ex.span);
let new_str = self.rewrite_expr(ex, MAX_WIDTH - offset, offset);
let new_str = self.rewrite_expr(ex, config!(max_width) - offset, offset);
self.changes.push_str_span(ex.span, &new_str);
self.last_pos = ex.span.hi;
}
@ -65,7 +65,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
self.changes.push_str_span(b.span, "{");
self.last_pos = self.last_pos + BytePos(1);
self.block_indent += TAB_SPACES;
self.block_indent += config!(tab_spaces);
for stmt in &b.stmts {
self.visit_stmt(&stmt)
@ -78,7 +78,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
None => {}
}
self.block_indent -= TAB_SPACES;
self.block_indent -= config!(tab_spaces);
// TODO we should compress any newlines here to just one
self.format_missing_with_indent(b.span.hi - BytePos(1));
self.changes.push_str_span(b.span, "}");
@ -149,8 +149,8 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
match vp.node {
ast::ViewPath_::ViewPathList(ref path, ref path_list) => {
let block_indent = self.block_indent;
let one_line_budget = MAX_WIDTH - block_indent;
let multi_line_budget = IDEAL_WIDTH - block_indent;
let one_line_budget = config!(max_width) - block_indent;
let multi_line_budget = config!(ideal_width) - block_indent;
let new_str = self.rewrite_use_list(block_indent,
one_line_budget,
multi_line_budget,
@ -170,9 +170,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
ast::Item_::ItemImpl(..) |
ast::Item_::ItemMod(_) |
ast::Item_::ItemTrait(..) => {
self.block_indent += TAB_SPACES;
self.block_indent += config!(tab_spaces);
visit::walk_item(self, item);
self.block_indent -= TAB_SPACES;
self.block_indent -= config!(tab_spaces);
}
ast::Item_::ItemExternCrate(_) => {
self.format_missing_with_indent(item.span.lo);