From f21db0afc0ba0076f03d556eadb86e271cacca21 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 18 Nov 2019 07:38:36 -0800 Subject: [PATCH] Rustup to rustc 1.41.0-nightly (a0d40f8bd 2019-11-18) --- Cargo.toml | 1 + clippy_lints/src/write.rs | 86 ++++++++++++++++----------------------- 2 files changed, 36 insertions(+), 51 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 300e40d4e358..b66182505341 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] } diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index b8773b47a99d..df298e847760 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -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}; @@ -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, @@ -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, @@ -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, ); @@ -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, @@ -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, ); @@ -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 || { @@ -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 @@ -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, Option) { +fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (Option, Option) { use fmt_macros::*; let tts = tts.clone(); @@ -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() { @@ -378,11 +368,7 @@ 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, ); } @@ -390,11 +376,7 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O expr } else { return ( - Some(FmtStr { - contents: fmtstr, - style: fmtstyle, - span: fmtspan, - }), + Some(fmtstr), None, ); }; @@ -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, c: Result| { let c = c.unwrap(); @@ -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), }