For example, with the following config file, rustfmt will ignore `src/types.rs`,
`src/foo/bar.rs` and every file under `examples/` directory.
```toml
[ignore]
files = [
"src/types.rs",
"src/foo/bar.rs",
]
directories = [
"examples",
]
```
This allows occurrences of `{` and `}` within `{}` placeholders in the
template, and also for having literal `{` and `}` in the template by
means of escaping (`\{`).
Unbalanced, unescaped `}` at the toplevel is a syntax error which
currently triggers a panic; I'll add proper error handling as I move the
license template parsing code into the config parsing phase.
I'm not quite sure how best to handle loading the license template from
a path -- I mean obviously I know *how* to do it, but I'm not sure where
to fit it in the codebase :) So this first attempt puts the license
template directly into the config file.
These are my misgivings about the license template config option as a
path to a file (I'd love feedback if some of these are wrong or can be
easily circumvented!):
1. I thought the obvious choice for the type of `license_template` in
`create_config!` should be `PathBuf`, but `PathBuf` doesn't implement
`FromStr` (yet? see https://github.com/rust-lang/rust/issues/44431), so
it would have to be wrapped in a tuple struct, and I went down that road
for a little while but then it seemed like too much ceremony for too
little gain.
2. So a plain `String` then (which, mind you, also means the same
`doc_hint()`, i.e. `<string>`, not `<path>` or something like that). The
fact that it's a valid path will be checked once we try to read the
file.
3. But where in the code should the license template be read? The
obvious choice for me would be somewhere in `Config::from_toml()`, but
since `Config` is defined via the `create_config!` macro, that would
mean tight coupling between the macro invocation (which defines the
configuration option `license_template`) and its definition (which would
rely on the existence of that option to run the template loading code).
4. `license_template` could also be made a special option which is
hardwired into the macro. This gets rid of the tight coupling, but
special-casing one of the config options would make the code harder to
navigate.
5. Instead, the macro could maybe be rewritten to allow for config
options that load additional resources from files when the config is
being parsed, but that's beyond my skill level I'm afraid (and probably
overengineering the problem if it's only ever going to be used for this
one option).
6. Finally, the file can be loaded at some later point in time, e.g. in
`format_lines()`, right before `check_license()` is called. But to
face a potential *IO* error at so late a stage, when the source files
have already been parsed... I don't know, it doesn't feel right.
BTW I don't like that I'm actually parsing the license template as late
as inside `check_license()` either, but for much the same reasons, I
don't know where else to put it. If the `Config` were hand-rolled
instead of a macro, I'd just define a custom `license_template` option
and load and parse the template in the `Config`'s init. But the way
things are, I'm a bit at a loss.
However, if someone more familiar with the project would kindly provide
a few hints as to how the path approach can be done in a way that is as
clean as possible in the context of the codebase, I'll be more than
happy to implement it! :)
Add `reorder_modules` config option.
Two things we must keep in mind when reordering modules:
1. We should not reorder modules with attributes, as doing so could
potentially break the code (e.g. `#[macro_use]`).
2. We should not reorder inline modules e.g. `mod foo { /* .. */ }`.
We should only reorder module declarations e.g. `mod foo;`.
Some open questions:
1. Should we bring modules with `pub` in front of those without `pub`
so that they stand out from others?
2. Instead of keeping modules with attributes in the same place,
can we bring them in front of others? Is this safe?
Expands the error message returned if the after_file function fails to
also include path_str. This allows users to better identify files that are
not being formatted.
This API isn't fantastic, but it's the best I can come up with without
something like `concat_idents!()`. There are relatively few places where
config is set, to hopefully the ugliness isn't disastrous.
Change previous occurences of `config.item = value` to this new API,
rather than using `config.override_value()`. Undo the changes to
`override_value()`, as it's no longer important to propogate the error
to the caller. Add a test for the new interface.
Preparation for #865, which proposes adding a flag which outputs which
config options are used during formatting.
This PR should not make any difference to functionality. A lot of this
was search-and-replace.
Some areas worthy of review/discussion:
- The method for each config item returns a clone of the underlying
value. We can't simply return an immutable reference, as lots of
places in the code expect to be able to pass the returned value as
`bool` (not `&bool). It would be nice if the `bool` items could
return a copy, but the more complex types a borrowed reference... but
unfortunately, I couldn't get the macro to do this.
- A few places (mostly tests and `src/bin/rustfmt.rs`) were overriding
config items by modifying the fields of the `Config` struct directly.
They now use the existing `override_value()` method, which has been
modified to return a `Result` for use by `src/bin/rustfmt.rs`. This
benefits of this are that the complex `file_lines` and `write_mode`
strings are now parsed in one place (`Config.override_value`) instead
of multiple. The disadvantages are that it moves the compile-time
checks for config names to become run-time checks.
Resolves#1335. Does not attempt to handle a `\r` not followed by a `\n` nor
attempt to handle Unicode intricacies (#6) including zero-width or multi-byte
characters.
This changes rustfmt to return exit code 4
when run with write mode diff and differences between
the formatted code and the original code are found.
Useful for CI to make sure your contributors actually ran rustfmt.
This commit adds a type to represent lines in files, and adds it to the
`Config` struct. It will be used for restricting formatting to specific
lines.
Refs #434
This commit adds a `codemap` module, and moves the `CodemapSpanUtils`
added in #857 to it. This is preparation for adding more `Codemap`
specific utilities.
Refs #434
* Handle pub(restricted)
This commit properly handles pub(restricted) as introduced in RFC 1422
[0]. The syntax support was added in #971, but they were not correctly
formatted.
[0] https://github.com/rust-lang/rfcs/blob/master/text/1422-pub-restricted.mdFixes#970
* Drop #[inline] attribute on format_visibility
* Make newly non-failing functions return String
The change to `format_visibiilty` means that `format_header` and
`format_unit_struct` can no longer fail. Their return type is updated to
reflect that.
The old behaviour stored everything in memory until we were finished. Now we write as soon as we can.
This gives better behaviour when formatting large programs, since there is some progress indication. It also opens the door to optimising memory use by not storing everything in memory unless it is required (which it still might be). That is left as future work though.
Outputting child module contents in the "Plain" write mode does not make
sense, since there is no way to differentiate code that came from a
child module from that which came from the parent file.
This `if` was used to separate error output from the formatting output, when they both used stdout. It was useful for integration with tools, which can submit input to stdin and read pretty printed result from stdout without worrying about errors intermingled with the actual result.
But now we write errors to `stderr`, so the problem disappears and we can safely remove this `if`.
Errors should never pass silently, unless explicitly silenced.