Skip to content

[2.x] Add withPath and visitPath helpers to NodeStack - #1186

Merged
lorisleiva merged 1 commit into
mainfrom
09-28-add_withpath_and_visitpath_helpers_to_nodestack
Sep 30, 2026
Merged

lorisleiva merged 1 commit into
mainfrom
09-28-add_withpath_and_visitpath_helpers_to_nodestack

Conversation

@lorisleiva

@lorisleiva lorisleiva commented Sep 28, 2026 •

Copy link
Copy Markdown
Member

This PR adds two helpers to NodeStack in @codama/visitors-core for jumping to another part of the tree, e.g. to the definition of a linked node.

  • withPath(path, callback) runs callback with path as the current path and restores the previous one, even if callback throws.
  • visitPath(path, visitor) visits the last node of path with the rest of path as the current path. The visited node is therefore recorded once, rather than twice as when the full path was pushed before visiting it.

The existing pushPath/popPath pairs in getByteSizeVisitor, getMaxByteSizeVisitor, getInstructionDataFields, unwrapDefinedTypesVisitor and dynamic-codecs now use these helpers.

@lorisleiva

Copy link
Copy Markdown
Member Author

@trevor-cortex

@trevor-cortex trevor-cortex left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Adds NodeStack.withPath(path, cb) and NodeStack.visitPath(path, visitor) to @codama/visitors-core and replaces the five hand-rolled pushPath/try/finally/popPath blocks across getByteSizeVisitor, getMaxByteSizeVisitor, getInstructionDataFields, unwrapDefinedTypesVisitor and dynamic-codecs with them. visitPath also fixes a subtle inaccuracy: the old callers pushed the full linked path and then visited its last node through a recordNodeStackVisitor-wrapped visitor, so the linked node appeared twice on the current path. It now appears once. New tests cover both helpers, including the throw/restore path.

The implementation is straightforward and I verified each call site picks the right helper: the three that visit the linked node itself through a stack-recording visitor use visitPath, and the two that descend into definedType.type directly (where the defined type genuinely belongs on the path) use withPath. No circular import is introduced (visitor.ts has no local imports), and the remaining visit / getLastNodeFromPath imports in the touched files are all still used.

Things to address

Missing changeset. CONTRIBUTING.md asks for a changeset for any user-facing change (npx changeset add --empty). This PR adds public API to @codama/visitors-core (which versions in the fixed core group) and changes the observable NodeStack contents while sizing/encoding a linked type in @codama/dynamic-codecs. I'd expect at least a minor for the new NodeStack methods; whether the dedup deserves its own patch entry for dynamic-codecs is your call, but it's worth a line since anyone reading stack.getPath() from a shared stack inside those visitors will see a different (correct) path.

README. packages/visitors-core/README.md → "Recording node paths" → NodeStack currently documents pushPath/popPath specifically for the "jump to a linked node and back" use case. Since withPath/visitPath are now the recommended way to do that, they should be added there (and the existing pushPath/popPath paragraph could point at them).

Notes for other reviewers

  • The behavioural change (linked node recorded once instead of twice) is intentional and only affects consumers that read the stack while inside a linked type via a shared NodeStack. linkables.getPath(...) resolution relies on findProgramNodeFromPath, which is unaffected by the duplicate, so link resolution behaves identically before and after.
  • visitPath's type signature (Visitor<TReturn, TNode['kind']> where TNode comes from NodePath<TNode>) accepts wider visitors, which is what makes the dynamic-codecs call with a Visitor<Codec, EncodableNodes['kind']> type-check against the linkable union.

Comment thread packages/visitors-core/test/NodeStack.test.ts
@lorisleiva
lorisleiva force-pushed the 09-28-add_withpath_and_visitpath_helpers_to_nodestack branch from 4a741b7 to 27b430c Compare September 28, 2026 15:05
@changeset-bot

changeset-bot Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 655bc94

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@trevor-cortex trevor-cortex left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review

Both follow-ups from the previous pass landed:

  • README — the NodeStack section now documents withPath/visitPath right after the pushPath/popPath example, including the "visitor must record on the same stack, otherwise use withPath" caveat. Reads well and matches the JSDoc on the methods.
  • Test nit — the visitPath test now has recordNodeStackVisitor last in the pipe and asserts [root, root.program, slot, slot.type], which is a much clearer demonstration of the "recorded once" property.

The implementation itself is unchanged and still looks correct.

Still outstanding

