Move formatted file writing to module

We will want to use this from other Rust-generating modules.
diff --git a/codegen/src/file.rs b/codegen/src/file.rs
new file mode 100644
index 0000000..fd1dd8a
--- /dev/null
+++ b/codegen/src/file.rs
@@ -0,0 +1,22 @@
+use proc_macro2::TokenStream;
+use rustfmt_nightly as rustfmt;
+use std::fs::File;
+use std::io::Write;
+
+pub fn write(path: &str, content: TokenStream) {
+    let mut file = File::create(path).unwrap();
+    write!(
+        file,
+        "// THIS FILE IS AUTOMATICALLY GENERATED; DO NOT EDIT\n\n"
+    )
+    .unwrap();
+    let mut config = rustfmt::Config::default();
+    config.set().emit_mode(rustfmt::EmitMode::Stdout);
+    config.set().verbose(rustfmt::Verbosity::Quiet);
+    config.set().format_macro_matchers(true);
+    config.set().normalize_doc_attributes(true);
+    let mut session = rustfmt::Session::new(config, Some(&mut file));
+    session
+        .format(rustfmt::Input::Text(content.to_string()))
+        .unwrap();
+}
diff --git a/codegen/src/gen.rs b/codegen/src/gen.rs
index 65ffb08..527662e 100644
--- a/codegen/src/gen.rs
+++ b/codegen/src/gen.rs
@@ -1,11 +1,7 @@
-use proc_macro2::TokenStream;
+use crate::file;
 use quote::quote;
-use rustfmt_nightly as rustfmt;
 use syn_codegen as types;
 
-use std::fs::File;
-use std::io::Write;
-
 const FOLD_SRC: &str = "../src/gen/fold.rs";
 const VISIT_SRC: &str = "../src/gen/visit.rs";
 const VISIT_MUT_SRC: &str = "../src/gen/visit_mut.rs";
@@ -609,24 +605,6 @@
     }
 }
 
-fn write_file(path: &str, content: TokenStream) {
-    let mut file = File::create(path).unwrap();
-    write!(
-        file,
-        "// THIS FILE IS AUTOMATICALLY GENERATED; DO NOT EDIT\n\n"
-    )
-    .unwrap();
-    let mut config = rustfmt::Config::default();
-    config.set().emit_mode(rustfmt::EmitMode::Stdout);
-    config.set().verbose(rustfmt::Verbosity::Quiet);
-    config.set().format_macro_matchers(true);
-    config.set().normalize_doc_attributes(true);
-    let mut session = rustfmt::Session::new(config, Some(&mut file));
-    session
-        .format(rustfmt::Input::Text(content.to_string()))
-        .unwrap();
-}
-
 const TERMINAL_TYPES: &[&str] = &["Span", "Ident"];
 
 pub fn generate(defs: &types::Definitions) {
@@ -668,7 +646,7 @@
 
     let fold_trait = state.fold_trait;
     let fold_impl = state.fold_impl;
-    write_file(
+    file::write(
         FOLD_SRC,
         quote! {
             // Unreachable code is generated sometimes without the full feature.
@@ -724,7 +702,7 @@
 
     let visit_trait = state.visit_trait;
     let visit_impl = state.visit_impl;
-    write_file(
+    file::write(
         VISIT_SRC,
         quote! {
             #![cfg_attr(feature = "cargo-clippy", allow(trivially_copy_pass_by_ref))]
@@ -756,7 +734,7 @@
 
     let visit_mut_trait = state.visit_mut_trait;
     let visit_mut_impl = state.visit_mut_impl;
-    write_file(
+    file::write(
         VISIT_MUT_SRC,
         quote! {
             use *;
diff --git a/codegen/src/main.rs b/codegen/src/main.rs
index d29a28c..01c3ec0 100644
--- a/codegen/src/main.rs
+++ b/codegen/src/main.rs
@@ -12,6 +12,7 @@
 #![recursion_limit = "128"]
 #![allow(clippy::needless_pass_by_value)]
 
+mod file;
 mod gen;
 mod json;
 mod parse;