Skip to content

Commit 1b87a8b

Browse files
topecongirocalebcartwright
authored andcommitted
Support @generated marker to skip code formatting
This is a copy of #4296 with these changes: * file is not reopened again to find if the file is generated * first five lines are scanned for `@generated` marker instead of one * no attempt is made to only search for marker in comments `@generated` marker is used by certain tools to understand that the file is generated, so it should be treated differently than a file written by a human: * linters should not be invoked on these files, * diffs in these files are less important, * and these files should not be reformatted. This PR proposes builtin support for `@generated` marker. I have not found a standard for a generated file marker, but: * Facebook [uses `@generated` marker](https://tinyurl.com/fb-generated) * Phabricator tool which was spawned from Facebook internal tool [also understands `@generated` marker](https://git.io/JnVHa) * Cargo inserts `@generated` marker into [generated Cargo.lock files](https://git.io/JnVHP) My personal story is that rust-protobuf project which I maintain was broken twice because of incompatibilities/bugs in rustfmt marker handling: [one](stepancheg/rust-protobuf#493), [two](stepancheg/rust-protobuf#551). (Also, rust-protobuf started generating `@generated` marker [6 years ago](https://git.io/JnV5h)). While rustfmt AST markers are useful to apply to a certain AST elements, disable whole-file-at-once all-tools-at-once text level marker might be easier to use and more reliable for generated code.
1 parent dc9c17a commit 1b87a8b

File tree

10 files changed

+63
-2
lines changed

10 files changed

+63
-2
lines changed

Configurations.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,15 @@ fn add_one(x: i32) -> i32 {
924924
}
925925
```
926926

927+
## `format_generated_files`
928+
929+
Format generated files. A file is considered generated
930+
if any of the first five lines contains `@generated` marker.
931+
932+
- **Default value**: `false`
933+
- **Possible values**: `true`, `false`
934+
- **Stable**: No
935+
927936
## `format_macro_matchers`
928937

929938
Format the metavariable matching patterns in macros.

src/config/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ create_config! {
136136
inline_attribute_width: usize, 0, false,
137137
"Write an item and its attribute on the same line \
138138
if their combined width is below a threshold";
139+
format_generated_files: bool, false, false, "Format generated files";
139140

140141
// Options that can change the source code beyond whitespace/blocks (somewhat linty things)
141142
merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one";
@@ -604,6 +605,7 @@ blank_lines_lower_bound = 0
604605
edition = "2015"
605606
version = "One"
606607
inline_attribute_width = 0
608+
format_generated_files = false
607609
merge_derives = true
608610
use_try_shorthand = false
609611
use_field_init_shorthand = false

src/formatting.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_span::Span;
1010
use self::newline_style::apply_newline_style;
1111
use crate::comment::{CharClasses, FullCodeCharKind};
1212
use crate::config::{Config, FileName, Verbosity};
13+
use crate::formatting::generated::is_generated_file;
1314
use crate::issues::BadIssueSeeker;
1415
use crate::modules::Module;
1516
use crate::syntux::parser::{DirectoryOwnership, Parser, ParserError};
@@ -18,6 +19,7 @@ use crate::utils::count_newlines;
1819
use crate::visitor::FmtVisitor;
1920
use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session};
2021

22+
mod generated;
2123
mod newline_style;
2224

2325
// A map of the files of a crate, with their new content
@@ -103,7 +105,12 @@ fn format_project<T: FormatHandler>(
103105
context.parse_session.set_silent_emitter();
104106

105107
for (path, module) in files {
106-
let should_ignore = !input_is_stdin && context.ignore_file(&path);
108+
let source_file = context.parse_session.span_to_file_contents(module.span);
109+
let src = source_file.src.as_ref().expect("SourceFile without src");
110+
111+
let should_ignore = (!input_is_stdin && context.ignore_file(&path))
112+
|| (!config.format_generated_files() && is_generated_file(src));
113+
107114
if (config.skip_children() && path != main_file) || should_ignore {
108115
continue;
109116
}

src/formatting/generated.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/// Returns `true` if the given span is a part of generated files.
2+
pub(super) fn is_generated_file(original_snippet: &str) -> bool {
3+
original_snippet
4+
.lines()
5+
.take(5) // looking for marker only in the beginning of the file
6+
.any(|line| line.contains("@generated"))
7+
}

src/syntux/session.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,12 @@ impl ParseSess {
175175
self.parse_sess.source_map().span_to_filename(span).into()
176176
}
177177

178+
pub(crate) fn span_to_file_contents(&self, span: Span) -> Lrc<rustc_span::SourceFile> {
179+
self.parse_sess
180+
.source_map()
181+
.lookup_source_file(span.data().lo)
182+
}
183+
178184
pub(crate) fn span_to_first_line_string(&self, span: Span) -> String {
179185
let file_lines = self.parse_sess.source_map().span_to_lines(span).ok();
180186

src/test/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,7 @@ fn read_significant_comments(file_name: &Path) -> HashMap<String, String> {
693693
reader
694694
.lines()
695695
.map(|line| line.expect("failed getting line"))
696-
.take_while(|line| line_regex.is_match(line))
696+
.filter(|line| line_regex.is_match(line))
697697
.filter_map(|line| {
698698
regex.captures_iter(&line).next().map(|capture| {
699699
(
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// @generated
2+
// rustfmt-format_generated_files: false
3+
4+
fn main()
5+
{
6+
println!("hello, world")
7+
;
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// @generated
2+
// rustfmt-format_generated_files: true
3+
4+
fn main()
5+
{
6+
println!("hello, world")
7+
;
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// @generated
2+
// rustfmt-format_generated_files: false
3+
4+
fn main()
5+
{
6+
println!("hello, world")
7+
;
8+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// @generated
2+
// rustfmt-format_generated_files: true
3+
4+
fn main() {
5+
println!("hello, world");
6+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy