Skip to content

Commit 65ed447

Browse files
committed
Auto merge of #4837 - flip1995:integration, r=<try>
[WIP] RIIR: Integration tests In #4825 the `rust-lang/chalk` test failed because the output was too large. I didn't want to completely disabling the output, since showing the backtrace of an ICE directly in travis is pretty useful. Since finding strings in command outputs is easier in Rust, than in bash, I just RIIRed it. This and also rewriting our tests in Rust may help with trying out new CI platforms (cc #4577) Based on #4825, so I could test it. changelog: none
2 parents b4f1769 + d5c485b commit 65ed447

28 files changed

+202
-219
lines changed

.travis.yml

+3-4
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,8 @@ matrix:
6565
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
6666
- env: INTEGRATION=Geal/nom
6767
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
68-
# FIXME blocked on https://github.com/rust-lang/rust-clippy/issues/4727
69-
#- env: INTEGRATION=rust-lang/rustfmt
70-
# if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
68+
- env: INTEGRATION=rust-lang/rustfmt
69+
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
7170
- env: INTEGRATION=hyperium/hyper
7271
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
7372
- env: INTEGRATION=bluss/rust-itertools
@@ -125,7 +124,7 @@ before_script:
125124
script:
126125
- |
127126
if [[ -n ${INTEGRATION} ]]; then
128-
./ci/integration-tests.sh && sleep 5
127+
cargo test --test integration --features integration && sleep 5
129128
else
130129
./ci/base-tests.sh && sleep 5
131130
fi

Cargo.toml

+5-1
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,13 @@ clippy_lints = { version = "0.0.212", path = "clippy_lints" }
3838
regex = "1"
3939
semver = "0.9"
4040
rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"}
41+
git2 = { version = "0.10", optional = true }
42+
tempfile = { version = "3.1.0", optional = true }
4143

4244
[dev-dependencies]
4345
cargo_metadata = "0.9.0"
44-
compiletest_rs = { version = "0.3.24", features = ["tmp"] }
46+
compiletest_rs = { version = "0.4.0", features = ["tmp"] }
47+
tester = "0.7"
4548
lazy_static = "1.0"
4649
clippy-mini-macro-test = { version = "0.2", path = "mini-macro" }
4750
serde = { version = "1.0", features = ["derive"] }
@@ -58,3 +61,4 @@ rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"}
5861
[features]
5962
deny-warnings = []
6063
debugging = []
64+
integration = ["git2", "tempfile"]

ci/integration-tests.sh

-37
This file was deleted.

clippy_lints/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
#![feature(box_syntax)]
44
#![feature(box_patterns)]
5-
#![feature(never_type)]
65
#![feature(rustc_private)]
76
#![feature(slice_patterns)]
87
#![feature(stmt_expr_attributes)]

