Repository: jinxdash/prettier-plugin-rust (language: rust)

Issue:
inconsistency in EOF (end of file newline)
### Input code

```rust
fn eof() {}
\n
```


### Output code

```rust
fn eof() {}
\ No newline at end of file
```


### Additional context

It seems that this plugin does always add an EOF (end of file newline). Specifically for functions it does not do that. If you have a file with just a comment `// test` it does make it into `// test\n`.

That said, in the following piece of code rust prettier does NOT add a newline.
```rust
fn eof() {}
// comment
```


Discussion / hints:
For me it even removes the empty line. I am happy that running `prettier --check` doesn't throw errors about missing EOF newline in `.rs` files :)

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8c33d3a..28757da 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@
 - feat: format `cfg_if!` macros
 - feat: format `@` character in `macro_rules`
 - fix: format `<number>.` and `<number>e0` to float instead of int ([#14](https://github.com/jinxdash/prettier-plugin-rust/issues/14), [#16](https://github.com/jinxdash/prettier-plugin-rust/issues/16))
+- fix: always end files with a newline ([#21](https://github.com/jinxdash/prettier-plugin-rust/issues/21)
 - fix: avoid removing optional semi in rare [rust compiler bug](https://github.com/rust-lang/rust/issues/70844) ([#22](https://github.com/jinxdash/prettier-plugin-rust/issues/22))
 
 ## 0.1.8
diff --git a/src/format/core.ts b/src/format/core.ts
index c65ddb1..3723177 100644
--- a/src/format/core.ts
+++ b/src/format/core.ts
@@ -49,6 +49,7 @@ import {
 	RangeNode,
 	RestPattern,
 	ReturnExpression,
+	SourceFile,
 	StructDeclaration,
 	StructLiteral,
 	StructLiteralPropertySpread,
@@ -129,6 +130,7 @@ import {
 	is_ReassignmentExpression,
 	is_ReassignmentNode,
 	is_RestPattern,
+	is_SourceFile,
 	is_StructDeclaration,
 	is_StructLiteral,
 	is_StructLiteralProperty,
@@ -149,7 +151,7 @@ import {
 	ownStart,
 	start,
 } from "jinx-rust/utils";
-import { assert, AssertTypesEq, exit, find_last, flat, Identity, iLast, last_of, Map_get, Narrow, spread } from "../utils/common";
+import { AssertTypesEq, Identity, Map_get, Narrow, assert, exit, find_last, flat, iLast, last_of, spread } from "../utils/common";
 import {
 	CF,
 	getFirstComment,
@@ -175,15 +177,15 @@ import {
 	is_short,
 } from "./complexity";
 import {
-	align,
 	AstPath,
+	DCM,
+	Doc,
+	align,
 	breakParent,
 	canBreak,
 	cleanDoc,
 	conditionalGroup,
-	DCM,
 	dedentToRoot,
-	Doc,
 	fill,
 	getDocParts,
 	group,
@@ -330,6 +332,10 @@ export function printBodyOrCases<T extends NodeWithBodyOrCases | BlockLikeMacroI
 	const ccomments = printDanglingCommentsForInline(node, DCM["cases"]);
 	if (ccomments) printed.push(ccomments);
 
+	if (is_Program(node) && is_SourceFile(getParentNode(node)!) && printed.length > 0 && !comments) {
+		printed.push(hardline);
+	}
+
 	return printed;
 
 	function bumpInnerAttributes(arr: { node: Node; doc: Doc }[]) {
diff --git a/src/format/plugin.ts b/src/format/plugin.ts
index dbf0d22..73e6318 100644
--- a/src/format/plugin.ts
+++ b/src/format/plugin.ts
@@ -1,7 +1,8 @@
-import { AttributeOrComment, IfBlockExpression, LocArray, Node, Program, rs } from "jinx-rust";
+import { AttributeOrComment, IfBlockExpression, Node, Program, rs } from "jinx-rust";
 import {
 	ArrayProps,
 	BoolProps,
+	NodeProps,
 	end,
 	hasAttributes,
 	insertNodes,
@@ -18,10 +19,9 @@ import {
 	is_Node,
 	is_PunctuationToken,
 	is_UnionPattern,
-	NodeProps,
 	start,
 } from "jinx-rust/utils";
-import { assert, color, each, exit, iLast, is_array, map_tagged_template, Narrow, print_string } from "../utils/common";
+import { Narrow, assert, color, each, exit, iLast, is_array, map_tagged_template, print_string } from "../utils/common";
 import {
 	CF,
 	escapeComments,
@@ -38,7 +38,7 @@ import {
 } from "./comments";
 import { withCheckContext } from "./complexity";
 import { isNoopExpressionStatement, maybeEmptyLine } from "./core";
-import { AstPath, CustomOptions, Doc, group, hardline, indent, line, Plugin, softline, Symbol_comments } from "./external";
+import { AstPath, CustomOptions, Doc, Plugin, Symbol_comments, group, hardline, indent, line, softline } from "./external";
 import { printer } from "./printer";
 import { needsInnerParens, needsOuterSoftbreakParens, shouldPrintOuterAttributesAbove } from "./styling";
 import { getCommentChildNodes, isTransformed, transform_ast } from "./transform";
@@ -247,7 +247,6 @@ export function canAttachComment(n: Node) {
 	return !is_Comment(n) && !isNoopExpressionStatement(n) && !is_MissingNode(n) && !is_PunctuationToken(n);
 }
 
-
 export const plugin: Plugin<Node> = {
 	languages: [
 		{
diff --git a/src/format/printer.ts b/src/format/printer.ts
index 9ece9cb..c305e28 100644
--- a/src/format/printer.ts
+++ b/src/format/printer.ts
@@ -52,14 +52,14 @@ import {
 	printUnionPattern,
 } from "./core";
 import { DCM, Doc, group, hardline, ifBreak, indent, join, line, softline, willBreak } from "./external";
-import { f, getOptions, getParentNode, pathCall, type print, sg_duo, sg_single } from "./plugin";
+import { f, getOptions, getParentNode, pathCall, sg_duo, sg_single, type print } from "./plugin";
 import { needsParens, stmtNeedsSemi } from "./styling";
 import {
 	BlockLikeMacroInvocation,
 	CallLikeMacroInvocation,
-	isTransformed,
 	is_BlockLikeMacroInvocation,
 	is_CallLikeMacroInvocation,
+	isTransformed,
 } from "./transform";
 
 type nPrint<T extends Node> = (print: print<T>, node: T) => Doc | never;


Test patch:
diff --git a/tests/output-ext/expressions/block.f.rs b/tests/output-ext/expressions/block.f.rs
index 487a042..f350801 100644
--- a/tests/output-ext/expressions/block.f.rs
+++ b/tests/output-ext/expressions/block.f.rs
@@ -125,4 +125,5 @@ a::b(async move {
     f!("g: {}", h);
   }
 });
+
 // source: "../../../ext/jinx-rust/tests/samples/expressions/block.rs"
\ No newline at end of file
diff --git a/tests/output-ext/expressions/closure.f.rs b/tests/output-ext/expressions/closure.f.rs
index b4abbfe..e03f887 100644
--- a/tests/output-ext/expressions/closure.f.rs
+++ b/tests/output-ext/expressions/closure.f.rs
@@ -191,4 +191,5 @@ type Ty = [
     0
   }
 ];
+
 // source: "../../../ext/jinx-rust/tests/samples/expressions/closure.rs"
\ No newline at end of file
diff --git a/tests/output-ext/expressions/expr.f.rs b/tests/output-ext/expressions/expr.f.rs
index dd2e112..5279768 100644
--- a/tests/output-ext/expressions/expr.f.rs
+++ b/tests/output-ext/expressions/expr.f.rs
@@ -318,4 +318,5 @@ pub trait Foo: Iterator<Item = <Self as Foo>::Key> {}
 fn f() {
   ::m!(S, x);
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/expressions/expr.rs"
\ No newline at end of file
diff --git a/tests/output-ext/expressions/flow_expr.f.rs b/tests/output-ext/expressions/flow_expr.f.rs
index 9fa909c..f40ed74 100644
--- a/tests/output-ext/expressions/flow_expr.f.rs
+++ b/tests/output-ext/expressions/flow_expr.f.rs
@@ -153,4 +153,5 @@ pub fn main() {
     return;
   };
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/expressions/flow_expr.rs"
\ No newline at end of file
diff --git a/tests/output-ext/expressions/ident.f.rs b/tests/output-ext/expressions/ident.f.rs
index 2404a3a..ea8e17a 100644
--- a/tests/output-ext/expressions/ident.f.rs
+++ b/tests/output-ext/expressions/ident.f.rs
@@ -28,4 +28,5 @@ mod u8 {
     u8
   }
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/expressions/ident.rs"
\ No newline at end of file
diff --git a/tests/output-ext/expressions/literal.f.rs b/tests/output-ext/expressions/literal.f.rs
index 63fbc6d..b9febff 100644
--- a/tests/output-ext/expressions/literal.f.rs
+++ b/tests/output-ext/expressions/literal.f.rs
@@ -171,4 +171,5 @@ literal";
     })
   ); //
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/expressions/literal.rs"
\ No newline at end of file
diff --git a/tests/output-ext/expressions/match.f.rs b/tests/output-ext/expressions/match.f.rs
index c41131c..916accb 100644
--- a/tests/output-ext/expressions/match.f.rs
+++ b/tests/output-ext/expressions/match.f.rs
@@ -280,4 +280,5 @@ fn a() {
     }
   }
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/expressions/match.rs"
\ No newline at end of file
diff --git a/tests/output-ext/expressions/parens.f.rs b/tests/output-ext/expressions/parens.f.rs
index 17355d6..b2eb496 100644
--- a/tests/output-ext/expressions/parens.f.rs
+++ b/tests/output-ext/expressions/parens.f.rs
@@ -190,4 +190,5 @@ fn x() {
   foo(#[attr] a.b.c);
   foo(#[attr] a.b.c);
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/expressions/parens.rs"
\ No newline at end of file
diff --git a/tests/output-ext/expressions/precedence.f.rs b/tests/output-ext/expressions/precedence.f.rs
index 819318a..af46b77 100644
--- a/tests/output-ext/expressions/precedence.f.rs
+++ b/tests/output-ext/expressions/precedence.f.rs
@@ -934,4 +934,5 @@ pub extern "ABI" fn f() {
   0 > (0 > 0),
   0 > (0..0),
 ];
+
 // source: "../../../ext/jinx-rust/tests/samples/expressions/precedence.rs"
\ No newline at end of file
diff --git a/tests/output-ext/expressions/range.f.rs b/tests/output-ext/expressions/range.f.rs
index 5d387e5..3752dae 100644
--- a/tests/output-ext/expressions/range.f.rs
+++ b/tests/output-ext/expressions/range.f.rs
@@ -170,4 +170,5 @@ fn f() {
   a()..b()
 }
 fn foo(-128..=127: i8) {}
+
 // source: "../../../ext/jinx-rust/tests/samples/expressions/range.rs"
\ No newline at end of file
diff --git a/tests/output-ext/features/arbitrary_enum_discriminant.f.rs b/tests/output-ext/features/arbitrary_enum_discriminant.f.rs
index 22f8d8b..093234b 100644
--- a/tests/output-ext/features/arbitrary_enum_discriminant.f.rs
+++ b/tests/output-ext/features/arbitrary_enum_discriminant.f.rs
@@ -106,4 +106,5 @@ enum Unsigned {
   U64Limit = (u64::MAX as u128) + 1,
   Next,
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/features/arbitrary_enum_discriminant.rs"
\ No newline at end of file
diff --git a/tests/output-ext/features/associated_type_bounds.f.rs b/tests/output-ext/features/associated_type_bounds.f.rs
index 7504f79..dee51d2 100644
--- a/tests/output-ext/features/associated_type_bounds.f.rs
+++ b/tests/output-ext/features/associated_type_bounds.f.rs
@@ -8,4 +8,5 @@ fn f<'b, F>() where for<'a> F: Iterator<Item: 'a> + 'b {}
 trait A: MP {
   fn f<IM>(&self) -> i32 where for<'a> IM: T<T: U<<Self as MP>::T<'a>>>;
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/features/associated_type_bounds.rs"
\ No newline at end of file
diff --git a/tests/output-ext/features/async_closure.f.rs b/tests/output-ext/features/async_closure.f.rs
index 26418d7..bd7ef83 100644
--- a/tests/output-ext/features/async_closure.f.rs
+++ b/tests/output-ext/features/async_closure.f.rs
@@ -1,4 +1,5 @@
 #![feature(async_closure)]
 
 const X = async |x| 0;
+
 // source: "../../../ext/jinx-rust/tests/samples/features/async_closure.rs"
\ No newline at end of file
diff --git a/tests/output-ext/features/auto_traits.f.rs b/tests/output-ext/features/auto_traits.f.rs
index 33023fd..eb29e80 100644
--- a/tests/output-ext/features/auto_traits.f.rs
+++ b/tests/output-ext/features/auto_traits.f.rs
@@ -13,4 +13,5 @@ auto trait T {
 auto trait T {
   #![attr_1] // comment
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/features/auto_traits.rs"
\ No newline at end of file
diff --git a/tests/output-ext/features/const_generics_defaults.f.rs b/tests/output-ext/features/const_generics_defaults.f.rs
index 0d518cd..7201b07 100644
--- a/tests/output-ext/features/const_generics_defaults.f.rs
+++ b/tests/output-ext/features/const_generics_defaults.f.rs
@@ -61,4 +61,5 @@ struct FooBarrrrrrrr<
       1
   }
 >;
+
 // source: "../../../ext/jinx-rust/tests/samples/features/const_generics_defaults.rs"
\ No newline at end of file
diff --git a/tests/output-ext/features/const_trait_impl.f.rs b/tests/output-ext/features/const_trait_impl.f.rs
index 536902e..81bb7d5 100644
--- a/tests/output-ext/features/const_trait_impl.f.rs
+++ b/tests/output-ext/features/const_trait_impl.f.rs
@@ -30,4 +30,5 @@ trait F {
 const fn qux<T: ~const Foo>() {}
 const fn test1<T: ~const Foo + Bar>() {}
 const fn test2<T: ~const Foo + ~const Bar>() {}
+
 // source: "../../../ext/jinx-rust/tests/samples/features/const_trait_impl.rs"
\ No newline at end of file
diff --git a/tests/output-ext/features/decl_macro.f.rs b/tests/output-ext/features/decl_macro.f.rs
index 26d876e..8244deb 100644
--- a/tests/output-ext/features/decl_macro.f.rs
+++ b/tests/output-ext/features/decl_macro.f.rs
@@ -1,4 +1,5 @@
 #![feature(decl_macro)]
 
 macro m() {}
+
 // source: "../../../ext/jinx-rust/tests/samples/features/decl_macro.rs"
\ No newline at end of file
diff --git a/tests/output-ext/features/destructuring_assignment.f.rs b/tests/output-ext/features/destructuring_assignment.f.rs
index 2e86dde..0a4012f 100644
--- a/tests/output-ext/features/destructuring_assignment.f.rs
+++ b/tests/output-ext/features/destructuring_assignment.f.rs
@@ -65,4 +65,5 @@ fn main() {
   TupleStruct(a, a, b) = TupleStruct(1, 2);
   TupleStruct(a, b) = TupleStruct(0, 1);
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/features/destructuring_assignment.rs"
\ No newline at end of file
diff --git a/tests/output-ext/features/generators.f.rs b/tests/output-ext/features/generators.f.rs
index 054c7e8..d393e82 100644
--- a/tests/output-ext/features/generators.f.rs
+++ b/tests/output-ext/features/generators.f.rs
@@ -11,4 +11,5 @@
     });
   },
 ];
+
 // source: "../../../ext/jinx-rust/tests/samples/features/generators.rs"
\ No newline at end of file
diff --git a/tests/output-ext/features/if_let_guard.f.rs b/tests/output-ext/features/if_let_guard.f.rs
index 44eb86a..4b1a749 100644
--- a/tests/output-ext/features/if_let_guard.f.rs
+++ b/tests/output-ext/features/if_let_guard.f.rs
@@ -11,4 +11,5 @@ fn main() {
     _ => {}
   }
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/features/if_let_guard.rs"
\ No newline at end of file
diff --git a/tests/output-ext/features/inline_const.f.rs b/tests/output-ext/features/inline_const.f.rs
index 674b402..c13d02d 100644
--- a/tests/output-ext/features/inline_const.f.rs
+++ b/tests/output-ext/features/inline_const.f.rs
@@ -3,4 +3,5 @@
 fn f() {
   const {}
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/features/inline_const.rs"
\ No newline at end of file
diff --git a/tests/output-ext/features/inline_const_pat.f.rs b/tests/output-ext/features/inline_const_pat.f.rs
index dc30124..fe1040d 100644
--- a/tests/output-ext/features/inline_const_pat.f.rs
+++ b/tests/output-ext/features/inline_const_pat.f.rs
@@ -7,4 +7,5 @@ fn f() {
     const { one() } => {}
   }
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/features/inline_const_pat.rs"
\ No newline at end of file
diff --git a/tests/output-ext/features/let_chains.f.rs b/tests/output-ext/features/let_chains.f.rs
index 094aefa..f9b75a4 100644
--- a/tests/output-ext/features/let_chains.f.rs
+++ b/tests/output-ext/features/let_chains.f.rs
@@ -38,4 +38,5 @@ fn f() {
   while let A(ref a) = e && let b = a && let _p = b {}
   while let A(ref a) = e && let R { c: d, y: _ } = a && let B = d {}
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/features/let_chains.rs"
\ No newline at end of file
diff --git a/tests/output-ext/features/let_else.f.rs b/tests/output-ext/features/let_else.f.rs
index 0b79e7e..da0d5bb 100644
--- a/tests/output-ext/features/let_else.f.rs
+++ b/tests/output-ext/features/let_else.f.rs
@@ -1,4 +1,5 @@
 #![feature(let_else)]
 
 let a = 1 else { 2 };
+
 // source: "../../../ext/jinx-rust/tests/samples/features/let_else.rs"
\ No newline at end of file
diff --git a/tests/output-ext/features/negative_impls.f.rs b/tests/output-ext/features/negative_impls.f.rs
index 3e6a1aa..66b77e3 100644
--- a/tests/output-ext/features/negative_impls.f.rs
+++ b/tests/output-ext/features/negative_impls.f.rs
@@ -13,4 +13,5 @@ impl !Sync for A {}
 impl<'a, T> !MyPredicate<'a> for &T where T: 'a {}
 impl<T> !Foo for &T where T: 'static {}
 impl<E> !Future for Option<E> where E: Sized {}
+
 // source: "../../../ext/jinx-rust/tests/samples/features/negative_impls.rs"
\ No newline at end of file
diff --git a/tests/output-ext/features/trait_alias.f.rs b/tests/output-ext/features/trait_alias.f.rs
index 63de555..51b2485 100644
--- a/tests/output-ext/features/trait_alias.f.rs
+++ b/tests/output-ext/features/trait_alias.f.rs
@@ -2,4 +2,5 @@
 
 trait A =;
 trait A = std::fmt::Debug + Send;
+
 // source: "../../../ext/jinx-rust/tests/samples/features/trait_alias.rs"
\ No newline at end of file
diff --git a/tests/output-ext/macro/attributes.f.rs b/tests/output-ext/macro/attributes.f.rs
index bb27a90..6cbe50c 100644
--- a/tests/output-ext/macro/attributes.f.rs
+++ b/tests/output-ext/macro/attributes.f.rs
@@ -708,4 +708,5 @@ struct Foo;
   )
 )]
 const MIN_ALIGN: usize = 16;
+
 // source: "../../../ext/jinx-rust/tests/samples/macro/attributes.rs"
\ No newline at end of file
diff --git a/tests/output-ext/macro/macro.invocation.f.rs b/tests/output-ext/macro/macro.invocation.f.rs
index 339fd56..095e567 100644
--- a/tests/output-ext/macro/macro.invocation.f.rs
+++ b/tests/output-ext/macro/macro.invocation.f.rs
@@ -742,4 +742,5 @@ c!(pub(in path::to));
 c!(pub(in ::path::to));
 c!(pub(in self::path::to));
 c!(pub(in super::path::to));
+
 // source: "../../../ext/jinx-rust/tests/samples/macro/macro.invocation.rs"
\ No newline at end of file
diff --git a/tests/output-ext/macro/macro.item.f.rs b/tests/output-ext/macro/macro.item.f.rs
index abaa311..39a57ab 100644
--- a/tests/output-ext/macro/macro.item.f.rs
+++ b/tests/output-ext/macro/macro.item.f.rs
@@ -18,4 +18,5 @@ pub macro create_struct($a:ident) {}
 pub(crate) macro mac {
   ($arg:expr) => { $arg + $arg };
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/macro/macro.item.rs"
\ No newline at end of file
diff --git a/tests/output-ext/macro/macro.match.f.rs b/tests/output-ext/macro/macro.match.f.rs
index db5abc0..b1505e5 100644
--- a/tests/output-ext/macro/macro.match.f.rs
+++ b/tests/output-ext/macro/macro.match.f.rs
@@ -459,4 +459,5 @@ macro_rules! c {
     $(,)?
   ) => {};
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/macro/macro.match.rs"
\ No newline at end of file
diff --git a/tests/output-ext/macro/macro.tokens.f.rs b/tests/output-ext/macro/macro.tokens.f.rs
index 1a684b4..8f6c0e5 100644
--- a/tests/output-ext/macro/macro.tokens.f.rs
+++ b/tests/output-ext/macro/macro.tokens.f.rs
@@ -492,4 +492,5 @@ let ret = structure.gen_impl(
     }
 }
 );
+
 // source: "../../../ext/jinx-rust/tests/samples/macro/macro.tokens.rs"
\ No newline at end of file
diff --git a/tests/output-ext/macro/macro.transform.f.rs b/tests/output-ext/macro/macro.transform.f.rs
index 7cbc4ce..20aeb45 100644
--- a/tests/output-ext/macro/macro.transform.f.rs
+++ b/tests/output-ext/macro/macro.transform.f.rs
@@ -3391,4 +3391,5 @@ macro complex_nonterminal($nt_item:item) {
 
     n!(a $nt_item b); // comment
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/macro/macro.transform.rs"
\ No newline at end of file
diff --git a/tests/output-ext/miscellaneous/ast-program-locs-attr.f.rs b/tests/output-ext/miscellaneous/ast-program-locs-attr.f.rs
index b6871f3..7a929a3 100644
--- a/tests/output-ext/miscellaneous/ast-program-locs-attr.f.rs
+++ b/tests/output-ext/miscellaneous/ast-program-locs-attr.f.rs
@@ -3,4 +3,5 @@
 #[attr]
 struct T;
 // comment
+
 // source: "../../../ext/jinx-rust/tests/samples/miscellaneous/ast-program-locs-attr.rs"
\ No newline at end of file
diff --git a/tests/output-ext/miscellaneous/ast-program-locs.f.rs b/tests/output-ext/miscellaneous/ast-program-locs.f.rs
index 1a2a9c0..51254f3 100644
--- a/tests/output-ext/miscellaneous/ast-program-locs.f.rs
+++ b/tests/output-ext/miscellaneous/ast-program-locs.f.rs
@@ -2,4 +2,5 @@
 // comment
 struct T;
 // comment
+
 // source: "../../../ext/jinx-rust/tests/samples/miscellaneous/ast-program-locs.rs"
\ No newline at end of file
diff --git a/tests/output-ext/miscellaneous/empty-attr-x.f.rs b/tests/output-ext/miscellaneous/empty-attr-x.f.rs
index d610039..600a95e 100644
--- a/tests/output-ext/miscellaneous/empty-attr-x.f.rs
+++ b/tests/output-ext/miscellaneous/empty-attr-x.f.rs
@@ -3,4 +3,5 @@
 #![attr]
 
 #![attr]
+
 // source: "../../../ext/jinx-rust/tests/samples/miscellaneous/empty-attr-x.rs"
\ No newline at end of file
diff --git a/tests/output-ext/miscellaneous/empty-attr.f.rs b/tests/output-ext/miscellaneous/empty-attr.f.rs
index 3339851..2fd1028 100644
--- a/tests/output-ext/miscellaneous/empty-attr.f.rs
+++ b/tests/output-ext/miscellaneous/empty-attr.f.rs
@@ -1,2 +1,3 @@
 #![attr]
+
 // source: "../../../ext/jinx-rust/tests/samples/miscellaneous/empty-attr.rs"
\ No newline at end of file
diff --git a/tests/output-ext/miscellaneous/shebang-b.f.rs b/tests/output-ext/miscellaneous/shebang-b.f.rs
index a70c164..e5f6dd9 100644
--- a/tests/output-ext/miscellaneous/shebang-b.f.rs
+++ b/tests/output-ext/miscellaneous/shebang-b.f.rs
@@ -6,4 +6,5 @@
 //!
 
 use std;
+
 // source: "../../../ext/jinx-rust/tests/samples/miscellaneous/shebang-b.rs"
\ No newline at end of file
diff --git a/tests/output-ext/patterns/pattern.f.rs b/tests/output-ext/patterns/pattern.f.rs
index 42b8dec..19de868 100644
--- a/tests/output-ext/patterns/pattern.f.rs
+++ b/tests/output-ext/patterns/pattern.f.rs
@@ -144,4 +144,5 @@ fn a() {
   let &&&&_ = &&&&1_usize;
   let &&&&&_ = &&&&&1_usize;
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/patterns/pattern.rs"
\ No newline at end of file
diff --git a/tests/output-ext/patterns/rest.f.rs b/tests/output-ext/patterns/rest.f.rs
index 4c31ad4..85b25c6 100644
--- a/tests/output-ext/patterns/rest.f.rs
+++ b/tests/output-ext/patterns/rest.f.rs
@@ -60,4 +60,5 @@ fn b() {
   let a @ [b, .., c] = [C, mk_c(), C];
   let a @ [b, mid @ .., c] = [C, mk_c(), C];
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/patterns/rest.rs"
\ No newline at end of file
diff --git a/tests/output-ext/patterns/union.f.rs b/tests/output-ext/patterns/union.f.rs
index 46034de..c2b2bbd 100644
--- a/tests/output-ext/patterns/union.f.rs
+++ b/tests/output-ext/patterns/union.f.rs
@@ -194,4 +194,5 @@ accept_pat!((p | q,));
 accept_pat!(TS(p | q));
 accept_pat!(NS { f: p | q });
 accept_pat!([p | q]);
+
 // source: "../../../ext/jinx-rust/tests/samples/patterns/union.rs"
\ No newline at end of file
diff --git a/tests/output-ext/specifiers/extern.f.rs b/tests/output-ext/specifiers/extern.f.rs
index 4624bc0..4f737d4 100644
--- a/tests/output-ext/specifiers/extern.f.rs
+++ b/tests/output-ext/specifiers/extern.f.rs
@@ -22,4 +22,5 @@ extern {
   pub(super) const fn foo() -> *mut Bar;
   pub(crate) unsafe fn foo() -> *mut Bar;
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/specifiers/extern.rs"
\ No newline at end of file
diff --git a/tests/output-ext/specifiers/pub.f.rs b/tests/output-ext/specifiers/pub.f.rs
index 52663fe..3787eaf 100644
--- a/tests/output-ext/specifiers/pub.f.rs
+++ b/tests/output-ext/specifiers/pub.f.rs
@@ -72,4 +72,5 @@ pub macro m() {}
 pub(in Self::f) struct Z;
 pub extern crate self as name;
 pub use name::name as bug;
+
 // source: "../../../ext/jinx-rust/tests/samples/specifiers/pub.rs"
\ No newline at end of file
diff --git a/tests/output-ext/statements/const.f.rs b/tests/output-ext/statements/const.f.rs
index c39a091..f0c531c 100644
--- a/tests/output-ext/statements/const.f.rs
+++ b/tests/output-ext/statements/const.f.rs
@@ -14,4 +14,5 @@ const MY_A: A = A {
     }
   },
 };
+
 // source: "../../../ext/jinx-rust/tests/samples/statements/const.rs"
\ No newline at end of file
diff --git a/tests/output-ext/statements/enum.f.rs b/tests/output-ext/statements/enum.f.rs
index fafa970..09f6758 100644
--- a/tests/output-ext/statements/enum.f.rs
+++ b/tests/output-ext/statements/enum.f.rs
@@ -98,4 +98,5 @@ enum E<'a, 'b, 'c: 'b> {
 }
 
 pub enum X<D> where D: Copy + Debug + Eq {}
+
 // source: "../../../ext/jinx-rust/tests/samples/statements/enum.rs"
\ No newline at end of file
diff --git a/tests/output-ext/statements/impl.f.rs b/tests/output-ext/statements/impl.f.rs
index eb85a27..cecda6d 100644
--- a/tests/output-ext/statements/impl.f.rs
+++ b/tests/output-ext/statements/impl.f.rs
@@ -54,4 +54,5 @@ impl A for Box<C> {}
 impl A for lib::Something<C> {}
 impl A for D<C> {}
 impl<T: ::std::fmt::Display> A<T> {}
+
 // source: "../../../ext/jinx-rust/tests/samples/statements/impl.rs"
\ No newline at end of file
diff --git a/tests/output-ext/statements/self.f.rs b/tests/output-ext/statements/self.f.rs
index 9439245..42cd610 100644
--- a/tests/output-ext/statements/self.f.rs
+++ b/tests/output-ext/statements/self.f.rs
@@ -31,4 +31,5 @@ fn f(&self) -> Self;
 // fn f(self::S: S) {}
 // fn g(&self::S: &S) {}
 // fn h(&mut self::S: &mut S) {}
+
 // source: "../../../ext/jinx-rust/tests/samples/statements/self.rs"
\ No newline at end of file
diff --git a/tests/output-ext/statements/spread.f.rs b/tests/output-ext/statements/spread.f.rs
index 89381ec..b0fe7b8 100644
--- a/tests/output-ext/statements/spread.f.rs
+++ b/tests/output-ext/statements/spread.f.rs
@@ -30,4 +30,5 @@ trait T {
 extern "C" {
   pub fn foo(x: i32, ...);
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/statements/spread.rs"
\ No newline at end of file
diff --git a/tests/output-ext/statements/statements.f.rs b/tests/output-ext/statements/statements.f.rs
index 23806b8..3ec2ba3 100644
--- a/tests/output-ext/statements/statements.f.rs
+++ b/tests/output-ext/statements/statements.f.rs
@@ -153,4 +153,5 @@ extern r#"C"# {
 }
 
 type T = extern r#"C"# fn();
+
 // source: "../../../ext/jinx-rust/tests/samples/statements/statements.rs"
\ No newline at end of file
diff --git a/tests/output-ext/statements/static.f.rs b/tests/output-ext/statements/static.f.rs
index 912fbf3..42ffc8a 100644
--- a/tests/output-ext/statements/static.f.rs
+++ b/tests/output-ext/statements/static.f.rs
@@ -8,4 +8,5 @@ pub static B: &'static a = unsafe { &q };
 static A: fn(_) -> u8 = |_| 8;
 static BOO: dyn Fn() -> _ = "";
 static x: _;
+
 // source: "../../../ext/jinx-rust/tests/samples/statements/static.rs"
\ No newline at end of file
diff --git a/tests/output-ext/statements/struct.f.rs b/tests/output-ext/statements/struct.f.rs
index ed60a32..0dac632 100644
--- a/tests/output-ext/statements/struct.f.rs
+++ b/tests/output-ext/statements/struct.f.rs
@@ -60,4 +60,5 @@ struct S(<AT as A<DT>>::AS);
 pub struct A<I> where I: B<C: D> {
   w: <I::E as F>::G,
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/statements/struct.rs"
\ No newline at end of file
diff --git a/tests/output-ext/statements/trait.f.rs b/tests/output-ext/statements/trait.f.rs
index e767960..0ea1c22 100644
--- a/tests/output-ext/statements/trait.f.rs
+++ b/tests/output-ext/statements/trait.f.rs
@@ -27,4 +27,5 @@ trait A<X: T2 + ?Sized> {}
 pub trait A {}
 pub trait C = A + B;
 pub trait A<R: D>: Sized {}
+
 // source: "../../../ext/jinx-rust/tests/samples/statements/trait.rs"
\ No newline at end of file
diff --git a/tests/output-ext/statements/union.f.rs b/tests/output-ext/statements/union.f.rs
index 00ea090..22a5367 100644
--- a/tests/output-ext/statements/union.f.rs
+++ b/tests/output-ext/statements/union.f.rs
@@ -16,4 +16,5 @@ fn main() {
   let mut r#async = 1;
   union as T;
 }
+
 // source: "../../../ext/jinx-rust/tests/samples/statements/union.rs"
\ No newline at end of file
diff --git a/tests/output-ext/statements/use.f.rs b/tests/output-ext/statements/use.f.rs
index 9557618..28f3103 100644
--- a/tests/output-ext/statements/use.f.rs
+++ b/tests/output-ext/statements/use.f.rs
@@ -166,4 +166,5 @@ use imports_with_attr;
 use std::f64::consts::{ SQRT_2, E, PI };
 #[rustfmt::skip]
 use std::fmt::{self, {Display, Formatter}};
+
 // source: "../../../ext/jinx-rust/tests/samples/statements/use.rs"
\ No newline at end of file
diff --git a/tests/output-ext/types/cast.f.rs b/tests/output-ext/types/cast.f.rs
index 3d1d30d..7f25cd5 100644
--- a/tests/output-ext/types/cast.f.rs
+++ b/tests/output-ext/types/cast.f.rs
@@ -34,4 +34,5 @@ fn a() {
   ]
 }
 const A: *const u8 = &0 as *const _ as *const Q as *const u8;
+
 // source: "../../../ext/jinx-rust/tests/samples/types/cast.rs"
\ No newline at end of file
diff --git a/tests/output-ext/types/never.f.rs b/tests/output-ext/types/never.f.rs
index c301ff4..a7b6589 100644
--- a/tests/output-ext/types/never.f.rs
+++ b/tests/output-ext/types/never.f.rs
@@ -18,4 +18,5 @@ impl A<!> for B {
 }
 impl A for ! {}
 type A = !;
+
 // source: "../../../ext/jinx-rust/tests/samples/types/never.rs"
\ No newline at end of file
diff --git a/tests/output-ext/types/types.f.rs b/tests/output-ext/types/types.f.rs
index 444d22a..c45da32 100644
--- a/tests/output-ext/types/types.f.rs
+++ b/tests/output-ext/types/types.f.rs
@@ -397,4 +397,5 @@ mod a {
 
 pub type b = Box<dyn t + sync::Send + sync::Sync + 'static>;
 pub type b = Box<dyn for<'tcx> e<'tcx> + sync::Send + sync::Sync + 'static>;
+
 // source: "../../../ext/jinx-rust/tests/samples/types/types.rs"
\ No newline at end of file
diff --git a/tests/output/comments/assignment.f.rs b/tests/output/comments/assignment.f.rs
index efbf1a4..72642ba 100644
--- a/tests/output/comments/assignment.f.rs
+++ b/tests/output/comments/assignment.f.rs
@@ -308,4 +308,5 @@ fn foo() {
     ..a
   } = a);
 }
+
 // source: "../../samples/comments/assignment.rs"
\ No newline at end of file
diff --git a/tests/output/comments/binaryish.f.rs b/tests/output/comments/binaryish.f.rs
index 774920b..6fa62f6 100644
--- a/tests/output/comments/binaryish.f.rs
+++ b/tests/output/comments/binaryish.f.rs
@@ -104,4 +104,5 @@ a =
 0 ^
   // 35_______
   x;
+
 // source: "../../samples/comments/binaryish.rs"
\ No newline at end of file
diff --git a/tests/output/comments/blocks.f.rs b/tests/output/comments/blocks.f.rs
index edb6e9a..aeb8ad8 100644
--- a/tests/output/comments/blocks.f.rs
+++ b/tests/output/comments/blocks.f.rs
@@ -309,4 +309,5 @@ fn foo() {
     // work
   }).await;
 }
+
 // source: "../../samples/comments/blocks.rs"
\ No newline at end of file
diff --git a/tests/output/comments/chain.f.rs b/tests/output/comments/chain.f.rs
index a570fae..8d7888a 100644
--- a/tests/output/comments/chain.f.rs
+++ b/tests/output/comments/chain.f.rs
@@ -66,4 +66,5 @@ Observable.of(process)
     }
   )
   .takeUntil(exit);
+
 // source: "../../samples/comments/chain.rs"
\ No newline at end of file
diff --git a/tests/output/comments/closure.f.rs b/tests/output/comments/closure.f.rs
index 2e60336..a90b972 100644
--- a/tests/output/comments/closure.f.rs
+++ b/tests/output/comments/closure.f.rs
@@ -42,4 +42,5 @@ const rootEpic = |actions, store|
       getLogger().error(err);
       return stream;
     });
+
 // source: "../../samples/comments/closure.rs"
\ No newline at end of file
diff --git a/tests/output/comments/dangling.f.rs b/tests/output/comments/dangling.f.rs
index 936fb5e..87e3fc6 100644
--- a/tests/output/comments/dangling.f.rs
+++ b/tests/output/comments/dangling.f.rs
@@ -96,4 +96,5 @@ struct A;
 #[/* comment */]
 #[/* comment */]
 struct A;
+
 // source: "../../samples/comments/dangling.rs"
\ No newline at end of file
diff --git a/tests/output/comments/flow.f.rs b/tests/output/comments/flow.f.rs
index 3fc32bd..6a712ef 100644
--- a/tests/output/comments/flow.f.rs
+++ b/tests/output/comments/flow.f.rs
@@ -99,4 +99,5 @@ return A {
   // _______
   bar: baz() + 1,
 };
+
 // source: "../../samples/comments/flow.rs"
\ No newline at end of file
diff --git a/tests/output/comments/functions.f.rs b/tests/output/comments/functions.f.rs
index f68dda1..a0659b2 100644
--- a/tests/output/comments/functions.f.rs
+++ b/tests/output/comments/functions.f.rs
@@ -30,4 +30,5 @@ fn f4 /* _______ */(/* _______ */) {/* _______ */}
 fn f5(/* _______ */ /* _______ */ a) {}
 fn f6(/* _______ */ a /* _______ */) {}
 fn f7(/* _______ */ /* _______ */ a) {/* _______ */}
+
 // source: "../../samples/comments/functions.rs"
\ No newline at end of file
diff --git a/tests/output/comments/ignore.attr.f.rs b/tests/output/comments/ignore.attr.f.rs
index a1eb250..49a9b61 100644
--- a/tests/output/comments/ignore.attr.f.rs
+++ b/tests/output/comments/ignore.attr.f.rs
@@ -19,4 +19,5 @@ fn   f()    {
 	  1     + 1;
 	}
 }
+
 // source: "../../samples/comments/ignore.attr.rs"
\ No newline at end of file
diff --git a/tests/output/comments/ignore.f.rs b/tests/output/comments/ignore.f.rs
index e1814ef..e0a8453 100644
--- a/tests/output/comments/ignore.f.rs
+++ b/tests/output/comments/ignore.f.rs
@@ -107,4 +107,5 @@ const A {
   // prettier-ignore
   bar7 :            a,
 } = foo;
+
 // source: "../../samples/comments/ignore.rs"
\ No newline at end of file
diff --git a/tests/output/comments/imports.f.rs b/tests/output/comments/imports.f.rs
index ad5c78d..1422781 100644
--- a/tests/output/comments/imports.f.rs
+++ b/tests/output/comments/imports.f.rs
@@ -6,4 +6,5 @@ use list::{
 };
 use test::{ Other /* C   */, /*   A   */ self /*    B     */ };
 use ::{ /* Pre-comment! */ Foo, Bar /* comment */ };
+
 // source: "../../samples/comments/imports.rs"
\ No newline at end of file
diff --git a/tests/output/comments/macro.f.rs b/tests/output/comments/macro.f.rs
index dcd7920..e058e75 100644
--- a/tests/output/comments/macro.f.rs
+++ b/tests/output/comments/macro.f.rs
@@ -23,4 +23,5 @@ x! {~ {
     // ERROR!
 }
 }
+
 // source: "../../samples/comments/macro.rs"
\ No newline at end of file
diff --git a/tests/output/comments/parens.f.rs b/tests/output/comments/parens.f.rs
index 2155f1b..6d480de 100644
--- a/tests/output/comments/parens.f.rs
+++ b/tests/output/comments/parens.f.rs
@@ -257,4 +257,5 @@ Math.min(
     devsite_footer_height,
   0
 );
+
 // source: "../../samples/comments/parens.rs"
\ No newline at end of file
diff --git a/tests/output/common/arrays.f.rs b/tests/output/common/arrays.f.rs
index 238ce2e..72c572e 100644
--- a/tests/output/common/arrays.f.rs
+++ b/tests/output/common/arrays.f.rs
@@ -316,4 +316,5 @@ let test_case = [
     45,
   ],
 ];
+
 // source: "../../samples/common/arrays.rs"
\ No newline at end of file
diff --git a/tests/output/common/assignments.f.rs b/tests/output/common/assignments.f.rs
index 87c7648..e1686b5 100644
--- a/tests/output/common/assignments.f.rs
+++ b/tests/output/common/assignments.f.rs
@@ -406,4 +406,5 @@ let value =
 
 let value =
   ____________________________________________________..=____________________________________________________;
+
 // source: "../../samples/common/assignments.rs"
\ No newline at end of file
diff --git a/tests/output/common/binaryish.f.rs b/tests/output/common/binaryish.f.rs
index b2b6d86..06e4c48 100644
--- a/tests/output/common/binaryish.f.rs
+++ b/tests/output/common/binaryish.f.rs
@@ -540,4 +540,5 @@ while
     someVeryLongArgD
   )
 {}
+
 // source: "../../samples/common/binaryish.rs"
\ No newline at end of file
diff --git a/tests/output/common/chains.f.rs b/tests/output/common/chains.f.rs
index 16d2330..7859f7e 100644
--- a/tests/output/common/chains.f.rs
+++ b/tests/output/common/chains.f.rs
@@ -861,4 +861,5 @@ source
     scan(|acc, x| acc + x, 0)
   )
   .subscribe(|x| console.log(x));
+
 // source: "../../samples/common/chains.rs"
\ No newline at end of file
diff --git a/tests/output/common/chains.first-argument-expansion.f.rs b/tests/output/common/chains.first-argument-expansion.f.rs
index fe1b85e..201c812 100644
--- a/tests/output/common/chains.first-argument-expansion.f.rs
+++ b/tests/output/common/chains.first-argument-expansion.f.rs
@@ -187,4 +187,5 @@ db.collection("indexOptionDefault").createIndex(
     done();
   }
 );
+
 // source: "../../samples/common/chains.first-argument-expansion.rs"
\ No newline at end of file
diff --git a/tests/output/common/chains.last-argument-expansion.f.rs b/tests/output/common/chains.last-argument-expansion.f.rs
index 9a01522..c3fa51a 100644
--- a/tests/output/common/chains.last-argument-expansion.f.rs
+++ b/tests/output/common/chains.last-argument-expansion.f.rs
@@ -274,4 +274,5 @@ const contentTypes = |tile, singleSelection| {
     }
   );
 };
+
 // source: "../../samples/common/chains.last-argument-expansion.rs"
\ No newline at end of file
diff --git a/tests/output/common/closures.f.rs b/tests/output/common/closures.f.rs
index 99e1a9c..ecaf75c 100644
--- a/tests/output/common/closures.f.rs
+++ b/tests/output/common/closures.f.rs
@@ -264,4 +264,5 @@ map(|[resource]| A {
     this.resource = resource;
   },
 });
