Giter Site home page Giter Site logo

rustfix's Introduction

⚠️ Rustfix has moved

The rustfix crate has moved to https://github.com/rust-lang/cargo/tree/master/crates/rustfix. Any issues about the rustfix library or cargo fix should be filed at https://github.com/rust-lang/cargo/issues. Any issues about the suggestions generated by the compiler should be filed at https://github.com/rust-lang/rust/issues.


rustfix

Latest Version Rust Documentation

Rustfix is a library defining useful structures that represent fix suggestions from rustc.

Current status

Currently, rustfix is split into two crates:

  • rustfix, a library for consuming and applying suggestions in the format that rustc outputs (this crate)
  • cargo-fix, a binary that works as cargo subcommand and that end users will use to fix their code (maintained in the cargo repo).

The library (and therefore this repo) is considered largely feature-complete. This is because:

  • There is no compiler or even rust-specific logic here
  • New lints and suggestions come from the Rust compiler (and external lints, like clippy).
  • rustfix doesn't touch the filesystem to implement fixes, or read from disk

Installation

cargo fix is a built-in command in Cargo since Rust 1.29. There is no need to install it separately from crates.io.

To use the rustfix library for use in your own fix project, add it to your Cargo.toml.

Using cargo fix --edition to transition to Rust 2021

Instructions on how to use this tool to transition a crate to Rust 2021 can be found in the Rust Edition Guide.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

rustfix's People

Contributors

3tilley avatar alexcrichton avatar bors[bot] avatar brainmaestro avatar calebcartwright avatar deeprobin avatar dnbln avatar ehuss avatar euclio avatar gnzlbg avatar jsgf avatar killercup avatar kornelski avatar leseulartichaut avatar light4 avatar little-dude avatar manishearth avatar matthiaskrgr avatar mitsuhiko avatar mre avatar oli-obk avatar p1n3appl3 avatar phansch avatar philipc avatar pietroalbini avatar pseitz avatar smoelius avatar yaahc avatar yvan-sraka avatar zackmdavis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rustfix's Issues

Emit a warning if automatically applied changes cause build to fail

We've got logic to automatically back out changes in this situation but we should also warn the user when this happens. Ideally we'd even say what the fixes were in the file with the errors and what the relevant code looked like, also ideally with links and instructions of how to report a bug to us.

Inform user of dirty working dir

If the cargo project we are in is a {git, hg, pijul, …} repo, we should check if the working tree is dirty. This way, it's much easier to track all the changes rustfix made.

If the tree is dirty, inform the user about it, and exit before applying any fixes. This should be overridable with an --allow-dirty flag.

Also cf. #73

Add in guard rails for auto-fixing code

Currently cargo fix will blindly apply fixes that it feels confident are the only way to fix something. This, with bugs, can cause code to stop compiling, however.

We should check that if a cargo check succeeds before rustfix runs and then fails afterwards, all fixes are backed out and a large warning/error is presented to the user. Ideally this message we present even includes information like how to report a bug to the rustfix repository and what information to include.

How interactive should rustfix be?

The current thinking is that we'll want rustfix to be entirely automatic by default, but that doesn't mean that we don't also want some level of user-interactivity. What's the right amount of user interactivity, how's it enabled, and how should it work?

Future-proof `cargo fix` CLI flags with Cargo's

Right now we blindly forward all arguments to cargo fix down to cargo check, which means that it may be difficult for us to add arguments to cargo fix itself. We'll want a story for how to add arguments to cargo fix specifically and how to specifically add arguments to the underlying Cargo subcommand.

UI for the 2018 edition release

The rustfix tool is going to be a banner feature of the 2018 edition coming up later this year, so I think we'll want to UI to be as good as we can get it to ensure that everyone's got a smooth experience with applying the tool and updating code.

How does rustfix work today?

I've been reading the code as-is to better understand how it works today, and I'll try to summarize it here for the unfamiliar but please correct me if I'm wrong! Today you can either execute rustfix or cargo fix and they'll do the same thing. The CLI takes no arguments and has a few flags that change its operation. Just executing rustfix means that it'll instead run cargo rustc -- --message-format json.

Once Cargo/rustc is executed rustfix slurps up all the output of rustc. The stderr stream is then parsed into a list of suggestions and replacements. All suggestions are then iterated over and by default presented to the user to ask whether the fix should be applied or not. If accepted then it's queued up to be applied later. This then happens for all suggestions found, and there's a flag as well to say "don't query me, just apply everything".