Changeset. The changed-files list still contains nothing under .changeset/. CONTRIBUTING.md requires one for user-facing changes and this adds two public methods to @codama/visitors-core (fixed core group), so a minor entry is needed before merge. Optionally a patch line for @codama/dynamic-codecs noting the linked node is no longer duplicated on the stack.

That's the only blocker; happy to approve once the changeset is in.

@lorisleiva
lorisleiva force-pushed the 09-28-adapt_dynamic-codecs_to_codama_v2 branch from b926e05 to 8d5b927 Compare September 30, 2026 14:07
@lorisleiva
lorisleiva force-pushed the 09-28-add_withpath_and_visitpath_helpers_to_nodestack branch from d770279 to 61564be Compare September 30, 2026 14:08
@lorisleiva
lorisleiva force-pushed the 09-28-adapt_dynamic-codecs_to_codama_v2 branch 2 times, most recently from 1416323 to dfad4fa Compare September 30, 2026 14:09
@lorisleiva
lorisleiva force-pushed the 09-28-add_withpath_and_visitpath_helpers_to_nodestack branch from 61564be to c2a6daa Compare September 30, 2026 14:09
@lorisleiva
lorisleiva force-pushed the 09-28-adapt_dynamic-codecs_to_codama_v2 branch from dfad4fa to d814828 Compare September 30, 2026 14:11
@lorisleiva
lorisleiva force-pushed the 09-28-add_withpath_and_visitpath_helpers_to_nodestack branch 2 times, most recently from deab972 to 96364bb Compare September 30, 2026 14:12
@lorisleiva
lorisleiva force-pushed the 09-28-adapt_dynamic-codecs_to_codama_v2 branch 2 times, most recently from 8a0ec75 to ed7bb21 Compare September 30, 2026 14:13
@lorisleiva
lorisleiva force-pushed the 09-28-add_withpath_and_visitpath_helpers_to_nodestack branch 2 times, most recently from 96364bb to be3aa52 Compare September 30, 2026 14:13
@lorisleiva
lorisleiva force-pushed the 09-28-adapt_dynamic-codecs_to_codama_v2 branch 2 times, most recently from ed7bb21 to 7cf264c Compare September 30, 2026 14:14
@lorisleiva
lorisleiva force-pushed the 09-28-add_withpath_and_visitpath_helpers_to_nodestack branch from be3aa52 to 0bd6cdb Compare September 30, 2026 14:14
@lorisleiva
lorisleiva force-pushed the 09-28-adapt_dynamic-codecs_to_codama_v2 branch from 7cf264c to ea8ce7d Compare September 30, 2026 14:15
@lorisleiva
lorisleiva force-pushed the 09-28-add_withpath_and_visitpath_helpers_to_nodestack branch from 0bd6cdb to 97392e5 Compare September 30, 2026 14:15
@lorisleiva
lorisleiva force-pushed the 09-28-adapt_dynamic-codecs_to_codama_v2 branch from ea8ce7d to 22d0df8 Compare September 30, 2026 14:16
@lorisleiva
lorisleiva force-pushed the 09-28-add_withpath_and_visitpath_helpers_to_nodestack branch from 97392e5 to 690ceb0 Compare September 30, 2026 14:16
@lorisleiva
lorisleiva force-pushed the 09-28-adapt_dynamic-codecs_to_codama_v2 branch from 22d0df8 to 26f1b77 Compare September 30, 2026 14:17
@lorisleiva
lorisleiva force-pushed the 09-28-add_withpath_and_visitpath_helpers_to_nodestack branch 2 times, most recently from 0c50243 to 6218f87 Compare September 30, 2026 14:18
@lorisleiva
lorisleiva force-pushed the 09-28-adapt_dynamic-codecs_to_codama_v2 branch from 26f1b77 to 027a158 Compare September 30, 2026 14:18
Base automatically changed from 09-28-adapt_dynamic-codecs_to_codama_v2 to main September 30, 2026 14:18
@lorisleiva
lorisleiva force-pushed the 09-28-add_withpath_and_visitpath_helpers_to_nodestack branch from 6218f87 to 655bc94 Compare September 30, 2026 14:18
@lorisleiva
lorisleiva marked this pull request as ready for review September 30, 2026 14:19
@lorisleiva
lorisleiva merged commit f5f0f3b into main Sep 30, 2026
0 of 2 checks passed
@lorisleiva
lorisleiva deleted the 09-28-add_withpath_and_visitpath_helpers_to_nodestack branch September 30, 2026 14:19
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.

2 participants