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

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

このコミットは、Go言語のドキュメンテーションツールであるgodocの表示に関する修正です。具体的には、godocが生成するHTMLドキュメントにおいて、インデックスエントリが不必要にリンク化されるのを防ぐための変更が行われています。

コミット

commit 79682199ce56c9afa1edac6c61da3c7abb9393b7
Author: Robert Griesemer <gri@golang.org>
Date:   Tue Apr 2 12:05:14 2013 -0700

    cmd/godoc: don't linkify index entries
    
    Fixes #5186.
    
    R=bradfitz
    CC=golang-dev
    https://golang.org/cl/8267044

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

https://github.com/golang/go/commit/79682199ce56c9afa1edac6c61da3c7abb9393b7

元コミット内容

cmd/godoc: don't linkify index entries Fixes #5186.

このコミットは、godocコマンドが生成するドキュメントにおいて、インデックスのエントリがリンク化されないようにするものです。これは、Goの内部的な課題追跡システムにおけるIssue #5186を修正します。

変更の背景

godocはGo言語のソースコードからドキュメントを自動生成するツールであり、開発者がGoのパッケージや関数、型などの情報を参照する際に非常に重要な役割を果たします。生成されるドキュメントはHTML形式であり、通常、関数名や型名などはその定義箇所へのリンクとして表示されます。

しかし、このコミットの背景には、godocが生成するパッケージのインデックス(目次のようなもの)において、本来リンクである必要のない箇所までリンク化されてしまうという問題がありました。特に、インデックス内のエントリが、その宣言全体をリンクとして表示してしまうと、視覚的に煩雑になるだけでなく、ユーザーエクスペリエンスを損なう可能性がありました。

この問題は、godocのHTMLテンプレートと、コードをHTMLに変換するロジックの連携に起因していました。特定の要素(例えば、関数の宣言全体)が、その要素自体がリンクであるべきではない文脈(インデックスなど)でも、デフォルトでリンクとして処理されてしまっていたと考えられます。

前提知識の解説

  • godoc: Go言語のソースコードからドキュメントを生成し、HTTPサーバーとして提供するツールです。Goの標準ライブラリのドキュメントもgodocによって生成されています。
  • HTMLテンプレート: godocはGoのhtml/templateパッケージを使用してHTMLドキュメントを生成します。テンプレートファイル(例: package.html)は、Goのコードから取得したデータ(パッケージ情報、関数、型など)を埋め込んで最終的なHTMLを構築します。
  • ast.Node: Goのgo/astパッケージで定義されている抽象構文木(AST)のノードを表すインターフェースです。Goのソースコードは、パースされるとASTとして表現され、godocはこのASTを走査してドキュメント情報を抽出します。
  • リンク化 (Linkify): テキスト内の特定の要素(例: 関数名、型名)を、その定義箇所や関連情報へのハイパーリンクに変換する処理を指します。godocでは、ソースコード内の識別子を、その識別子の宣言箇所へのリンクとして表示する機能があります。
  • node_htmlFunc: godocの内部で、ASTノードをHTML形式に変換する際に使用される関数です。この関数は、Goのコード要素(関数宣言、変数宣言など)を整形してHTML文字列として出力する役割を担っています。

技術的詳細

このコミットの主要な変更点は、godocのHTML生成ロジックにおいて、ASTノードをHTMLに変換するnode_htmlFunc関数に新しい引数linkify(ブール値)が追加されたことです。

変更前は、node_htmlFuncはASTノードを受け取り、そのノードをHTMLとして整形する際に、常にリンク化の可能性を考慮していました。特に、declLinksというフラグが有効な場合、識別子をその宣言へのリンクとして変換しようと試みていました。

変更後は、node_htmlFuncのシグネチャが以下のように変更されました。

func node_htmlFunc(info *PageInfo, node interface{}, linkify bool) string

このlinkify引数は、そのASTノードをHTMLに変換する際に、識別子をリンク化するかどうかを明示的に制御します。

  • linkifytrueの場合: 以前と同様に、declLinksフラグが有効であれば、識別子はリンク化されます。
  • linkifyfalseの場合: 識別子はリンク化されず、単なるテキストとして整形されます。

この変更により、lib/godoc/package.htmlテンプレート内でnode_htmlFuncを呼び出す際に、文脈に応じてlinkify引数をtrueまたはfalseで渡すことができるようになりました。

具体的には、パッケージのインデックス部分(関数、型、定数、変数などの一覧)では、宣言全体をリンク化する必要がないため、linkifyfalseが渡されるようになりました。これにより、インデックスエントリは整形されたテキストとして表示され、不必要なリンクが生成されなくなりました。