Finally after all this the suggestions will be applied one-by-one, updating the files on the filesystem.

What do we want the UI for the edition to feel like?

I think we're largely undecided on this in the sense that we haven't concretely nailed this down (although I may have missed it!). I'll put forth a strawman though for how I could see this working.

First off before we release the edition we'll want to test out lints, language features, and rustfix. To do that you'll first add #![warn(rust_2018_migration)] to the crate you'd like to update. This will include src/lib.rs, src/main.rs, tests/*.rs, examples/*.rs, etc. They'll all need this annotation. After that's applied you'll execute cargo fix. This'll then apply as many fixes as it can (no user interaction), but also continue to emit normal compiler warnings about things that couldn't be fixed.

The second scenario is when we've actually released the edition itself. The only difference here is that instead of #![warn(..)] all over the place you'll instead just say rust = '2018' in your Cargo.toml.

How to implement this?

Rustfix is shaping up to be a pretty simple tool (yay!). It's largely just taking suggestions from the compiler and actually applying them on the filesystem, assuming the compiler is correctly informing rustfix of changes that need to be made.

The actual integration though is going to be pretty tricky. For a the best-quality experience we'll want to make sure that rustfix gracefully handles things like workspaces, multiple crates/targets in a workspace, cross-compilation, etc. I think that we can get all this done with a "hack" which has worked out quite well for rustbuild historically, override rustc.

A new CLI

I'm envisioning a CLI that looks like this for rustfix:

# Works like `cargo check --all-targets`, fixes all warnings that `cargo check --all-targets`
# would otherwise produce. This involves updating libraries, binaries, examples,
# tests, etc.
$ cargo fix

# Fixes all warning that `cargo build` would otherwise produce
$ cargo fix build

# Fixes all warning that `cargo test` would otherwise produce
$ cargo test

# Fixes all warnings specifically for Windows
$ cargo fix --target x86_64-pc-windows-msvc

# Fixes all warnings for just one example and the library, if any:
$ cargo fix build --example foo

The general idea is that cargo fix is the main entry point, and it otherwise mirrors Cargo's normal invocations. It will operate "as if" some other cargo command is executing, only a bunch of warnings are fixed along the way.

If a subcommand to fix isn't specified it's assumed to be check. If nothing is passed it's the special case check --all-targets to fix as much as possible. Otherwise flags are all forwarded to cargo subcommands as usual to execute various compilations.

This should have the benefit of working on workspaces, working on all targets, and hopefully even being future compatible with future Cargo features!

Overriding rustc

To actually implement the above interface I think we'll want to execute cargo (the CLI) with the RUSTC environment variable set to rustfix's binary itself. That way it'll get reexecuted and have control over the compilation.

In this way we've now provided a hook to all rustc compilations, allowing us to intercept error messages and such to see what's going on. I think the logic of the script will look like:

  • Find an argument that looks like a filename. If it doesn't exist exec rustc.
  • If the filename looks like it's from a crates.io crate or otherwise not relevant to the workspace we're working in, exec rustc.
  • Now that we know this is a local crate, we fix all lints
    • The compiler is executed in --emit metadata mode (injected if not already present). All output is slurped up with --error-format=json as well.
    • All fixes are parsed and applied
      • This can possibly involve IPC back to the main parent process if we want interactivity
    • TODO: what if the compilation here fails?
  • Next we actually compile the crate
    • The compiler is invoked with the original arguments passed to the script (no output capture)
    • This is now executing with fixed code, and the user never saw warnings that ended up being fixed
    • Warnings that weren't automatically fixed will still be emitted
    • TODO: what if compilation fails here?

And I think that's enough to basically get the feeling of "automatically fix all the code" while also assuming as little as possible about Cargo itself.

Some possible caveats are:

  • There won't be an easy way to roll back fixes once we've gone past a crate. For example if a crate successfully compiles but fails other downstream compilations, it'll be hard to go back and revert the original crate.
  • If the fixed code fails to compile, we may have a bad UI presented here. We can go back and revert all the fixes we applied and tell the user what happened, but they run the risk of being confused.
  • We want to force Cargo to not actually cache anything and recompile local crates, so somehow we'll want to make repeated invocations of cargo fix actually run over code that may need fixing.

