about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMarcus Klaas de Vries <mail@marcusklaas.nl>2015-10-23 22:57:43 +0200
committerMarcus Klaas de Vries <mail@marcusklaas.nl>2015-10-23 22:57:43 +0200
commit02c118ae7207c2d5a48a2b1cf5f6a59dbbe1d314 (patch)
treef73c9f7d9e06fe9026de8a729da7dfbc7a63e2e8 /src
parent7e76fad1f55945c196b32e6629ebaecc4ebfda74 (diff)
parent7fdfff6e58cd30548b1d02946364b746243cdc02 (diff)
Merge pull request #523 from alexcrichton/stable
Move to stable Rust
Diffstat (limited to 'src')
-rw-r--r--src/bin/rustfmt.rs86
-rw-r--r--src/chains.rs12
-rw-r--r--src/comment.rs2
-rw-r--r--src/lib.rs84
-rw-r--r--src/macros.rs54
-rw-r--r--src/utils.rs3
6 files changed, 89 insertions, 152 deletions
diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs
index 01c292948df..6b3405aa936 100644
--- a/src/bin/rustfmt.rs
+++ b/src/bin/rustfmt.rs
@@ -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();
-
-    // 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");
+    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;
+        }
+    };
+
+    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))
 }
diff --git a/src/chains.rs b/src/chains.rs
index 4b6824a9073..4716f545b3f 100644
--- a/src/chains.rs
+++ b/src/chains.rs
@@ -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)
diff --git a/src/comment.rs b/src/comment.rs
index 045d1cb5047..091b4293ad3 100644
--- a/src/comment.rs
+++ b/src/comment.rs
@@ -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),
diff --git a/src/lib.rs b/src/lib.rs
index 03422a20c36..51497e3b1c3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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>>>,
-}
-
-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");
-    }
-
-    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));
+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);
 
-    {
-        let config = Rc::new(config.clone());
-        let mut call_ctxt = RustFmtCalls {
-            config: config,
-            result: result.clone(),
-        };
-        rustc_driver::run_compiler(&args, &mut call_ctxt);
-    }
+    // 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);
 
-    // 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));
 
diff --git a/src/macros.rs b/src/macros.rs
index 9035b0c7d8b..bede00d6e9e 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -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![];
-
-        loop {
-            expr_vec.push(parser.parse_expr());
-
-            match parser.token {
-                Token::Eof => break,
-                Token::Comma => (),
-                _ => panic!("Macro not list-like, skiping..."),
-            }
-
-            let _ = parser.bump();
-
-            if parser.token == Token::Eof {
-                return None;
-            }
+    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(match parser.parse_expr_nopanic() {
+            Ok(expr) => expr,
+            Err(..) => 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 => {
diff --git a/src/utils.rs b/src/utils.rs
index 0fd749a5471..fea385532d0 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -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,
     }
 }