+
 // source: "../../samples/common/closures.rs"
\ No newline at end of file
diff --git a/tests/output/common/destructuring.f.rs b/tests/output/common/destructuring.f.rs
index 53a714e..967431d 100644
--- a/tests/output/common/destructuring.f.rs
+++ b/tests/output/common/destructuring.f.rs
@@ -38,4 +38,5 @@ const A {
   bar: bazAndSomething,
   quxIsLong,
 } = someBigFunctionName("foo")("bar");
+
 // source: "../../samples/common/destructuring.rs"
\ No newline at end of file
diff --git a/tests/output/common/members.f.rs b/tests/output/common/members.f.rs
index fd15345..6f28a47 100644
--- a/tests/output/common/members.f.rs
+++ b/tests/output/common/members.f.rs
@@ -106,4 +106,5 @@ const g = classnames(A {
 
 const h = A { foo: "bar", baz: r"Lorem
 ipsum" };
+
 // source: "../../samples/common/members.rs"
\ No newline at end of file
diff --git a/tests/output/common/types.f.rs b/tests/output/common/types.f.rs
index b88e1be..f2711b2 100644
--- a/tests/output/common/types.f.rs
+++ b/tests/output/common/types.f.rs
@@ -387,4 +387,5 @@ const appIDs = createSelector(
   PubXURLParams.APP_IDS,
   |rawAppIDs| -> Array<AppID> { deserializeList(rawAppIDs) }
 );
+
 // source: "../../samples/common/types.rs"
\ No newline at end of file
diff --git a/tests/output/issues/0.f.rs b/tests/output/issues/0.f.rs
index 3363aa2..c272874 100644
--- a/tests/output/issues/0.f.rs
+++ b/tests/output/issues/0.f.rs
@@ -2365,4 +2365,5 @@ let notify::event::Event {
   paths,
   ..
 } = event;
+
 // source: "../../samples/issues/0.rs"
\ No newline at end of file
diff --git a/tests/output/issues/14.f.rs b/tests/output/issues/14.f.rs
index 2b2ee63..6df9607 100644
--- a/tests/output/issues/14.f.rs
+++ b/tests/output/issues/14.f.rs
@@ -1,2 +1,3 @@
 [10.0, 10.0, 10.0, 10];
+
 // source: "../../samples/issues/14.rs"
\ No newline at end of file
diff --git a/tests/output/issues/21/fn_comment.f.rs b/tests/output/issues/21/fn_comment.f.rs
new file mode 100644
index 0000000..a0005ee
--- /dev/null
+++ b/tests/output/issues/21/fn_comment.f.rs
@@ -0,0 +1,4 @@
+fn eof() {}
+// comment
+
+// source: "../../../samples/issues/21/fn_comment.rs"
\ No newline at end of file
diff --git a/tests/output/issues/21/fn_fn.f.rs b/tests/output/issues/21/fn_fn.f.rs
new file mode 100644
index 0000000..cd07fdb
--- /dev/null
+++ b/tests/output/issues/21/fn_fn.f.rs
@@ -0,0 +1,4 @@
+fn eof1() {}
+fn eof2() {}
+
+// source: "../../../samples/issues/21/fn_fn.rs"
\ No newline at end of file
diff --git a/tests/output/issues/21/fn_ln.f.rs b/tests/output/issues/21/fn_ln.f.rs
new file mode 100644
index 0000000..21b379f
--- /dev/null
+++ b/tests/output/issues/21/fn_ln.f.rs
@@ -0,0 +1,3 @@
+fn eof() {}
+
+// source: "../../../samples/issues/21/fn_ln.rs"
\ No newline at end of file
diff --git a/tests/output/issues/21/ln_fn_ln.f.rs b/tests/output/issues/21/ln_fn_ln.f.rs
new file mode 100644
index 0000000..402b892
--- /dev/null
+++ b/tests/output/issues/21/ln_fn_ln.f.rs
@@ -0,0 +1,3 @@
+fn eof() {}
+
+// source: "../../../samples/issues/21/ln_fn_ln.rs"
\ No newline at end of file
diff --git a/tests/output/issues/21/mod.f.rs b/tests/output/issues/21/mod.f.rs
new file mode 100644
index 0000000..b13b1ba
--- /dev/null
+++ b/tests/output/issues/21/mod.f.rs
@@ -0,0 +1,3 @@
+mod eof {}
+
+// source: "../../../samples/issues/21/mod.rs"
\ No newline at end of file
diff --git a/tests/output/issues/22.f.rs b/tests/output/issues/22.f.rs
index b429fcf..3eabb6c 100644
--- a/tests/output/issues/22.f.rs
+++ b/tests/output/issues/22.f.rs
@@ -70,4 +70,5 @@ fn inner_attr() {
   }
   #![attr]
 }
+
 // source: "../../samples/issues/22.rs"
\ No newline at end of file
diff --git a/tests/output/issues/nth-pass.f.1.rs b/tests/output/issues/nth-pass.f.1.rs
index 33f57fd..f3b38ac 100644
--- a/tests/output/issues/nth-pass.f.1.rs
+++ b/tests/output/issues/nth-pass.f.1.rs
@@ -28,5 +28,6 @@ let zzzz =
 
   c, //
 ];
+
 // format: lost 4 comments
 // source: "../../samples/issues/nth-pass.rs"
\ No newline at end of file
diff --git a/tests/output/issues/nth-pass.f.rs b/tests/output/issues/nth-pass.f.rs
index bfa454f..eeff8f6 100644
--- a/tests/output/issues/nth-pass.f.rs
+++ b/tests/output/issues/nth-pass.f.rs
@@ -32,5 +32,6 @@ let zzzz =
 
   c, //
 ];
