#2622·ast-grep

[feature] Text equality via regex extraction on rule object.

Author: samwighttCreated May 5, 2026Updated May 25, 2026
Labelsenhancement

⭐ Suggestion

I'm trying to make an ast-grep rule to prevent an antipattern in RSpec. In our codebase, when a let var needs to exist prior to an it, we often do something like this:

rb
let(:something) { create(:something) }

before { something }

This is an antipattern, and the proper way is to instead use let!, which does the same thing:

rb
let!(:something) { create(:something) } # This desugars to the same as the above.

The ast-grep rule I'd like to write looks like this (see playground):

yaml
id: no-let-before
language: ruby
severity: error
message: "Don't reference a `let` var inside `before`. Use `let!($NAME)` instead."
files:
  - "spec/**/*_spec.rb"
rule:
  pattern: let($NAME) { $$$_ }
  precedes:
    stopBy: end
    pattern: before { $NAME }

However, inside let(:something), :something is a simple_symbol that includes the colon (:) in its text. So the above does not match because a) the types differ, and b) the text is not the same.

This means that I can't write any rules related to let usage in RSpec, and I have to reach for something like Rubocop for this rule instead (eww).

I think what I'd ideally like is the ability to somehow do simple string equality combined with the ability to do regex extraction, similar to what you can do in transform with capture groups. That'd allow me to do maybe something like:

yaml
rule:
  pattern: let($SYMBOL) { $$$_ }
  precedes:
    stopBy: end
    pattern: before { $METHOD }
constraints:
  SYMBOL:
    compare:
      source: ":(.*)"
      target: $METHOD

Unsure about exactly this design, but there's a few other cases where I've needed something like this. This feels similar enough to the stuff found in transforms that it seems like it might belong here. Idk, I go back and forth.