feat(steps): a run of calls that happens once per item says so
A body drawn once, with nothing to say it repeats, is a quiet lie about the order — so the reading now reads the loops a site is written inside, the same way it reads its conditions: one climb up the same ancestors, per language, `for` / `foreach` / `for … in` / `while` / `do` / `repeat`, with the header as written (`item of items`, `queue.length > 0`) and where the loop starts. Loops and forks nest in either direction, and neither reading knows about the other, so the block builder merges them by where each construct BEGINS: on one ancestor chain the outer one always starts first, which rebuilds the nesting from the positions alone. A `for` inside an `if` and an `if` inside a `for` come out the way the code has them. With it, the per-framework readings are pinned: an Express handler with its helper drawn inside the reply it builds, a FastAPI `raise HTTPException` ending the arm it is in, a Spring early `return` as the other arm of its `if` (with the comparison flipped, not wrapped), an ASP.NET handler's two outcomes, and a Nest controller read on through the service it delegates to. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01REFyW9hmNrxhwN5wxRoAkC
This commit is contained in:
co-authored by
Claude Opus 5
parent
9acab0020f
commit
7b6704a70d
@@ -41,7 +41,7 @@ import type CodeGraph from '../../index';
|
||||
import type { Edge, Language, Node, UnresolvedReference } from '../../types';
|
||||
import { badRequest, intParam, notFound } from './respond';
|
||||
import { createSiteReader } from './when';
|
||||
import type { BranchGuard, SiteTrigger } from '../../graph/branch-guards';
|
||||
import type { BranchGuard, SiteLoop, SiteTrigger } from '../../graph/branch-guards';
|
||||
import { buildProgram, type ProgramSite, type WireProgram } from './program';
|
||||
import { classifyEffect, implicitResponseStatus, responseStatus, type Effect } from './effects';
|
||||
import { guardLabel } from '../../graph/branch-guards';
|
||||
@@ -383,6 +383,8 @@ export async function buildSteps(cg: CodeGraph, projectRoot: string, query: URLS
|
||||
const calls = createSiteReader(cg, projectRoot, MAX_CALL_SITES);
|
||||
/** The conditions a site runs under, structured — one read, joined where a string is wanted. */
|
||||
const guardsAt = (caller: Node, site: { line?: number; column?: number }) => reader.guards(caller, site);
|
||||
/** The loops a site is written inside — a run of calls that happens once per item. */
|
||||
const loopsAt = (caller: Node, site: { line?: number; column?: number }) => reader.loops(caller, site);
|
||||
const argsAt = (caller: Node, site: { line?: number; column?: number }) => reader.args(caller, site);
|
||||
const withArgs = async (site: WireStepSite, caller: Node, at: { line?: number; column?: number }): Promise<WireStepSite> => {
|
||||
const args = await argsAt(caller, at);
|
||||
@@ -553,7 +555,8 @@ export async function buildSteps(cg: CodeGraph, projectRoot: string, query: URLS
|
||||
hop: HopSite,
|
||||
guards: readonly BranchGuard[],
|
||||
what: { step?: string; link?: string; into?: string },
|
||||
trigger: WireStepTrigger | null = null
|
||||
trigger: WireStepTrigger | null = null,
|
||||
loops: readonly SiteLoop[] = []
|
||||
): void => {
|
||||
let sites = programs.get(fn.id);
|
||||
if (!sites) {
|
||||
@@ -567,6 +570,7 @@ export async function buildSteps(cg: CodeGraph, projectRoot: string, query: URLS
|
||||
at: { line: hop.line, column: hop.column, end: hop.end },
|
||||
...(hop.within ? { within: hop.within } : {}),
|
||||
guards: [...guards],
|
||||
...(loops.length > 0 ? { loops: [...loops] } : {}),
|
||||
...(trigger ? { trigger } : {}),
|
||||
});
|
||||
};
|
||||
@@ -754,7 +758,7 @@ export async function buildSteps(cg: CodeGraph, projectRoot: string, query: URLS
|
||||
if (!target.first) target.first = hop;
|
||||
const fired = trigger ?? (await triggerAt(fold.node, at));
|
||||
const id = link(step, target, 'effect', fold.chain, [...fold.whens, when], wireSite, null, fired, hop.within);
|
||||
record(fold.node, local, guards, { step: target.id, link: id }, fired);
|
||||
record(fold.node, local, guards, { step: target.id, link: id }, fired, await loopsAt(fold.node, at));
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -1145,7 +1149,7 @@ export async function buildSteps(cg: CodeGraph, projectRoot: string, query: URLS
|
||||
const hop = fold.first ?? local;
|
||||
if (!to.first) to.first = hop;
|
||||
const id = link(step, to, a.linkKind, fold.chain, [...fold.whens, when], site, a.e, a.trigger, hop.within);
|
||||
record(fold.node, local, guards, { step: to.id, link: id }, a.trigger);
|
||||
record(fold.node, local, guards, { step: to.id, link: id }, a.trigger, await loopsAt(fold.node, at));
|
||||
if (to.root !== null && !explored.has(to.id)) {
|
||||
explored.add(to.id);
|
||||
queue.push(to);
|
||||
@@ -1183,7 +1187,7 @@ export async function buildSteps(cg: CodeGraph, projectRoot: string, query: URLS
|
||||
const local = await hopAt(fold.node, at, target.name);
|
||||
const hop = fold.first ?? local;
|
||||
const id = link(step, known, 'calls', fold.chain, [...fold.whens, guardLabel(guards)], await withArgs(a.site, fold.node, at), e, a.trigger, hop.within);
|
||||
record(fold.node, local, guards, { step: known.id, link: id }, a.trigger);
|
||||
record(fold.node, local, guards, { step: known.id, link: id }, a.trigger, await loopsAt(fold.node, at));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -1210,7 +1214,7 @@ export async function buildSteps(cg: CodeGraph, projectRoot: string, query: URLS
|
||||
const first = fold.first ?? local;
|
||||
// The helper is drawn where it is CALLED: its own records are its
|
||||
// body, and this is the site the rail nests them under.
|
||||
record(fold.node, local, guards, { into: target.id }, a.trigger);
|
||||
record(fold.node, local, guards, { into: target.id }, a.trigger, await loopsAt(fold.node, at));
|
||||
next.push({ node: target, chain: [...fold.chain, target], whens: [...fold.whens, guardLabel(guards)], first });
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user