Skip to content

Introduce Oxc::Node and Oxc::Visitor - #3

Merged
marcoroth merged 1 commit into
mainfrom
estree-visitor
Aug 25, 2026
Merged

Introduce Oxc::Node and Oxc::Visitor#3
marcoroth merged 1 commit into
mainfrom
estree-visitor

Conversation

@marcoroth

Copy link
Copy Markdown
Owner

This pull request gives parse a way to be walked. Until now it only returned a JSON blob with no way of traversing it.

root = Oxc.parse(source).root

root.every("Identifier")   # every node of a type
root.at(offset)            # the innermost node covering a byte offset
root.each                  # an Enumerator, and Enumerable, so find and count work
root.ancestors             # what it sits inside
root.slice(source)         # its own source back

A field reads by name, and comes back wrapped when it holds a node, so reads chain.

declaration.kind                          #=> "let"
declaration.declarations.first.id["name"] #=> "count"

respond_to_missing? is wired to the real keys, so a field the node does not carry raises NoMethodError.

Oxc::Visitor answers a node with the method named after its type, and walks through anything nothing answers.

class Reads < Oxc::Visitor
  def visit_assignment_expression(node)
    puts "#{node.left["name"]} #{node.operator}"

    visit_children(node)
  end
end

Reads.new.visit(Oxc.parse(source))

Dispatch snake-cases the ESTree type with acronym runs handled, so TSTypeAnnotation answers to visit_ts_type_annotation and JSXElement to visit_jsx_element.

@marcoroth
marcoroth enabled auto-merge (squash) August 25, 2026 20:32
@marcoroth
marcoroth merged commit e0b5ef3 into main Aug 25, 2026
11 checks passed
@marcoroth
marcoroth deleted the estree-visitor branch August 25, 2026 20:35
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.

1 participant