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
14 changes: 14 additions & 0 deletions USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,13 @@ source line hits the body byte cap, continuation still advances to the following
source line because body paging is line-based. `inspect --json` also includes
`body_mode` metadata so clients can see whether body content was requested,
whether it is present, and which follow-up flags to use.

For `references`, `callers`, and `callees`, `--body` and `--snippet-lines`
describe the requested body work independently of `--fields`. A projection that
omits every `body_*` field is valid and suppresses body materialization, while
`--fields all` or explicit body fields keep the selected body content, range,
truncation, and recovery metadata. Omitting `--body` still makes an
explicit `--snippet-lines` a usage error.
Count-only JSON (`--count --json` or `--format count` where supported) is a
single object with `count`, applied `query_context`, freshness metadata
(`indexed_file_count`, `indexed_at`, `freshness_available`), and trust flags
Expand Down Expand Up @@ -4002,6 +4009,13 @@ top-level group を選択します。`--outline-only` は
も返します。`inspect --json` には `body_mode`
metadata も含まれるため、body content が要求済みか、存在するか、次に使う flag が何かを
client 側で判断できます。

`references`、`callers`、`callees` では、`--body` と `--snippet-lines` が表す body
取得意図は `--fields` から独立しています。すべての `body_*` field を省く投影も有効で、
その場合は body の materialization を省略します。`--fields all` または明示的な body field
を指定した場合は、選択した body content、範囲、truncation、recovery の metadata を
維持します。`--body` を省略したまま `--snippet-lines` を明示すると、従来どおり usage error
になります。
count-only JSON(対応 command の `--count --json` または `--format count`)は、
`count`、適用済み `query_context`、freshness metadata(`indexed_file_count`、
`indexed_at`、`freshness_available`)、trust flag の `degraded` /
Expand Down
17 changes: 17 additions & 0 deletions changelog.d/unreleased/5094.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
category: fixed
issues:
- 5094
affected:
- src/CodeIndex/Cli/JsonEnvelopeWrapper.Bounded.cs
- src/CodeIndex/Cli/QueryCommandRunner.Graph.cs
- USER_GUIDE.md
---

## English