+
 // format: lost 4 comments
 // source: "../../samples/issues/nth-pass.rs"
\ No newline at end of file
diff --git a/tests/output/macros/cfg_if.f.rs b/tests/output/macros/cfg_if.f.rs
index cc88f9f..0197554 100644
--- a/tests/output/macros/cfg_if.f.rs
+++ b/tests/output/macros/cfg_if.f.rs
@@ -74,4 +74,5 @@
   },
   cfg_if! { if true{} },
 ];
+
 // source: "../../samples/macros/cfg_if.rs"
\ No newline at end of file
diff --git a/tests/output/macros/if_chain.f.rs b/tests/output/macros/if_chain.f.rs
index 50d5cb4..5135c22 100644
--- a/tests/output/macros/if_chain.f.rs
+++ b/tests/output/macros/if_chain.f.rs
@@ -30,4 +30,5 @@
 		else { d!(); }
 	},
 ];
+
 // source: "../../samples/macros/if_chain.rs"
\ No newline at end of file
diff --git a/tests/output/macros/matches.f.rs b/tests/output/macros/matches.f.rs
index aceffe8..41d82d2 100644
--- a/tests/output/macros/matches.f.rs
+++ b/tests/output/macros/matches.f.rs
@@ -3,4 +3,5 @@
   matches!(1 + 1,   Some(_) | None if 1 + 1 == 2),
   matches!(1 + 1, | Some(_) | None if 1 + 1 == 2),
 ];
