Skip to content

Commit

Permalink
Rustup to rustc 1.41.0-nightly (a0d40f8 2019-11-18)
Browse files Browse the repository at this point in the history
  • Loading branch information
Manishearth committed Nov 18, 2019
1 parent b4f1769 commit f21db0a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 51 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"}
[dev-dependencies]
cargo_metadata = "0.9.0"
compiletest_rs = { version = "0.3.24", features = ["tmp"] }
tester = "0.6"
lazy_static = "1.0"
clippy-mini-macro-test = { version = "0.2", path = "mini-macro" }
serde = { version = "1.0", features = ["derive"] }
Expand Down
86 changes: 35 additions & 51 deletions clippy_lints/src/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use rustc_errors::Applicability;
use rustc_lexer::unescape::{self, EscapeError};
use rustc_parse::parser;
use syntax::ast::*;
use syntax::symbol::Symbol;
use syntax::token;
use syntax::tokenstream::TokenStream;
use syntax_pos::{BytePos, Span};
Expand Down Expand Up @@ -190,7 +191,7 @@ impl EarlyLintPass for Write {
if mac.path == sym!(println) {
span_lint(cx, PRINT_STDOUT, mac.span, "use of `println!`");
if let (Some(fmt_str), _) = check_tts(cx, &mac.tts, false) {
if fmt_str.contents.is_empty() {
if fmt_str.symbol == Symbol::intern("") {
span_lint_and_sugg(
cx,
PRINTLN_EMPTY_STRING,
Expand All @@ -205,7 +206,7 @@ impl EarlyLintPass for Write {
} else if mac.path == sym!(print) {
span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`");
if let (Some(fmt_str), _) = check_tts(cx, &mac.tts, false) {
if check_newlines(&fmt_str.contents, fmt_str.style) {
if check_newlines(&fmt_str) {
span_lint_and_then(
cx,
PRINT_WITH_NEWLINE,
Expand All @@ -216,7 +217,7 @@ impl EarlyLintPass for Write {
"use `println!` instead",
vec![
(mac.path.span, String::from("println")),
(fmt_str.newline_span(), String::new()),
(newline_span(&fmt_str), String::new()),
],
Applicability::MachineApplicable,
);
Expand All @@ -226,7 +227,7 @@ impl EarlyLintPass for Write {
}
} else if mac.path == sym!(write) {
if let (Some(fmt_str), _) = check_tts(cx, &mac.tts, true) {
if check_newlines(&fmt_str.contents, fmt_str.style) {
if check_newlines(&fmt_str) {
span_lint_and_then(
cx,
WRITE_WITH_NEWLINE,
Expand All @@ -237,7 +238,7 @@ impl EarlyLintPass for Write {
"use `writeln!()` instead",
vec![
(mac.path.span, String::from("writeln")),
(fmt_str.newline_span(), String::new()),
(newline_span(&fmt_str), String::new()),
],
Applicability::MachineApplicable,
);
Expand All @@ -247,7 +248,7 @@ impl EarlyLintPass for Write {
}
} else if mac.path == sym!(writeln) {
if let (Some(fmt_str), expr) = check_tts(cx, &mac.tts, true) {
if fmt_str.contents.is_empty() {
if fmt_str.symbol == Symbol::intern("") {
let mut applicability = Applicability::MachineApplicable;
let suggestion = expr.map_or_else(
move || {
Expand All @@ -272,37 +273,27 @@ impl EarlyLintPass for Write {
}
}

/// The arguments of a `print[ln]!` or `write[ln]!` invocation.
struct FmtStr {
/// The contents of the format string (inside the quotes).
contents: String,
style: StrStyle,
/// The span of the format string, including quotes, the raw marker, and any raw hashes.
span: Span,
}

impl FmtStr {
/// Given a format string that ends in a newline and its span, calculates the span of the
/// newline.
fn newline_span(&self) -> Span {
let sp = self.span;
/// Given a format string that ends in a newline and its span, calculates the span of the
/// newline.
fn newline_span(fmtstr: &StrLit) -> Span {
let sp = fmtstr.span;
let contents = &fmtstr.symbol.as_str();

let newline_sp_hi = sp.hi()
- match self.style {
StrStyle::Cooked => BytePos(1),
StrStyle::Raw(hashes) => BytePos((1 + hashes).into()),
};

let newline_sp_len = if self.contents.ends_with('\n') {
BytePos(1)
} else if self.contents.ends_with(r"\n") {
BytePos(2)
} else {
panic!("expected format string to contain a newline");
let newline_sp_hi = sp.hi()
- match fmtstr.style {
StrStyle::Cooked => BytePos(1),
StrStyle::Raw(hashes) => BytePos((1 + hashes).into()),
};

sp.with_lo(newline_sp_hi - newline_sp_len).with_hi(newline_sp_hi)
}
let newline_sp_len = if contents.ends_with('\n') {
BytePos(1)
} else if contents.ends_with(r"\n") {
BytePos(2)
} else {
panic!("expected format string to contain a newline");
};

sp.with_lo(newline_sp_hi - newline_sp_len).with_hi(newline_sp_hi)
}

/// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two
Expand All @@ -325,7 +316,7 @@ impl FmtStr {
/// (Some("string to write: {}"), Some(buf))
/// ```
#[allow(clippy::too_many_lines)]
fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (Option<FmtStr>, Option<Expr>) {
fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (Option<StrLit>, Option<Expr>) {
use fmt_macros::*;
let tts = tts.clone();

Expand All @@ -342,12 +333,11 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O
}
}

let (fmtstr, fmtstyle) = match parser.parse_str().map_err(|mut err| err.cancel()) {
Ok((fmtstr, fmtstyle)) => (fmtstr.to_string(), fmtstyle),
let fmtstr = match parser.parse_str_lit() {
Ok(fmtstr) => fmtstr,
Err(_) => return (None, expr),
};
let fmtspan = parser.prev_span;
let tmp = fmtstr.clone();
let tmp = fmtstr.symbol.as_str();
let mut args = vec![];
let mut fmt_parser = Parser::new(&tmp, None, Vec::new(), false);
while let Some(piece) = fmt_parser.next() {
Expand Down Expand Up @@ -378,23 +368,15 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O
};
if !parser.eat(&token::Comma) {
return (
Some(FmtStr {
contents: fmtstr,
style: fmtstyle,
span: fmtspan,
}),
Some(fmtstr),
expr,
);
}
let token_expr = if let Ok(expr) = parser.parse_expr().map_err(|mut err| err.cancel()) {
expr
} else {
return (
Some(FmtStr {
contents: fmtstr,
style: fmtstyle,
span: fmtspan,
}),
Some(fmtstr),
None,
);
};
Expand Down Expand Up @@ -448,11 +430,13 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O
/// Checks if the format string contains a single newline that terminates it.
///
/// Literal and escaped newlines are both checked (only literal for raw strings).
fn check_newlines(contents: &str, style: StrStyle) -> bool {
fn check_newlines(fmtstr: &StrLit) -> bool {
let mut has_internal_newline = false;
let mut last_was_cr = false;
let mut should_lint = false;

let contents = &fmtstr.symbol.as_str();

let mut cb = |r: Range<usize>, c: Result<char, EscapeError>| {
let c = c.unwrap();

Expand All @@ -466,7 +450,7 @@ fn check_newlines(contents: &str, style: StrStyle) -> bool {
}
};

match style {
match fmtstr.style {
StrStyle::Cooked => unescape::unescape_str(contents, &mut cb),
StrStyle::Raw(_) => unescape::unescape_raw_str(contents, &mut cb),
}
Expand Down

0 comments on commit f21db0a

Please sign in to comment.