Skip to content

マクロ定義名が識別子として登録される #92

Description

@TwoSquirrels

現象

src/library/identifiers.rscollect_definitions/collect_leaf は、宣言ノードの name/declarator フィールドを型で場合分けせず一律に辿るため、プリプロセッサのマクロ定義 (#define FOO ... / #define FOO(x) ...) もそのマクロ名を「定義識別子」として tags.jsonfiles に記録してしまう。

なぜ無意味な過剰検出と言えるか

  • バンドル時の識別子検出 (detect.rs) は -E でプリプロセスしたの、<file> 由来の行だけを見る。オブジェクト形式マクロ (#define FOO 42) はトークンが現れた時点で必ず展開されるため、FOO という生の識別子がユーザーコード側に残ることはない。
  • 関数形式マクロ (#define REP(i, n) ...) も同様に、REP(...) の形で呼び出せば展開される。「間接的にリネームして ( を伴わず参照すれば展開を逃れるのでは」という仮説も検証したが、プリプロセッサの再走査 (rescanning) により #define MYREP REP 経由でも最終的に REP( として再展開されるため成立しない。

影響

過剰検出自体は risundle の「取りこぼしより過剰検出を優先する」設計方針の範囲内であり、正しさには影響しない (architecture.md の「tree-shaking は過剰検出側に倒す」参照)。実害は次の 2 点のみ:

  • tags.jsonfiles にマクロ名が無駄に混ざり、レコードが肥大化する。
  • risundle library show <id> -v の出力がマクロ名で埋まり、実際の型・関数名を確認する際のノイズになる。

原因: tree-sitter-cpp がプリプロセッサ指令に宣言と同じフィールド名を使っている

tree-sitter-cppnode-types.json を確認すると:

preproc_def          -> ['name', 'value']
preproc_function_def -> ['name', 'parameters', 'value']

プリプロセッサのマクロ定義ノードが、C++ の宣言ノードと同じ name フィールド名を使っている。risundle 側が「宣言ノードは name/declarator を持つ」という規約に一律で乗っかっているのは正当だが、C++ の宣言とは別の文法層であるプリプロセッサ指令にまで同じフィールド名を流用しているのは tree-sitter-cpp の設計であり、risundle の走査ロジックが雑というわけではない。

提案

risundle にはすでに SKIP_DESCENT (降りても C++ の定義が得られないノードを除外する既存のリスト。compound_statement 等) がある。preproc_defpreproc_function_def をこのリストに加えるだけで解決できる。これは「単純さを崩す特別扱いの追加」ではなく、「そもそも C++ の宣言ではないものを対象外にする、既存機構の本来の適用範囲に収める」変更であり、新しい分岐ロジックは増えない。

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Kind/EnhancementImprove existing functionalityModule: LibraryThe library registration domainPriority/LowThe priority is lowQuick FixFix is obvious and small in scope

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions