-
-
Notifications
You must be signed in to change notification settings - Fork 73
Description
Problem
Currently, ERB-related nodes in Herb are not associated with the corresponding Ruby AST nodes.
Limitation
Because of this, some analyses have to rely on inspecting Ruby source code as plain text:
herb/lib/herb/engine/debug_visitor.rb
Lines 316 to 345 in 5c92c3e
| # TODO: Rewrite using Prism Nodes once available | |
| def complex_rails_helper?(code) | |
| cleaned_code = code.strip.gsub(/\s+/, " ") | |
| return true if cleaned_code.match?(/\bturbo_frame_tag\s*[(\s]/) | |
| return true if cleaned_code.match?(/\blink_to\s.*\s+do\s*$/) || | |
| cleaned_code.match?(/\blink_to\s.*\{\s*$/) || | |
| cleaned_code.match?(/\blink_to\s.*\s+do\s*\|/) || | |
| cleaned_code.match?(/\blink_to\s.*\{\s*\|/) | |
| return true if cleaned_code.match?(/\brender[\s(]/) | |
| return true if cleaned_code.match?(/\bform_with\s.*\s+do\s*[|$]/) || | |
| cleaned_code.match?(/\bform_with\s.*\{\s*[|$]/) | |
| return true if cleaned_code.match?(/\bcontent_for\s.*\s+do\s*$/) || | |
| cleaned_code.match?(/\bcontent_for\s.*\{\s*$/) | |
| return true if cleaned_code.match?(/\bcontent_tag\s.*\s+do\s*$/) || | |
| cleaned_code.match?(/\bcontent_tag\s.*\{\s*$/) | |
| return true if cleaned_code.match?(/\bcontent_tag\(.*\s+do\s*$/) || | |
| cleaned_code.match?(/\bcontent_tag\(.*\{\s*$/) | |
| return true if cleaned_code.match?(/\btag\.\w+\s.*do\s*$/) || | |
| cleaned_code.match?(/\btag\.\w+\s.*\{\s*$/) | |
| false | |
| end |
Proposal (proof of concept)
I explored a proof of concept where ERB nodes are associated with Ruby AST nodes using extract_ruby.
The idea is:
- Extract Ruby code from the ERB template via extract_ruby
- Parse it as a single Ruby program with Prism
- For each ERB node, find the Prism node whose source range falls within the ERB node’s range
- Attach that Prism node to the ERB node for downstream visitors
I implemented this in Ruby as a small prototype ( PrismAstVisitor ) to validate the direction.
I’m aware that a real implementation would likely belong in the C layer; this experiment is purely to confirm feasibility and design direction.
https://gist.github.com/kozy4324/fd7f6542d77c273960ef8b96848cce32
Question
Does this direction align with your thinking?
If you already have a plan for this problem space, I’d love to hear it.
I’d also be happy to contribute if there’s something I can help with.