Skip to content

ERB nodes currently lack access to Ruby AST semantics #1036

@kozy4324

Description

@kozy4324

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:

# 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions