Merge pull request #523 from alexcrichton/stable

Move to stable Rust
This commit is contained in:
Marcus Klaas de Vries 2015-10-23 22:57:43 +02:00
commit 02c118ae72
13 changed files with 174 additions and 158 deletions

View File

@ -1,5 +1,7 @@
language: rust
rust:
- stable
- beta
- nightly
sudo: false

41
Cargo.lock generated
View File

@ -3,9 +3,13 @@ name = "rustfmt"
version = "0.0.1"
dependencies = [
"diff 0.1.7 (git+https://github.com/utkarshkukreti/diff.rs.git)",
"env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"strings 0.0.1 (git+https://github.com/nrc/strings.rs.git)",
"syntex_syntax 0.18.0 (git+https://github.com/serde-rs/syntex)",
"term 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -19,11 +23,30 @@ dependencies = [
"memchr 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bitflags"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "diff"
version = "0.1.7"
source = "git+https://github.com/utkarshkukreti/diff.rs.git#6edb9454bf4127087aced0fe07ab3ea6894083cb"
[[package]]
name = "env_logger"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "getopts"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "kernel32-sys"
version = "0.1.4"
@ -82,6 +105,19 @@ dependencies = [
"log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syntex_syntax"
version = "0.18.0"
source = "git+https://github.com/serde-rs/syntex#176ca5d8add606fac8d503b10c89ddb82f02d92b"
dependencies = [
"bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "term"
version = "0.2.12"
@ -104,6 +140,11 @@ name = "unicode-segmentation"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.2.4"

View File

@ -16,5 +16,9 @@ regex = "0.1.41"
term = "0.2.11"
strings = { version = "0.0.1", git = "https://github.com/nrc/strings.rs.git" }
diff = { git = "https://github.com/utkarshkukreti/diff.rs.git" }
syntex_syntax = { git = "https://github.com/serde-rs/syntex" }
log = "0.3.2"
env_logger = "0.3.1"
getopts = "0.2"
[dev-dependencies]

View File

@ -3,15 +3,34 @@
A tool for formatting Rust code according to style guidelines.
## Gotchas
* For things you do not want rustfmt to mangle, use
```rust
#[rustfmt_skip]
```
* When you run rustfmt use a file called rustfmt.toml to override the default settings of rustfmt.
* We create a functioning executable called rustfmt in the target directory
* For things you do not want rustfmt to mangle, use one of
```rust
#[rustfmt_skip]
#[cfg_attr(rustfmt, rustfmt_skip)]
```
* When you run rustfmt use a file called rustfmt.toml to override the default
settings of rustfmt.
* We create a functioning executable called `rustfmt` in the target directory
## Installation
> **Note:** this method currently requires you to be running a nightly install
> of Rust as `cargo install` has not yet made its way onto the stable channel.
```
cargo install --git https://github.com/nrc/rustfmt
```
or if you're using `multirust`
```
multirust run nightly cargo install --git https://github.com/nrc/rustfmt
```
## How to build and test
You'll need a pretty up to date version of the **nightly** version of Rust.
First make sure you've got Rust **1.3.0** or greater available, then:
`cargo build` to build.

View File

@ -7,30 +7,32 @@
// <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.
#![feature(path_ext)]
#![feature(rustc_private)]
#![cfg(not(test))]
#[macro_use]
extern crate log;
extern crate rustfmt;
extern crate toml;
extern crate env_logger;
extern crate getopts;
use rustfmt::{WriteMode, run};
use rustfmt::config::Config;
use std::env;
use std::fs::{File, PathExt};
use std::fs::{self, File};
use std::io::{self, Read};
use std::path::PathBuf;
use std::str::FromStr;
use getopts::Options;
// Try to find a project file in the current directory and its parents.
fn lookup_project_file() -> io::Result<PathBuf> {
let mut current = try!(env::current_dir());
loop {
let config_file = current.join("rustfmt.toml");
if config_file.exists() {
if fs::metadata(&config_file).is_ok() {
return Ok(config_file);
} else {
current = match current.parent() {
@ -52,7 +54,7 @@ fn lookup_and_read_project_file() -> io::Result<(PathBuf, String)> {
}
fn execute() -> i32 {
let (args, write_mode) = match determine_params(std::env::args()) {
let (file, write_mode) = match determine_params(std::env::args().skip(1)) {
Some(params) => params,
None => return 1,
};
@ -65,12 +67,14 @@ fn execute() -> i32 {
Err(_) => Default::default(),
};
run(args, write_mode, &config);
run(&file, write_mode, &config);
0
}
fn main() {
use std::io::Write;
let _ = env_logger::init();
let exit_code = execute();
// Make sure standard output is flushed before we exit
std::io::stdout().flush().unwrap();
@ -81,50 +85,52 @@ fn main() {
std::process::exit(exit_code);
}
fn print_usage<S: Into<String>>(reason: S) {
println!("{}\n\r usage: rustfmt [-h Help] [--write-mode=[replace|overwrite|display|diff]] \
<file_name>",
reason.into());
fn print_usage(opts: &Options, reason: &str) {
let reason = format!("{}\nusage: {} [options] <file>",
reason,
env::current_exe().unwrap().display());
println!("{}", opts.usage(&reason));
Config::print_docs();
}
fn determine_params<I>(args: I) -> Option<(Vec<String>, WriteMode)>
fn determine_params<I>(args: I) -> Option<(PathBuf, WriteMode)>
where I: Iterator<Item = String>
{
let arg_prefix = "-";
let write_mode_prefix = "--write-mode=";
let help_mode = "-h";
let long_help_mode = "--help";
let mut write_mode = WriteMode::Replace;
let mut rustc_args = Vec::new();
let mut opts = Options::new();
opts.optflag("h", "help", "show this message");
opts.optopt("",
"write-mode",
"mode to write in",
"[replace|overwrite|display|diff]");
let matches = match opts.parse(args) {
Ok(m) => m,
Err(e) => {
print_usage(&opts, &e.to_string());
return None;
}
};
// The NewFile option currently isn't supported because it requires another
// parameter, but it can be added later.
for arg in args {
if arg.starts_with(write_mode_prefix) {
match FromStr::from_str(&arg[write_mode_prefix.len()..]) {
Ok(mode) => write_mode = mode,
Err(_) => {
print_usage("Unrecognized write mode");
if matches.opt_present("h") {
print_usage(&opts, "");
}
let write_mode = match matches.opt_str("write-mode") {
Some(mode) => {
match mode.parse() {
Ok(mode) => mode,
Err(..) => {
print_usage(&opts, "Unrecognized write mode");
return None;
}
}
} else if arg.starts_with(help_mode) || arg.starts_with(long_help_mode) {
print_usage("");
return None;
} else if arg.starts_with(arg_prefix) {
print_usage("Invalid argument");
return None;
} else {
// Pass everything else to rustc
rustc_args.push(arg);
}
}
None => WriteMode::Replace,
};
if rustc_args.len() < 2 {
print_usage("Please provide a file to be formatted");
if matches.free.len() != 1 {
print_usage(&opts, "Please provide one file to format");
return None;
}
Some((rustc_args, write_mode))
Some((PathBuf::from(&matches.free[0]), write_mode))
}

View File

@ -72,11 +72,9 @@ pub fn rewrite_chain(mut expr: &ast::Expr,
.collect::<Option<Vec<_>>>());
// Total of all items excluding the last.
let almost_total = rewrites.split_last()
.unwrap()
.1
.iter()
.fold(0, |a, b| a + first_line_width(b)) +
let almost_total = rewrites[..rewrites.len() - 1]
.iter()
.fold(0, |a, b| a + first_line_width(b)) +
parent_rewrite.len();
let total_width = almost_total + first_line_width(rewrites.last().unwrap());
let veto_single_line = if context.config.take_source_hints && subexpr_list.len() > 1 {
@ -95,7 +93,9 @@ pub fn rewrite_chain(mut expr: &ast::Expr,
match subexpr_list[0].node {
ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions)
if context.config.chains_overflow_last => {
let (last, init) = rewrites.split_last_mut().unwrap();
let len = rewrites.len();
let (init, last) = rewrites.split_at_mut(len - 1);
let last = &mut last[0];
if init.iter().all(|s| !s.contains('\n')) && total_width <= width {
let last_rewrite = width.checked_sub(almost_total)

View File

@ -437,7 +437,7 @@ mod test {
}
#[test]
#[rustfmt_skip]
#[cfg_attr(rustfmt, rustfmt_skip)]
fn format_comments() {
let config = Default::default();
assert_eq!("/* test */", rewrite_comment(" //test", true, 100, Indent::new(0, 100),

View File

@ -8,13 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(rustc_private)]
#![feature(custom_attribute)]
#![feature(slice_splits)]
#![feature(slice_patterns)]
#![feature(catch_panic)]
#![allow(unused_attributes)]
// TODO we're going to allocate a whole bunch of temp Strings, is it worth
// keeping some scratch mem for this and running our own StrPool?
// TODO for lint violations of names, emit a refactor script
@ -22,10 +15,7 @@
#[macro_use]
extern crate log;
extern crate getopts;
extern crate rustc;
extern crate rustc_driver;
extern crate syntax;
extern crate syntex_syntax as syntax;
extern crate rustc_serialize;
extern crate strings;
@ -35,22 +25,15 @@ extern crate regex;
extern crate diff;
extern crate term;
use rustc::session::Session;
use rustc::session::config as rustc_config;
use rustc::session::config::Input;
use rustc_driver::{driver, CompilerCalls, Compilation};
use syntax::ast;
use syntax::codemap::{CodeMap, Span};
use syntax::diagnostics;
use syntax::parse::{self, ParseSess};
use std::ops::{Add, Sub};
use std::path::PathBuf;
use std::path::Path;
use std::collections::HashMap;
use std::fmt;
use std::str::FromStr;
use std::rc::Rc;
use std::cell::RefCell;
use issues::{BadIssueSeeker, Issue};
use filemap::FileMap;
@ -387,65 +370,24 @@ pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport {
report
}
struct RustFmtCalls {
config: Rc<Config>,
result: Rc<RefCell<Option<FileMap>>>,
}
pub fn format(file: &Path, config: &Config) -> FileMap {
let parse_session = ParseSess::new();
let krate = parse::parse_crate_from_file(file, Vec::new(), &parse_session);
let mut file_map = fmt_ast(&krate, parse_session.codemap(), config);
impl<'a> CompilerCalls<'a> for RustFmtCalls {
fn no_input(&mut self,
_: &getopts::Matches,
_: &rustc_config::Options,
_: &Option<PathBuf>,
_: &Option<PathBuf>,
_: &diagnostics::registry::Registry)
-> Option<(Input, Option<PathBuf>)> {
panic!("No input supplied to RustFmt");
}
// For some reason, the codemap does not include terminating
// newlines so we must add one on for each file. This is sad.
filemap::append_newlines(&mut file_map);
fn build_controller(&mut self, _: &Session) -> driver::CompileController<'a> {
let result = self.result.clone();
let config = self.config.clone();
let mut control = driver::CompileController::basic();
control.after_parse.stop = Compilation::Stop;
control.after_parse.callback = Box::new(move |state| {
let krate = state.krate.unwrap();
let codemap = state.session.codemap();
let mut file_map = fmt_ast(krate, codemap, &*config);
// For some reason, the codemap does not include terminating
// newlines so we must add one on for each file. This is sad.
filemap::append_newlines(&mut file_map);
*result.borrow_mut() = Some(file_map);
});
control
}
}
pub fn format(args: Vec<String>, config: &Config) -> FileMap {
let result = Rc::new(RefCell::new(None));
{
let config = Rc::new(config.clone());
let mut call_ctxt = RustFmtCalls {
config: config,
result: result.clone(),
};
rustc_driver::run_compiler(&args, &mut call_ctxt);
}
// Peel the union.
Rc::try_unwrap(result).ok().unwrap().into_inner().unwrap()
return file_map;
}
// 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.
pub fn run(args: Vec<String>, write_mode: WriteMode, config: &Config) {
let mut result = format(args, config);
pub fn run(file: &Path, write_mode: WriteMode, config: &Config) {
let mut result = format(file, config);
println!("{}", fmt_lines(&mut result, config));

View File

@ -19,8 +19,6 @@
// List-like invocations with parentheses will be formatted as function calls,
// and those with brackets will be formatted as array literals.
use std::thread;
use syntax::ast;
use syntax::parse::token::{Eof, Comma, Token};
use syntax::parse::{ParseSess, tts_to_parser};
@ -34,12 +32,6 @@ use utils::{wrap_str, span_after};
static FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"];
// We need to pass `TokenTree`s to our expression parsing thread, but they are
// not `Send`. We wrap them in a `Send` container to force our will.
// FIXME: this is a pretty terrible hack. Any other solution would be preferred.
struct ForceSend<T>(pub T);
unsafe impl<T> Send for ForceSend<T> {}
// FIXME: use the enum from libsyntax?
#[derive(Clone, Copy)]
enum MacroStyle {
@ -81,34 +73,28 @@ pub fn rewrite_macro(mac: &ast::Mac,
};
}
let wrapped_tt_vec = ForceSend(mac.node.tts.clone());
// Wrap expression parsing logic in a thread since the libsyntax parser
// panics on failure, which we do not want to propagate.
// The expression vector is wrapped in an Option inside a Result.
let expr_vec_result = thread::catch_panic(move || {
let parse_session = ParseSess::new();
let mut parser = tts_to_parser(&parse_session, wrapped_tt_vec.0, vec![]);
let mut expr_vec = vec![];
let parse_session = ParseSess::new();
let mut parser = tts_to_parser(&parse_session, mac.node.tts.clone(), Vec::new());
let mut expr_vec = Vec::new();
loop {
expr_vec.push(parser.parse_expr());
loop {
expr_vec.push(match parser.parse_expr_nopanic() {
Ok(expr) => expr,
Err(..) => return None,
});
match parser.token {
Token::Eof => break,
Token::Comma => (),
_ => panic!("Macro not list-like, skiping..."),
}
let _ = parser.bump();
if parser.token == Token::Eof {
return None;
}
match parser.token {
Token::Eof => break,
Token::Comma => (),
_ => return None,
}
Some(expr_vec)
});
let expr_vec = try_opt!(try_opt!(expr_vec_result.ok()));
let _ = parser.bump();
if parser.token == Token::Eof {
return None;
}
}
match style {
MacroStyle::Parens => {

View File

@ -75,6 +75,9 @@ pub fn last_line_width(s: &str) -> usize {
fn is_skip(meta_item: &MetaItem) -> bool {
match meta_item.node {
MetaItem_::MetaWord(ref s) => *s == SKIP_ANNOTATION,
MetaItem_::MetaList(ref s, ref l) => {
*s == "cfg_attr" && l.len() == 2 && is_skip(&l[1])
}
_ => false,
}
}

View File

@ -0,0 +1,7 @@
macro_rules! test {
($($t:tt)*) => {}
}
fn main() {
test!( a : B => c d );
}

View File

@ -135,7 +135,6 @@ fn print_mismatches(result: HashMap<String, Vec<Mismatch>>) {
pub fn idempotent_check(filename: String) -> Result<FormatReport, HashMap<String, Vec<Mismatch>>> {
let sig_comments = read_significant_comments(&filename);
let mut config = get_config(sig_comments.get("config").map(|x| &(*x)[..]));
let args = vec!["rustfmt".to_owned(), filename];
for (key, val) in &sig_comments {
if key != "target" && key != "config" {
@ -146,7 +145,7 @@ pub fn idempotent_check(filename: String) -> Result<FormatReport, HashMap<String
// Don't generate warnings for to-do items.
config.report_todo = ReportTactic::Never;
let mut file_map = format(args, &config);
let mut file_map = format(Path::new(&filename), &config);
let format_report = fmt_lines(&mut file_map, &config);
// Won't panic, as we're not doing any IO.

View File

@ -0,0 +1,7 @@
macro_rules! test {
($($t:tt)*) => {}
}
fn main() {
test!( a : B => c d );
}