If we were to do this it's a pretty major rewrite/rethinking of the current CLI, so I'd like to get others' opinions on this! I'm curious if we can improve various aspects or otherwise make us better suited for the edition release!

How to force rustfix to rerun

i am using VSCode configured to run cargo clippy on save which shows me lot of warning particularly unused imports. If I run rustfix, I get I don't have any suggestions for you right now. Check back later!.

How can I force rustfix to run and fix suggestion provided by clippy? I even tried to delete the target directory but always get the same message.

Add a debug mode

For each suggestion,

  1. Write down the CLI output ("Info … Suggestions - Replace … with …")
  2. Write down the corresponding JSON (or, at first, the Suggestion struct debug output)
  3. The diff of the file after the replacement

Should rustfix fix broken code?

Should cargo fix keep going if the first cargo check fails? That is, if we're looking at broken code, should cargo fix attempt to keep going and fixing code?

In situations like this we can't actually detect if our changes caused further breakage, so we'd run the risk of making the situation worse by adding more errors.

How to display what just happend?

Right now cargo fix produces no output of its own, mostly relying on Cargo to produce such output. It seems like it'd be a good idea, however, for cargo fix to produce its own output which may include information like:

  • How many fixes were applied
  • What files fixes were applied to
  • Maybe even the diff of fixes
  • Number of remaining warnings to take care of
  • etc etc.

thread 'main' panicked at 'begin <= end (6 <= 0) when slicing ``

After a bunch of times pressing r while running rustfix on trust-dns:

Suggestion accepted. I'll remember that and apply it later.
thread 'main' panicked at 'begin <= end (6 <= 0) when slicing ``', ../src/libcore/str/mod.rs:1692
stack backtrace:
   1:        0x10d41db0b - std::sys::backtrace::tracing::imp::write::h29f5fdb9fc0a7395
   2:        0x10d4230ca - std::panicking::default_hook::_$u7b$$u7b$closure$u7d$$u7d$::h2cc84f0378700526
   3:        0x10d421788 - std::panicking::default_hook::hbbe7fa36a995aca0
   4:        0x10d421e18 - std::panicking::rust_panic_with_hook::h105c3d42fcd2fb5e
   5:        0x10d421c76 - std::panicking::begin_panic::hbf62ea4a5ff3f9de
   6:        0x10d421b88 - std::panicking::begin_panic_fmt::h20f5943904e5791d
   7:        0x10d421adf - rust_begin_unwind
   8:        0x10d449150 - core::panicking::panic_fmt::h19323e466869c656
   9:        0x10d44a07a - core::str::slice_error_fail::h0bcf68c8ce40ec27
  10:        0x10d3aa2ff - rustfix::handle_suggestions::h78dd61d6c28e0b4e
  11:        0x10d3a863c - rustfix::main::hecb56893e98700f4
  12:        0x10d421a4d - std::panicking::try::call::h5df3ac2979db3c90
  13:        0x10d4233eb - __rust_try
  14:        0x10d4232a5 - __rust_maybe_catch_panic
  15:        0x10d421101 - std::rt::lang_start::hfe9ab243c60ffb9b

Fixing unused imports

I really like rustfix and expectations are more :)

cargo build identifies unused imports. I would like to see rustfix provides similar suggestion and remove these unused imports.

e.g.

warning: unused import: `std::io::prelude::*`
  --> src/tiso/tiso_msg.rs:10:5
   |
10 | use std::io::prelude::*;
   |     ^^^^^^^^^^^^^^^^^^^

warning: unused import: `std::fmt`
  --> src/tiso/tiso_msg.rs:13:5
   |
13 | use std::fmt;
   |     ^^^^^^^^

Bug: Code is removed while applying suggestion

rustfix idenfied an issue and suggested to replace self with *self to avoid & in each match type.

Info: you don't need to add `&` to all patterns
  --> decline_reason_code.rs:26:9-34:10

instead of prefixing all patterns with `&`, you can dereference the expression
[0]: Replace:

            match self {
            &DeclineReasonCode::UnsuccessfulDetok => "0390",
            &DeclineReasonCode::TokenNotFound => "0391",
            &DeclineReasonCode::AuthExpired => "0392",
            &DeclineReasonCode::TokenNotActive => "0393",
            &DeclineReasonCode::TokenExpired => "0394",
            &DeclineReasonCode::None => "",

        }

with:

    match *self { .. }
