diff --git a/src/bin/cargo/commands/fix.rs b/src/bin/cargo/commands/fix.rs index f552b7d024c..6285481bca9 100644 --- a/src/bin/cargo/commands/fix.rs +++ b/src/bin/cargo/commands/fix.rs @@ -54,7 +54,7 @@ pub fn cli() -> App { ) .after_help( "\ -This Cargo subcommmand will automatically take rustc's suggestions from +This Cargo subcommand will automatically take rustc's suggestions from diagnostics like warnings and apply them to your source code. This is intended to help automate tasks that rustc itself already knows how to tell you to fix! The `cargo fix` subcommand is also being developed for the Rust 2018 edition diff --git a/src/cargo/core/compiler/build_config.rs b/src/cargo/core/compiler/build_config.rs index 1f5d213c9bb..890e35a811b 100644 --- a/src/cargo/core/compiler/build_config.rs +++ b/src/cargo/core/compiler/build_config.rs @@ -16,6 +16,8 @@ pub struct BuildConfig { pub mode: CompileMode, /// Whether to print std output in json format (for machine reading) pub message_format: MessageFormat, + /// Force cargo to do a full rebuild and treat each target as changed. + pub force_rebuild: bool, /// Output a build plan to stdout instead of actually compiling. pub build_plan: bool, /// Use Cargo itself as the wrapper around rustc, only used for `cargo fix` @@ -79,6 +81,7 @@ impl BuildConfig { release: false, mode, message_format: MessageFormat::Human, + force_rebuild: false, build_plan: false, cargo_as_rustc_wrapper: false, extra_rustc_env: Vec::new(), diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 50ab534f2eb..3e2ab3a6792 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -101,6 +101,7 @@ fn compile<'a, 'cfg: 'a>( ) -> CargoResult<()> { let bcx = cx.bcx; let build_plan = bcx.build_config.build_plan; + let force_rebuild = bcx.build_config.force_rebuild; if !cx.compiled.insert(*unit) { return Ok(()); } @@ -124,6 +125,7 @@ fn compile<'a, 'cfg: 'a>( ) } else { let (mut freshness, dirty, fresh) = fingerprint::prepare_target(cx, unit)?; + let work = if unit.mode.is_doc() { rustdoc(cx, unit)? } else { @@ -133,7 +135,7 @@ fn compile<'a, 'cfg: 'a>( let dirty = work.then(link_targets(cx, unit, false)?).then(dirty); let fresh = link_targets(cx, unit, true)?.then(fresh); - if exec.force_rebuild(unit) { + if exec.force_rebuild(unit) || force_rebuild { freshness = Freshness::Dirty; } diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index b8e30ca5d15..070743dce55 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -433,7 +433,7 @@ impl CompileFilter { /// Generates all the base targets for the packages the user has requested to /// compile. Dependencies for these targets are computed later in /// `unit_dependencies`. -fn generate_targets<'a>( +pub fn generate_targets<'a>( ws: &Workspace, profiles: &Profiles, packages: &[&'a Package], diff --git a/src/cargo/ops/fix.rs b/src/cargo/ops/fix.rs index 75231b1139a..7bad01ca741 100644 --- a/src/cargo/ops/fix.rs +++ b/src/cargo/ops/fix.rs @@ -43,6 +43,8 @@ pub fn fix(ws: &Workspace, opts: &mut FixOptions) -> CargoResult<()> { )); let _started = lock_server.start()?; + opts.compile_opts.build_config.force_rebuild = true; + if opts.broken_code { let key = BROKEN_CODE_ENV.to_string(); opts.compile_opts.build_config.extra_rustc_env.push((key, "1".to_string())); diff --git a/src/cargo/ops/mod.rs b/src/cargo/ops/mod.rs index 9c09f14f5ed..737439b8812 100644 --- a/src/cargo/ops/mod.rs +++ b/src/cargo/ops/mod.rs @@ -1,5 +1,5 @@ pub use self::cargo_clean::{clean, CleanOptions}; -pub use self::cargo_compile::{compile, compile_with_exec, compile_ws, CompileOptions}; +pub use self::cargo_compile::{compile, compile_with_exec, compile_ws, CompileOptions, generate_targets}; pub use self::cargo_compile::{CompileFilter, FilterRule, Packages}; pub use self::cargo_read_manifest::{read_package, read_packages}; pub use self::cargo_run::run; diff --git a/tests/testsuite/fix.rs b/tests/testsuite/fix.rs index bce8bf8fffd..ef32eaffc75 100644 --- a/tests/testsuite/fix.rs +++ b/tests/testsuite/fix.rs @@ -1068,3 +1068,118 @@ fn does_not_warn_about_dirty_ignored_files() { execs().with_status(0), ); } + +#[test] +fn shows_warnings_on_second_run_without_changes() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + "#, + ) + .file( + "src/lib.rs", + r#" + use std::default::Default; + + pub fn foo() { + } + "#, + ) + .build(); + + assert_that( + p.cargo("fix --allow-no-vcs"), + execs().with_status(0).with_stderr_contains("[..]warning: unused import[..]"), + ); + + assert_that( + p.cargo("fix --allow-no-vcs"), + execs().with_status(0).with_stderr_contains("[..]warning: unused import[..]"), + ); +} + +#[test] +fn shows_warnings_on_second_run_without_changes_on_multiple_targets() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [workspace] + "#, + ) + .file( + "src/lib.rs", + r#" + use std::default::Default; + + pub fn a() -> u32 { 3 } + "#, + ) + .file( + "src/main.rs", + r#" + use std::default::Default; + fn main() { println!("3"); } + "#, + ) + .file( + "tests/foo.rs", + r#" + use std::default::Default; + #[test] + fn foo_test() { + println!("3"); + } + "#, + ) + .file( + "tests/bar.rs", + r#" + use std::default::Default; + + #[test] + fn foo_test() { + println!("3"); + } + "#, + ) + .file( + "examples/fooxample.rs", + r#" + use std::default::Default; + + fn main() { + println!("3"); + } + "#, + ) + .build(); + + assert_that( + p.cargo("fix --allow-no-vcs --all-targets"), + execs().with_status(0) + .with_stderr_contains(" --> examples/fooxample.rs:2:21") + .with_stderr_contains(" --> src/lib.rs:2:21") + .with_stderr_contains(" --> src/main.rs:2:21") + .with_stderr_contains(" --> tests/bar.rs:2:21") + .with_stderr_contains(" --> tests/foo.rs:2:21"), + ); + + assert_that( + p.cargo("fix --allow-no-vcs --all-targets"), + execs().with_status(0) + .with_stderr_contains(" --> examples/fooxample.rs:2:21") + .with_stderr_contains(" --> src/lib.rs:2:21") + .with_stderr_contains(" --> src/main.rs:2:21") + .with_stderr_contains(" --> tests/bar.rs:2:21") + .with_stderr_contains(" --> tests/foo.rs:2:21"), + ); +}