Skip to content

fix(AC0032): treat Next as a read operation in MethodOperationMap - #490

Merged
Arthurvdv merged 3 commits into
mainfrom
fix/ac0032-next-read-operation
Aug 28, 2026
Merged

fix(AC0032): treat Next as a read operation in MethodOperationMap#490
Arthurvdv merged 3 commits into
mainfrom
fix/ac0032-next-read-operation

Conversation

@Arthurvdv

Copy link
Copy Markdown
Member

Summary

Fixes #466.

Next was missing from MethodOperationMap, so a codeunit that only iterates a record set (repeat … until Rec.Next() = 0) positioned by another object's FindSet looked like it never read the table, and AC0032 reported its tabledata X = r entry as unused. Next() advances the server-side cursor and reads rows in the calling object, and permissions do not flow through the call stack, so that r is genuinely required.

  • MethodOperationMap: add NextRead. Every consumer (AC0031 RequiredPermissionDetector, AC0032 pre-filter / resolution / RecordRef bailout) picks it up automatically.
  • RecordMethodClassification.ReadMethods deliberately does not gain Next (AC0030 and partial-record analysis reason about the buffer a read fills); doc comment updated to explain the intentional divergence.
  • 9 regression fixtures (5 AC0032, 4 AC0031); .claude/rules updated.

⚠️ Behaviour change: AC0031

AC0031 now reports Next() on a non-temporary record that is not covered by any permission source — e.g. a procedure that iterates a var record parameter without Permissions = tabledata X = r. These are true positives at runtime (the object needs r), but existing projects may see new AC0031 diagnostics after upgrading. Please call this out in the release notes.

Verification

  • dotnet test ALCops.sln — all green (AC0030 / PC partial-record suites unaffected)
  • dotnet format ALCops.sln --verify-no-changes — no findings
  • ALCops.Common and ALCops.ApplicationCop build on netstandard2.1;net8.0;net10.0 with ContinuousIntegrationBuild=true, 0 warnings
  • Pre-fix: the AC0032 repro fixtures and AC0031 NextWithoutPermissions fail; post-fix: pass

Docs companion: ALCops/alcops.dev#156

🤖 Generated with Claude Code

Arthurvdv and others added 3 commits August 28, 2026 15:11
Cover `Next` as a database read in both permission cops:

AC0032 (unused permissions)
- NoDiagnostic/NextOnVarParameterFilledElsewhere.al - the #466 repro:
  a helper codeunit positions the set with FindSet on a var parameter and
  the caller only iterates with repeat .. until Next() = 0.
- NoDiagnostic/NextWithoutParentheses.al, NoDiagnostic/NextStandAlone.al
- NoDiagnostic/RecordRefNext.al - RecordRef whole-object bailout
- HasDiagnostic/NextPartialUnused.al - only `r` of `rimd` is used

AC0031 (requires permissions)
- HasDiagnostic/NextWithoutPermissions.al
- NoDiagnostic/NextWithPermissions.al, PageSourceTableNext.al,
  TemporaryRecordNext.al

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`Next()` advances the server-side cursor and fetches the next row, so it
reads the database in the object that calls it. Because permissions do not
flow through the call stack, a record set positioned by another object's
`FindSet` still requires `tabledata <T> = r` in the iterating object.
Missing that mapping made AC0032 report such a permission as unused
(issue #466).

Both permission cops consult the single map, so AC0031 now symmetrically
demands `r` for `Next()` on records without a covering permission - a true
positive that was previously missed. `RecordRef.Next()` needs no extra
code: it is picked up by the existing whole-object RecordRef bailout.

`Next` is deliberately NOT added to `RecordMethodClassification.ReadMethods`;
its consumers (AC0030's return-value check, the partial-record analysis)
reason about the buffer a read fills, which does not apply to `Next`. The
doc comment now states that divergence.

Fixes #466

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Arthurvdv
Arthurvdv merged commit c892ca4 into main Aug 28, 2026
53 checks passed
@Arthurvdv
Arthurvdv deleted the fix/ac0032-next-read-operation branch August 28, 2026 13:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: AC0032 - False Postive when FindSet is inside a procedure (of diff object)

1 participant