clippy_lints/src/loops.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ fn never_loop_expr(expr: &Expr, main_loop_id: HirId) -> NeverLoopResult {
720720
ExprKind::Struct(_, _, None)
721721
| ExprKind::Yield(_, _)
722722
| ExprKind::Closure(_, _, _, _, _)
723-
| ExprKind::InlineAsm(_, _, _)
723+
| ExprKind::InlineAsm(_)
724724
| ExprKind::Path(_)
725725
| ExprKind::Lit(_)
726726
| ExprKind::Err => NeverLoopResult::Otherwise,

clippy_lints/src/utils/author.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -458,8 +458,8 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
458458
println!("Ret(None) = {};", current);
459459
}
460460
},
461-
ExprKind::InlineAsm(_, ref _input, ref _output) => {
462-
println!("InlineAsm(_, ref input, ref output) = {};", current);
461+
ExprKind::InlineAsm(_) => {
462+
println!("InlineAsm(_) = {};", current);
463463
println!(" // unimplemented: `ExprKind::InlineAsm` is not further destructured at the moment");
464464
},
465465
ExprKind::Struct(ref path, ref fields, ref opt_base) => {

clippy_lints/src/utils/inspector.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -282,14 +282,16 @@ fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr, indent: usize) {
282282
print_expr(cx, e, indent + 1);
283283
}
284284
},
285-
hir::ExprKind::InlineAsm(_, ref input, ref output) => {
285+
hir::ExprKind::InlineAsm(ref asm) => {
286+
let inputs = &asm.inputs_exprs;
287+
let outputs = &asm.outputs_exprs;
286288
println!("{}InlineAsm", ind);
287289
println!("{}inputs:", ind);
288-
for e in input {
290+
for e in inputs.iter() {
289291
print_expr(cx, e, indent + 1);
290292
}
291293
println!("{}outputs:", ind);
292-
for e in output {
294+
for e in outputs.iter() {
293295
print_expr(cx, e, indent + 1);
294296
}
295297
},

clippy_lints/src/write.rs

+35-57
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_errors::Applicability;
88
use rustc_lexer::unescape::{self, EscapeError};
99
use rustc_parse::parser;
1010
use syntax::ast::*;
11+
use syntax::symbol::Symbol;
1112
use syntax::token;
1213
use syntax::tokenstream::TokenStream;
1314
use syntax_pos::{BytePos, Span};
@@ -190,7 +191,7 @@ impl EarlyLintPass for Write {
190191
if mac.path == sym!(println) {
191192
span_lint(cx, PRINT_STDOUT, mac.span, "use of `println!`");
192193
if let (Some(fmt_str), _) = check_tts(cx, &mac.tts, false) {
193-
if fmt_str.contents.is_empty() {
194+
if fmt_str.symbol == Symbol::intern("") {
194195
span_lint_and_sugg(
195196
cx,
196197
PRINTLN_EMPTY_STRING,
@@ -205,7 +206,7 @@ impl EarlyLintPass for Write {
205206
} else if mac.path == sym!(print) {
206207
span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`");
207208
if let (Some(fmt_str), _) = check_tts(cx, &mac.tts, false) {
208-
if check_newlines(&fmt_str.contents, fmt_str.style) {
209+
if check_newlines(&fmt_str) {
209210
span_lint_and_then(
210211
cx,
211212
PRINT_WITH_NEWLINE,
@@ -216,7 +217,7 @@ impl EarlyLintPass for Write {
216217
"use `println!` instead",
217218
vec![
218219
(mac.path.span, String::from("println")),
219-
(fmt_str.newline_span(), String::new()),
220+
(newline_span(&fmt_str), String::new()),
220221
],
221222
Applicability::MachineApplicable,
222223
);
@@ -226,7 +227,7 @@ impl EarlyLintPass for Write {
226227
}
227228
} else if mac.path == sym!(write) {
228229
if let (Some(fmt_str), _) = check_tts(cx, &mac.tts, true) {
229-
if check_newlines(&fmt_str.contents, fmt_str.style) {
230+
if check_newlines(&fmt_str) {
230231
span_lint_and_then(
231232
cx,
232233
WRITE_WITH_NEWLINE,
@@ -237,7 +238,7 @@ impl EarlyLintPass for Write {
237238
"use `writeln!()` instead",
238239
vec![
239240
(mac.path.span, String::from("writeln")),
240-
(fmt_str.newline_span(), String::new()),
241+
(newline_span(&fmt_str), String::new()),
241242
],
242243
Applicability::MachineApplicable,
243244
);
@@ -247,7 +248,7 @@ impl EarlyLintPass for Write {
247248
}
248249
} else if mac.path == sym!(writeln) {
249250
if let (Some(fmt_str), expr) = check_tts(cx, &mac.tts, true) {
250-
if fmt_str.contents.is_empty() {
251+
if fmt_str.symbol == Symbol::intern("") {
251252
let mut applicability = Applicability::MachineApplicable;
252253
let suggestion = expr.map_or_else(
253254
move || {
@@ -272,37 +273,27 @@ impl EarlyLintPass for Write {
272273
}
273274
}
274275

275-
/// The arguments of a `print[ln]!` or `write[ln]!` invocation.
276-
struct FmtStr {
277-
/// The contents of the format string (inside the quotes).
278-
contents: String,
279-
style: StrStyle,
280-
/// The span of the format string, including quotes, the raw marker, and any raw hashes.
281-
span: Span,
282-
}
283-
284-
impl FmtStr {
285-
/// Given a format string that ends in a newline and its span, calculates the span of the
286-
/// newline.
287-
fn newline_span(&self) -> Span {
288-
let sp = self.span;
276+
/// Given a format string that ends in a newline and its span, calculates the span of the
277+
/// newline.
278+
fn newline_span(fmtstr: &StrLit) -> Span {
279+
let sp = fmtstr.span;
280+
let contents = &fmtstr.symbol.as_str();
289281

290-
let newline_sp_hi = sp.hi()
291-
- match self.style {
292-
StrStyle::Cooked => BytePos(1),
293-
StrStyle::Raw(hashes) => BytePos((1 + hashes).into()),
294-
};
295-
296-
let newline_sp_len = if self.contents.ends_with('\n') {
297-
BytePos(1)
298-
} else if self.contents.ends_with(r"\n") {
299-
BytePos(2)
300-
} else {
301-
panic!("expected format string to contain a newline");
282+
let newline_sp_hi = sp.hi()
283+
- match fmtstr.style {
284+
StrStyle::Cooked => BytePos(1),
285+
StrStyle::Raw(hashes) => BytePos((1 + hashes).into()),
302286
};
303287

304-
sp.with_lo(newline_sp_hi - newline_sp_len).with_hi(newline_sp_hi)
305-
}
288+
let newline_sp_len = if contents.ends_with('\n') {
289+
BytePos(1)
290+
} else if contents.ends_with(r"\n") {
291+
BytePos(2)
292+
} else {
293+
panic!("expected format string to contain a newline");
294+
};
295+
296+
sp.with_lo(newline_sp_hi - newline_sp_len).with_hi(newline_sp_hi)
306297
}
307298

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

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

345-
let (fmtstr, fmtstyle) = match parser.parse_str().map_err(|mut err| err.cancel()) {
346-
Ok((fmtstr, fmtstyle)) => (fmtstr.to_string(), fmtstyle),
336+
let fmtstr = match parser.parse_str_lit() {
337+
Ok(fmtstr) => fmtstr,
347338
Err(_) => return (None, expr),
348339
};
349-
let fmtspan = parser.prev_span;
350-
let tmp = fmtstr.clone();
340+
let tmp = fmtstr.symbol.as_str();
351341
let mut args = vec![];
352342
let mut fmt_parser = Parser::new(&tmp, None, Vec::new(), false);
353343
while let Some(piece) = fmt_parser.next() {
@@ -377,26 +367,12 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O
377367
ty_span: None,
378368
};
379369
if !parser.eat(&token::Comma) {
380-
return (
381-
Some(FmtStr {
382-
contents: fmtstr,
383-
style: fmtstyle,
384-
span: fmtspan,
385-
}),
386-
expr,
387-
);
370+
return (Some(fmtstr), expr);
388371
}
389372
let token_expr = if let Ok(expr) = parser.parse_expr().map_err(|mut err| err.cancel()) {
390373
expr
391374
} else {
392-
return (
393-
Some(FmtStr {
394-
contents: fmtstr,
395-
style: fmtstyle,
396-
span: fmtspan,
397-
}),
398-
None,
399-
);
375+
return (Some(fmtstr), None);
400376
};
401377
match &token_expr.kind {
402378
ExprKind::Lit(_) => {
@@ -448,11 +424,13 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O
448424
/// Checks if the format string contains a single newline that terminates it.
449425
///
450426
/// Literal and escaped newlines are both checked (only literal for raw strings).
451-
fn check_newlines(contents: &str, style: StrStyle) -> bool {
427+
fn check_newlines(fmtstr: &StrLit) -> bool {
452428
let mut has_internal_newline = false;
453429
let mut last_was_cr = false;
454430
let mut should_lint = false;
455431

432+
let contents = &fmtstr.symbol.as_str();
433+
456434
let mut cb = |r: Range<usize>, c: Result<char, EscapeError>| {
457435
let c = c.unwrap();
458436

@@ -466,7 +444,7 @@ fn check_newlines(contents: &str, style: StrStyle) -> bool {
466444
}
467445
};
468446

469-
match style {
447+
match fmtstr.style {
470448
StrStyle::Cooked => unescape::unescape_str(contents, &mut cb),
471449
StrStyle::Raw(_) => unescape::unescape_raw_str(contents, &mut cb),
472450
}

src/driver.rs

+6
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
7575
clippy_lints::register_pre_expansion_lints(&mut lint_store, &conf);
7676
clippy_lints::register_renamed(&mut lint_store);
7777
}));
78+
79+
// FIXME: #4825; This is required, because Clippy lints that are based on MIR have to be
80+
// run on the unoptimized MIR. On the other hand this results in some false negatives. If
81+
// MIR passes can be enabled / disabled separately, we should figure out, what passes to
82+
// use for Clippy.
83+
config.opts.debugging_opts.mir_opt_level = 0;
7884
}
7985
}
8086

tests/compile-test.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![feature(test)]
22

33
use compiletest_rs as compiletest;
4-
extern crate test;
4+
extern crate tester as test;
55

66
use std::env::{set_var, var};
77
use std::ffi::OsStr;

0 commit comments

Comments
 (0)