Coder Social home page Coder Social logo

rust-lang / rustfmt Goto Github PK

View Code? Open in Web Editor NEW
5.8K 49.0 850.0 14.01 MB

Format Rust code

Home Page: https://rust-lang.github.io/rustfmt/

License: Apache License 2.0

Rust 99.10% Shell 0.52% RenderScript 0.36% Batchfile 0.02%
rust rustfmt formatter codeformatter

rustfmt's Introduction

rustfmt linux mac windows crates.io

A tool for formatting Rust code according to style guidelines.

If you'd like to help out (and you should, it's a fun project!), see Contributing.md and our Code of Conduct.

You can use rustfmt in Travis CI builds. We provide a minimal Travis CI configuration (see here).

Quick start

You can run rustfmt with Rust 1.24 and above.

On the Stable toolchain

To install:

rustup component add rustfmt

To run on a cargo project in the current working directory:

cargo fmt

On the Nightly toolchain

For the latest and greatest rustfmt, nightly is required.

To install:

rustup component add rustfmt --toolchain nightly

To run on a cargo project in the current working directory:

cargo +nightly fmt

Limitations

Rustfmt tries to work on as much Rust code as possible. Sometimes, the code doesn't even need to compile! In general, we are looking to limit areas of instability; in particular, post-1.0, the formatting of most code should not change as Rustfmt improves. However, there are some things that Rustfmt can't do or can't do well (and thus where formatting might change significantly, even post-1.0). We would like to reduce the list of limitations over time.

