Module: Synvert::Core::NodeQuery

Defined in:
lib/synvert/core/node_query.rb,
lib/synvert/core/node_query/parser.racc.rb

Overview

NodeQuery defines a node query language, which is a css like syntax for matching nodes.

It supports the following selectors:

  • AST node type: .class, .send

  • attribute value: .send[receiver = nil], .send[message = create]

  • attribute regex: .send[key=~/\A:([^'"]+)\z/], .send[key!~/\A:([^'"]+)\z/]

  • attribute conditions: .send[message != nil], .send[value > 1], .send[value >= 1], .send[value < 1], .send[value <= 1]

  • nested attribute: .send[caller.message = map], .send[arguments.size = 2]

  • descendant: .class .send

  • child: .class > .def

  • following sibling: .def + .def

  • subsequnt sibling: .def ~ .def

  • has: .class:has(.def)

It also supports some custom selectors:

  • not_has: .class:not_has(.def), it’s same as :not(:has()) in css, just to make implementation easy.

  • nested selector: .send[arguments = [size = 2][first = .sym][last = .hash]]

  • array value: .send[arguments = (a b)]

  • IN operator: .send[message IN (try try!)]

  • NOT IN operator: .send[message NOT IN (create build)]

  • INCLUDES operator: .send[arguments INCLUDES &block]

  • dynamic attribute value: .hash > .pair

  • goto scope: .class body > .def

Examples:

# it matches methods call nodes, like `puts message` or `p message`
Synvert::Core::NodeQuery::Parser.parse('.send[receiver = nil][message IN (puts, p)]').query_nodes(node)

Defined Under Namespace

Modules: Compiler Classes: Lexer, Parser