tagsファイルをパースして関数一覧を取得する
プロジェクト内の関数一覧を取得したいとPLに言われたので、適当に方法を考えてみました。構文解析から愚直にやると地獄を見そうなので、今回はCtagsを利用し、tagsファイルをパースするスクリプトをpythonで書きます。
結論
Ctagsを入手します。以下からwindows向けCtags日本語版バイナリをダウンロードできます。
https://hp.vector.co.jp/authors/VA025040/ctags/
mac OSへの導入は以下です。
https://log.yostos.org/2017/05/22/installing-ctags-to-mac/
以下コマンドをプロジェクトのトップディレクトリで実行します。
ctags --excmd==n -R .
生成されたtagsファイルのある場所で、以下スクリプトを実行すると、関数一覧をresult.txtに抽出できます。(オーバーロードしている関数は1関数とみなし、重複分を含めない形で出力します)
funcs = [] with open("tags", mode="r") as tags_file: # result.txtに関数名一覧を出力 out = open("result.txt", mode="w") lines = tags_file.readlines() for line in lines: symbol_info = line.strip().split("\t") func = symbol_info[0] # 関数のみ取得 if symbol_info[-1] == "f": func = symbol_info[0] # 重複した関数は除く if func in funcs: continue # 新規関数はresult.txtに出力 else: funcs.append(func) out.write(func + "\n") out.close()
補足説明あれこれ
Ctags
wikipediaの引用です↓
Ctags(英: Ctags)はソース及びヘッダ内にある名前のインデックス(又はタグ)ファイルを生成するプログラム。様々なプログラミング言語に対応している。言語に依存するが、サブルーチン(関数)、変数、クラスのメンバ、マクロ等がインデックス化される。これらのタグによりテキストエディタなどのツールで高速かつ容易に定義を参照できる。相互参照ファイルを出力でき、また名前についての情報を人が読みやすい形で列挙した言語ファイルを生成することもできる。
Ctagsが生成するtagsファイルを解釈できれば、軽量で限定的な機能しか持たないエディタでも手軽に定義元ジャンプが利用できるようになります。tagsは以下のようなフォーマットで1タグにつき1行ずつ記述されます。
tag_name <TAB> file_name <TAB> ex_cmd;" <TAB> extension_fields
記述 | 概要 |
---|---|
tag_name | タグ名(関数や変数など) |
file_name | 定義元ファイルまでの相対パス |
ex_cmd | ファイル内の定義位置までジャンプするためのコマンド |
extension_fields | exコマンドに付随するkey-value形式のコメント |
extension_fieldsにはオプション次第で種々の情報が含まれますが、今回はkind
で示されるタグtypeを参照して関数の定義のみを取得します。プロジェクトのトップディレクトリで以下コマンドを実行し、tagsファイルを生成します。
ctags --excmd==n -R .
--excmd
により、tagsファイルに記述されるex_cmdの内容が変わります。n
(number)を指定すると行数のみで定義元へジャンプするようになり、tagsファイルのサイズを最小にできます(その分ソースファイル編集するごとにtagsを更新する必要があるという欠点もあります)。今回は関数一覧を取得したいだけなので、ファイルサイズが小さくなるようにn
を指定します。-R
は再帰的探索のオプションです。
extension_fieldsに含まれるkind
はタグの種類(関数、変数、メソッド、クラスなど)を示してくれるので、これを使えば任意の種類のタグが取得できるようになります。タグは言語によって異なるため、以下コマンドで確認できます。
ctags --list-kinds=<言語の名前>
$ ctags --list-kinds=c c classes d macro definitions e enumerators (values inside an enumeration) f function definitions g enumeration names l local variables [off] m class, struct, and union members n namespaces p function prototypes [off] s structure names t typedefs u union names v variable definitions x external and forward variable declarations [off]
関数定義はf
で表されるので、上記のスクリプトではこれをキーとしてタグを判別しています。この部分を変更すれば他タグも取得できますが、key-valueペアとなるタグtypeもあるため適宜書き換える必要があります。
Ctagsの詳細な使用方法やtagsファイルのフォーマットは以下のドキュメントで確認できます。
http://ctags.sourceforge.net/ctags.html
まとめ
tagsファイルを使用して関数一覧を取得しました。普段はVSCodeを使用しているのでCtagsは使ったことがなかったのですが、意外な使い道を見つけられて嬉しいです。