+
 // source: "../../samples/macros/matches.rs"
\ No newline at end of file
diff --git a/tests/output/styling/blockify.f.rs b/tests/output/styling/blockify.f.rs
index b93beaa..7b8b54a 100644
--- a/tests/output/styling/blockify.f.rs
+++ b/tests/output/styling/blockify.f.rs
@@ -31,4 +31,5 @@
   || -> T const {},
   || -> T async {},
 ];
+
 // source: "../../samples/styling/blockify.rs"
\ No newline at end of file
diff --git a/tests/output/styling/canInlineBlockBody.f.rs b/tests/output/styling/canInlineBlockBody.f.rs
index 2da9eab..2b25513 100644
--- a/tests/output/styling/canInlineBlockBody.f.rs
+++ b/tests/output/styling/canInlineBlockBody.f.rs
@@ -170,4 +170,5 @@
     }
   },
 ];
+
 // source: "../../samples/styling/canInlineBlockBody.rs"
\ No newline at end of file
diff --git a/tests/output/styling/needsParens.f.rs b/tests/output/styling/needsParens.f.rs
index f30927a..91ecd9f 100644
--- a/tests/output/styling/needsParens.f.rs
+++ b/tests/output/styling/needsParens.f.rs
@@ -7,4 +7,5 @@ type A: (impl B + C);
 
 trait A = B + C;
 trait A = (impl B + C);
