diff --git a/Configurations.md b/Configurations.md
index 469deccc56e..84e8c3f7db6 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -924,6 +924,15 @@ fn add_one(x: i32) -> i32 {
 }
 ```
 
+## `format_generated_files`
+
+Format generated files. A file is considered generated
+if any of the first five lines contains `@generated` marker.
+
+- **Default value**: `false`
+- **Possible values**: `true`, `false`
+- **Stable**: No
+
 ## `format_macro_matchers`
 
 Format the metavariable matching patterns in macros.
diff --git a/src/config/mod.rs b/src/config/mod.rs
index 8c04363b1fd..3d6e32fdb60 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -136,6 +136,7 @@ create_config! {
     inline_attribute_width: usize, 0, false,
         "Write an item and its attribute on the same line \
         if their combined width is below a threshold";
+    format_generated_files: bool, false, false, "Format generated files";
 
     // Options that can change the source code beyond whitespace/blocks (somewhat linty things)
     merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one";
@@ -604,6 +605,7 @@ blank_lines_lower_bound = 0
 edition = "2015"
 version = "One"
 inline_attribute_width = 0
+format_generated_files = false
 merge_derives = true
 use_try_shorthand = false
 use_field_init_shorthand = false
diff --git a/src/formatting.rs b/src/formatting.rs
index e0403574eeb..9ef47b887ca 100644
--- a/src/formatting.rs
+++ b/src/formatting.rs
@@ -10,6 +10,7 @@ use rustc_span::Span;
 use self::newline_style::apply_newline_style;
 use crate::comment::{CharClasses, FullCodeCharKind};
 use crate::config::{Config, FileName, Verbosity};
+use crate::formatting::generated::is_generated_file;
 use crate::issues::BadIssueSeeker;
 use crate::modules::Module;
 use crate::syntux::parser::{DirectoryOwnership, Parser, ParserError};
@@ -18,6 +19,7 @@ use crate::utils::count_newlines;
 use crate::visitor::FmtVisitor;
 use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session};
 
+mod generated;
 mod newline_style;
 
 // A map of the files of a crate, with their new content
@@ -103,7 +105,12 @@ fn format_project<T: FormatHandler>(
     context.parse_session.set_silent_emitter();
 
     for (path, module) in files {
-        let should_ignore = !input_is_stdin && context.ignore_file(&path);
+        let source_file = context.parse_session.span_to_file_contents(module.span);
+        let src = source_file.src.as_ref().expect("SourceFile without src");
+
+        let should_ignore = (!input_is_stdin && context.ignore_file(&path))
+            || (!config.format_generated_files() && is_generated_file(src));
+
         if (config.skip_children() && path != main_file) || should_ignore {
             continue;
         }
diff --git a/src/formatting/generated.rs b/src/formatting/generated.rs
new file mode 100644
index 00000000000..58f43f17ee1
--- /dev/null
+++ b/src/formatting/generated.rs
@@ -0,0 +1,7 @@
+/// Returns `true` if the given span is a part of generated files.
+pub(super) fn is_generated_file(original_snippet: &str) -> bool {
+    original_snippet
+        .lines()
+        .take(5) // looking for marker only in the beginning of the file
+        .any(|line| line.contains("@generated"))
+}
diff --git a/src/syntux/session.rs b/src/syntux/session.rs
index 870f0acfe39..94257e1ce7f 100644
--- a/src/syntux/session.rs
+++ b/src/syntux/session.rs
@@ -175,6 +175,12 @@ impl ParseSess {
         self.parse_sess.source_map().span_to_filename(span).into()
     }
 
+    pub(crate) fn span_to_file_contents(&self, span: Span) -> Lrc<rustc_span::SourceFile> {
+        self.parse_sess
+            .source_map()
+            .lookup_source_file(span.data().lo)
+    }
+
     pub(crate) fn span_to_first_line_string(&self, span: Span) -> String {
         let file_lines = self.parse_sess.source_map().span_to_lines(span).ok();
 
diff --git a/src/test/mod.rs b/src/test/mod.rs
index cb52346a13a..ece1b91bfd7 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -694,7 +694,7 @@ fn read_significant_comments(file_name: &Path) -> HashMap<String, String> {
     reader
         .lines()
         .map(|line| line.expect("failed getting line"))
-        .take_while(|line| line_regex.is_match(line))
+        .filter(|line| line_regex.is_match(line))
         .filter_map(|line| {
             regex.captures_iter(&line).next().map(|capture| {
                 (
diff --git a/tests/source/configs/format_generated_files/false.rs b/tests/source/configs/format_generated_files/false.rs
new file mode 100644
index 00000000000..dec1e00d117
--- /dev/null
+++ b/tests/source/configs/format_generated_files/false.rs
@@ -0,0 +1,8 @@
+// @generated
+// rustfmt-format_generated_files: false
+
+fn main()
+{
+    println!("hello, world")
+    ;
+}
diff --git a/tests/source/configs/format_generated_files/true.rs b/tests/source/configs/format_generated_files/true.rs
new file mode 100644
index 00000000000..a25ddc25a6a
--- /dev/null
+++ b/tests/source/configs/format_generated_files/true.rs
@@ -0,0 +1,8 @@
+// @generated
+// rustfmt-format_generated_files: true
+
+fn main()
+{
+    println!("hello, world")
+    ;
+}
diff --git a/tests/target/configs/format_generated_files/false.rs b/tests/target/configs/format_generated_files/false.rs
new file mode 100644
index 00000000000..dec1e00d117
--- /dev/null
+++ b/tests/target/configs/format_generated_files/false.rs
@@ -0,0 +1,8 @@
+// @generated
+// rustfmt-format_generated_files: false
+
+fn main()
+{
+    println!("hello, world")
+    ;
+}
diff --git a/tests/target/configs/format_generated_files/true.rs b/tests/target/configs/format_generated_files/true.rs
new file mode 100644
index 00000000000..5fea7e8b341
--- /dev/null
+++ b/tests/target/configs/format_generated_files/true.rs
@@ -0,0 +1,6 @@
+// @generated
+// rustfmt-format_generated_files: true
+
+fn main() {
+    println!("hello, world");
+}