==> What do you want to do? [0-9] | [r]eplace | [s]kip | save and [q]uit | [a]bort (without saving)
  > r
Suggestion accepted. I'll remember that and apply it later.

Original Code:

pub fn as_str(&self) -> &'static str {
        match self {
            &DeclineReasonCode::UnsuccessfulDetok => "0390",
            &DeclineReasonCode::TokenNotFound => "0391",
            &DeclineReasonCode::AuthExpired => "0392",
            &DeclineReasonCode::TokenNotActive => "0393",
            &DeclineReasonCode::TokenExpired => "0394",
            &DeclineReasonCode::None => "",

        }
    }

Replaced code after applying rustfix suggestion:

pub fn as_str(&self) -> &'static str {
        match *self { .. }
    }

Support more than fixing `cargo check`

Right now cargo fix is hardcoded to always run cargo check. That should catch almost all warnings but it won't catch perhaps super-late codegen-time warnings. It may be worthwhile supporting something like cargo fix test to give the guise of "just put fix in there and all your worries are taken care of!"

Detect overlapping fixes and identical fixes

If two fixes occur in the same area of text, rustfix will apply both and it will clash.

  • Worth having an explicit message that this is happening #94
  • and perhaps a mode between --yolo and normal mode that yolo-applies everything except when there's a clash (aside from the first fix). #94
  • Also, ignoring duplicate fixups (e.g. when a macro causes a lint -- it ends up with tons of identical replacements) would be nice.

Failed to install rustfix

I tried to update the rustfix using cargo and it's failing.

Error:

error: no method named `parameter_environment` found for type `rustc::ty::TyCtxt<'a, 'tcx, 'tcx>` in the current scope
   --> /Users/ytr289/.cargo/registry/src/github.com-1ecc6299db9ec823/clippy_lints-0.0.134/src/utils/mod.rs:790:32
    |
790 |     let parameter_env = cx.tcx.parameter_environment(parameter_item);
    |                                ^^^^^^^^^^^^^^^^^^^^^

error: no method named `parameter_environment` found for type `rustc::ty::TyCtxt<'a, 'tcx, 'tcx>` in the current scope
   --> /Users/ytr289/.cargo/registry/src/github.com-1ecc6299db9ec823/clippy_lints-0.0.134/src/utils/mod.rs:810:22
    |
810 |     let env = cx.tcx.parameter_environment(env);
    |                      ^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
   --> /Users/ytr289/.cargo/registry/src/github.com-1ecc6299db9ec823/clippy_lints-0.0.134/src/utils/mod.rs:811:69
    |
811 |     !ty.subst(cx.tcx, substs).moves_by_default(cx.tcx.global_tcx(), &env, DUMMY_SP)
    |                                                                     ^^^^ expected struct `rustc::ty::ParamEnv`, found reference
    |
    = note: expected type `rustc::ty::ParamEnv<'_>`
               found type `&_`

error: no method named `parameter_environment` found for type `rustc::ty::TyCtxt<'a, 'tcx, 'tcx>` in the current scope
  --> /Users/ytr289/.cargo/registry/src/github.com-1ecc6299db9ec823/clippy_lints-0.0.134/src/needless_pass_by_value.rs:85:40
   |
85 |             let parameter_env = cx.tcx.parameter_environment(fn_def_id);
   |                                        ^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 4 previous errors

error: Could not compile `clippy_lints`.
Build failed, waiting for other jobs to finish...
error: failed to compile `clippy v0.0.134`, intermediate artifacts can be found at `/var/folders/zl/4vh8ccr57954fgw4c9xzpfrsyclf11/T/cargo-install.erha8y19M1vy`

Rust toolchain version:

 rustup show
Default host: x86_64-apple-darwin

active toolchain
----------------

nightly-x86_64-apple-darwin (default)
rustc 1.19.0-nightly (5b13bff52 2017-05-23)

Warn if a VCS isn't detected

If we don't manage to find anything like Git/Mercurial/SVN then we should display a warning in one way or another and maybe even wait for the user to confirm before proceeding. Automatically changing code without version control is a scary prospect!

"Edition mode"

Would be nice to have a mode where:

  • It only applies edition lints
  • It does this automatically, but prompts for approximate suggestions
  • You can optionally ask it to apply idiom lints too

We can hardcode the list of edition lints and idiom lints

rustfix run from the `src` directory fails

