(
step: StepRecord,
fold: Fold,
ref: { referenceName: string; referenceKind: 'calls' | 'instantiates'; line: number; column?: number },
trigger: WireStepTrigger | null,
fallbackArgs: string | null = null,
requireReceiver = false,
/** A site that is no call — a handler's `return "redirect:/x"` — arrives already classified. */
preset: { effect: Effect; status: number | null } | null = null
)
| 895 | |
| 896 | /** One effect site: the call as written, what it passes, when, what fires it, and — for a response — the status. */ |
| 897 | const effectLink = async ( |
| 898 | step: StepRecord, |
| 899 | fold: Fold, |
| 900 | ref: { referenceName: string; referenceKind: 'calls' | 'instantiates'; line: number; column?: number }, |
| 901 | trigger: WireStepTrigger | null, |
| 902 | fallbackArgs: string | null = null, |
| 903 | requireReceiver = false, |
| 904 | /** A site that is no call — a handler's `return "redirect:/x"` — arrives already classified. */ |
| 905 | preset: { effect: Effect; status: number | null } | null = null |
| 906 | ): Promise<boolean> => { |
| 907 | const at = { line: ref.line, column: ref.column }; |
| 908 | const site = preset ? null : await callAt(fold.node, { ...at, callee: ref.referenceName }); |
| 909 | // The site read must be THIS call: its last segment is the reference's. |
| 910 | const last = (n: string) => n.replace(/\([^()]*\)/g, '').split(/[.:]/).pop() ?? n; |
| 911 | const usable = !!site && site.callee !== '' && last(site.callee) === last(ref.referenceName); |
| 912 | const text = usable ? site.callee : ref.referenceName; |
| 913 | if (requireReceiver && !/[.:>]/.test(text)) return false; |
| 914 | const args = usable ? site.args : fallbackArgs; |
| 915 | // The receiver's declared type counts only when the call leaves the |
| 916 | // index through it: a library's `Repository<Cat>`, or the project's own |
| 917 | // `OwnerRepository` interface whose `save` comes from Spring Data — never |
| 918 | // a project class that declares the method, which is a place to walk into. |
| 919 | let effect: Effect | null = preset?.effect ?? null; |
| 920 | if (!preset) { |
| 921 | const declared = await receiverTypeFor(fold.node, text); |
| 922 | const receiverType = declared && (await resolveByReceiver(fold.node, text)) === null ? declared : null; |
| 923 | effect = classifyEffect({ |
| 924 | text, |
| 925 | kind: ref.referenceKind, |
| 926 | language: fold.node.language, |
| 927 | project, |
| 928 | receiverType, |
| 929 | args, |
| 930 | projectType: fold.node.language === 'swift' && (await declaresSwiftType(text)), |
| 931 | }); |
| 932 | } |
| 933 | if (effect === null) return false; |
| 934 | // A reply's status, read before its box exists — the box is per outcome. |
| 935 | // `NextResponse.json(user, { status: 201 })`: the code sits in an object |
| 936 | // the abbreviation reduced to its keys; the site reader kept it. And a |
| 937 | // body-sending reply that sets none is a 200, so a success has a box of |
| 938 | // its own beside the 401's. |
| 939 | const status = preset |
| 940 | ? preset.status |
| 941 | : effect.category === 'response' |
| 942 | ? (responseStatus(text, args, ref.referenceKind) ?? (usable && typeof site.status === 'number' ? site.status : null) ?? implicitResponseStatus(text)) |
| 943 | : null; |
| 944 | // What fires this call, read before its box is made: a call bound inside |
| 945 | // ANOTHER effect's arguments — the axios.delete in a confirm dialog's |
| 946 | // button — hangs off that box, one step deeper, not off the screen. |
| 947 | const fired = trigger ?? (await triggerAt(fold.node, at)); |
| 948 | const from = fired?.of ? (firedByEffect(fold.node.id, at, fired.of) ?? step) : step; |
| 949 | const target = effectStep(fold.node, { referenceName: text, line: ref.line }, effect, from.depth + 1, status); |
| 950 | if (target === null) return true; |
| 951 | const guards = await guardsAt(fold.node, at); |
| 952 | const when = guardLabel(guards); |
| 953 | const wireSite: WireStepSite = { file: posix(fold.node.filePath), line: ref.line, text, when: '' }; |
| 954 | if (args !== null) wireSite.args = args; |
no test coverage detected