- **Projected graph JSON now validates `--body` from parsed intent (#5094)** — `references`, `callers`, and `callees` no longer report that `--snippet-lines` lacks `--body` when `--fields` omits body fields. Non-body projections also skip body materialization, while explicit body fields and `all` retain the selected body, truncation, and recovery metadata.

## 日本語

- **graph JSON の投影時に parsed intent から `--body` を検証するようになりました (#5094)** — `references`、`callers`、`callees` で `--fields` が body field を省いても、`--snippet-lines` に `--body` が無いという誤ったエラーを返さなくなりました。body を含まない投影では body の materialization も省略し、明示的な body field と `all` では選択した body、truncation、recovery の metadata を維持します。
30 changes: 25 additions & 5 deletions src/CodeIndex/Cli/JsonEnvelopeWrapper.Bounded.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,8 @@ private static int RunBoundedResponse(
}
var bodyProjected = HasExplicitBodyProjection(controls.Fields);
var bodyOutputHidden = !bodyProjected
&& (controls.Compact || controls.Fields is { Count: > 0 });
&& controls.Compact
&& controls.Fields is not { Count: > 0 };
if (!QueryCommandRunner.TryValidateBoundedGraphSnippetLinesOption(command, args, bodyOutputHidden))
return CommandExitCodes.UsageError;
if (HasArgument(args, "--count")
Expand Down Expand Up @@ -1549,9 +1550,10 @@ private static bool ReadOptionalBool(JsonObject obj, string propertyName, bool d
private static string[] PrepareBoundedInnerArgs(string command, string[] args, BoundedResponseControls controls)
{
var stripped = StripResponseOptions(command, args, stripLimit: PageableResponseCommands.Contains(command));
var bodyRequested = HasExplicitBodyProjection(controls.Fields);
if (command != "outline"
&& !bodyRequested
var bodyProjected = HasExplicitBodyProjection(controls.Fields);
var bodyOptionRequested = args.Any(arg => string.Equals(arg, "--body", StringComparison.Ordinal));
if (command is not ("outline" or "references" or "callers" or "callees")
&& !bodyProjected
&& (controls.Compact || controls.Fields is { Count: > 0 }))
{
stripped.RemoveAll(arg => string.Equals(arg, "--body", StringComparison.Ordinal));
Expand All @@ -1563,7 +1565,11 @@ private static string[] PrepareBoundedInnerArgs(string command, string[] args, B
additions.Add(controls.PageLimit.ToString(CultureInfo.InvariantCulture));
}
if (controls.Compact
&& (command == "map" || LegacyLocationCompactCommands.Contains(command) && !bodyRequested))
&& (command == "map"
|| LegacyLocationCompactCommands.Contains(command)
&& !bodyProjected
&& (command is not ("references" or "callers" or "callees")
|| !bodyOptionRequested)))
{
additions.Add("--format");
additions.Add("compact");
Expand Down Expand Up @@ -2349,6 +2355,20 @@ internal static int GetBoundedResponseOffset(string command)
: 0;
}

internal static bool ShouldMaterializeBody(string command)
{
var execution = BoundedExecution.Value;
if (execution is null
|| !string.Equals(execution.Command, CanonicalizeCommandName(command), StringComparison.Ordinal))
{
return true;
}

return execution.Fields is { Count: > 0 }
? HasExplicitBodyProjection(execution.Fields)
: !execution.Compact;
}

internal static (string? Path, int? Line, int? FileOrdinal, int? MatchOrdinal, int? ByteOffset) GetBoundedFindResume()
{
var execution = BoundedExecution.Value;
Expand Down
6 changes: 3 additions & 3 deletions src/CodeIndex/Cli/QueryCommandRunner.Graph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public static int RunReferences(string[] cmdArgs, JsonSerializerOptions jsonOpti
}

var results = reader.SearchReferences(options.Query, options.Limit, options.Lang, options.Kind, options.PathPatterns, options.ExcludePaths, options.ExcludeTests, exact, options.MaxLineWidth, offset: JsonEnvelopeWrapper.GetBoundedResponseOffset("references"), includeQualifiedCommonCalls: options.IncludeQualifiedCommonCalls);
if (options.IncludeBody)
if (options.IncludeBody && JsonEnvelopeWrapper.ShouldMaterializeBody("references"))
AttachBodyExcerpts(reader, results, options.SnippetLines, options.MaxLineWidth);
ApplyBodyRecoveryCommands(results, options.DbPath, options.RedactPaths ?? true);
var sqlGraphSignal = NarrowSqlGraphContractSignalByLanguages(baseSqlGraphSignal, results.Select(result => result.Lang), options.Lang, exactGraphLanguage);
Expand Down Expand Up @@ -203,7 +203,7 @@ public static int RunCallers(string[] cmdArgs, JsonSerializerOptions jsonOptions
}

var results = reader.GetCallers(query, options.Limit, options.Lang, options.Kind, options.PathPatterns, options.ExcludePaths, options.ExcludeTests, exact, options.RawKinds, options.RankMode, offset: JsonEnvelopeWrapper.GetBoundedResponseOffset("callers"), includeQualifiedCommonCalls: options.IncludeQualifiedCommonCalls, includeMemberReads: options.IncludeMemberReads);
if (options.IncludeBody)
if (options.IncludeBody && JsonEnvelopeWrapper.ShouldMaterializeBody("callers"))
AttachBodyExcerpts(reader, results, options.SnippetLines, options.MaxLineWidth);
ApplyBodyRecoveryCommands(results, options.DbPath, options.RedactPaths ?? true);
var sqlGraphSignal = NarrowSqlGraphContractSignalByLanguages(baseSqlGraphSignal, results.Select(result => result.Lang), options.Lang, exactGraphLanguage);
Expand Down Expand Up @@ -350,7 +350,7 @@ public static int RunCallees(string[] cmdArgs, JsonSerializerOptions jsonOptions
}

var results = reader.GetCallees(query, options.Limit, options.Lang, options.Kind, options.PathPatterns, options.ExcludePaths, options.ExcludeTests, exact, options.RawKinds, options.RankMode, offset: JsonEnvelopeWrapper.GetBoundedResponseOffset("callees"), includeQualifiedCommonCalls: options.IncludeQualifiedCommonCalls, includeMemberReads: options.IncludeMemberReads);
if (options.IncludeBody)
if (options.IncludeBody && JsonEnvelopeWrapper.ShouldMaterializeBody("callees"))
AttachBodyExcerpts(reader, results, options.SnippetLines, options.MaxLineWidth);
ApplyBodyRecoveryCommands(results, options.DbPath, options.RedactPaths ?? true);
var sqlGraphSignal = NarrowSqlGraphContractSignalByLanguages(baseSqlGraphSignal, results.Select(result => result.Lang), options.Lang, exactGraphLanguage);
Expand Down
Loading
Loading