一方で、実際の宣言箇所(例: 関数の詳細セクション)では、引き続き識別子をリンク化する必要があるため、linkifytrueが渡されています。

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

lib/godoc/package.html

このファイルは、godocがパッケージのドキュメントを生成する際に使用するHTMLテンプレートです。 変更点としては、node_htmlテンプレート関数が呼び出されている箇所で、第2引数にfalseまたはtrueが追加されています。

--- a/lib/godoc/package.html
+++ b/lib/godoc/package.html
@@ -60,18 +60,18 @@
 			{{end}}
 			{{range .Funcs}}
 				{{$name_html := html .Name}}
-				<dd><a href="#{{$name_html}}">{{node_html $ .Decl}}</a></dd>
+				<dd><a href="#{{$name_html}}">{{node_html $ .Decl false}}</a></dd>
 			{{end}}
 			{{range .Types}}
 				{{$tname_html := html .Name}}
 				<dd><a href="#{{$tname_html}}">type {{$tname_html}}</a></dd>
 				{{range .Funcs}}
 					{{$name_html := html .Name}}
-					<dd>&nbsp; &nbsp; <a href="#{{$name_html}}">{{node_html $ .Decl}}</a></dd>
+					<dd>&nbsp; &nbsp; <a href="#{{$name_html}}">{{node_html $ .Decl false}}</a></dd>
 				{{end}}
 				{{range .Methods}}
 					{{$name_html := html .Name}}
-					<dd>&nbsp; &nbsp; <a href="#{{$tname_html}}.{{$name_html}}">{{node_html $ .Decl}}</a></dd>
+					<dd>&nbsp; &nbsp; <a href="#{{$tname_html}}.{{$name_html}}">{{node_html $ .Decl false}}</a></dd>
 				{{end}}
 			{{end}}
 			{{if $.Notes}}
@@ -109,14 +109,14 @@
 		{{with .Consts}}
 			<h2 id="pkg-constants">Constants</h2>
 			{{range .}}
-				<pre>{{node_html $ .Decl}}</pre>
+				<pre>{{node_html $ .Decl true}}</pre>
 				{{comment_html .Doc}}\n
 			{{end}}
 		{{end}}
 		{{with .Vars}}
 			<h2 id="pkg-variables">Variables</h2>
 			{{range .}}
-				<pre>{{node_html $ .Decl}}</pre>
+				<pre>{{node_html $ .Decl true}}</pre>
 				{{comment_html .Doc}}\n
 			{{end}}
 		{{end}}
@@ -124,7 +124,7 @@
 			{{/* Name is a string - no need for FSet */}}
 			{{$name_html := html .Name}}
 			<h2 id="{{$name_html}}">func <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h2>
-			<pre>{{node_html $ .Decl}}</pre>
+			<pre>{{node_html $ .Decl true}}</pre>
 			{{comment_html .Doc}}\n
 			{{example_html $ .Name}}\n
 		{{end}}
@@ -132,16 +132,16 @@
 			{{$tname := .Name}}
 			{{$tname_html := html .Name}}\n
 			<h2 id="{{$tname_html}}">type <a href="{{posLink_url $ .Decl}}">{{$tname_html}}</a></h2>
-			<pre>{{node_html $ .Decl}}</pre>
+			<pre>{{node_html $ .Decl true}}</pre>
 			{{comment_html .Doc}}\n
 
 			{{range .Consts}}
-				<pre>{{node_html $ .Decl}}</pre>
+				<pre>{{node_html $ .Decl true}}</pre>
 				{{comment_html .Doc}}\n
 			{{end}}
 
 			{{range .Vars}}
-				<pre>{{node_html $ .Decl}}</pre>
+				<pre>{{node_html $ .Decl true}}</pre>
 				{{comment_html .Doc}}\n
 			{{end}}
 
@@ -150,7 +150,7 @@
 			{{range .Funcs}}
 				{{$name_html := html .Name}}
 				<h3 id="{{$name_html}}">func <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h3>
-				<pre>{{node_html $ .Decl}}</pre>
+				<pre>{{node_html $ .Decl true}}</pre>
 				{{comment_html .Doc}}\n
 				{{example_html $ .Name}}\n
 			{{end}}
@@ -158,7 +158,7 @@
 			{{range .Methods}}
 				{{$name_html := html .Name}}
 				<h3 id="{{$tname_html}}.{{$name_html}}">func ({{html .Recv}}) <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a></h3>
