From 579fb34417844cf6242c62ba0b6f2f9c72772ba0 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 22 Oct 2015 14:37:13 -0700 Subject: [PATCH] Remove dependence on rustc/rustc_driver, use syntex Instead just parse manually with the `syntex_syntax` crate which is a clone of libsyntax on crates.io which builds on stable Rust. --- Cargo.lock | 24 +++++++++++++++ Cargo.toml | 1 + src/lib.rs | 77 +++++++++---------------------------------------- src/macros.rs | 74 ++++++++++++----------------------------------- tests/system.rs | 3 +- 5 files changed, 57 insertions(+), 122 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 61a586da4f39..d3f20f8b7591 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,7 @@ dependencies = [ "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)", @@ -21,6 +22,11 @@ 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" @@ -93,6 +99,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" @@ -115,6 +134,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" diff --git a/Cargo.toml b/Cargo.toml index fc8f0aa6026e..60df8ac69048 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ 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" diff --git a/src/lib.rs b/src/lib.rs index 0e3dff21b694..51497e3b1c35 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,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; @@ -28,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; @@ -380,65 +370,24 @@ pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { report } -struct RustFmtCalls { - config: Rc, - result: Rc>>, -} +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, - _: &Option, - _: &diagnostics::registry::Registry) - -> Option<(Input, Option)> { - 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, 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, 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 37ae0af3a0be..bede00d6e9e3 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -19,15 +19,10 @@ // 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 std::collections::hash_map::{HashMap, Entry}; - use syntax::ast; use syntax::parse::token::{Eof, Comma, Token}; use syntax::parse::{ParseSess, tts_to_parser}; use syntax::codemap::{mk_sp, BytePos}; -use syntax::parse::token; -use syntax::util::interner::StrInterner; use Indent; use rewrite::RewriteContext; @@ -37,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(pub T); -unsafe impl Send for ForceSend {} - // FIXME: use the enum from libsyntax? #[derive(Clone, Copy)] enum MacroStyle { @@ -84,38 +73,28 @@ pub fn rewrite_macro(mac: &ast::Mac, }; } - let wrapped_tt_vec = ForceSend(mac.node.tts.clone()); - let my_interner = ForceSend(clone_interner()); + 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(); - // 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::spawn(move || { - let parse_session = ParseSess::new(); - let mut parser = tts_to_parser(&parse_session, wrapped_tt_vec.0, vec![]); - let mut expr_vec = vec![]; - token::get_ident_interner().reset(my_interner.0); + loop { + expr_vec.push(match parser.parse_expr_nopanic() { + Ok(expr) => expr, + Err(..) => return None, + }); - 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; - } + match parser.token { + Token::Eof => break, + Token::Comma => (), + _ => return None, } - Some(ForceSend((expr_vec, clone_interner()))) - }); - let (expr_vec, interner) = try_opt!(try_opt!(expr_vec_result.join().ok())).0; - token::get_ident_interner().reset(interner); + let _ = parser.bump(); + + if parser.token == Token::Eof { + return None; + } + } match style { MacroStyle::Parens => { @@ -146,23 +125,6 @@ pub fn rewrite_macro(mac: &ast::Mac, } } -fn clone_interner() -> StrInterner { - let old = token::get_ident_interner(); - let new = StrInterner::new(); - let mut map = HashMap::new(); - for name in (0..old.len()).map(|i| i as u32).map(ast::Name) { - match map.entry(old.get(name)) { - Entry::Occupied(e) => { - new.gensym_copy(*e.get()); - } - Entry::Vacant(e) => { - e.insert(new.intern(&old.get(name))); - } - } - } - return new -} - fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle { let snippet = context.snippet(mac.span); let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value()); diff --git a/tests/system.rs b/tests/system.rs index b6dee149ed1f..649ccdf5647a 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -135,7 +135,6 @@ fn print_mismatches(result: HashMap>) { pub fn idempotent_check(filename: String) -> Result>> { 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