Skip to content

feat: resolve $dynamicRef against the dynamic scope#504

Open
aqeelat wants to merge 1 commit into
mattpolzin:release/7_0from
aqeelat:dynamic-scope-resolution
Open

feat: resolve $dynamicRef against the dynamic scope#504
aqeelat wants to merge 1 commit into
mattpolzin:release/7_0from
aqeelat:dynamic-scope-resolution

Conversation

@aqeelat

@aqeelat aqeelat commented Jul 11, 2026

Copy link
Copy Markdown

Part of #359.

Implements the "dynamic-scope-aware dereferencing" item from the #359 task list. locallyDereferenced() / JSONSchema.dereferenced(in:) now resolve $dynamicRef against the dynamic scope (the outermost in-scope $dynamicAnchor wins, per JSON Schema 2020-12 §7.7), instead of throwing on every $dynamicRef.

Behavior

  • Non-recursive $dynamicRef (e.g. the JSON Schema "generics" pattern — $dynamicRef "#T" → a leaf $defs entry): the target is inlined.
  • Recursive or unresolvable $dynamicRef: throws (ReferenceCycleError / GenericError), consistent with how recursive static $ref already fails and with the Dereferenced... invariant that a DereferencedJSONSchema contains no references.
  • The dynamic scope is reconstructed from the document's static structure: seeded from each schema's own $dynamicAnchor (and $defs-declared anchors, first-wins/outermost-wins) and threaded through subschemas and across $ref boundaries.

Notes

  • Raw-AST consumers (most generators, e.g. swift-openapi-generator) are unaffected — .dynamicReference on JSONSchema is unchanged; only locallyDereferenced() behavior changes (strictly an improvement: previously it threw on all $dynamicRef; now only recursive/unresolvable ones).
  • Edits the same migration-guide section as feat: externally dereference $dynamicRef #503 (external deref); trivial doc reconcile on merge.

Testing

  • New deref tests: generics-inline, recursive-throws, unresolvable-throws, non-anchor-throws, optional+described propagation, sibling dynamic-ref independence, scope-propagates-across-$ref, $ref$dynamicRef name propagation, optional $ref property.
  • Full suite: 2165 tests, 0 failures (2157 prior + 8 new; no regressions — the .reference refactor is behavior-preserving).
  • 100% region coverage on the new code (llvm-cov-verified: 0 uncovered regions in the scope-aware _dereferenced + the ArrayContext/ObjectContext threading).

This PR was drafted with assistance from AI tooling. The submitter has reviewed and validated the contents prior to submission.

…ferencing

locallyDereferenced() / dereferenced(in:) now resolve $dynamicRef against the
dynamic scope (outermost $dynamicAnchor wins, per JSON Schema 2020-12).
Non-recursive targets are inlined; recursive or unresolvable dynamic refs
throw, consistent with static $ref cycles and the Dereferenced... invariant
(a DereferencedJSONSchema must not contain references).

Implements the 'dynamic-scope-aware dereferencing' item from mattpolzin#359. Edits the
same migration-guide section as mattpolzin#503 (external deref); reconcile on merge.

Part of mattpolzin#359.
@aqeelat aqeelat force-pushed the dynamic-scope-resolution branch from cbba88a to 26b74d9 Compare July 11, 2026 09:16
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.

1 participant