I was working on a cargo project and I ran rustfix from the src directory. This seemed to be working but ended with:

An error occured: I/O error
Io(Os { code: 2, kind: NotFound, message: "No such file or directory" })
Cause: Os { code: 2, kind: NotFound, message: "No such file or directory" }

Running from alongside the Cargo.toml worked fine.

Include clippy?

rustfix is far more useful when it can use clippy's lints, so it might be a good idea to include clippy in rustfix itself.

Advantages:

  • ≥150 more lints, many with suggestions we can tap into
  • No need to tell people to install cargo clippy
  • No need to always write rustfix --clippy (which most user would probably need to do otherwise)

Disadvantages:

  • We depend on clippy
  • Clippy depends on specific versions of rust nightly, as does serde (which we already depend on)
  • We might need to update far more often

Unclear:

  • We might just need to copy/include the code from the cargo-clippy binary

Alternatives:

  • Set --clippy by default and tell people (with a nice error message) to install it
  • rustfix could also become a part of cargo clippy

Deal with multiple replacements in one file

Currently, rustfix will explode (or wreck your source file to be more precise) when it applies multiply suggestions to the same file -- The file changes but we still use the original byte offsets given by rustc.

We could instead use a rope-like data structure and remember the original indices. Also, it might be nice to only write the file once, after all suggestions for a file were dealt with by the user (i.e., ≥ 0 were accepted).

Testing

Test this to hell and back.

Figure out how to force `cargo fix` to run

Currently if you run cargo +nightly check and then cargo +nightly fix it won't actually do anything because Cargo will think it's cached. Somehow we should convince Cargo that it should at least rerun itself for the workspace-related crates.

Diff-like output

While it's nice to read something like

Suggestion - Replace:

    mem::transmute::<*mut c_void,
                     &mut Box<FnMut(&MenuItem, &Window)>>(data)(&menu_item, &window);

with:

    &mut *(data as *mut Box<for<'r, 'r> std::ops::FnMut(&'r menus::MenuItem, &'r windows::Window)>)

it might be more useful to have a bit of context and see exactly what is getting replaced. A diff-view (with character-precision highlighting, not just lines) should work nicely.

This could also be an optional CLI flag, though it might be better to just keep rustfix as simple (and non-configurable) as possible for now.