+
 // source: "../../samples/styling/needsParens.rs"
\ No newline at end of file
diff --git a/tests/output/styling/needsSemi.f.rs b/tests/output/styling/needsSemi.f.rs
index c6daa4c..8e5d416 100644
--- a/tests/output/styling/needsSemi.f.rs
+++ b/tests/output/styling/needsSemi.f.rs
@@ -8,4 +8,5 @@ fn f() {
     1
   }
 }
+
 // source: "../../samples/styling/needsSemi.rs"
\ No newline at end of file
diff --git a/tests/samples/issues/21/fn_comment.rs b/tests/samples/issues/21/fn_comment.rs
new file mode 100644
index 0000000..5dbd969
--- /dev/null
+++ b/tests/samples/issues/21/fn_comment.rs
@@ -0,0 +1,2 @@
+fn eof() {}
+// comment
\ No newline at end of file
diff --git a/tests/samples/issues/21/fn_fn.rs b/tests/samples/issues/21/fn_fn.rs
new file mode 100644
index 0000000..788d977
--- /dev/null
+++ b/tests/samples/issues/21/fn_fn.rs
@@ -0,0 +1,2 @@
+fn eof1() {}
+fn eof2() {}
\ No newline at end of file
diff --git a/tests/samples/issues/21/fn_ln.rs b/tests/samples/issues/21/fn_ln.rs
new file mode 100644
index 0000000..dc3e174
--- /dev/null
+++ b/tests/samples/issues/21/fn_ln.rs
@@ -0,0 +1,1 @@
+fn eof() {}
diff --git a/tests/samples/issues/21/ln_fn_ln.rs b/tests/samples/issues/21/ln_fn_ln.rs
new file mode 100644
index 0000000..2d7b103
--- /dev/null
+++ b/tests/samples/issues/21/ln_fn_ln.rs
@@ -0,0 +1,2 @@
+
+fn eof(){}
diff --git a/tests/samples/issues/21/mod.rs b/tests/samples/issues/21/mod.rs
new file mode 100644
index 0000000..f465792
--- /dev/null
+++ b/tests/samples/issues/21/mod.rs
@@ -0,0 +1,1 @@
+mod eof {}
\ No newline at end of file