yeast: Extend `rule!` macro with support for raw captures by tausbn · Pull Request #22070 · github/codeql · GitHub
Skip to content

yeast: Extend rule! macro with support for raw captures#22070

Open
tausbn wants to merge 4 commits into
mainfrom
tausbn/yeast-add-raw-capture-syntax
Open

yeast: Extend rule! macro with support for raw captures#22070
tausbn wants to merge 4 commits into
mainfrom
tausbn/yeast-add-raw-capture-syntax

Conversation

@tausbn

@tausbn tausbn commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

This entirely supersedes the previous manual_rule! macro, which effectively marked all captures as raw.

With the changes in this PR, writing a capture as @@foo instead of @foo makes it a raw capture. These captures must be translated manually by calling ctx.translate(foo) at the appropriate time.

I opted for the @@ prefix as raw capture marker, as it still signals "capture", but doesn't introduce a new symbol. Normal captures get the shorter syntax, as they are the more common case.

Also, in terms of evaluation, normal captures are translated eagerly, before the body of the macro is run.

There are a few remaining annoyances that I want to address (but not in this PR). The fact that we have two types (NodeRef and Id) that are essentially just usize, and that we need to explicitly .into() to convert between is annoying. I think these types can be unified relatively easily.

tausbn added 3 commits June 26, 2026 12:07
The `@@name` capture marker in `rule!` queries skips the
auto-translate prefix for that specific capture, letting the body see
the original capture (and thus delay its translation using
`ctx.translate` until it becomes convenient).

Regular `@name` captures continue to be auto-translated as before.
Specifically these are translated _eagerly_, before the main body of the
rewrite rule is run.

I settled on `@@` as the syntax because it did not add new symbols that
the user has to keep track of (it's still a kind of capture), but it's
still visually distinct enough that the user should be able to tell that
there's something special going on. In principle one could accidentally
write one form of capture where the other was intended, but in practice
this would result in code that did not compile (because the types would
not match).
With `@@name` available, there's no longer a need to use `manual_rule!`.
Every place where it is used, we can instead just mark the relevant raw
captures as such. This results in quite a lot of cleanup! (Also, to me
at least, it makes these rules a lot easier to reason about.)

A first iteration of this approach resulted in a lot of
`.map(Into::into)` being needed, because `SwiftContext` stores `Id`s,
but captures produce `NodeRef`s. To avoid this, I swapped it around so
that the context stores `NodeRef`s. This does require adding `.into()`
in a few places, but it makes the rest of the code a lot more ergonomic.
The `manual_rule!` macro is now fully subsumed by `rule!` + `@@name`, so
this commit simply gets rid of the now no longer needed code.
@tausbn tausbn marked this pull request as ready for review June 26, 2026 13:01
@tausbn tausbn requested a review from a team as a code owner June 26, 2026 13:01
Copilot AI review requested due to automatic review settings June 26, 2026 13:01
@tausbn tausbn requested a review from a team as a code owner June 26, 2026 13:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR extends the Yeast rule! macro to support raw captures via an @@name marker, allowing rules to opt out of the macro’s OneShot auto-translation prefix for specific captures (so the rule body can manually call ctx.translate(...) at the right time). It also removes the superseded manual_rule! macro and restores the ergonomics of not having to explicitly return Ok(...) from rule bodies.

Changes:

  • Add @@name capture markers in the macro parser and plumb a per-rule “skip list” into auto_translate_captures.
  • Implement capture-mapping support to skip auto-translation for selected capture names; remove manual_rule! exports/implementation.
  • Update Swift desugaring rules to use rule! + @@... instead of manual_rule!, and add tests/docs for raw capture behavior.
Show a summary per file
File Description
unified/extractor/src/languages/swift/swift.rs Migrates former manual_rule! usages to rule! with @@ raw captures and adjusts context fields/types accordingly.
shared/yeast/tests/test.rs Adds tests covering @@ raw capture behavior and explicit translation from rule bodies.
shared/yeast/src/lib.rs Adds From<Id> for NodeRef and extends auto-translate to accept a skip list of capture names.
shared/yeast/src/captures.rs Adds try_map_captures_except to skip auto-translation for selected capture keys.
shared/yeast/doc/yeast.md Documents @@name raw captures and their intended use.
shared/yeast-macros/src/parse.rs Parses @@ markers, extracts “raw capture” metadata, and passes a skip list to the generated auto-translate prefix; wraps transform results in Ok(...).
shared/yeast-macros/src/lib.rs Removes the manual_rule! proc-macro entrypoint.

Review details

  • Files reviewed: 7/7 changed files
  • Comments generated: 3
  • Review effort level: Low

Comment thread unified/extractor/src/languages/swift/swift.rs
Comment thread shared/yeast/doc/yeast.md
Comment thread shared/yeast/tests/test.rs Outdated
- unified/swift: Mark `binding_kind` as a raw `@@` capture in the
  property_declaration rule. It is only used to read its source text
  (`ctx.ast.source_text`), never as a translated node. With `@` the
  auto-translate prefix would route the unnamed `let`/`var` token
  through the catch-all `_ @node => {node}` fallback for a no-op
  roundtrip; `@@` makes the intent explicit and removes that reliance.

- shared/yeast/tests: Reword a stale comment in test_raw_capture_marker.
  The text claimed a "second assertion" exists in this test, but the
  explicit-translation check actually lives in the companion
  test_raw_capture_marker_explicit_translate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants