Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions DEVELOPER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,15 @@ unqualified name receive a global candidate only when that name is unique in the
symbol set. Otherwise they remain `ambiguous` or `unresolved`, and dependency queries do not
fall back to a same-name edge.

C# common member names are never discarded during extraction. The writer persists their
receiver/type evidence in `target_qualifier`, and reference finalization records
`resolution_state`. Default bare-name `references` / `callers` / `callees` queries and hotspot
aggregation suppress only rows that are both qualified and unresolved; `resolved` and
`resolved_group` rows remain authoritative by default. The CLI
`--include-qualified-common-calls` flag and MCP `includeQualifiedCommonCalls` argument bypass
that query-time noise filter. Keep dependency edges identity-scoped: the completeness option
must expose unresolved evidence without converting it into a same-name file dependency.

C# `type_reference` candidates are filtered before qualifier and namespace ranking. A candidate
must be a type-like symbol (`class`, `struct`, `record`, `interface`, `enum`, or `delegate`), and
when the reference's generic arity can be recovered from its normalized line context, that arity
Expand Down Expand Up @@ -4394,6 +4403,14 @@ resolution を再構築し、同じ transaction で marker を設定します。
対象となる symbol 集合で名前が一意の場合だけ global candidate を持ちます。それ以外は
`ambiguous` または `unresolved` のままとし、dependency query は同名 edge へ fallback しません。

C# の一般的な member 名は extraction 時に破棄しません。writer は receiver / 型の evidence を
`target_qualifier` に永続化し、reference finalization は `resolution_state` を記録します。無修飾名の
`references` / `callers` / `callees` query と hotspot 集計の既定動作では、修飾され、かつ未解決の
row だけを除外し、`resolved` / `resolved_group` row は authoritative な既定結果として維持します。
CLI の `--include-qualified-common-calls` と MCP の `includeQualifiedCommonCalls` は、この query-time
noise filter を無効化します。dependency edge は identity scope のままにし、completeness option で
未解決 evidence を公開しても、同名の file dependency へ変換してはいけません。

