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

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

このコミットは、Go言語のEmacsメジャーモードであるgo-mode.elにおける、メソッドのシンタックスハイライト(fontification)に関するバグ修正です。具体的には、go-fontify-function-calls変数がnil(無効)に設定されている場合に、メソッド宣言の誤った部分がハイライトされてしまう問題を解決します。

コミット

  • コミットハッシュ: e9ba9470bc0c7042e2e5aac6838aa86f2f514ca3
  • Author: Dominik Honnef dominik.honnef@gmail.com
  • Date: Wed Mar 12 11:02:42 2014 -0400

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

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

元コミット内容

misc/emacs: correctly fontify methods when go-fontify-function-calls is nil

We were fontifying the wrong part of method declarations

LGTM=adonovan
R=adonovan
CC=golang-codereviews
https://golang.org/cl/66120043

変更の背景

Emacsのgo-mode.elでは、Go言語のコードを適切にシンタックスハイライトするための設定が含まれています。go-fontify-function-callsという変数は、関数呼び出しやメソッド呼び出しをハイライトするかどうかを制御します。この変数がnilに設定されている場合、つまり関数呼び出しのハイライトが無効になっている場合でも、メソッド宣言自体は適切にハイライトされるべきです。

しかし、このコミット以前のgo-mode.elの実装では、go-fontify-function-callsnilの際に、メソッド宣言のハイライトにおいて正規表現のキャプチャグループの指定が誤っていました。これにより、メソッド名ではなく、メソッド宣言全体の別の部分(例えばレシーバの型など)が誤ってハイライトされてしまう問題が発生していました。このコミットは、この誤ったハイライトを修正し、メソッド名が正しくハイライトされるようにすることを目的としています。

前提知識の解説

Emacs font-lock-mode

font-lock-modeは、Emacsにおける主要なシンタックスハイライト(構文強調)システムです。このモードは、バッファの内容を解析し、特定のパターン(通常は正規表現)に一致するテキストに異なるフォントフェイス(色、太字、斜体など)を適用することで、コードの可読性を向上させます。

font-lock-modeは、各メジャーモード(例: go-modepython-modeなど)が定義するfont-lock-keywordsという変数に依存します。この変数には、ハイライトのルールを定義するリストが格納されています。

font-lock-keywordsの構造と正規表現グループ

font-lock-keywordsの各エントリは、通常、以下の形式を取ります。

(REGEXP (GROUP FACE) ...)

  • REGEXP: ハイライトしたいテキストパターンを定義する正規表現です。この正規表現内で括弧()を使用すると、キャプチャグループを定義できます。
  • GROUP: REGEXP内で定義されたキャプチャグループの番号(整数)を指定します。0は正規表現全体の一致を指し、1は最初のキャプチャグループ、2は2番目のキャプチャグループ、といった具合に続きます。
  • FACE: GROUPで指定されたキャプチャグループに適用されるフォントフェイス(例: font-lock-function-name-facefont-lock-type-faceなど)です。

font-lock-modeは、REGEXPがバッファ内で一致するたびに、指定されたGROUPの内容にFACEを適用します。この仕組みを利用して、例えば関数定義全体ではなく、関数名だけをハイライトするといった細かい制御が可能になります。

このコミットの文脈では、go-func-meth-regexpという正規表現がメソッド宣言全体を捕捉し、その正規表現内の特定のキャプチャグループがメソッド名に対応していると推測されます。

技術的詳細

このコミットの核心は、Emacs Lispのfont-lock-modeにおける正規表現のキャプチャグループの指定ミスを修正することです。

go-mode.elの関連するコードスニペットは、go-fontify-function-calls変数の値に基づいて、異なるハイライトルールを適用しています。

元のコードでは、go-fontify-function-callsnilの場合に適用されるルールが以下のようになっていました。

`((,go-func-meth-regexp 1 font-lock-function-name-face))) ;; method name

ここで、,go-func-meth-regexpはメソッド宣言に一致する正規表現です。そして、1は、この正規表現の最初のキャプチャグループfont-lock-function-name-face(関数名用のフォントフェイス)を適用することを意味しています。

しかし、実際にはgo-func-meth-regexpという正規表現の構造上、メソッド名が格納されているのは2番目のキャプチャグループでした。そのため、1を指定すると、メソッド名ではない別の部分(例えばレシーバの型など)が誤ってハイライトされてしまっていたのです。

このコミットでは、このGROUPの指定を1から2に変更することで、go-func-meth-regexpの2番目のキャプチャグループ、すなわちメソッド名に正しくfont-lock-function-name-faceが適用されるように修正しています。

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

変更はmisc/emacs/go-mode.elファイルの一箇所のみです。

--- a/misc/emacs/go-mode.el
+++ b/misc/emacs/go-mode.el
@@ -269,7 +269,7 @@ For mode=set, all covered lines will have this weight.\"\
    (if go-fontify-function-calls
        `((,(concat \"\\\\(\" go-identifier-regexp \"\\\\)[[:space:]]*(\") 1 font-lock-function-name-face) ;; function call/method name
          (,(concat \"[^[:word:][:multibyte:]](\\\\(\" go-identifier-regexp \"\\\\))[[:space:]]*(\") 1 font-lock-function-name-face)) ;; bracketed function call
-     `((,go-func-meth-regexp 1 font-lock-function-name-face))) ;; method name
+     `((,go-func-meth-regexp 2 font-lock-function-name-face))) ;; method name
 
    `(\
      (,(concat (go--regexp-enclose-in-symbol \"type\") \"[[:space:]]+\\\\([^[:space:]]+\\\\)\") 1 font-lock-type-face) ;; types

コアとなるコードの解説

変更された行は以下の部分です。

-     `((,go-func-meth-regexp 1 font-lock-function-name-face))) ;; method name
+     `((,go-func-meth-regexp 2 font-lock-function-name-face))) ;; method name

このコードは、go-fontify-function-callsnilの場合に適用されるfont-lock-keywordsのエントリを定義しています。

  • -で始まる行は削除された元のコードです。
  • +で始まる行は追加された新しいコードです。

変更点は、正規表現go-func-meth-regexpに続く数字が1から2に変更されたことです。

この変更により、go-func-meth-regexpが一致した際に、font-lock-function-name-faceが適用される対象のキャプチャグループが、元の「1番目のキャプチャグループ」から「2番目のキャプチャグループ」へと変更されました。これにより、go-func-meth-regexpがGo言語のメソッド宣言をパースする際に、メソッド名が正しく2番目のキャプチャグループに格納されるという前提に基づき、メソッド名のみが適切にハイライトされるようになりました。

この修正は、Emacsのシンタックスハイライトが、正規表現のキャプチャグループの正確な理解と指定にどれほど依存しているかを示す良い例です。

関連リンク

参考にした情報源リンク