4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

なぜファイル末尾の「No newline at end of file」は直さないとダメなのか

4
Posted at

no-newline-at-end-of-file.png

コードレビューをしているときに、未だに出会うことが多いNo newline at end of fileですが、Prettierやエディタ設定のおかげで、そもそも認識すらしてない人も多いのでは?とも思います。
「ファイルの末尾には改行を入れてください」と言うのは簡単ですが、「なぜ入れないといけないのか」をきちんと説明できたほうが、レビューに説得力が増すので、改めて調べてみました。

理由その1: 【歴史・規格】POSIXにおける「行(line)」の定義

技術的な大前提として、UNIXやLinuxなどの標準規格であるPOSIXにおいて、「行」の定義が以下のように決まっています。

行(line)とは

0個以上の改行以外の文字と、末尾の改行文字(LF) の連なりのこと。

つまり、「改行で終わっていない文字列は、正式な『行』とは認められない(不完全な行)」というのが、コンピュータの世界の古くからのルールです。

コンパイラの小話

古いC言語の処理系では、ファイル末尾に改行がないことでプリプロセッサ処理が正しく行われず、予期せぬエラーを引き起こすことがありました。

そのため、C言語の規格でも「空でないソースファイルは改行文字で終わらなければならない」と定義されています。

理由その2: 【実務】Gitの「差分(diff)」とgit blameが汚れる

これが一番実務で影響が出る部分だと思います。
GitHubだと行の末尾に⛔️(赤い進入禁止みたいなマーク)が出ますよね。

例えば、末尾に改行がないファイル(A.txt)があるとします。

A.txt
hello
world[ここに改行がない]

後から別の開発者が、3行目を追加しようとすると、ツールが自動で2行目の末尾に改行を補完した上で3行目を追加します。

A.txt
hello
world
new line

このとき、Gitの差分(diff)をとると、以下のように見えてしまいます。

Gitの差分
 hello
-world
+world
+new line

本当はnew lineを追加しただけなのに、「触っていないはずのworldの行まで変更された」とGitにみなされてしまいます。

これにより、コードレビュー時に余計なノイズが生じるだけでなく、末尾行のgit blameが実際の変更内容とは無関係なコミットで更新されてしまうという実害も発生します。

理由その3: 【CLI】伝統的なUNIXコマンドが意図しない挙動をする

ターミナルでファイルを操作するとき、末尾改行がないとツールが正しく処理できないことがあります。

wc -l(行数を数えるコマンド)のカウント漏れ

wc -lは「改行の数」をカウントするコマンドです。そのため、POSIXの定義通り「改行がない文字列は行とみなされない」結果、末尾に改行がないと実際の行数より1行少なくカウントされてしまうという現象が起きます。

bash
# 改行がないファイル
$ echo -n "hello" > no_newline.txt
$ wc -l no_newline.txt
0 no_newline.txt  # 1行あるのに0とカウントされてしまう

catコマンドで結合したときの崩れ

例えばファイルをcat file1.txt file2.txtで結合したとき、file1.txtの末尾に改行がないと、file2.txtの1行目が同じ行にくっついて出力されてしまいます。

bash
# 改行がないファイル
$ echo -n "hello" > no_newline.txt
$ cat no_newline.txt no_newline.txt
hellohello # 改行がないため、2つのファイルが繋がってしまう

対策

手動で毎回改行を入れるのは不毛ですし、忘れることもあります。こういう類のものはツールの設定で自動化してしまいましょう。

EditorConfigの設定(推奨)

チーム開発であれば、個人のエディタ設定に依存するのではなく、リポジトリに.editorconfigを配置して統一するのがおすすめです。

root = true

[*]
insert_final_newline = true

insert_final_newline = trueを指定すると、対応しているエディタで保存時に末尾改行が自動挿入されるようになります。

EditorConfigはVS CodeやWebStormをはじめ、多くのエディタやIDEでサポートされています。

チーム全体で末尾改行の有無を統一したい場合は、エディタ個別の設定よりもEditorConfigによる管理のほうが効果的です。

VS Codeの設定

settings.json に以下の1行を追加するだけで、すべてのファイルで保存時に自動で末尾改行が挿入されるようになります。

"files.insertFinalNewline": true

Prettierの設定

Prettierを導入している場合、標準で末尾改行が挿入される仕様になっています。
もし動いていない場合は、フォーマット対象にそのファイルの拡張子が含まれているか確認してみてください。

参考文献・公式仕様

この記事で紹介した内容の一次情報(仕様書・ドキュメント)です。さらに詳しく知りたい方はこちらを参照してください。

  • POSIXによる「行」の定義(英語)
  • C言語の標準規格(ISO/IEC 9899)におけるソースファイルの定義(英語)
  • GNU Diffutils(diffコマンド)の仕様(英語)

まとめ

現代の開発環境では大きな問題になりにくくなったものの、

  • POSIXの行定義に沿う
  • Gitの差分ノイズを減らす
  • CLIツールとの相性を良くする

といった理由から、末尾には改行を入れてNo newline at end of fileを回避するのがベストプラクティスです。

結論

改行しろ

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?