C# の `type_reference` candidate は qualifier / namespace の順位付け前に絞り込みます。candidate は
型相当の symbol(`class`、`struct`、`record`、`interface`、`enum`、`delegate`)でなければならず、
正規化済み行 context から reference の generic arity を復元できる場合は declaration の arity と
Expand Down
2 changes: 2 additions & 0 deletions TESTING_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ Use `docs/test-doc-maintenance-plan.md` before moving oversized suites or adding
Use `AssertReferencesDoNotContain(...)` for negative checks over one reference kind; retain direct predicates when the exclusion depends on container, context, line, or other metadata.
`ReferenceExtractorTests.ExtractSymbolsAndReferences(...)` owns the common symbol-then-reference extraction setup for tests that need both lists; use it instead of repeating the two extractor calls when the fixture does not need a specialized path or workspace symbol setup, and discard the symbol tuple element with `_` instead of keeping an unused `symbols` local when the test only asserts references.
C# named-argument coverage keeps syntax discrimination in `ReferenceExtractorCSharpTests` and persisted query/dependency behavior in `QueryCommandRunnerIssue4833Tests`; preserve positional and reordered arguments, attributes, constructors, nested and multiline calls, expression-side, named-`out`, explicitly typed lambda/anonymous-method, and typed LINQ range-variable type references, property-subpattern types, and negative controls for aliases, labels, nullable types, and ternaries (#4833; regressions #106 and #122).
C# qualified common-call coverage keeps static BCL, instance, LINQ extension, alias-qualified, current-instance, and unresolved-receiver cases together. Assert that extraction retains every row, default bare-name references/callers/callees and hotspot counts retain resolved evidence while excluding unresolved noise, the completeness option restores that noise deterministically, and dependency queries remain identity-scoped (#4867).
Crystal, Groovy, Tcl, Prolog, and `ambiguous_pl` graph fixtures keep imports, parenthesized calls, conservative same-file command/predicate calls, caller containers, and keyword false-positive controls independently diagnosable; capability tests must keep their advertised symbol/reference/graph flags aligned with those extractor fixtures (#4746).
Database status tests must also pin stale and current extractor-version stamps for those languages so pre-graph rows cannot report authoritative graph readiness.
HDL graph coverage keeps Verilog, SystemVerilog, and VHDL in one coordinated extractor fixture for syntax-visible hierarchy/package/architecture edges, known same-file signal/type references, scope attribution, declaration/literal false-positive suppression, and comment masking. The paired `QueryCommandRunnerReferencesTests` fixture must persist and query one representative edge per HDL language so extractor-only assertions cannot hide database or CLI graph drift. `IndexCommandRunnerFullScanTests` must also clear the HDL graph contract and persisted edge, then prove that a normal full scan refreshes an unchanged HDL file before restoring readiness.
Expand Down Expand Up @@ -1011,6 +1012,7 @@ dotnet test --filter "FullyQualifiedName~GitHelperTests"
1つの reference kind に対する否定チェックには `AssertReferencesDoNotContain(...)` を使い、container、context、line など他の metadata に依存する除外は直接 predicate を維持します。
`ReferenceExtractorTests.ExtractSymbolsAndReferences(...)` は symbol 抽出から reference 抽出までの共通 setup を所有します。fixture が特殊な path や workspace symbol setup を必要としない場合は 2 つの extractor 呼び出しを繰り返さずこの helper を使い、reference だけを検証するテストでは未使用の `symbols` local を残さず symbol 側を `_` で捨ててください。
C# named-argument の coverage は構文の判別を `ReferenceExtractorCSharpTests`、永続化後の query / dependency 動作を `QueryCommandRunnerIssue4833Tests` に保持します。positional argument との混在、並べ替え、attribute、constructor、nested / multiline call、value 式側、named `out` declaration、明示型 lambda / anonymous method、および型付き LINQ range variable の type reference、property subpattern の型、ならびに alias、label、nullable type、ternary に対する負例を維持してください(#4833、回帰 #106 / #122)。
C# の修飾付き一般名 call の coverage は、static BCL、instance、LINQ extension、alias 修飾、current instance、未解決 receiver の各 case を同じ fixture に維持します。extraction が全 row を保持すること、無修飾名による references / callers / callees と hotspot count の既定動作が解決済み evidence を維持しつつ未解決 noise を除外すること、completeness option がその noise を決定的に復元すること、dependency query が identity scope のままであることを検証してください(#4867)。
Crystal、Groovy、Tcl、Prolog、`ambiguous_pl` の graph fixture では、import、括弧付き call、同一ファイルに限定した保守的な command / predicate call、caller container、keyword の false-positive control を個別に診断可能な状態で維持し、capability test の symbol / reference / graph 広告を extractor fixture と一致させてください(#4746)。
さらに database status test でこれらの言語の古い extractor-version stamp と現行 stamp を固定し、graph 対応前の row が authoritative な graph readiness を報告できないことを検証してください。
HDL graph coverage では Verilog、SystemVerilog、VHDL を1つの連携した extractor fixture にまとめ、構文上確認できる hierarchy/package/architecture edge、同一ファイル内の既知 signal/type reference、scope attribution、declaration/literal の false-positive 抑止、comment masking を検証します。対になる `QueryCommandRunnerReferencesTests` fixture では各 HDL 言語の代表 edge を1件ずつ永続化して query し、extractor-only assertion が database または CLI graph のずれを隠せないようにします。さらに `IndexCommandRunnerFullScanTests` では HDL graph contract と永続化 edge を消去し、通常の full scan が未変更 HDL file を更新してから readiness を復元することを検証します。
Expand Down
4 changes: 4 additions & 0 deletions USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1737,6 +1737,8 @@ When you pass `--lang` for an unsupported language, human-readable graph command

By default, `callers` and `callees` return only executable call, construction, and subscription edges. Their public `reference_kind`, `reference_kinds`, and `reference_kind_counts` fields use one canonical vocabulary: `call`, `instantiate`, and `subscribe`. Type and metadata edges such as `generic_type_argument`, `capture`, `friend`, and `project_reference` remain available through `references` or an explicit kind filter; use `--raw-kinds` when you need extractor labels such as `unsubscribe` or `razor_event_binding`.

C# indexing retains receiver- and type-qualified calls even when their member name is common, including `int.Parse`, LINQ `Where` / `Select` / `ToList`, and instance `Read` / `Write` calls. Bare-name `references`, `callers`, and `callees` queries keep resolved qualified calls in the default result while suppressing only unresolved qualified common-name calls as noise. Use `--include-qualified-common-calls` (or MCP `includeQualifiedCommonCalls: true`) when you need those unresolved rows too; an explicit qualified query such as `references int.Parse --exact` is already treated as an intentional completeness request.

`callers` and `callees` rank results by weighted structural importance by default: `instantiate` edges count as `3.0`, direct `call` edges as `1.0`, and event `subscribe` edges as `0.1`. This keeps factory or composition-root constructor use from being buried under noisy event subscriptions. Use `--rank-by count` to restore raw `reference_count` ordering, or `--rank-by kind` to group `instantiate`, `call`, then `subscribe` before count. JSON rows keep the raw `reference_count` and add `reference_kind_counts` plus `reference_weight_score` so consumers can re-rank without losing the source counts; MCP structured rows expose the same data as `referenceKindCounts` and `referenceWeightScore`.

Grouped `callees` rows preserve the earliest precise call site separately from the aggregate `reference_count`. CLI JSON exposes its 1-based `first_line`, nullable `first_column`, and persisted physical-token `first_length`; MCP uses the corresponding `firstLine`, `firstColumn`, and `firstLength` fields. This keeps resolved constructor-chain calls on their actual `base`, `super`, or `this` token. Compact and quickfix output use the same 1-based column, SARIF carries the same token-sized region, and LSP converts it to a zero-based, non-empty token range. If every contributing legacy reference lacks a column, the column remains `null`, quickfix reports column `0`, SARIF omits `endColumn`, and LSP returns a zero-width range at the start of the retained source line. If a migrated row retains its column but has no persisted span length, SARIF still omits `endColumn` and LSP returns a zero-width range at that column instead of inventing a token width.
Expand Down Expand Up @@ -4958,6 +4960,8 @@ cdidx callees AddToGitExclude --exclude-tests

既定の `callers` / `callees` は、実行可能な call、construction、subscription edge だけを返します。公開される `reference_kind`、`reference_kinds`、`reference_kind_counts` は、`call`、`instantiate`、`subscribe` という 1 つの canonical 語彙を共有します。`generic_type_argument`、`capture`、`friend`、`project_reference` などの型 / metadata edge は `references` または明示 kind filter で引き続き利用できます。`unsubscribe` や `razor_event_binding` のような extractor label が必要な場合は `--raw-kinds` を使ってください。

C# の indexing は member 名が一般的な場合でも、`int.Parse`、LINQ の `Where` / `Select` / `ToList`、instance の `Read` / `Write` など、receiver または型で修飾された call を保持します。無修飾名による `references`、`callers`、`callees` query の既定結果では、解決済みの修飾 call を維持し、未解決の修飾付き一般名 call だけを noise として除外します。未解決 row も必要な場合は `--include-qualified-common-calls`(MCP では `includeQualifiedCommonCalls: true`)を使ってください。`references int.Parse --exact` のような明示的な修飾 query は、それ自体を completeness の指定として扱います。

`callers` と `callees` は既定で構造的重要度の weighted 順に並びます。`instantiate` は `3.0`、直接 `call` は `1.0`、event `subscribe` は `0.1` として数えるため、factory や composition root の constructor 利用が大量の event subscription に埋もれにくくなります。従来どおり生の `reference_count` で並べたい場合は `--rank-by count`、reference kind を優先して `instantiate`、`call`、`subscribe` の順でまとめたい場合は `--rank-by kind` を使ってください。JSON の各行は生の `reference_count` を維持し、`reference_kind_counts` と `reference_weight_score` も追加で返します。MCP structured row では同じ情報を `referenceKindCounts` と `referenceWeightScore` として返すため、consumer 側で再ランキングできます。

集約された `callees` 行は、集約値の `reference_count` とは別に、最初の精密な call site を保持します。CLI JSON は 1-based の `first_line`、nullable な `first_column`、永続化された物理 token 幅の `first_length` を返し、MCP は対応する `firstLine`、`firstColumn`、`firstLength` を使います。そのため、解決後の constructor-chain call も実際の `base`、`super`、`this` token を指します。compact / quickfix も同じ 1-based 列を使い、SARIF は同じ token 幅の region、LSP は 0-based の非空 token range に変換します。寄与する legacy reference の全てで列が欠けている場合は列を `null` のまま保ち、quickfix は列 `0`、SARIF は `endColumn` を省略し、LSP は保持した source line の先頭に zero-width range を返します。移行済み row に列はあるものの永続化 span 長がない場合も、SARIF は `endColumn` を省略し、LSP はその列に zero-width range を返すため、token 幅を捏造しません。
Expand Down
22 changes: 22 additions & 0 deletions changelog.d/unreleased/4867.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
category: fixed
issues:
- 4867
affected:
- src/CodeIndex/Indexer/References
- src/CodeIndex/Database
- src/CodeIndex/Cli
- src/CodeIndex/Mcp
- tests/CodeIndex.Tests
- USER_GUIDE.md
- DEVELOPER_GUIDE.md
- TESTING_GUIDE.md
---

## English

- **C# qualified common-name calls are retained and filtered by resolution evidence (#4867)** — Indexing now preserves static BCL, instance, extension, aliased, and unresolved qualified calls such as `int.Parse`, `Where`, `Select`, `ToList`, `Read`, and `Write`; the C# extractor contract refreshes unchanged files from older indexes on the next full scan. Bare-name `references`, `callers`, `callees`, and hotspot defaults suppress only unresolved qualified noise while retaining resolved calls; `--include-qualified-common-calls` and MCP `includeQualifiedCommonCalls` expose the complete deterministic evidence without creating unresolved dependency edges.

## 日本語

- **C# の修飾付き一般名 call を保持し、解決 evidence に基づいて絞り込むようにしました (#4867)** — indexing は `int.Parse`、`Where`、`Select`、`ToList`、`Read`、`Write` など、static BCL、instance、extension、alias 修飾、未解決の修飾 call を保持し、C# extractor contract により旧 index の未変更ファイルも次回の full scan で更新します。無修飾名による `references`、`callers`、`callees` と hotspot の既定動作は解決済み call を維持し、未解決の修飾 noise だけを除外します。`--include-qualified-common-calls` と MCP の `includeQualifiedCommonCalls` で、未解決 dependency edge を作らずに完全で決定的な evidence を取得できます。
1 change: 1 addition & 0 deletions src/CodeIndex/Cli/CliFlagSchema.cs
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,7 @@ private static IReadOnlyList<CliFlag> BuildAll()
new() { Name = "--rank-by", ValuePlaceholder = "<weighted|count|kind>", Description = "Rank callers/callees by weighted structural score, raw count, or kind bucket", PrimaryCommands = Set(RankByCommands) },
new() { Name = "--sort", ValuePlaceholder = "<mode>", Description = "Symbols/outline: order audit output by a ranking signal; outline also accepts source, kind, references, size, complexity, path, and name", PrimaryCommands = Set(SymbolSortCommands) },
new() { Name = "--raw-kinds", Description = "Show raw reference kinds instead of logical graph kinds", PrimaryCommands = Set(RawKindsCommands) },
new() { Name = "--include-qualified-common-calls", Description = "Include unresolved receiver/type-qualified C# calls with common member names", PrimaryCommands = Set("references", "callers", "callees") },
new() { Name = "--count", Description = "Count only; result limits are ignored by count modes, but scan caps can still mark approximate counts as degraded", PrimaryCommands = Set(CountCommands) },
new() { Name = "--group-partials", Description = "Definition/Symbols/Inspect: collapse C# partial-type declarations into logical families", PrimaryCommands = Set("definition", "symbols", "inspect") },
new() { Name = "--strict-not-found", Description = "Return exit code 2 when a valid query has zero rows", PrimaryCommands = Set(StrictNotFoundCommands), Safety = CliOptionSafety.StrictFailure },
Expand Down
Loading
Loading