This might be as easy as adjusting the "apply replacement" function to not always save the output and run print_diff over a slice of max(0, start.line - context)...min(file.lines().count(), end.line + context.

feature-request: all changes printed to a "fix-log"

Hey!

just curious if you plan to create some kind of, I call it "fixlog", where every replace-to hunk will be logged. I don't know the real use for this yet but I'd like to see what I changed or better said what rustfix suggested. Maybe as a learning/best practice resource afterwards?

greets
Charlie

Don't eat laundry

Currently, it replaces the wrong bytes in my input file examples. I haven't investigated if this is an error in the JSON input (it blindly trusts byte_start/byte_end) or some mistake on my end.

Apply only certain fixes

I can not find any docs about functionality applying only certain fixes,
so here is feature request: it would be nice to filter possible fixes and applying only some classes of them.

For example, during development phase you can have bunch of warning unused something,
this is ok on development stage, but should be fixed on stabializing feature stage.

Also, for example I read about rustfix here and would like to try to fix use issues, but only for them.

So, it would be great to have something like --ignore-class=unused and --apply-only-for-class=use command line arguments.

Usability Roadmap

  1. cargo clippy -- -Z unstable-options --error-format json | rustfix --
  2. cargo clippy --json | rustfix --interactive
  3. cargo fix --with-clippy
  4. ???
  5. PROFIT!

Rustfix doesn't work in the presence of multiple targets

I get

SubcommandError("cargo rustc", "error: extra arguments to `rustc` can only be passed to one target, consider filtering\nthe package by passing e.g. `--lib` or `--bin NAME` to specify a single target\n")

Should probably use cargo_metadata to find all targets like cargo clippy does

Error applying replacements from module files

It seems I have reintroduced a bug with regard to byte indices in module files.

Simple example: This change to rustfix itself

diff --git a/cargo-fix/src/cli.rs b/cargo-fix/src/cli.rs
index fbbdfe6..32a9bb4 100644
--- a/cargo-fix/src/cli.rs
+++ b/cargo-fix/src/cli.rs
@@ -107,6 +107,8 @@ fn log_for_human(kind: &str, msg: &str) -> Result<(), Error> {
     let mut stream = StandardStream::stderr(color_choice);
     stream.reset()?;
 
+    let mut i = 42;
+
     stream.set_color(ColorSpec::new().set_bold(true).set_fg(Some(Color::Cyan)))?;
     // Justify to 12 chars just like cargo
     write!(&mut stream, "{:>12}", kind)?;

leads to this output

Checking cargo-fix v0.2.0 (file:///Users/pascal/Projekte/rustfix/cargo-fix)
error: Could not find data slice that covers range 3823..3827
error: Could not compile `cargo-fix`.

That range looks an awful lot like the index in the whole crate's source, not in cli.rs. I'm pretty sure there is such a property in the compiler's json output, though, and I'm just not using it correctly.

Special case insertions and removals

replacing "" with "foo" should not display the original text and the new text like it's doing right now. instead it should point at the char where the text will be inserted and say something like Suggestion - Insert "foo" at ...

The opposite, removals are even easier, they can simply skip the with part and just display the original snippet with the text that should be removed highlighted as it's already happening

Use fancy interactive select in CLI

While entering letters to step through suggestions is fun, it might be cooler to have an interactive select box.

The node module inquirer does some cool stuff in that regard, e.g.

or

I think this is a great opportunity to create a new crate. The closest thing I could find in rust (without going all the way to curses-rs) is this snippet which uses termbox-bindings. termion, a pure-rust termbox clone, might also be interesting.

Fixing new_without_default

The positioning of the replacement seems to be off.

Trying https://github.com/killercup/rustfix/tree/6937912bb89da024f6da89a35b2308f31af7663d on https://github.com/bluejekyll/trust-dns/tree/26b44483b0151682a7d835ddbd6ff9261c0651b6

Info: you should consider adding a `Default` implementation for `rr::resource::Record`
      #[warn(new_without_default)] on by default
  --> src/rr/resource.rs:78:3-78:3
Suggestion - Replace:

    pub fn new() -> Record {

with:

    impl Default for rr::resource::Record {
          fn default() -> Self {
              Self::new()
          }
      }

based on:

{
  "message": "you should consider adding a `Default` implementation for `rr::resource::Record`, #[warn(new_without_default)] on by default",
  "code": null,
  "level": "warning",
  "spans": [
    {
      "file_name": "src/rr/resource.rs",
      "byte_start": 40920,
      "byte_end": 41185,
      "line_start": 78,
      "line_end": 87,
      "column_start": 3,
      "column_end": 4,
      "is_primary": true,
      "text": [
        {
          "text": "  pub fn new() -> Record {",
          "highlight_start": 3,
          "highlight_end": 27
        },
        {
          "text": "    Record {",
          "highlight_start": 1,
          "highlight_end": 13
        },
        {
          "text": "      // TODO: these really should all be Optionals, I was lazy.",
          "highlight_start": 1,
          "highlight_end": 65
        },
        {
          "text": "      name_labels: domain::Name::new(),",
          "highlight_start": 1,
          "highlight_end": 40
        },
        {
          "text": "      rr_type: RecordType::A,",
          "highlight_start": 1,
          "highlight_end": 30
        },
        {
          "text": "      dns_class: DNSClass::IN,",
          "highlight_start": 1,
          "highlight_end": 31
        },
        {
          "text": "      ttl: 0,",
          "highlight_start": 1,
          "highlight_end": 14
        },
        {
          "text": "      rdata: RData::NULL(NULL::new())",
          "highlight_start": 1,
          "highlight_end": 38
        },
        {
          "text": "    }",
          "highlight_start": 1,
          "highlight_end": 6
        },
        {
          "text": "  }",
          "highlight_start": 1,
          "highlight_end": 4
        }
      ],
      "label": null,
      "suggested_replacement": null,
      "expansion": null
    }
  ],
  "children": [
    {
      "message": "try this",
      "code": null,
      "level": "help",
      "spans": [
        {
          "file_name": "src/rr/resource.rs",
          "byte_start": 40920,
          "byte_end": 40920,
          "line_start": 78,
          "line_end": 78,
          "column_start": 3,
          "column_end": 3,
          "is_primary": true,
          "text": [
            {
              "text": "  pub fn new() -> Record {",
              "highlight_start": 3,
              "highlight_end": 3
            }
          ],
          "label": null,
          "suggested_replacement": "impl Default for rr::resource::Record {\n      fn default() -> Self {\n          Self::new()\n      }\n  }\n\n  ",
          "expansion": null
        }
      ],
      "children": [],
      "rendered": "  impl Default for rr::resource::Record {\n      fn default() -> Self {\n          Self::new()\n      }\n  }\n\n  pub fn new() -> Record {"
    },
    {
      "message": "for further information visit https://github.com/Manishearth/rust-clippy/wiki#new_without_default",
      "code": null,
      "level": "help",
      "spans": [],
      "children": [],
      "rendered": null
    }
  ],
  "rendered": null
}

does this:

@@ -75,6 +75,12 @@ impl Record {
   ///
   /// There are no optional elements in this object, defaults are an empty name, type A, class IN,
   /// ttl of 0 and the 0.0.0.0 ip address.
+  impl Default for rr::resource::Record {
+      fn default() -> Self {
+          Self::new()
+      }
+  }
+
   pub fn new() -> Record {
     Record {
       // TODO: these really should all be Optionals, I was lazy.

And this:

Info: you should consider deriving a `Default` implementation for `rr::domain::Name`
      #[warn(new_without_default_derive)] on by default
  --> src/rr/domain.rs:37:3-37:3
Suggestion - Replace:

    pub fn new() -> Self {

with:

    #[derive(Default)]

based on:

{
  "message": "you should consider deriving a `Default` implementation for `rr::domain::Name`, #[warn(new_without_default_derive)] on by default",
  "code": null,
  "level": "warning",
  "spans": [
    {
      "file_name": "src/rr/domain.rs",
      "byte_start": 95979,
      "byte_end": 96046,
      "line_start": 37,
      "line_end": 39,
      "column_start": 3,
      "column_end": 4,
      "is_primary": true,
      "text": [
        {
          "text": "  pub fn new() -> Self {",
          "highlight_start": 3,
          "highlight_end": 25
        },
        {
          "text": "    Name { labels: Rc::new(Vec::new()) }",
          "highlight_start": 1,
          "highlight_end": 41
        },
        {
          "text": "  }",
          "highlight_start": 1,
          "highlight_end": 4
        }
      ],
      "label": null,
      "suggested_replacement": null,
      "expansion": null
    }
  ],
  "children": [
    {
      "message": "try this",
      "code": null,
      "level": "help",
      "spans": [
        {
          "file_name": "src/rr/domain.rs",
          "byte_start": 95979,
          "byte_end": 95979,
          "line_start": 37,
          "line_end": 37,
          "column_start": 3,
          "column_end": 3,
          "is_primary": true,
          "text": [
            {
              "text": "  pub fn new() -> Self {",
              "highlight_start": 3,
              "highlight_end": 3
            }
          ],
          "label": null,
          "suggested_replacement": "#[derive(Default)]\n  ",
          "expansion": null
        }
      ],
      "children": [],
      "rendered": "  #[derive(Default)]\n  pub fn new() -> Self {"
    },
    {
      "message": "for further information visit https://github.com/Manishearth/rust-clippy/wiki#new_without_default_derive",
      "code": null,
      "level": "help",
      "spans": [],
      "children": [],
      "rendered": null
    }
  ],
  "rendered": null
}

does this:

@@ -34,6 +34,7 @@ pub struct Name {
 }

 impl Name {
+  #[derive(Default)]
   pub fn new() -> Self {
     Name { labels: Rc::new(Vec::new()) }
   }

cc @mcarton

Trials & Errors

Let's collect some problems with rustfix encountered in real life here.

Continuous integration

Not sure how that would look... probably create some mode that automatically applies suggestions and then compare the file out put and command line output.

Or maybe we can feed a file as command line input.

Collapse spans

We should consider collapsing mutliple spans/suggestions into one.

As @mcarton mentioned elsewhere, he might add/added lints that yield multiple suggestions to add e.g. #[derive(Default)] (IIRC), so it makes sense to let user accept the complete change in one step.

I'm not sure when to collapse spans, though.

This will look far better with a diff-like output (cf #13).

In autofix mode, skip suggestions with multiple options

Some lints yield multiple valid suggestions, e.g., here

fn main() {
    let xs = vec![String::from("foo")];
    let d: &Display = &xs;
    println!("{}", d);
}

We should not try to apply suggestions with more than one option and instead just skip them.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.