-				<pre>{{node_html $ .Decl}}</pre>
+				<pre>{{node_html $ .Decl true}}</pre>
 				{{comment_html .Doc}}\n
 				{{$name := printf "%s_%s" $tname .Name}}\n
 				{{example_html $ $name}}\n
@@ -179,7 +179,7 @@
 {{end}}\n
 {{with .PAst}}
-\t<pre>{{node_html $ .}}</pre>
+\t<pre>{{node_html $ . false}}</pre>
 {{end}}\n
 {{with .Dirs}}

src/cmd/godoc/godoc.go

このファイルはgodocコマンドの主要なロジックを含んでいます。 node_htmlFunc関数のシグネチャが変更され、linkify引数が追加されました。また、その引数に基づいてリンク化の処理を条件分岐するようになりました。

--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -279,14 +279,12 @@ func nodeFunc(info *PageInfo, node interface{}) string {
 	return buf.String()
 }
 
-func node_htmlFunc(info *PageInfo, node interface{}) string {
+func node_htmlFunc(info *PageInfo, node interface{}, linkify bool) string {
 	var buf1 bytes.Buffer
 	writeNode(&buf1, info.FSet, node)
 
 	var buf2 bytes.Buffer
-	// Don't linkify full source text (info.PAst != nil) - identifier
-	// resolution is not strong enough without full type checking.
-	if n, _ := node.(ast.Node); n != nil && *declLinks && info.PAst == nil {
+	if n, _ := node.(ast.Node); n != nil && linkify && *declLinks {
 		LinkifyText(&buf2, buf1.Bytes(), n)
 	} else {
 		FormatText(&buf2, buf1.Bytes(), -1, true, "", nil)
@@ -394,7 +392,7 @@ func example_htmlFunc(info *PageInfo, funcName string) string {
 
 		// print code
 		cnode := &printer.CommentedNode{Node: eg.Code, Comments: eg.Comments}
-		code := node_htmlFunc(info, cnode)
+		code := node_htmlFunc(info, cnode, true)
 		out := eg.Output
 		wholeFile := true
 

コアとなるコードの解説

src/cmd/godoc/godoc.go内のnode_htmlFunc関数は、GoのASTノードをHTML形式の文字列に変換する役割を担っています。この関数は、Goのコード要素(関数宣言、変数宣言、型宣言など)を整形し、必要に応じて識別子をリンク化します。

変更前は、この関数はinfo *PageInfonode interface{}の2つの引数を受け取っていました。info.PAst == nilという条件で、完全なソーステキストではない場合にリンク化を行うというロジックが含まれていましたが、これがインデックスエントリの不必要なリンク化を引き起こしていました。

変更後は、linkify boolという新しい引数が追加されました。この引数は、呼び出し元が明示的にリンク化を許可するかどうかを制御します。

if n, _ := node.(ast.Node); n != nil && linkify && *declLinks {
    LinkifyText(&buf2, buf1.Bytes(), n)
} else {
    FormatText(&buf2, buf1.Bytes(), -1, true, "", nil)
}

このif文が、リンク化の有無を決定する主要なロジックです。

  • n != nil: 変換対象が有効なASTノードであること。
  • linkify: 新しく追加された引数で、呼び出し元がリンク化を許可していること。
  • *declLinks: グローバルな設定で、宣言へのリンクが有効になっていること。

これらの条件がすべて満たされた場合にのみ、LinkifyText関数が呼び出され、ASTノード内の識別子が対応する宣言へのリンクとして変換されます。それ以外の場合は、FormatText関数が呼び出され、単なる整形されたテキストとして出力されます。

lib/godoc/package.htmlテンプレートでは、このnode_htmlFuncの変更に合わせて、各箇所でlinkify引数が適切に渡されるようになりました。

  • パッケージのインデックス部分(Funcs, Types, Methodsなどのddタグ内)では、node_html $ .Decl falseのようにfalseが渡され、リンク化が抑制されます。これにより、インデックスは簡潔なテキスト表示になります。
  • 定数、変数、関数、型の詳細な宣言部分(h2, h3タグの後のpreタグ内)では、node_html $ .Decl trueのようにtrueが渡され、識別子が引き続きリンク化されます。これは、これらの箇所では詳細な情報へのナビゲーションが期待されるためです。

この修正により、godocの出力はより洗練され、ユーザーがドキュメントを閲覧する際の視覚的なノイズが減少し、必要な情報へのアクセスが改善されました。

関連リンク

参考にした情報源リンク