mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-22 04:34:51 +00:00
commit
02c118ae72
@ -1,5 +1,7 @@
|
||||
language: rust
|
||||
rust:
|
||||
- stable
|
||||
- beta
|
||||
- nightly
|
||||
|
||||
sudo: false
|
||||
|
41
Cargo.lock
generated
41
Cargo.lock
generated
@ -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"
|
||||
|
@ -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]
|
||||
|
33
README.md
33
README.md
@ -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.
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
|
84
src/lib.rs
84
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>>>,
|
||||
}
|
||||
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));
|
||||
|
||||
|
@ -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 => {
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
7
tests/source/macro_not_expr.rs
Normal file
7
tests/source/macro_not_expr.rs
Normal file
@ -0,0 +1,7 @@
|
||||
macro_rules! test {
|
||||
($($t:tt)*) => {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test!( a : B => c d );
|
||||
}
|
@ -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.
|
||||
|
7
tests/target/macro_not_expr.rs
Normal file
7
tests/target/macro_not_expr.rs
Normal file
@ -0,0 +1,7 @@
|
||||
macro_rules! test {
|
||||
($($t:tt)*) => {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test!( a : B => c d );
|
||||
}
|
Loading…
Reference in New Issue
Block a user