Transaction analyzer: a lambda/local-function boundary is not "might queue more than once" (#3166)
TryGetBranch lumped IAnonymousFunctionOperation and ILocalFunctionOperation in with ILoopOperation and returned false, which the caller reads as "this call can queue N times" and uses to disqualify the whole transaction. Roslyn hands out no separate operation block for a lambda or local function - the body arrives as part of the containing method - so every transaction written inside one was silently invisible. That includes top-level statements, where the entire program body is one synthesised method, so the analyzer said nothing at all about the commonest way a small repro gets written. The repeat risk belongs to the *captured* transaction, not to the boundary itself. A transaction that is a local of the function being walked out of is created afresh on each invocation, so one invocation holds one whole transaction and the counts within it are exact; whatever encloses the function governs how many transactions there are, not what goes into each. The two boundary cases now stop the walk and accept when the transaction local belongs to that function, and keep returning false when it was captured from outside. A loop inside such a function is still hit first, as it must be. Tests: the two existing negatives were already the captured shape, so they are unchanged and still pass. Four added - transaction declared in a local function (the reported shape), in a lambda, in a local function called in a loop (N transactions, not one with N commands), and a loop inside such a function (still suppressed). docs/rules/index.md stated the old blanket behaviour as an intentional limitation; corrected. No AnalyzerReleases change: detection coverage only, no new or altered diagnostic IDs.
M
Marc Gravell committed
5517cbf219095ac5d97b863915164d82bfc7b3c9
Parent: 0ee2082
Committed by GitHub <noreply@github.com>
on 8/6/2026, 10:42:23 AM