Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 17330] ファイルの概要

このコミットは、Go言語のEmacsモード(go-mode.el)において、カバレッジレポートがソースファイルよりも古い場合に、その旨をユーザーに通知する機能を追加するものです。これにより、ユーザーは表示されているカバレッジ情報が最新のものではないことを認識し、必要に応じてカバレッジレポートを再生成するなどの対応を取ることができます。

コミット

commit dccf651b24831a3f3f2657cf211129bb03c18ed4
Author: Aaron France <aaron.l.france@gmail.com>
Date:   Mon Aug 19 16:32:00 2013 -0400

    misc/emacs: Detect stale coverage reports

    When the coverage report file is older than the file we're
    showing the coverage report for, then we show a simple message
    to state this fact.

    R=adonovan, dominik.honnef, bradfitz
    CC=golang-dev
    https://golang.org/cl/12919044

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/dccf651b24831a3f3f2657cf211129bb03c18ed4

元コミット内容

このコミットの目的は、EmacsのGoモードにおいて、表示されているカバレッジレポートが、そのレポートの対象となっているソースファイルよりも古い場合に、その状態を検出してユーザーに通知することです。具体的には、「カバレッジファイルがソースファイルよりも古い」というメッセージを表示します。

変更の背景

Go言語には、go test -cover コマンドによってコードカバレッジを測定し、その結果をファイルに出力する機能があります。EmacsのGoモードは、このカバレッジレポートを読み込み、ソースコード上にカバレッジ情報をオーバーレイ表示する機能を提供しています。

しかし、ソースコードを編集した後、カバレッジレポートを再生成し忘れると、Emacsに表示されるカバレッジ情報は古いままになってしまいます。これにより、開発者は誤ったカバレッジ情報に基づいて判断を下してしまう可能性があります。

このコミットは、このような「古いカバレッジレポート」の問題を解決するために導入されました。カバレッジレポートファイルの最終更新時刻と、対象となるソースファイルの最終更新時刻を比較することで、レポートが古いかどうかを判断し、ユーザーに警告を発することで、常に最新のカバレッジ情報に基づいて作業を進められるように支援します。

前提知識の解説

Emacs Lisp (Elisp)

Emacs Lispは、Emacsエディタの拡張言語です。Emacsのほとんどの機能はEmacs Lispで書かれており、ユーザーはEmacs Lispを使ってEmacsをカスタマイズしたり、新しい機能を追加したりできます。このコミットで変更されているgo-mode.elもEmacs Lispで書かれたファイルです。

Go言語のコードカバレッジ

Go言語では、go test -coverprofile=coverage.out のようにコマンドを実行することで、テスト実行時のコードカバレッジ情報をcoverage.outのようなファイルに出力できます。このファイルには、どのコード行がテストによって実行されたか(またはされなかったか)の情報が含まれています。

go-mode.el

go-mode.elは、EmacsでGo言語のコードを編集するためのメジャーモードです。シンタックスハイライト、インデント、コード補完、そして本コミットに関連するコードカバレッジの表示など、Go言語開発を支援する様々な機能を提供します。

ファイルの属性とタイムスタンプ

ファイルシステム上の各ファイルには、最終更新時刻(modification time, mtime)などの属性が関連付けられています。これらのタイムスタンプは、ファイルが最後に変更された日時を示します。このコミットでは、カバレッジレポートファイルとソースファイルのmtimeを比較することで、どちらが新しいかを判断しています。

技術的詳細

このコミットの核心は、Emacs Lispの以下の関数を使用してファイルのタイムスタンプを取得し、比較することにあります。

  • file-attributes FILENAME: FILENAMEで指定されたファイルの属性リストを返します。このリストの6番目の要素(インデックス5)は、ファイルの最終更新時刻(mtime)を表すタイムスタンプオブジェクトです。
  • float-time TIME: タイムスタンプオブジェクトTIMEを浮動小数点数に変換します。これにより、異なるファイルのタイムスタンプを数値として直接比較できるようになります。

変更箇所では、まずカバレッジレポートファイル(coverage-file)と、カバレッジを表示している現在のソースファイル(origin-bufferのファイル名)のfile-attributesを取得します。 次に、それぞれのファイルのmtime(cov-mtimecur-mtime)を抽出し、float-timeを使って浮動小数点数に変換します。

そして、(< (float-time cov-mtime) (float-time cur-mtime)) という条件式で、カバレッジファイルのmtimeがソースファイルのmtimeよりも古いかどうかをチェックします。 この条件が真(つまり、カバレッジファイルがソースファイルよりも古い)の場合、message関数を使ってEmacsのミニバッファに「Coverage file is older than the source file.」という警告メッセージを表示します。

このシンプルな比較により、ユーザーはカバレッジ情報が最新ではない可能性を即座に知ることができます。

コアとなるコードの変更箇所

変更はmisc/emacs/go-mode.elファイル内のgo-coverage-mode関数(またはそれに近いカバレッジ表示ロジックの一部)で行われています。

--- a/misc/emacs/go-mode.el
+++ b/misc/emacs/go-mode.el
@@ -1110,7 +1110,13 @@ for."
          (coverage-file (or coverage-file (go--coverage-file)))\
          (ranges-and-divisor (go--coverage-parse-file\
                               coverage-file\
-                              (file-name-nondirectory (buffer-file-name origin-buffer)))))\
+                              (file-name-nondirectory (buffer-file-name origin-buffer))))\
+         (cov-mtime (nth 5 (file-attributes coverage-file)))\
+         (cur-mtime (nth 5 (file-attributes (buffer-file-name origin-buffer)))))\
+\
+    (if (< (float-time cov-mtime) (float-time cur-mtime))\
+        (message "Coverage file is older than the source file."))\
+\
     (with-current-buffer (or (get-buffer gocov-buffer-name)\
                              (make-indirect-buffer origin-buffer gocov-buffer-name t))\
       (set (make-local-variable 'go--coverage-origin-buffer) origin-buffer)\

コアとなるコードの解説

追加された行は以下の通りです。

  1. (cov-mtime (nth 5 (file-attributes coverage-file)))
    • coverage-file(カバレッジレポートファイルのパス)のファイル属性を取得し、そのリストの6番目の要素(インデックス5)である最終更新時刻(mtime)をcov-mtime変数に格納します。
  2. (cur-mtime (nth 5 (file-attributes (buffer-file-name origin-buffer))))
    • origin-buffer(カバレッジを表示している現在のソースバッファ)のファイル名を取得し、そのファイルの属性からmtimeを抽出し、cur-mtime変数に格納します。
  3. (if (< (float-time cov-mtime) (float-time cur-mtime))
    • cov-mtimecur-mtimeをそれぞれfloat-timeで浮動小数点数に変換し、カバレッジファイルのmtimeがソースファイルのmtimeよりも古いかどうかを比較します。
  4. (message "Coverage file is older than the source file."))
    • 上記のif条件が真(カバレッジファイルが古い)の場合、Emacsのミニバッファに警告メッセージを表示します。

この変更により、カバレッジ表示のロジックに、ファイルのタイムスタンプ比較による「鮮度チェック」が組み込まれました。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Emacs Lispの公式ドキュメント
  • GitHubのgolang/goリポジトリのコミット履歴
  • Go言語のコードカバレッジに関するブログ記事
  • Emacs Lispのfile-attributesおよびfloat-time関数のドキュメント
  • コミットメッセージ内のGo CLリンク: https://golang.org/cl/12919044 (現在はhttps://go.dev/cl/12919044にリダイレクトされる可能性があります)