The following list enumerates areas where Rustfmt does not work or where the stability guarantees do not apply (we don't make a distinction between the two because in the future Rustfmt might work on code where it currently does not):

  • a program where any part of the program does not parse (parsing is an early stage of compilation and in Rust includes macro expansion).
  • Macro declarations and uses (current status: some macro declarations and uses are formatted).
  • Comments, including any AST node with a comment 'inside' (Rustfmt does not currently attempt to format comments, it does format code with comments inside, but that formatting may change in the future).
  • Rust code in code blocks in comments.
  • Any fragment of a program (i.e., stability guarantees only apply to whole programs, even where fragments of a program can be formatted today).
  • Code containing non-ascii unicode characters (we believe Rustfmt mostly works here, but do not have the test coverage or experience to be 100% sure).
  • Bugs in Rustfmt (like any software, Rustfmt has bugs, we do not consider bug fixes to break our stability guarantees).

Running

You can run Rustfmt by just typing rustfmt filename if you used cargo install. This runs rustfmt on the given file, if the file includes out of line modules, then we reformat those too. So to run on a whole module or crate, you just need to run on the root file (usually mod.rs or lib.rs). Rustfmt can also read data from stdin. Alternatively, you can use cargo fmt to format all binary and library targets of your crate.

You can run rustfmt --help for information about available arguments. The easiest way to run rustfmt against a project is with cargo fmt. cargo fmt works on both single-crate projects and cargo workspaces. Please see cargo fmt --help for usage information.

You can specify the path to your own rustfmt binary for cargo to use by setting theRUSTFMT environment variable. This was added in v1.4.22, so you must have this version or newer to leverage this feature (cargo fmt --version)

Running rustfmt directly

To format individual files or arbitrary codes from stdin, the rustfmt binary should be used. Some examples follow:

  • rustfmt lib.rs main.rs will format "lib.rs" and "main.rs" in place
  • rustfmt will read a code from stdin and write formatting to stdout
    • echo "fn main() {}" | rustfmt would emit "fn main() {}".

For more information, including arguments and emit options, see rustfmt --help.

Verifying code is formatted

When running with --check, Rustfmt will exit with 0 if Rustfmt would not make any formatting changes to the input, and 1 if Rustfmt would make changes. In other modes, Rustfmt will exit with 1 if there was some error during formatting (for example a parsing or internal error) and 0 if formatting completed without error (whether or not changes were made).

Running Rustfmt from your editor

Checking style on a CI server

To keep your code base consistently formatted, it can be helpful to fail the CI build when a pull request contains unformatted code. Using --check instructs rustfmt to exit with an error code if the input is not formatted correctly. It will also print any found differences. (Older versions of Rustfmt don't support --check, use --write-mode diff).

A minimal Travis setup could look like this (requires Rust 1.31.0 or greater):

language: rust
before_script:
- rustup component add rustfmt
script:
- cargo build
- cargo test
- cargo fmt --all -- --check

See this blog post for more info.

How to build and test

cargo build to build.

cargo test to run all tests.

To run rustfmt after this, use cargo run --bin rustfmt -- filename. See the notes above on running rustfmt.

Configuring Rustfmt

Rustfmt is designed to be very configurable. You can create a TOML file called rustfmt.toml or .rustfmt.toml, place it in the project or any other parent directory and it will apply the options in that file. See rustfmt --help=config for the options which are available, or if you prefer to see visual style previews, GitHub page.

By default, Rustfmt uses a style which conforms to the Rust style guide that has been formalized through the style RFC process.

Configuration options are either stable or unstable. Stable options can always be used, while unstable ones are only available on a nightly toolchain, and opt-in. See GitHub page for details.

Rust's Editions

Rustfmt is able to pick up the edition used by reading the Cargo.toml file if executed through the Cargo's formatting tool cargo fmt. Otherwise, the edition needs to be specified in rustfmt.toml, e.g., with edition = "2018".

Tips

  • For things you do not want rustfmt to mangle, use #[rustfmt::skip]

  • To prevent rustfmt from formatting a macro or an attribute, use #[rustfmt::skip::macros(target_macro_name)] or #[rustfmt::skip::attributes(target_attribute_name)]

    Example:

    #![rustfmt::skip::attributes(custom_attribute)]
    
    #[custom_attribute(formatting , here , should , be , Skipped)]
    #[rustfmt::skip::macros(html)]
    fn main() {
        let macro_result1 = html! { <div>
    Hello</div>
        }.to_string();
  • When you run rustfmt, place a file named rustfmt.toml or .rustfmt.toml in target file directory or its parents to override the default settings of rustfmt. You can generate a file containing the default configuration with rustfmt --print-config default rustfmt.toml and customize as needed.

  • After successful compilation, a rustfmt executable can be found in the target directory.

  • If you're having issues compiling Rustfmt (or compile errors when trying to install), make sure you have the most recent version of Rust installed.

  • You can change the way rustfmt emits the changes with the --emit flag:

    Example:

    cargo fmt -- --emit files

    Options:

    Flag Description Nightly Only
    files overwrites output to files No
    stdout writes output to stdout No
    coverage displays how much of the input file was processed Yes
    checkstyle emits in a checkstyle format Yes
    json emits diffs in a json format Yes

License

Rustfmt is distributed under the terms of both the MIT license and the Apache License (Version 2.0).

See LICENSE-APACHE and LICENSE-MIT for details.

rustfmt's People

Contributors

alexcrichton avatar ayazhafiz avatar bash avatar bors avatar calebcartwright avatar cassiersg avatar cbrewster avatar csmoe avatar davidalber avatar dlukes avatar fee1-dead avatar janlikar avatar jugglerchris avatar kamalmarhubi avatar marcusklaas avatar markstory avatar matklad avatar matthiaskrgr avatar nnethercote avatar nrc avatar oli-obk avatar otavio avatar rchaser53 avatar rreverser avatar scampi avatar sinkuu avatar topecongiro avatar xanewok avatar yalter avatar ytmimi 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  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

rustfmt's Issues

Format required methods

We currently don't format required methods (i.e., trait methods without bodies). It should be relatively easy to do so - all the hard bits are there, just need to adjust the ast visitor.

make sure we work with unicode

In particular, we use byte positions where we should use char positions in many places. Furthermore, when we do use char positions, we don't check the 'physical' width of the character.

windows line endings `\r\n` are mutated to `\n`

I'd fix it myself, but I don't know what the best way would be.

There are also other things like adding a \n at the end of file.

What do you think about doing it git-style. Reading files skips \r, but sets a flag if it encounters an \r. Writing back adds \r before every \n. This would prevent any fancy conditionals inside the logic code.

Comments in odd places in functions

We miss comments in some places in functions. The most common, I expect is between the closing ) and opening {, e.g.

fn qux(a: dadsfa,   // Comment 1
       b: sdfasdfa, // Comment 2
       c: dsfdsafa) // Comment 3
{

Also before the opening ( (likely if there are generics with comments). And between any of the boilerplate at the start of the function (most likely case, I think, would be comments on the abi).

The only way to fix this is to either have spans for every token, or to have comments in the AST. I want both things, but neither is going to happen very quickly.

Format expressions deeply

Not sure if we are formatting sub-expressions if we don't format the top-level expression. I think we are, but I'm not 100% convinced.

Meta: format control statements

if, while, loop, for. if is the most interesting because of else clauses.

Please file an issue for each kind of statement if you want to work on one.

Symbol not found in OS X

running 1 test
dyld: lazy symbol binding failed: Symbol not found: __ZN12run_compiler20hc88ddcd6c053f075F4bE
  Referenced from: /Users/zonyitoo/Projects/rustfmt/target/debug/rustfmt-4f9b0c3263d54116
  Expected in: /usr/local/lib/librustc_driver-4e7c5e5c.dylib

dyld: Symbol not found: __ZN12run_compiler20hc88ddcd6c053f075F4bE
  Referenced from: /Users/zonyitoo/Projects/rustfmt/target/debug/rustfmt-4f9b0c3263d54116
  Expected in: /usr/local/lib/librustc_driver-4e7c5e5c.dylib

Rustc version is

rustc 1.1.0-nightly (90cc83015 2015-04-22) (built 2015-04-22)

Removing trailing spaces in doc comments is wrong

Doc comments should typically be considered to be Markdown; Markdown has this crazy idea where two trailing spaces on a line means “put a line break here”. Not my idea, I didn’t do it, but that’s the way it is.

Anyway, rustfmt wants to strip trailing whitespace, even in comments; this does this to mopa, for example:

diff --git a/src/lib.rs b/src/lib.rs
index c74869e..c4ec34d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -25,10 +25,10 @@
 //! its original type, right? Alas, you can’t write a type like `Box<Person + Any>` (at present,
 //! anyway). So what do you do instead? Do you give up? No, no! No, no! Enter MOPA.
 //!
-//! > There once was a quite friendly trait  
-//! > Called `Person`, with much on its plate.  
-//! >     “I need to be `Any`  
-//! >     To downcast to `Benny`—  
+//! > There once was a quite friendly trait
+//! > Called `Person`, with much on its plate.
+//! >     “I need to be `Any`
+//! >     To downcast to `Benny`—
 //! > But I’m not, so I guess I’ll just wait.”
 //!
 //! A pitiful tale, isn’t it? Especially given that there was a bear chasing it with intent to eat

That would utterly ruin my limerick (when rendered with most flavours of Markdown; GitHub Flavoured Markdown does its own thing treating line breaks in the source as line breaks in HTML, but that’s not my fault) and so I am made sad by this rule.

pub use

we lose the pub at the moment

Put the closing brace of an empty function on the same line

fn _assert_send<T: Send>() { }  // Not uncommon in library testing
fn main() { }  // Common in trivial “does this technique work?” experiments

In cases like these I would tend to prefer the closing curly brace on the same line rather than on the next line as rustfmt currently does.

Opinions may differ here.

Format boolean expressions

Similar to arithmetic expressions I expect.

I'm slightly more motivated about these because they often give long lines in if expressions.

Again, easy-ish

Docs

I should write about how this works

Attributes on modules

We currently just ignore them. This is a hack to get around attributes inside a module in another file. We do want to go over these attributes and not skip them though. I think we have to be a bit smarter about how we handle multiple files and modules/attributes.

This is kind of urgent because

#[cfg(test)]
mod test {
    ...
}

is a common pattern (although we don't cause errors here, afaik)

Latest commit broke build

This is with latest nightly rust, compiling 1a09a6d:

cargo build --release
   Compiling rustfmt v0.0.1 (file:///Users/sirver/Desktop/Programming/rust/rustfmt)
src/lib.rs:50:5: 50:11 error: file not found for module `config`
src/lib.rs:50 mod config;
                  ^~~~~~
src/lib.rs:50:5: 50:11 help: name the file either config.rs or config/mod.rs inside the directory "src"
Could not compile `rustfmt`.

space around bounds

T: X + 'a vs T: X+'a

We currently do the latter, we should probably do the former. But most code in the repo uses the latter (at least in bounds, perhaps not where clauses), so I'm 100% sure about this.

Fallback

Where formatting produces an item or statement which exceeds the max width, we should warn the user and fallback to using the original source code. The aim should be to never make things worse, so we should assume the users failure is better than our failure.

Fallback should pretty much only be done at the highest level (i.e., not on sub-expressions). but we might want to be able to give up pre-emptively in some cases.

Build failure

src/visitor.rs:101:13: 101:77 error: this pattern has 5 fields, but the corresponding variant has 6 fields [E0023]
src/visitor.rs:101             visit::FkItemFn(ident, ref generics, ref unsafety, ref abi, vis) => {

Caused by rust-lang/rust#25609

Handle unformatted spans across file boundaries

If we have files which don't get formatted then we end up with a span of 'missing' code which crosses file boundaries, that will throw an assertion in format_missing_inner. We should make this work properly

Tests

Oh my, we need so many tests. See also #2 and #3.

We need many unit tests.

We also need some framework for system tests and then we need lots of them. And soon.

Meta: make tidy parity

The first big goal for rustfmt should be parity with make tidy, i.e., we do all the checks that make tidy does and is usable as part of the rust distro build process. This needs three things - feature parity, non-bugginess and configurability.

Feature parity

Need to find out exactly what make tidy does, but things that come to mind are: warnings on cfg(stage0), checking for TODO, checking licenses.

Non-bugginess

In order to be part of the build process, we need to be able to run rustfmt on the whole repo without breaking anything. This will need lots of testing and some big PRs to the Rust repo for the initial reformatting.

To make this tractable, we'll want to turn rustfmt on one crate at a time and keep the make tidy step until the end (it might make sense to keep make tidy forever for the test suite, although it would be nice to kill it.

Configurability

There will be bugs, we need to be able to turn rustfmt off for some sections of a file until rustfmt can be fixed. We'll also want to evolve rustfmt (make tidy parity does not (and should not) require all formatting rules are enforced, and we'll want to add more rules as time goes by), we'll want to be able to feature gate some features of rustfmt so that they can be tested without applying to the rust repo or forking rustfmt.

We'll also need configurability for some of the make tidy features, for example license checking, since different projects will have different licences.

Format paths

We often want to split paths, so this seems like an important thing to tackle

Report formatting coverage

I.e., how much of a source file is properly reformatted and how much is skipped and recreated from spans

Format macro uses

Treat them like method calls. I think this could be tricky because, aiui, we don't parse macro uses. But we can call the parsing code to create an AST, and then we can reformat the body of the use.

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.