Mini Shell
# frozen_string_literal: true
=begin
This file is generated by the templates/template.rb script and should not be
modified manually. See templates/lib/prism/node.rb.erb
if you are looking to modify the template
=end
module Prism
# This represents a node in the tree. It is the parent class of all of the
# various node types.
class Node
# A Location instance that represents the location of this node in the
# source.
attr_reader :location
def newline? # :nodoc:
@newline ? true : false
end
def set_newline_flag(newline_marked) # :nodoc:
line = location.start_line
unless newline_marked[line]
newline_marked[line] = true
@newline = true
end
end
# Slice the location of the node from the source.
def slice
location.slice
end
# Similar to inspect, but respects the current level of indentation given by
# the pretty print object.
def pretty_print(q)
q.seplist(inspect.chomp.each_line, -> { q.breakable }) do |line|
q.text(line.chomp)
end
q.current_group.break
end
# Convert this node into a graphviz dot graph string.
def to_dot
DotVisitor.new.tap { |visitor| accept(visitor) }.to_dot
end
end
# Represents the use of the `alias` keyword to alias a global variable.
#
# alias $foo $bar
# ^^^^^^^^^^^^^^^
class AliasGlobalVariableNode < Node
# attr_reader new_name: Node
attr_reader :new_name
# attr_reader old_name: Node
attr_reader :old_name
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# def initialize: (new_name: Node, old_name: Node, keyword_loc: Location, location: Location) -> void
def initialize(new_name, old_name, keyword_loc, location)
@new_name = new_name
@old_name = old_name
@keyword_loc = keyword_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_alias_global_variable_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[new_name, old_name]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[new_name, old_name]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[new_name, old_name, keyword_loc]
end
# def copy: (**params) -> AliasGlobalVariableNode
def copy(**params)
AliasGlobalVariableNode.new(
params.fetch(:new_name) { new_name },
params.fetch(:old_name) { old_name },
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ new_name: new_name, old_name: old_name, keyword_loc: keyword_loc, location: location }
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── new_name:\n"
inspector << inspector.child_node(new_name, "│ ")
inspector << "├── old_name:\n"
inspector << inspector.child_node(old_name, "│ ")
inspector << "└── keyword_loc: #{inspector.location(keyword_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:alias_global_variable_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:alias_global_variable_node
end
end
# Represents the use of the `alias` keyword to alias a method.
#
# alias foo bar
# ^^^^^^^^^^^^^
class AliasMethodNode < Node
# attr_reader new_name: Node
attr_reader :new_name
# attr_reader old_name: Node
attr_reader :old_name
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# def initialize: (new_name: Node, old_name: Node, keyword_loc: Location, location: Location) -> void
def initialize(new_name, old_name, keyword_loc, location)
@new_name = new_name
@old_name = old_name
@keyword_loc = keyword_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_alias_method_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[new_name, old_name]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[new_name, old_name]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[new_name, old_name, keyword_loc]
end
# def copy: (**params) -> AliasMethodNode
def copy(**params)
AliasMethodNode.new(
params.fetch(:new_name) { new_name },
params.fetch(:old_name) { old_name },
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ new_name: new_name, old_name: old_name, keyword_loc: keyword_loc, location: location }
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── new_name:\n"
inspector << inspector.child_node(new_name, "│ ")
inspector << "├── old_name:\n"
inspector << inspector.child_node(old_name, "│ ")
inspector << "└── keyword_loc: #{inspector.location(keyword_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:alias_method_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:alias_method_node
end
end
# Represents an alternation pattern in pattern matching.
#
# foo => bar | baz
# ^^^^^^^^^
class AlternationPatternNode < Node
# attr_reader left: Node
attr_reader :left
# attr_reader right: Node
attr_reader :right
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (left: Node, right: Node, operator_loc: Location, location: Location) -> void
def initialize(left, right, operator_loc, location)
@left = left
@right = right
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_alternation_pattern_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[left, right]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[left, right]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[left, right, operator_loc]
end
# def copy: (**params) -> AlternationPatternNode
def copy(**params)
AlternationPatternNode.new(
params.fetch(:left) { left },
params.fetch(:right) { right },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ left: left, right: right, operator_loc: operator_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── left:\n"
inspector << inspector.child_node(left, "│ ")
inspector << "├── right:\n"
inspector << inspector.child_node(right, "│ ")
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:alternation_pattern_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:alternation_pattern_node
end
end
# Represents the use of the `&&` operator or the `and` keyword.
#
# left and right
# ^^^^^^^^^^^^^^
class AndNode < Node
# attr_reader left: Node
attr_reader :left
# attr_reader right: Node
attr_reader :right
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (left: Node, right: Node, operator_loc: Location, location: Location) -> void
def initialize(left, right, operator_loc, location)
@left = left
@right = right
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_and_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[left, right]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[left, right]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[left, right, operator_loc]
end
# def copy: (**params) -> AndNode
def copy(**params)
AndNode.new(
params.fetch(:left) { left },
params.fetch(:right) { right },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ left: left, right: right, operator_loc: operator_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── left:\n"
inspector << inspector.child_node(left, "│ ")
inspector << "├── right:\n"
inspector << inspector.child_node(right, "│ ")
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:and_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:and_node
end
end
# Represents a set of arguments to a method or a keyword.
#
# return foo, bar, baz
# ^^^^^^^^^^^^^
class ArgumentsNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader arguments: Array[Node]
attr_reader :arguments
# def initialize: (flags: Integer, arguments: Array[Node], location: Location) -> void
def initialize(flags, arguments, location)
@flags = flags
@arguments = arguments
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_arguments_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[*arguments]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[*arguments]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*arguments]
end
# def copy: (**params) -> ArgumentsNode
def copy(**params)
ArgumentsNode.new(
params.fetch(:flags) { flags },
params.fetch(:arguments) { arguments },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, arguments: arguments, location: location }
end
# def contains_keyword_splat?: () -> bool
def contains_keyword_splat?
flags.anybits?(ArgumentsNodeFlags::CONTAINS_KEYWORD_SPLAT)
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("contains_keyword_splat" if contains_keyword_splat?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
inspector << "└── arguments: #{inspector.list("#{inspector.prefix} ", arguments)}"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:arguments_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:arguments_node
end
end
# Represents an array literal. This can be a regular array using brackets or
# a special array using % like %w or %i.
#
# [1, 2, 3]
# ^^^^^^^^^
class ArrayNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader elements: Array[Node]
attr_reader :elements
# attr_reader opening_loc: Location?
attr_reader :opening_loc
# attr_reader closing_loc: Location?
attr_reader :closing_loc
# def initialize: (flags: Integer, elements: Array[Node], opening_loc: Location?, closing_loc: Location?, location: Location) -> void
def initialize(flags, elements, opening_loc, closing_loc, location)
@flags = flags
@elements = elements
@opening_loc = opening_loc
@closing_loc = closing_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_array_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[*elements]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[*elements]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*elements, *opening_loc, *closing_loc]
end
# def copy: (**params) -> ArrayNode
def copy(**params)
ArrayNode.new(
params.fetch(:flags) { flags },
params.fetch(:elements) { elements },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, elements: elements, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
end
# def contains_splat?: () -> bool
def contains_splat?
flags.anybits?(ArrayNodeFlags::CONTAINS_SPLAT)
end
# def opening: () -> String?
def opening
opening_loc&.slice
end
# def closing: () -> String?
def closing
closing_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("contains_splat" if contains_splat?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
inspector << "├── elements: #{inspector.list("#{inspector.prefix}│ ", elements)}"
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "└── closing_loc: #{inspector.location(closing_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:array_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:array_node
end
end
# Represents an array pattern in pattern matching.
#
# foo in 1, 2
# ^^^^^^^^^^^
#
# foo in [1, 2]
# ^^^^^^^^^^^^^
#
# foo in *1
# ^^^^^^^^^
#
# foo in Bar[]
# ^^^^^^^^^^^^
#
# foo in Bar[1, 2, 3]
# ^^^^^^^^^^^^^^^^^^^
class ArrayPatternNode < Node
# attr_reader constant: Node?
attr_reader :constant
# attr_reader requireds: Array[Node]
attr_reader :requireds
# attr_reader rest: Node?
attr_reader :rest
# attr_reader posts: Array[Node]
attr_reader :posts
# attr_reader opening_loc: Location?
attr_reader :opening_loc
# attr_reader closing_loc: Location?
attr_reader :closing_loc
# def initialize: (constant: Node?, requireds: Array[Node], rest: Node?, posts: Array[Node], opening_loc: Location?, closing_loc: Location?, location: Location) -> void
def initialize(constant, requireds, rest, posts, opening_loc, closing_loc, location)
@constant = constant
@requireds = requireds
@rest = rest
@posts = posts
@opening_loc = opening_loc
@closing_loc = closing_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_array_pattern_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[constant, *requireds, rest, *posts]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << constant if constant
compact.concat(requireds)
compact << rest if rest
compact.concat(posts)
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*constant, *requireds, *rest, *posts, *opening_loc, *closing_loc]
end
# def copy: (**params) -> ArrayPatternNode
def copy(**params)
ArrayPatternNode.new(
params.fetch(:constant) { constant },
params.fetch(:requireds) { requireds },
params.fetch(:rest) { rest },
params.fetch(:posts) { posts },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ constant: constant, requireds: requireds, rest: rest, posts: posts, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
end
# def opening: () -> String?
def opening
opening_loc&.slice
end
# def closing: () -> String?
def closing
closing_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (constant = self.constant).nil?
inspector << "├── constant: ∅\n"
else
inspector << "├── constant:\n"
inspector << constant.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── requireds: #{inspector.list("#{inspector.prefix}│ ", requireds)}"
if (rest = self.rest).nil?
inspector << "├── rest: ∅\n"
else
inspector << "├── rest:\n"
inspector << rest.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── posts: #{inspector.list("#{inspector.prefix}│ ", posts)}"
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "└── closing_loc: #{inspector.location(closing_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:array_pattern_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:array_pattern_node
end
end
# Represents a hash key/value pair.
#
# { a => b }
# ^^^^^^
class AssocNode < Node
# attr_reader key: Node
attr_reader :key
# attr_reader value: Node?
attr_reader :value
# attr_reader operator_loc: Location?
attr_reader :operator_loc
# def initialize: (key: Node, value: Node?, operator_loc: Location?, location: Location) -> void
def initialize(key, value, operator_loc, location)
@key = key
@value = value
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_assoc_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[key, value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << key
compact << value if value
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[key, *value, *operator_loc]
end
# def copy: (**params) -> AssocNode
def copy(**params)
AssocNode.new(
params.fetch(:key) { key },
params.fetch(:value) { value },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ key: key, value: value, operator_loc: operator_loc, location: location }
end
# def operator: () -> String?
def operator
operator_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── key:\n"
inspector << inspector.child_node(key, "│ ")
if (value = self.value).nil?
inspector << "├── value: ∅\n"
else
inspector << "├── value:\n"
inspector << value.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:assoc_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:assoc_node
end
end
# Represents a splat in a hash literal.
#
# { **foo }
# ^^^^^
class AssocSplatNode < Node
# attr_reader value: Node?
attr_reader :value
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (value: Node?, operator_loc: Location, location: Location) -> void
def initialize(value, operator_loc, location)
@value = value
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_assoc_splat_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << value if value
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*value, operator_loc]
end
# def copy: (**params) -> AssocSplatNode
def copy(**params)
AssocSplatNode.new(
params.fetch(:value) { value },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ value: value, operator_loc: operator_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (value = self.value).nil?
inspector << "├── value: ∅\n"
else
inspector << "├── value:\n"
inspector << value.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:assoc_splat_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:assoc_splat_node
end
end
# Represents reading a reference to a field in the previous match.
#
# $'
# ^^
class BackReferenceReadNode < Node
# attr_reader name: Symbol
attr_reader :name
# def initialize: (name: Symbol, location: Location) -> void
def initialize(name, location)
@name = name
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_back_reference_read_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> BackReferenceReadNode
def copy(**params)
BackReferenceReadNode.new(
params.fetch(:name) { name },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── name: #{name.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:back_reference_read_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:back_reference_read_node
end
end
# Represents a begin statement.
#
# begin
# foo
# end
# ^^^^^
class BeginNode < Node
# attr_reader begin_keyword_loc: Location?
attr_reader :begin_keyword_loc
# attr_reader statements: StatementsNode?
attr_reader :statements
# attr_reader rescue_clause: RescueNode?
attr_reader :rescue_clause
# attr_reader else_clause: ElseNode?
attr_reader :else_clause
# attr_reader ensure_clause: EnsureNode?
attr_reader :ensure_clause
# attr_reader end_keyword_loc: Location?
attr_reader :end_keyword_loc
# def initialize: (begin_keyword_loc: Location?, statements: StatementsNode?, rescue_clause: RescueNode?, else_clause: ElseNode?, ensure_clause: EnsureNode?, end_keyword_loc: Location?, location: Location) -> void
def initialize(begin_keyword_loc, statements, rescue_clause, else_clause, ensure_clause, end_keyword_loc, location)
@begin_keyword_loc = begin_keyword_loc
@statements = statements
@rescue_clause = rescue_clause
@else_clause = else_clause
@ensure_clause = ensure_clause
@end_keyword_loc = end_keyword_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_begin_node(self)
end
def set_newline_flag(newline_marked) # :nodoc:
# Never mark BeginNode with a newline flag, mark children instead
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[statements, rescue_clause, else_clause, ensure_clause]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << statements if statements
compact << rescue_clause if rescue_clause
compact << else_clause if else_clause
compact << ensure_clause if ensure_clause
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*begin_keyword_loc, *statements, *rescue_clause, *else_clause, *ensure_clause, *end_keyword_loc]
end
# def copy: (**params) -> BeginNode
def copy(**params)
BeginNode.new(
params.fetch(:begin_keyword_loc) { begin_keyword_loc },
params.fetch(:statements) { statements },
params.fetch(:rescue_clause) { rescue_clause },
params.fetch(:else_clause) { else_clause },
params.fetch(:ensure_clause) { ensure_clause },
params.fetch(:end_keyword_loc) { end_keyword_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ begin_keyword_loc: begin_keyword_loc, statements: statements, rescue_clause: rescue_clause, else_clause: else_clause, ensure_clause: ensure_clause, end_keyword_loc: end_keyword_loc, location: location }
end
# def begin_keyword: () -> String?
def begin_keyword
begin_keyword_loc&.slice
end
# def end_keyword: () -> String?
def end_keyword
end_keyword_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── begin_keyword_loc: #{inspector.location(begin_keyword_loc)}\n"
if (statements = self.statements).nil?
inspector << "├── statements: ∅\n"
else
inspector << "├── statements:\n"
inspector << statements.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
if (rescue_clause = self.rescue_clause).nil?
inspector << "├── rescue_clause: ∅\n"
else
inspector << "├── rescue_clause:\n"
inspector << rescue_clause.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
if (else_clause = self.else_clause).nil?
inspector << "├── else_clause: ∅\n"
else
inspector << "├── else_clause:\n"
inspector << else_clause.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
if (ensure_clause = self.ensure_clause).nil?
inspector << "├── ensure_clause: ∅\n"
else
inspector << "├── ensure_clause:\n"
inspector << ensure_clause.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "└── end_keyword_loc: #{inspector.location(end_keyword_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:begin_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:begin_node
end
end
# Represents block method arguments.
#
# bar(&args)
# ^^^^^^^^^^
class BlockArgumentNode < Node
# attr_reader expression: Node?
attr_reader :expression
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (expression: Node?, operator_loc: Location, location: Location) -> void
def initialize(expression, operator_loc, location)
@expression = expression
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_block_argument_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[expression]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << expression if expression
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*expression, operator_loc]
end
# def copy: (**params) -> BlockArgumentNode
def copy(**params)
BlockArgumentNode.new(
params.fetch(:expression) { expression },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ expression: expression, operator_loc: operator_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (expression = self.expression).nil?
inspector << "├── expression: ∅\n"
else
inspector << "├── expression:\n"
inspector << expression.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:block_argument_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:block_argument_node
end
end
# Represents a block local variable.
#
# a { |; b| }
# ^
class BlockLocalVariableNode < Node
# attr_reader name: Symbol
attr_reader :name
# def initialize: (name: Symbol, location: Location) -> void
def initialize(name, location)
@name = name
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_block_local_variable_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> BlockLocalVariableNode
def copy(**params)
BlockLocalVariableNode.new(
params.fetch(:name) { name },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── name: #{name.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:block_local_variable_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:block_local_variable_node
end
end
# Represents a block of ruby code.
#
# [1, 2, 3].each { |i| puts x }
# ^^^^^^^^^^^^^^
class BlockNode < Node
# attr_reader locals: Array[Symbol]
attr_reader :locals
# attr_reader locals_body_index: Integer
attr_reader :locals_body_index
# attr_reader parameters: Node?
attr_reader :parameters
# attr_reader body: Node?
attr_reader :body
# attr_reader opening_loc: Location
attr_reader :opening_loc
# attr_reader closing_loc: Location
attr_reader :closing_loc
# def initialize: (locals: Array[Symbol], locals_body_index: Integer, parameters: Node?, body: Node?, opening_loc: Location, closing_loc: Location, location: Location) -> void
def initialize(locals, locals_body_index, parameters, body, opening_loc, closing_loc, location)
@locals = locals
@locals_body_index = locals_body_index
@parameters = parameters
@body = body
@opening_loc = opening_loc
@closing_loc = closing_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_block_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[parameters, body]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << parameters if parameters
compact << body if body
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*parameters, *body, opening_loc, closing_loc]
end
# def copy: (**params) -> BlockNode
def copy(**params)
BlockNode.new(
params.fetch(:locals) { locals },
params.fetch(:locals_body_index) { locals_body_index },
params.fetch(:parameters) { parameters },
params.fetch(:body) { body },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ locals: locals, locals_body_index: locals_body_index, parameters: parameters, body: body, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
end
# def opening: () -> String
def opening
opening_loc.slice
end
# def closing: () -> String
def closing
closing_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── locals: #{locals.inspect}\n"
inspector << "├── locals_body_index: #{locals_body_index.inspect}\n"
if (parameters = self.parameters).nil?
inspector << "├── parameters: ∅\n"
else
inspector << "├── parameters:\n"
inspector << parameters.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
if (body = self.body).nil?
inspector << "├── body: ∅\n"
else
inspector << "├── body:\n"
inspector << body.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "└── closing_loc: #{inspector.location(closing_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:block_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:block_node
end
end
# Represents a block parameter to a method, block, or lambda definition.
#
# def a(&b)
# ^^
# end
class BlockParameterNode < Node
# attr_reader name: Symbol?
attr_reader :name
# attr_reader name_loc: Location?
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (name: Symbol?, name_loc: Location?, operator_loc: Location, location: Location) -> void
def initialize(name, name_loc, operator_loc, location)
@name = name
@name_loc = name_loc
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_block_parameter_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*name_loc, operator_loc]
end
# def copy: (**params) -> BlockParameterNode
def copy(**params)
BlockParameterNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, operator_loc: operator_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (name = self.name).nil?
inspector << "├── name: ∅\n"
else
inspector << "├── name: #{name.inspect}\n"
end
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:block_parameter_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:block_parameter_node
end
end
# Represents a block's parameters declaration.
#
# -> (a, b = 1; local) { }
# ^^^^^^^^^^^^^^^^^
#
# foo do |a, b = 1; local|
# ^^^^^^^^^^^^^^^^^
# end
class BlockParametersNode < Node
# attr_reader parameters: ParametersNode?
attr_reader :parameters
# attr_reader locals: Array[Node]
attr_reader :locals
# attr_reader opening_loc: Location?
attr_reader :opening_loc
# attr_reader closing_loc: Location?
attr_reader :closing_loc
# def initialize: (parameters: ParametersNode?, locals: Array[Node], opening_loc: Location?, closing_loc: Location?, location: Location) -> void
def initialize(parameters, locals, opening_loc, closing_loc, location)
@parameters = parameters
@locals = locals
@opening_loc = opening_loc
@closing_loc = closing_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_block_parameters_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[parameters, *locals]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << parameters if parameters
compact.concat(locals)
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*parameters, *locals, *opening_loc, *closing_loc]
end
# def copy: (**params) -> BlockParametersNode
def copy(**params)
BlockParametersNode.new(
params.fetch(:parameters) { parameters },
params.fetch(:locals) { locals },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ parameters: parameters, locals: locals, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
end
# def opening: () -> String?
def opening
opening_loc&.slice
end
# def closing: () -> String?
def closing
closing_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (parameters = self.parameters).nil?
inspector << "├── parameters: ∅\n"
else
inspector << "├── parameters:\n"
inspector << parameters.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── locals: #{inspector.list("#{inspector.prefix}│ ", locals)}"
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "└── closing_loc: #{inspector.location(closing_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:block_parameters_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:block_parameters_node
end
end
# Represents the use of the `break` keyword.
#
# break foo
# ^^^^^^^^^
class BreakNode < Node
# attr_reader arguments: ArgumentsNode?
attr_reader :arguments
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# def initialize: (arguments: ArgumentsNode?, keyword_loc: Location, location: Location) -> void
def initialize(arguments, keyword_loc, location)
@arguments = arguments
@keyword_loc = keyword_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_break_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[arguments]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << arguments if arguments
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*arguments, keyword_loc]
end
# def copy: (**params) -> BreakNode
def copy(**params)
BreakNode.new(
params.fetch(:arguments) { arguments },
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ arguments: arguments, keyword_loc: keyword_loc, location: location }
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (arguments = self.arguments).nil?
inspector << "├── arguments: ∅\n"
else
inspector << "├── arguments:\n"
inspector << arguments.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "└── keyword_loc: #{inspector.location(keyword_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:break_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:break_node
end
end
# Represents the use of the `&&=` operator on a call.
#
# foo.bar &&= value
# ^^^^^^^^^^^^^^^^^
class CallAndWriteNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader receiver: Node?
attr_reader :receiver
# attr_reader call_operator_loc: Location?
attr_reader :call_operator_loc
# attr_reader message_loc: Location?
attr_reader :message_loc
# attr_reader read_name: Symbol
attr_reader :read_name
# attr_reader write_name: Symbol
attr_reader :write_name
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (flags: Integer, receiver: Node?, call_operator_loc: Location?, message_loc: Location?, read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node, location: Location) -> void
def initialize(flags, receiver, call_operator_loc, message_loc, read_name, write_name, operator_loc, value, location)
@flags = flags
@receiver = receiver
@call_operator_loc = call_operator_loc
@message_loc = message_loc
@read_name = read_name
@write_name = write_name
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_call_and_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[receiver, value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << receiver if receiver
compact << value
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*receiver, *call_operator_loc, *message_loc, operator_loc, value]
end
# def copy: (**params) -> CallAndWriteNode
def copy(**params)
CallAndWriteNode.new(
params.fetch(:flags) { flags },
params.fetch(:receiver) { receiver },
params.fetch(:call_operator_loc) { call_operator_loc },
params.fetch(:message_loc) { message_loc },
params.fetch(:read_name) { read_name },
params.fetch(:write_name) { write_name },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, receiver: receiver, call_operator_loc: call_operator_loc, message_loc: message_loc, read_name: read_name, write_name: write_name, operator_loc: operator_loc, value: value, location: location }
end
# def safe_navigation?: () -> bool
def safe_navigation?
flags.anybits?(CallNodeFlags::SAFE_NAVIGATION)
end
# def variable_call?: () -> bool
def variable_call?
flags.anybits?(CallNodeFlags::VARIABLE_CALL)
end
# def attribute_write?: () -> bool
def attribute_write?
flags.anybits?(CallNodeFlags::ATTRIBUTE_WRITE)
end
# def call_operator: () -> String?
def call_operator
call_operator_loc&.slice
end
# def message: () -> String?
def message
message_loc&.slice
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("safe_navigation" if safe_navigation?), ("variable_call" if variable_call?), ("attribute_write" if attribute_write?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
if (receiver = self.receiver).nil?
inspector << "├── receiver: ∅\n"
else
inspector << "├── receiver:\n"
inspector << receiver.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── call_operator_loc: #{inspector.location(call_operator_loc)}\n"
inspector << "├── message_loc: #{inspector.location(message_loc)}\n"
inspector << "├── read_name: #{read_name.inspect}\n"
inspector << "├── write_name: #{write_name.inspect}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:call_and_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:call_and_write_node
end
end
# Represents a method call, in all of the various forms that can take.
#
# foo
# ^^^
#
# foo()
# ^^^^^
#
# +foo
# ^^^^
#
# foo + bar
# ^^^^^^^^^
#
# foo.bar
# ^^^^^^^
#
# foo&.bar
# ^^^^^^^^
class CallNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader receiver: Node?
attr_reader :receiver
# attr_reader call_operator_loc: Location?
attr_reader :call_operator_loc
# attr_reader name: Symbol
attr_reader :name
# attr_reader message_loc: Location?
attr_reader :message_loc
# attr_reader opening_loc: Location?
attr_reader :opening_loc
# attr_reader arguments: ArgumentsNode?
attr_reader :arguments
# attr_reader closing_loc: Location?
attr_reader :closing_loc
# attr_reader block: Node?
attr_reader :block
# def initialize: (flags: Integer, receiver: Node?, call_operator_loc: Location?, name: Symbol, message_loc: Location?, opening_loc: Location?, arguments: ArgumentsNode?, closing_loc: Location?, block: Node?, location: Location) -> void
def initialize(flags, receiver, call_operator_loc, name, message_loc, opening_loc, arguments, closing_loc, block, location)
@flags = flags
@receiver = receiver
@call_operator_loc = call_operator_loc
@name = name
@message_loc = message_loc
@opening_loc = opening_loc
@arguments = arguments
@closing_loc = closing_loc
@block = block
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_call_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[receiver, arguments, block]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << receiver if receiver
compact << arguments if arguments
compact << block if block
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*receiver, *call_operator_loc, *message_loc, *opening_loc, *arguments, *closing_loc, *block]
end
# def copy: (**params) -> CallNode
def copy(**params)
CallNode.new(
params.fetch(:flags) { flags },
params.fetch(:receiver) { receiver },
params.fetch(:call_operator_loc) { call_operator_loc },
params.fetch(:name) { name },
params.fetch(:message_loc) { message_loc },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:arguments) { arguments },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:block) { block },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, receiver: receiver, call_operator_loc: call_operator_loc, name: name, message_loc: message_loc, opening_loc: opening_loc, arguments: arguments, closing_loc: closing_loc, block: block, location: location }
end
# def safe_navigation?: () -> bool
def safe_navigation?
flags.anybits?(CallNodeFlags::SAFE_NAVIGATION)
end
# def variable_call?: () -> bool
def variable_call?
flags.anybits?(CallNodeFlags::VARIABLE_CALL)
end
# def attribute_write?: () -> bool
def attribute_write?
flags.anybits?(CallNodeFlags::ATTRIBUTE_WRITE)
end
# def call_operator: () -> String?
def call_operator
call_operator_loc&.slice
end
# def message: () -> String?
def message
message_loc&.slice
end
# def opening: () -> String?
def opening
opening_loc&.slice
end
# def closing: () -> String?
def closing
closing_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("safe_navigation" if safe_navigation?), ("variable_call" if variable_call?), ("attribute_write" if attribute_write?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
if (receiver = self.receiver).nil?
inspector << "├── receiver: ∅\n"
else
inspector << "├── receiver:\n"
inspector << receiver.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── call_operator_loc: #{inspector.location(call_operator_loc)}\n"
inspector << "├── name: #{name.inspect}\n"
inspector << "├── message_loc: #{inspector.location(message_loc)}\n"
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
if (arguments = self.arguments).nil?
inspector << "├── arguments: ∅\n"
else
inspector << "├── arguments:\n"
inspector << arguments.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
if (block = self.block).nil?
inspector << "└── block: ∅\n"
else
inspector << "└── block:\n"
inspector << block.inspect(inspector.child_inspector(" ")).delete_prefix(inspector.prefix)
end
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:call_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:call_node
end
end
# Represents the use of an assignment operator on a call.
#
# foo.bar += baz
# ^^^^^^^^^^^^^^
class CallOperatorWriteNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader receiver: Node?
attr_reader :receiver
# attr_reader call_operator_loc: Location?
attr_reader :call_operator_loc
# attr_reader message_loc: Location?
attr_reader :message_loc
# attr_reader read_name: Symbol
attr_reader :read_name
# attr_reader write_name: Symbol
attr_reader :write_name
# attr_reader operator: Symbol
attr_reader :operator
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (flags: Integer, receiver: Node?, call_operator_loc: Location?, message_loc: Location?, read_name: Symbol, write_name: Symbol, operator: Symbol, operator_loc: Location, value: Node, location: Location) -> void
def initialize(flags, receiver, call_operator_loc, message_loc, read_name, write_name, operator, operator_loc, value, location)
@flags = flags
@receiver = receiver
@call_operator_loc = call_operator_loc
@message_loc = message_loc
@read_name = read_name
@write_name = write_name
@operator = operator
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_call_operator_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[receiver, value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << receiver if receiver
compact << value
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*receiver, *call_operator_loc, *message_loc, operator_loc, value]
end
# def copy: (**params) -> CallOperatorWriteNode
def copy(**params)
CallOperatorWriteNode.new(
params.fetch(:flags) { flags },
params.fetch(:receiver) { receiver },
params.fetch(:call_operator_loc) { call_operator_loc },
params.fetch(:message_loc) { message_loc },
params.fetch(:read_name) { read_name },
params.fetch(:write_name) { write_name },
params.fetch(:operator) { operator },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, receiver: receiver, call_operator_loc: call_operator_loc, message_loc: message_loc, read_name: read_name, write_name: write_name, operator: operator, operator_loc: operator_loc, value: value, location: location }
end
# def safe_navigation?: () -> bool
def safe_navigation?
flags.anybits?(CallNodeFlags::SAFE_NAVIGATION)
end
# def variable_call?: () -> bool
def variable_call?
flags.anybits?(CallNodeFlags::VARIABLE_CALL)
end
# def attribute_write?: () -> bool
def attribute_write?
flags.anybits?(CallNodeFlags::ATTRIBUTE_WRITE)
end
# def call_operator: () -> String?
def call_operator
call_operator_loc&.slice
end
# def message: () -> String?
def message
message_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("safe_navigation" if safe_navigation?), ("variable_call" if variable_call?), ("attribute_write" if attribute_write?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
if (receiver = self.receiver).nil?
inspector << "├── receiver: ∅\n"
else
inspector << "├── receiver:\n"
inspector << receiver.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── call_operator_loc: #{inspector.location(call_operator_loc)}\n"
inspector << "├── message_loc: #{inspector.location(message_loc)}\n"
inspector << "├── read_name: #{read_name.inspect}\n"
inspector << "├── write_name: #{write_name.inspect}\n"
inspector << "├── operator: #{operator.inspect}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:call_operator_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:call_operator_write_node
end
end
# Represents the use of the `||=` operator on a call.
#
# foo.bar ||= value
# ^^^^^^^^^^^^^^^^^
class CallOrWriteNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader receiver: Node?
attr_reader :receiver
# attr_reader call_operator_loc: Location?
attr_reader :call_operator_loc
# attr_reader message_loc: Location?
attr_reader :message_loc
# attr_reader read_name: Symbol
attr_reader :read_name
# attr_reader write_name: Symbol
attr_reader :write_name
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (flags: Integer, receiver: Node?, call_operator_loc: Location?, message_loc: Location?, read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node, location: Location) -> void
def initialize(flags, receiver, call_operator_loc, message_loc, read_name, write_name, operator_loc, value, location)
@flags = flags
@receiver = receiver
@call_operator_loc = call_operator_loc
@message_loc = message_loc
@read_name = read_name
@write_name = write_name
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_call_or_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[receiver, value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << receiver if receiver
compact << value
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*receiver, *call_operator_loc, *message_loc, operator_loc, value]
end
# def copy: (**params) -> CallOrWriteNode
def copy(**params)
CallOrWriteNode.new(
params.fetch(:flags) { flags },
params.fetch(:receiver) { receiver },
params.fetch(:call_operator_loc) { call_operator_loc },
params.fetch(:message_loc) { message_loc },
params.fetch(:read_name) { read_name },
params.fetch(:write_name) { write_name },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, receiver: receiver, call_operator_loc: call_operator_loc, message_loc: message_loc, read_name: read_name, write_name: write_name, operator_loc: operator_loc, value: value, location: location }
end
# def safe_navigation?: () -> bool
def safe_navigation?
flags.anybits?(CallNodeFlags::SAFE_NAVIGATION)
end
# def variable_call?: () -> bool
def variable_call?
flags.anybits?(CallNodeFlags::VARIABLE_CALL)
end
# def attribute_write?: () -> bool
def attribute_write?
flags.anybits?(CallNodeFlags::ATTRIBUTE_WRITE)
end
# def call_operator: () -> String?
def call_operator
call_operator_loc&.slice
end
# def message: () -> String?
def message
message_loc&.slice
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("safe_navigation" if safe_navigation?), ("variable_call" if variable_call?), ("attribute_write" if attribute_write?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
if (receiver = self.receiver).nil?
inspector << "├── receiver: ∅\n"
else
inspector << "├── receiver:\n"
inspector << receiver.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── call_operator_loc: #{inspector.location(call_operator_loc)}\n"
inspector << "├── message_loc: #{inspector.location(message_loc)}\n"
inspector << "├── read_name: #{read_name.inspect}\n"
inspector << "├── write_name: #{write_name.inspect}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:call_or_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:call_or_write_node
end
end
# Represents assigning to a method call.
#
# foo.bar, = 1
# ^^^^^^^
#
# begin
# rescue => foo.bar
# ^^^^^^^
# end
#
# for foo.bar in baz do end
# ^^^^^^^
class CallTargetNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader receiver: Node
attr_reader :receiver
# attr_reader call_operator_loc: Location
attr_reader :call_operator_loc
# attr_reader name: Symbol
attr_reader :name
# attr_reader message_loc: Location
attr_reader :message_loc
# def initialize: (flags: Integer, receiver: Node, call_operator_loc: Location, name: Symbol, message_loc: Location, location: Location) -> void
def initialize(flags, receiver, call_operator_loc, name, message_loc, location)
@flags = flags
@receiver = receiver
@call_operator_loc = call_operator_loc
@name = name
@message_loc = message_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_call_target_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[receiver]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[receiver]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[receiver, call_operator_loc, message_loc]
end
# def copy: (**params) -> CallTargetNode
def copy(**params)
CallTargetNode.new(
params.fetch(:flags) { flags },
params.fetch(:receiver) { receiver },
params.fetch(:call_operator_loc) { call_operator_loc },
params.fetch(:name) { name },
params.fetch(:message_loc) { message_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, receiver: receiver, call_operator_loc: call_operator_loc, name: name, message_loc: message_loc, location: location }
end
# def safe_navigation?: () -> bool
def safe_navigation?
flags.anybits?(CallNodeFlags::SAFE_NAVIGATION)
end
# def variable_call?: () -> bool
def variable_call?
flags.anybits?(CallNodeFlags::VARIABLE_CALL)
end
# def attribute_write?: () -> bool
def attribute_write?
flags.anybits?(CallNodeFlags::ATTRIBUTE_WRITE)
end
# def call_operator: () -> String
def call_operator
call_operator_loc.slice
end
# def message: () -> String
def message
message_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("safe_navigation" if safe_navigation?), ("variable_call" if variable_call?), ("attribute_write" if attribute_write?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
inspector << "├── receiver:\n"
inspector << inspector.child_node(receiver, "│ ")
inspector << "├── call_operator_loc: #{inspector.location(call_operator_loc)}\n"
inspector << "├── name: #{name.inspect}\n"
inspector << "└── message_loc: #{inspector.location(message_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:call_target_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:call_target_node
end
end
# Represents assigning to a local variable in pattern matching.
#
# foo => [bar => baz]
# ^^^^^^^^^^^^
class CapturePatternNode < Node
# attr_reader value: Node
attr_reader :value
# attr_reader target: Node
attr_reader :target
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (value: Node, target: Node, operator_loc: Location, location: Location) -> void
def initialize(value, target, operator_loc, location)
@value = value
@target = target
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_capture_pattern_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value, target]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value, target]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[value, target, operator_loc]
end
# def copy: (**params) -> CapturePatternNode
def copy(**params)
CapturePatternNode.new(
params.fetch(:value) { value },
params.fetch(:target) { target },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ value: value, target: target, operator_loc: operator_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── value:\n"
inspector << inspector.child_node(value, "│ ")
inspector << "├── target:\n"
inspector << inspector.child_node(target, "│ ")
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:capture_pattern_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:capture_pattern_node
end
end
# Represents the use of a case statement for pattern matching.
#
# case true
# in false
# end
# ^^^^^^^^^
class CaseMatchNode < Node
# attr_reader predicate: Node?
attr_reader :predicate
# attr_reader conditions: Array[Node]
attr_reader :conditions
# attr_reader consequent: ElseNode?
attr_reader :consequent
# attr_reader case_keyword_loc: Location
attr_reader :case_keyword_loc
# attr_reader end_keyword_loc: Location
attr_reader :end_keyword_loc
# def initialize: (predicate: Node?, conditions: Array[Node], consequent: ElseNode?, case_keyword_loc: Location, end_keyword_loc: Location, location: Location) -> void
def initialize(predicate, conditions, consequent, case_keyword_loc, end_keyword_loc, location)
@predicate = predicate
@conditions = conditions
@consequent = consequent
@case_keyword_loc = case_keyword_loc
@end_keyword_loc = end_keyword_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_case_match_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[predicate, *conditions, consequent]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << predicate if predicate
compact.concat(conditions)
compact << consequent if consequent
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*predicate, *conditions, *consequent, case_keyword_loc, end_keyword_loc]
end
# def copy: (**params) -> CaseMatchNode
def copy(**params)
CaseMatchNode.new(
params.fetch(:predicate) { predicate },
params.fetch(:conditions) { conditions },
params.fetch(:consequent) { consequent },
params.fetch(:case_keyword_loc) { case_keyword_loc },
params.fetch(:end_keyword_loc) { end_keyword_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ predicate: predicate, conditions: conditions, consequent: consequent, case_keyword_loc: case_keyword_loc, end_keyword_loc: end_keyword_loc, location: location }
end
# def case_keyword: () -> String
def case_keyword
case_keyword_loc.slice
end
# def end_keyword: () -> String
def end_keyword
end_keyword_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (predicate = self.predicate).nil?
inspector << "├── predicate: ∅\n"
else
inspector << "├── predicate:\n"
inspector << predicate.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── conditions: #{inspector.list("#{inspector.prefix}│ ", conditions)}"
if (consequent = self.consequent).nil?
inspector << "├── consequent: ∅\n"
else
inspector << "├── consequent:\n"
inspector << consequent.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── case_keyword_loc: #{inspector.location(case_keyword_loc)}\n"
inspector << "└── end_keyword_loc: #{inspector.location(end_keyword_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:case_match_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:case_match_node
end
end
# Represents the use of a case statement.
#
# case true
# when false
# end
# ^^^^^^^^^^
class CaseNode < Node
# attr_reader predicate: Node?
attr_reader :predicate
# attr_reader conditions: Array[Node]
attr_reader :conditions
# attr_reader consequent: ElseNode?
attr_reader :consequent
# attr_reader case_keyword_loc: Location
attr_reader :case_keyword_loc
# attr_reader end_keyword_loc: Location
attr_reader :end_keyword_loc
# def initialize: (predicate: Node?, conditions: Array[Node], consequent: ElseNode?, case_keyword_loc: Location, end_keyword_loc: Location, location: Location) -> void
def initialize(predicate, conditions, consequent, case_keyword_loc, end_keyword_loc, location)
@predicate = predicate
@conditions = conditions
@consequent = consequent
@case_keyword_loc = case_keyword_loc
@end_keyword_loc = end_keyword_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_case_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[predicate, *conditions, consequent]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << predicate if predicate
compact.concat(conditions)
compact << consequent if consequent
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*predicate, *conditions, *consequent, case_keyword_loc, end_keyword_loc]
end
# def copy: (**params) -> CaseNode
def copy(**params)
CaseNode.new(
params.fetch(:predicate) { predicate },
params.fetch(:conditions) { conditions },
params.fetch(:consequent) { consequent },
params.fetch(:case_keyword_loc) { case_keyword_loc },
params.fetch(:end_keyword_loc) { end_keyword_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ predicate: predicate, conditions: conditions, consequent: consequent, case_keyword_loc: case_keyword_loc, end_keyword_loc: end_keyword_loc, location: location }
end
# def case_keyword: () -> String
def case_keyword
case_keyword_loc.slice
end
# def end_keyword: () -> String
def end_keyword
end_keyword_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (predicate = self.predicate).nil?
inspector << "├── predicate: ∅\n"
else
inspector << "├── predicate:\n"
inspector << predicate.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── conditions: #{inspector.list("#{inspector.prefix}│ ", conditions)}"
if (consequent = self.consequent).nil?
inspector << "├── consequent: ∅\n"
else
inspector << "├── consequent:\n"
inspector << consequent.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── case_keyword_loc: #{inspector.location(case_keyword_loc)}\n"
inspector << "└── end_keyword_loc: #{inspector.location(end_keyword_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:case_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:case_node
end
end
# Represents a class declaration involving the `class` keyword.
#
# class Foo end
# ^^^^^^^^^^^^^
class ClassNode < Node
# attr_reader locals: Array[Symbol]
attr_reader :locals
# attr_reader class_keyword_loc: Location
attr_reader :class_keyword_loc
# attr_reader constant_path: Node
attr_reader :constant_path
# attr_reader inheritance_operator_loc: Location?
attr_reader :inheritance_operator_loc
# attr_reader superclass: Node?
attr_reader :superclass
# attr_reader body: Node?
attr_reader :body
# attr_reader end_keyword_loc: Location
attr_reader :end_keyword_loc
# attr_reader name: Symbol
attr_reader :name
# def initialize: (locals: Array[Symbol], class_keyword_loc: Location, constant_path: Node, inheritance_operator_loc: Location?, superclass: Node?, body: Node?, end_keyword_loc: Location, name: Symbol, location: Location) -> void
def initialize(locals, class_keyword_loc, constant_path, inheritance_operator_loc, superclass, body, end_keyword_loc, name, location)
@locals = locals
@class_keyword_loc = class_keyword_loc
@constant_path = constant_path
@inheritance_operator_loc = inheritance_operator_loc
@superclass = superclass
@body = body
@end_keyword_loc = end_keyword_loc
@name = name
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_class_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[constant_path, superclass, body]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << constant_path
compact << superclass if superclass
compact << body if body
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[class_keyword_loc, constant_path, *inheritance_operator_loc, *superclass, *body, end_keyword_loc]
end
# def copy: (**params) -> ClassNode
def copy(**params)
ClassNode.new(
params.fetch(:locals) { locals },
params.fetch(:class_keyword_loc) { class_keyword_loc },
params.fetch(:constant_path) { constant_path },
params.fetch(:inheritance_operator_loc) { inheritance_operator_loc },
params.fetch(:superclass) { superclass },
params.fetch(:body) { body },
params.fetch(:end_keyword_loc) { end_keyword_loc },
params.fetch(:name) { name },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ locals: locals, class_keyword_loc: class_keyword_loc, constant_path: constant_path, inheritance_operator_loc: inheritance_operator_loc, superclass: superclass, body: body, end_keyword_loc: end_keyword_loc, name: name, location: location }
end
# def class_keyword: () -> String
def class_keyword
class_keyword_loc.slice
end
# def inheritance_operator: () -> String?
def inheritance_operator
inheritance_operator_loc&.slice
end
# def end_keyword: () -> String
def end_keyword
end_keyword_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── locals: #{locals.inspect}\n"
inspector << "├── class_keyword_loc: #{inspector.location(class_keyword_loc)}\n"
inspector << "├── constant_path:\n"
inspector << inspector.child_node(constant_path, "│ ")
inspector << "├── inheritance_operator_loc: #{inspector.location(inheritance_operator_loc)}\n"
if (superclass = self.superclass).nil?
inspector << "├── superclass: ∅\n"
else
inspector << "├── superclass:\n"
inspector << superclass.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
if (body = self.body).nil?
inspector << "├── body: ∅\n"
else
inspector << "├── body:\n"
inspector << body.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── end_keyword_loc: #{inspector.location(end_keyword_loc)}\n"
inspector << "└── name: #{name.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:class_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:class_node
end
end
# Represents the use of the `&&=` operator for assignment to a class variable.
#
# @@target &&= value
# ^^^^^^^^^^^^^^^^^^
class ClassVariableAndWriteNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (name: Symbol, name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
def initialize(name, name_loc, operator_loc, value, location)
@name = name
@name_loc = name_loc
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_class_variable_and_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, operator_loc, value]
end
# def copy: (**params) -> ClassVariableAndWriteNode
def copy(**params)
ClassVariableAndWriteNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:class_variable_and_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:class_variable_and_write_node
end
end
# Represents assigning to a class variable using an operator that isn't `=`.
#
# @@target += value
# ^^^^^^^^^^^^^^^^^
class ClassVariableOperatorWriteNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# attr_reader operator: Symbol
attr_reader :operator
# def initialize: (name: Symbol, name_loc: Location, operator_loc: Location, value: Node, operator: Symbol, location: Location) -> void
def initialize(name, name_loc, operator_loc, value, operator, location)
@name = name
@name_loc = name_loc
@operator_loc = operator_loc
@value = value
@operator = operator
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_class_variable_operator_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, operator_loc, value]
end
# def copy: (**params) -> ClassVariableOperatorWriteNode
def copy(**params)
ClassVariableOperatorWriteNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:operator) { operator },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, operator_loc: operator_loc, value: value, operator: operator, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "├── value:\n"
inspector << inspector.child_node(value, "│ ")
inspector << "└── operator: #{operator.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:class_variable_operator_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:class_variable_operator_write_node
end
end
# Represents the use of the `||=` operator for assignment to a class variable.
#
# @@target ||= value
# ^^^^^^^^^^^^^^^^^^
class ClassVariableOrWriteNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (name: Symbol, name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
def initialize(name, name_loc, operator_loc, value, location)
@name = name
@name_loc = name_loc
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_class_variable_or_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, operator_loc, value]
end
# def copy: (**params) -> ClassVariableOrWriteNode
def copy(**params)
ClassVariableOrWriteNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:class_variable_or_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:class_variable_or_write_node
end
end
# Represents referencing a class variable.
#
# @@foo
# ^^^^^
class ClassVariableReadNode < Node
# attr_reader name: Symbol
attr_reader :name
# def initialize: (name: Symbol, location: Location) -> void
def initialize(name, location)
@name = name
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_class_variable_read_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> ClassVariableReadNode
def copy(**params)
ClassVariableReadNode.new(
params.fetch(:name) { name },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── name: #{name.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:class_variable_read_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:class_variable_read_node
end
end
# Represents writing to a class variable in a context that doesn't have an explicit value.
#
# @@foo, @@bar = baz
# ^^^^^ ^^^^^
class ClassVariableTargetNode < Node
# attr_reader name: Symbol
attr_reader :name
# def initialize: (name: Symbol, location: Location) -> void
def initialize(name, location)
@name = name
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_class_variable_target_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> ClassVariableTargetNode
def copy(**params)
ClassVariableTargetNode.new(
params.fetch(:name) { name },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── name: #{name.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:class_variable_target_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:class_variable_target_node
end
end
# Represents writing to a class variable.
#
# @@foo = 1
# ^^^^^^^^^
class ClassVariableWriteNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader value: Node
attr_reader :value
# attr_reader operator_loc: Location?
attr_reader :operator_loc
# def initialize: (name: Symbol, name_loc: Location, value: Node, operator_loc: Location?, location: Location) -> void
def initialize(name, name_loc, value, operator_loc, location)
@name = name
@name_loc = name_loc
@value = value
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_class_variable_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, value, *operator_loc]
end
# def copy: (**params) -> ClassVariableWriteNode
def copy(**params)
ClassVariableWriteNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:value) { value },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, value: value, operator_loc: operator_loc, location: location }
end
# def operator: () -> String?
def operator
operator_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── value:\n"
inspector << inspector.child_node(value, "│ ")
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:class_variable_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:class_variable_write_node
end
end
# Represents the use of the `&&=` operator for assignment to a constant.
#
# Target &&= value
# ^^^^^^^^^^^^^^^^
class ConstantAndWriteNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (name: Symbol, name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
def initialize(name, name_loc, operator_loc, value, location)
@name = name
@name_loc = name_loc
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_constant_and_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, operator_loc, value]
end
# def copy: (**params) -> ConstantAndWriteNode
def copy(**params)
ConstantAndWriteNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:constant_and_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:constant_and_write_node
end
end
# Represents assigning to a constant using an operator that isn't `=`.
#
# Target += value
# ^^^^^^^^^^^^^^^
class ConstantOperatorWriteNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# attr_reader operator: Symbol
attr_reader :operator
# def initialize: (name: Symbol, name_loc: Location, operator_loc: Location, value: Node, operator: Symbol, location: Location) -> void
def initialize(name, name_loc, operator_loc, value, operator, location)
@name = name
@name_loc = name_loc
@operator_loc = operator_loc
@value = value
@operator = operator
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_constant_operator_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, operator_loc, value]
end
# def copy: (**params) -> ConstantOperatorWriteNode
def copy(**params)
ConstantOperatorWriteNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:operator) { operator },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, operator_loc: operator_loc, value: value, operator: operator, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "├── value:\n"
inspector << inspector.child_node(value, "│ ")
inspector << "└── operator: #{operator.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:constant_operator_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:constant_operator_write_node
end
end
# Represents the use of the `||=` operator for assignment to a constant.
#
# Target ||= value
# ^^^^^^^^^^^^^^^^
class ConstantOrWriteNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (name: Symbol, name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
def initialize(name, name_loc, operator_loc, value, location)
@name = name
@name_loc = name_loc
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_constant_or_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, operator_loc, value]
end
# def copy: (**params) -> ConstantOrWriteNode
def copy(**params)
ConstantOrWriteNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:constant_or_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:constant_or_write_node
end
end
# Represents the use of the `&&=` operator for assignment to a constant path.
#
# Parent::Child &&= value
# ^^^^^^^^^^^^^^^^^^^^^^^
class ConstantPathAndWriteNode < Node
# attr_reader target: ConstantPathNode
attr_reader :target
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (target: ConstantPathNode, operator_loc: Location, value: Node, location: Location) -> void
def initialize(target, operator_loc, value, location)
@target = target
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_constant_path_and_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[target, value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[target, value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[target, operator_loc, value]
end
# def copy: (**params) -> ConstantPathAndWriteNode
def copy(**params)
ConstantPathAndWriteNode.new(
params.fetch(:target) { target },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ target: target, operator_loc: operator_loc, value: value, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── target:\n"
inspector << inspector.child_node(target, "│ ")
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:constant_path_and_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:constant_path_and_write_node
end
end
# Represents accessing a constant through a path of `::` operators.
#
# Foo::Bar
# ^^^^^^^^
class ConstantPathNode < Node
# attr_reader parent: Node?
attr_reader :parent
# attr_reader child: Node
attr_reader :child
# attr_reader delimiter_loc: Location
attr_reader :delimiter_loc
# def initialize: (parent: Node?, child: Node, delimiter_loc: Location, location: Location) -> void
def initialize(parent, child, delimiter_loc, location)
@parent = parent
@child = child
@delimiter_loc = delimiter_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_constant_path_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[parent, child]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << parent if parent
compact << child
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*parent, child, delimiter_loc]
end
# def copy: (**params) -> ConstantPathNode
def copy(**params)
ConstantPathNode.new(
params.fetch(:parent) { parent },
params.fetch(:child) { child },
params.fetch(:delimiter_loc) { delimiter_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ parent: parent, child: child, delimiter_loc: delimiter_loc, location: location }
end
# def delimiter: () -> String
def delimiter
delimiter_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (parent = self.parent).nil?
inspector << "├── parent: ∅\n"
else
inspector << "├── parent:\n"
inspector << parent.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── child:\n"
inspector << inspector.child_node(child, "│ ")
inspector << "└── delimiter_loc: #{inspector.location(delimiter_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:constant_path_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:constant_path_node
end
end
# Represents assigning to a constant path using an operator that isn't `=`.
#
# Parent::Child += value
# ^^^^^^^^^^^^^^^^^^^^^^
class ConstantPathOperatorWriteNode < Node
# attr_reader target: ConstantPathNode
attr_reader :target
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# attr_reader operator: Symbol
attr_reader :operator
# def initialize: (target: ConstantPathNode, operator_loc: Location, value: Node, operator: Symbol, location: Location) -> void
def initialize(target, operator_loc, value, operator, location)
@target = target
@operator_loc = operator_loc
@value = value
@operator = operator
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_constant_path_operator_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[target, value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[target, value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[target, operator_loc, value]
end
# def copy: (**params) -> ConstantPathOperatorWriteNode
def copy(**params)
ConstantPathOperatorWriteNode.new(
params.fetch(:target) { target },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:operator) { operator },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ target: target, operator_loc: operator_loc, value: value, operator: operator, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── target:\n"
inspector << inspector.child_node(target, "│ ")
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "├── value:\n"
inspector << inspector.child_node(value, "│ ")
inspector << "└── operator: #{operator.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:constant_path_operator_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:constant_path_operator_write_node
end
end
# Represents the use of the `||=` operator for assignment to a constant path.
#
# Parent::Child ||= value
# ^^^^^^^^^^^^^^^^^^^^^^^
class ConstantPathOrWriteNode < Node
# attr_reader target: ConstantPathNode
attr_reader :target
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (target: ConstantPathNode, operator_loc: Location, value: Node, location: Location) -> void
def initialize(target, operator_loc, value, location)
@target = target
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_constant_path_or_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[target, value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[target, value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[target, operator_loc, value]
end
# def copy: (**params) -> ConstantPathOrWriteNode
def copy(**params)
ConstantPathOrWriteNode.new(
params.fetch(:target) { target },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ target: target, operator_loc: operator_loc, value: value, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── target:\n"
inspector << inspector.child_node(target, "│ ")
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:constant_path_or_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:constant_path_or_write_node
end
end
# Represents writing to a constant path in a context that doesn't have an explicit value.
#
# Foo::Foo, Bar::Bar = baz
# ^^^^^^^^ ^^^^^^^^
class ConstantPathTargetNode < Node
# attr_reader parent: Node?
attr_reader :parent
# attr_reader child: Node
attr_reader :child
# attr_reader delimiter_loc: Location
attr_reader :delimiter_loc
# def initialize: (parent: Node?, child: Node, delimiter_loc: Location, location: Location) -> void
def initialize(parent, child, delimiter_loc, location)
@parent = parent
@child = child
@delimiter_loc = delimiter_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_constant_path_target_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[parent, child]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << parent if parent
compact << child
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*parent, child, delimiter_loc]
end
# def copy: (**params) -> ConstantPathTargetNode
def copy(**params)
ConstantPathTargetNode.new(
params.fetch(:parent) { parent },
params.fetch(:child) { child },
params.fetch(:delimiter_loc) { delimiter_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ parent: parent, child: child, delimiter_loc: delimiter_loc, location: location }
end
# def delimiter: () -> String
def delimiter
delimiter_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (parent = self.parent).nil?
inspector << "├── parent: ∅\n"
else
inspector << "├── parent:\n"
inspector << parent.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── child:\n"
inspector << inspector.child_node(child, "│ ")
inspector << "└── delimiter_loc: #{inspector.location(delimiter_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:constant_path_target_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:constant_path_target_node
end
end
# Represents writing to a constant path.
#
# ::Foo = 1
# ^^^^^^^^^
#
# Foo::Bar = 1
# ^^^^^^^^^^^^
#
# ::Foo::Bar = 1
# ^^^^^^^^^^^^^^
class ConstantPathWriteNode < Node
# attr_reader target: ConstantPathNode
attr_reader :target
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (target: ConstantPathNode, operator_loc: Location, value: Node, location: Location) -> void
def initialize(target, operator_loc, value, location)
@target = target
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_constant_path_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[target, value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[target, value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[target, operator_loc, value]
end
# def copy: (**params) -> ConstantPathWriteNode
def copy(**params)
ConstantPathWriteNode.new(
params.fetch(:target) { target },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ target: target, operator_loc: operator_loc, value: value, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── target:\n"
inspector << inspector.child_node(target, "│ ")
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:constant_path_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:constant_path_write_node
end
end
# Represents referencing a constant.
#
# Foo
# ^^^
class ConstantReadNode < Node
# attr_reader name: Symbol
attr_reader :name
# def initialize: (name: Symbol, location: Location) -> void
def initialize(name, location)
@name = name
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_constant_read_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> ConstantReadNode
def copy(**params)
ConstantReadNode.new(
params.fetch(:name) { name },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── name: #{name.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:constant_read_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:constant_read_node
end
end
# Represents writing to a constant in a context that doesn't have an explicit value.
#
# Foo, Bar = baz
# ^^^ ^^^
class ConstantTargetNode < Node
# attr_reader name: Symbol
attr_reader :name
# def initialize: (name: Symbol, location: Location) -> void
def initialize(name, location)
@name = name
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_constant_target_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> ConstantTargetNode
def copy(**params)
ConstantTargetNode.new(
params.fetch(:name) { name },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── name: #{name.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:constant_target_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:constant_target_node
end
end
# Represents writing to a constant.
#
# Foo = 1
# ^^^^^^^
class ConstantWriteNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader value: Node
attr_reader :value
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (name: Symbol, name_loc: Location, value: Node, operator_loc: Location, location: Location) -> void
def initialize(name, name_loc, value, operator_loc, location)
@name = name
@name_loc = name_loc
@value = value
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_constant_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, value, operator_loc]
end
# def copy: (**params) -> ConstantWriteNode
def copy(**params)
ConstantWriteNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:value) { value },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, value: value, operator_loc: operator_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── value:\n"
inspector << inspector.child_node(value, "│ ")
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:constant_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:constant_write_node
end
end
# Represents a method definition.
#
# def method
# end
# ^^^^^^^^^^
class DefNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader receiver: Node?
attr_reader :receiver
# attr_reader parameters: ParametersNode?
attr_reader :parameters
# attr_reader body: Node?
attr_reader :body
# attr_reader locals: Array[Symbol]
attr_reader :locals
# attr_reader locals_body_index: Integer
attr_reader :locals_body_index
# attr_reader def_keyword_loc: Location
attr_reader :def_keyword_loc
# attr_reader operator_loc: Location?
attr_reader :operator_loc
# attr_reader lparen_loc: Location?
attr_reader :lparen_loc
# attr_reader rparen_loc: Location?
attr_reader :rparen_loc
# attr_reader equal_loc: Location?
attr_reader :equal_loc
# attr_reader end_keyword_loc: Location?
attr_reader :end_keyword_loc
# def initialize: (name: Symbol, name_loc: Location, receiver: Node?, parameters: ParametersNode?, body: Node?, locals: Array[Symbol], locals_body_index: Integer, def_keyword_loc: Location, operator_loc: Location?, lparen_loc: Location?, rparen_loc: Location?, equal_loc: Location?, end_keyword_loc: Location?, location: Location) -> void
def initialize(name, name_loc, receiver, parameters, body, locals, locals_body_index, def_keyword_loc, operator_loc, lparen_loc, rparen_loc, equal_loc, end_keyword_loc, location)
@name = name
@name_loc = name_loc
@receiver = receiver
@parameters = parameters
@body = body
@locals = locals
@locals_body_index = locals_body_index
@def_keyword_loc = def_keyword_loc
@operator_loc = operator_loc
@lparen_loc = lparen_loc
@rparen_loc = rparen_loc
@equal_loc = equal_loc
@end_keyword_loc = end_keyword_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_def_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[receiver, parameters, body]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << receiver if receiver
compact << parameters if parameters
compact << body if body
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, *receiver, *parameters, *body, def_keyword_loc, *operator_loc, *lparen_loc, *rparen_loc, *equal_loc, *end_keyword_loc]
end
# def copy: (**params) -> DefNode
def copy(**params)
DefNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:receiver) { receiver },
params.fetch(:parameters) { parameters },
params.fetch(:body) { body },
params.fetch(:locals) { locals },
params.fetch(:locals_body_index) { locals_body_index },
params.fetch(:def_keyword_loc) { def_keyword_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:lparen_loc) { lparen_loc },
params.fetch(:rparen_loc) { rparen_loc },
params.fetch(:equal_loc) { equal_loc },
params.fetch(:end_keyword_loc) { end_keyword_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, receiver: receiver, parameters: parameters, body: body, locals: locals, locals_body_index: locals_body_index, def_keyword_loc: def_keyword_loc, operator_loc: operator_loc, lparen_loc: lparen_loc, rparen_loc: rparen_loc, equal_loc: equal_loc, end_keyword_loc: end_keyword_loc, location: location }
end
# def def_keyword: () -> String
def def_keyword
def_keyword_loc.slice
end
# def operator: () -> String?
def operator
operator_loc&.slice
end
# def lparen: () -> String?
def lparen
lparen_loc&.slice
end
# def rparen: () -> String?
def rparen
rparen_loc&.slice
end
# def equal: () -> String?
def equal
equal_loc&.slice
end
# def end_keyword: () -> String?
def end_keyword
end_keyword_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
if (receiver = self.receiver).nil?
inspector << "├── receiver: ∅\n"
else
inspector << "├── receiver:\n"
inspector << receiver.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
if (parameters = self.parameters).nil?
inspector << "├── parameters: ∅\n"
else
inspector << "├── parameters:\n"
inspector << parameters.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
if (body = self.body).nil?
inspector << "├── body: ∅\n"
else
inspector << "├── body:\n"
inspector << body.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── locals: #{locals.inspect}\n"
inspector << "├── locals_body_index: #{locals_body_index.inspect}\n"
inspector << "├── def_keyword_loc: #{inspector.location(def_keyword_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "├── lparen_loc: #{inspector.location(lparen_loc)}\n"
inspector << "├── rparen_loc: #{inspector.location(rparen_loc)}\n"
inspector << "├── equal_loc: #{inspector.location(equal_loc)}\n"
inspector << "└── end_keyword_loc: #{inspector.location(end_keyword_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:def_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:def_node
end
end
# Represents the use of the `defined?` keyword.
#
# defined?(a)
# ^^^^^^^^^^^
class DefinedNode < Node
# attr_reader lparen_loc: Location?
attr_reader :lparen_loc
# attr_reader value: Node
attr_reader :value
# attr_reader rparen_loc: Location?
attr_reader :rparen_loc
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# def initialize: (lparen_loc: Location?, value: Node, rparen_loc: Location?, keyword_loc: Location, location: Location) -> void
def initialize(lparen_loc, value, rparen_loc, keyword_loc, location)
@lparen_loc = lparen_loc
@value = value
@rparen_loc = rparen_loc
@keyword_loc = keyword_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_defined_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*lparen_loc, value, *rparen_loc, keyword_loc]
end
# def copy: (**params) -> DefinedNode
def copy(**params)
DefinedNode.new(
params.fetch(:lparen_loc) { lparen_loc },
params.fetch(:value) { value },
params.fetch(:rparen_loc) { rparen_loc },
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ lparen_loc: lparen_loc, value: value, rparen_loc: rparen_loc, keyword_loc: keyword_loc, location: location }
end
# def lparen: () -> String?
def lparen
lparen_loc&.slice
end
# def rparen: () -> String?
def rparen
rparen_loc&.slice
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── lparen_loc: #{inspector.location(lparen_loc)}\n"
inspector << "├── value:\n"
inspector << inspector.child_node(value, "│ ")
inspector << "├── rparen_loc: #{inspector.location(rparen_loc)}\n"
inspector << "└── keyword_loc: #{inspector.location(keyword_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:defined_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:defined_node
end
end
# Represents an `else` clause in a `case`, `if`, or `unless` statement.
#
# if a then b else c end
# ^^^^^^^^^^
class ElseNode < Node
# attr_reader else_keyword_loc: Location
attr_reader :else_keyword_loc
# attr_reader statements: StatementsNode?
attr_reader :statements
# attr_reader end_keyword_loc: Location?
attr_reader :end_keyword_loc
# def initialize: (else_keyword_loc: Location, statements: StatementsNode?, end_keyword_loc: Location?, location: Location) -> void
def initialize(else_keyword_loc, statements, end_keyword_loc, location)
@else_keyword_loc = else_keyword_loc
@statements = statements
@end_keyword_loc = end_keyword_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_else_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[statements]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << statements if statements
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[else_keyword_loc, *statements, *end_keyword_loc]
end
# def copy: (**params) -> ElseNode
def copy(**params)
ElseNode.new(
params.fetch(:else_keyword_loc) { else_keyword_loc },
params.fetch(:statements) { statements },
params.fetch(:end_keyword_loc) { end_keyword_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ else_keyword_loc: else_keyword_loc, statements: statements, end_keyword_loc: end_keyword_loc, location: location }
end
# def else_keyword: () -> String
def else_keyword
else_keyword_loc.slice
end
# def end_keyword: () -> String?
def end_keyword
end_keyword_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── else_keyword_loc: #{inspector.location(else_keyword_loc)}\n"
if (statements = self.statements).nil?
inspector << "├── statements: ∅\n"
else
inspector << "├── statements:\n"
inspector << statements.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "└── end_keyword_loc: #{inspector.location(end_keyword_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:else_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:else_node
end
end
# Represents an interpolated set of statements.
#
# "foo #{bar}"
# ^^^^^^
class EmbeddedStatementsNode < Node
# attr_reader opening_loc: Location
attr_reader :opening_loc
# attr_reader statements: StatementsNode?
attr_reader :statements
# attr_reader closing_loc: Location
attr_reader :closing_loc
# def initialize: (opening_loc: Location, statements: StatementsNode?, closing_loc: Location, location: Location) -> void
def initialize(opening_loc, statements, closing_loc, location)
@opening_loc = opening_loc
@statements = statements
@closing_loc = closing_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_embedded_statements_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[statements]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << statements if statements
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[opening_loc, *statements, closing_loc]
end
# def copy: (**params) -> EmbeddedStatementsNode
def copy(**params)
EmbeddedStatementsNode.new(
params.fetch(:opening_loc) { opening_loc },
params.fetch(:statements) { statements },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ opening_loc: opening_loc, statements: statements, closing_loc: closing_loc, location: location }
end
# def opening: () -> String
def opening
opening_loc.slice
end
# def closing: () -> String
def closing
closing_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
if (statements = self.statements).nil?
inspector << "├── statements: ∅\n"
else
inspector << "├── statements:\n"
inspector << statements.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "└── closing_loc: #{inspector.location(closing_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:embedded_statements_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:embedded_statements_node
end
end
# Represents an interpolated variable.
#
# "foo #@bar"
# ^^^^^
class EmbeddedVariableNode < Node
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader variable: Node
attr_reader :variable
# def initialize: (operator_loc: Location, variable: Node, location: Location) -> void
def initialize(operator_loc, variable, location)
@operator_loc = operator_loc
@variable = variable
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_embedded_variable_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[variable]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[variable]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[operator_loc, variable]
end
# def copy: (**params) -> EmbeddedVariableNode
def copy(**params)
EmbeddedVariableNode.new(
params.fetch(:operator_loc) { operator_loc },
params.fetch(:variable) { variable },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ operator_loc: operator_loc, variable: variable, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── variable:\n"
inspector << inspector.child_node(variable, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:embedded_variable_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:embedded_variable_node
end
end
# Represents an `ensure` clause in a `begin` statement.
#
# begin
# foo
# ensure
# ^^^^^^
# bar
# end
class EnsureNode < Node
# attr_reader ensure_keyword_loc: Location
attr_reader :ensure_keyword_loc
# attr_reader statements: StatementsNode?
attr_reader :statements
# attr_reader end_keyword_loc: Location
attr_reader :end_keyword_loc
# def initialize: (ensure_keyword_loc: Location, statements: StatementsNode?, end_keyword_loc: Location, location: Location) -> void
def initialize(ensure_keyword_loc, statements, end_keyword_loc, location)
@ensure_keyword_loc = ensure_keyword_loc
@statements = statements
@end_keyword_loc = end_keyword_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_ensure_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[statements]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << statements if statements
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[ensure_keyword_loc, *statements, end_keyword_loc]
end
# def copy: (**params) -> EnsureNode
def copy(**params)
EnsureNode.new(
params.fetch(:ensure_keyword_loc) { ensure_keyword_loc },
params.fetch(:statements) { statements },
params.fetch(:end_keyword_loc) { end_keyword_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ ensure_keyword_loc: ensure_keyword_loc, statements: statements, end_keyword_loc: end_keyword_loc, location: location }
end
# def ensure_keyword: () -> String
def ensure_keyword
ensure_keyword_loc.slice
end
# def end_keyword: () -> String
def end_keyword
end_keyword_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── ensure_keyword_loc: #{inspector.location(ensure_keyword_loc)}\n"
if (statements = self.statements).nil?
inspector << "├── statements: ∅\n"
else
inspector << "├── statements:\n"
inspector << statements.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "└── end_keyword_loc: #{inspector.location(end_keyword_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:ensure_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:ensure_node
end
end
# Represents the use of the literal `false` keyword.
#
# false
# ^^^^^
class FalseNode < Node
# def initialize: (location: Location) -> void
def initialize(location)
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_false_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> FalseNode
def copy(**params)
FalseNode.new(
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:false_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:false_node
end
end
# Represents a find pattern in pattern matching.
#
# foo in *bar, baz, *qux
# ^^^^^^^^^^^^^^^
#
# foo in [*bar, baz, *qux]
# ^^^^^^^^^^^^^^^^^
#
# foo in Foo(*bar, baz, *qux)
# ^^^^^^^^^^^^^^^^^^^^
class FindPatternNode < Node
# attr_reader constant: Node?
attr_reader :constant
# attr_reader left: Node
attr_reader :left
# attr_reader requireds: Array[Node]
attr_reader :requireds
# attr_reader right: Node
attr_reader :right
# attr_reader opening_loc: Location?
attr_reader :opening_loc
# attr_reader closing_loc: Location?
attr_reader :closing_loc
# def initialize: (constant: Node?, left: Node, requireds: Array[Node], right: Node, opening_loc: Location?, closing_loc: Location?, location: Location) -> void
def initialize(constant, left, requireds, right, opening_loc, closing_loc, location)
@constant = constant
@left = left
@requireds = requireds
@right = right
@opening_loc = opening_loc
@closing_loc = closing_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_find_pattern_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[constant, left, *requireds, right]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << constant if constant
compact << left
compact.concat(requireds)
compact << right
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*constant, left, *requireds, right, *opening_loc, *closing_loc]
end
# def copy: (**params) -> FindPatternNode
def copy(**params)
FindPatternNode.new(
params.fetch(:constant) { constant },
params.fetch(:left) { left },
params.fetch(:requireds) { requireds },
params.fetch(:right) { right },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ constant: constant, left: left, requireds: requireds, right: right, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
end
# def opening: () -> String?
def opening
opening_loc&.slice
end
# def closing: () -> String?
def closing
closing_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (constant = self.constant).nil?
inspector << "├── constant: ∅\n"
else
inspector << "├── constant:\n"
inspector << constant.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── left:\n"
inspector << inspector.child_node(left, "│ ")
inspector << "├── requireds: #{inspector.list("#{inspector.prefix}│ ", requireds)}"
inspector << "├── right:\n"
inspector << inspector.child_node(right, "│ ")
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "└── closing_loc: #{inspector.location(closing_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:find_pattern_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:find_pattern_node
end
end
# Represents the use of the `..` or `...` operators to create flip flops.
#
# baz if foo .. bar
# ^^^^^^^^^^
class FlipFlopNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader left: Node?
attr_reader :left
# attr_reader right: Node?
attr_reader :right
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (flags: Integer, left: Node?, right: Node?, operator_loc: Location, location: Location) -> void
def initialize(flags, left, right, operator_loc, location)
@flags = flags
@left = left
@right = right
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_flip_flop_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[left, right]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << left if left
compact << right if right
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*left, *right, operator_loc]
end
# def copy: (**params) -> FlipFlopNode
def copy(**params)
FlipFlopNode.new(
params.fetch(:flags) { flags },
params.fetch(:left) { left },
params.fetch(:right) { right },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, left: left, right: right, operator_loc: operator_loc, location: location }
end
# def exclude_end?: () -> bool
def exclude_end?
flags.anybits?(RangeFlags::EXCLUDE_END)
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("exclude_end" if exclude_end?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
if (left = self.left).nil?
inspector << "├── left: ∅\n"
else
inspector << "├── left:\n"
inspector << left.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
if (right = self.right).nil?
inspector << "├── right: ∅\n"
else
inspector << "├── right:\n"
inspector << right.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:flip_flop_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:flip_flop_node
end
end
# Represents a floating point number literal.
#
# 1.0
# ^^^
class FloatNode < Node
# def initialize: (location: Location) -> void
def initialize(location)
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_float_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> FloatNode
def copy(**params)
FloatNode.new(
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:float_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:float_node
end
end
# Represents the use of the `for` keyword.
#
# for i in a end
# ^^^^^^^^^^^^^^
class ForNode < Node
# attr_reader index: Node
attr_reader :index
# attr_reader collection: Node
attr_reader :collection
# attr_reader statements: StatementsNode?
attr_reader :statements
# attr_reader for_keyword_loc: Location
attr_reader :for_keyword_loc
# attr_reader in_keyword_loc: Location
attr_reader :in_keyword_loc
# attr_reader do_keyword_loc: Location?
attr_reader :do_keyword_loc
# attr_reader end_keyword_loc: Location
attr_reader :end_keyword_loc
# def initialize: (index: Node, collection: Node, statements: StatementsNode?, for_keyword_loc: Location, in_keyword_loc: Location, do_keyword_loc: Location?, end_keyword_loc: Location, location: Location) -> void
def initialize(index, collection, statements, for_keyword_loc, in_keyword_loc, do_keyword_loc, end_keyword_loc, location)
@index = index
@collection = collection
@statements = statements
@for_keyword_loc = for_keyword_loc
@in_keyword_loc = in_keyword_loc
@do_keyword_loc = do_keyword_loc
@end_keyword_loc = end_keyword_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_for_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[index, collection, statements]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << index
compact << collection
compact << statements if statements
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[index, collection, *statements, for_keyword_loc, in_keyword_loc, *do_keyword_loc, end_keyword_loc]
end
# def copy: (**params) -> ForNode
def copy(**params)
ForNode.new(
params.fetch(:index) { index },
params.fetch(:collection) { collection },
params.fetch(:statements) { statements },
params.fetch(:for_keyword_loc) { for_keyword_loc },
params.fetch(:in_keyword_loc) { in_keyword_loc },
params.fetch(:do_keyword_loc) { do_keyword_loc },
params.fetch(:end_keyword_loc) { end_keyword_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ index: index, collection: collection, statements: statements, for_keyword_loc: for_keyword_loc, in_keyword_loc: in_keyword_loc, do_keyword_loc: do_keyword_loc, end_keyword_loc: end_keyword_loc, location: location }
end
# def for_keyword: () -> String
def for_keyword
for_keyword_loc.slice
end
# def in_keyword: () -> String
def in_keyword
in_keyword_loc.slice
end
# def do_keyword: () -> String?
def do_keyword
do_keyword_loc&.slice
end
# def end_keyword: () -> String
def end_keyword
end_keyword_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── index:\n"
inspector << inspector.child_node(index, "│ ")
inspector << "├── collection:\n"
inspector << inspector.child_node(collection, "│ ")
if (statements = self.statements).nil?
inspector << "├── statements: ∅\n"
else
inspector << "├── statements:\n"
inspector << statements.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── for_keyword_loc: #{inspector.location(for_keyword_loc)}\n"
inspector << "├── in_keyword_loc: #{inspector.location(in_keyword_loc)}\n"
inspector << "├── do_keyword_loc: #{inspector.location(do_keyword_loc)}\n"
inspector << "└── end_keyword_loc: #{inspector.location(end_keyword_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:for_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:for_node
end
end
# Represents forwarding all arguments to this method to another method.
#
# def foo(...)
# bar(...)
# ^^^
# end
class ForwardingArgumentsNode < Node
# def initialize: (location: Location) -> void
def initialize(location)
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_forwarding_arguments_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> ForwardingArgumentsNode
def copy(**params)
ForwardingArgumentsNode.new(
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:forwarding_arguments_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:forwarding_arguments_node
end
end
# Represents the use of the forwarding parameter in a method, block, or lambda declaration.
#
# def foo(...)
# ^^^
# end
class ForwardingParameterNode < Node
# def initialize: (location: Location) -> void
def initialize(location)
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_forwarding_parameter_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> ForwardingParameterNode
def copy(**params)
ForwardingParameterNode.new(
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:forwarding_parameter_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:forwarding_parameter_node
end
end
# Represents the use of the `super` keyword without parentheses or arguments.
#
# super
# ^^^^^
class ForwardingSuperNode < Node
# attr_reader block: BlockNode?
attr_reader :block
# def initialize: (block: BlockNode?, location: Location) -> void
def initialize(block, location)
@block = block
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_forwarding_super_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[block]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << block if block
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*block]
end
# def copy: (**params) -> ForwardingSuperNode
def copy(**params)
ForwardingSuperNode.new(
params.fetch(:block) { block },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ block: block, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (block = self.block).nil?
inspector << "└── block: ∅\n"
else
inspector << "└── block:\n"
inspector << block.inspect(inspector.child_inspector(" ")).delete_prefix(inspector.prefix)
end
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:forwarding_super_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:forwarding_super_node
end
end
# Represents the use of the `&&=` operator for assignment to a global variable.
#
# $target &&= value
# ^^^^^^^^^^^^^^^^^
class GlobalVariableAndWriteNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (name: Symbol, name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
def initialize(name, name_loc, operator_loc, value, location)
@name = name
@name_loc = name_loc
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_global_variable_and_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, operator_loc, value]
end
# def copy: (**params) -> GlobalVariableAndWriteNode
def copy(**params)
GlobalVariableAndWriteNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:global_variable_and_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:global_variable_and_write_node
end
end
# Represents assigning to a global variable using an operator that isn't `=`.
#
# $target += value
# ^^^^^^^^^^^^^^^^
class GlobalVariableOperatorWriteNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# attr_reader operator: Symbol
attr_reader :operator
# def initialize: (name: Symbol, name_loc: Location, operator_loc: Location, value: Node, operator: Symbol, location: Location) -> void
def initialize(name, name_loc, operator_loc, value, operator, location)
@name = name
@name_loc = name_loc
@operator_loc = operator_loc
@value = value
@operator = operator
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_global_variable_operator_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, operator_loc, value]
end
# def copy: (**params) -> GlobalVariableOperatorWriteNode
def copy(**params)
GlobalVariableOperatorWriteNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:operator) { operator },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, operator_loc: operator_loc, value: value, operator: operator, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "├── value:\n"
inspector << inspector.child_node(value, "│ ")
inspector << "└── operator: #{operator.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:global_variable_operator_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:global_variable_operator_write_node
end
end
# Represents the use of the `||=` operator for assignment to a global variable.
#
# $target ||= value
# ^^^^^^^^^^^^^^^^^
class GlobalVariableOrWriteNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (name: Symbol, name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
def initialize(name, name_loc, operator_loc, value, location)
@name = name
@name_loc = name_loc
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_global_variable_or_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, operator_loc, value]
end
# def copy: (**params) -> GlobalVariableOrWriteNode
def copy(**params)
GlobalVariableOrWriteNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:global_variable_or_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:global_variable_or_write_node
end
end
# Represents referencing a global variable.
#
# $foo
# ^^^^
class GlobalVariableReadNode < Node
# attr_reader name: Symbol
attr_reader :name
# def initialize: (name: Symbol, location: Location) -> void
def initialize(name, location)
@name = name
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_global_variable_read_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> GlobalVariableReadNode
def copy(**params)
GlobalVariableReadNode.new(
params.fetch(:name) { name },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── name: #{name.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:global_variable_read_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:global_variable_read_node
end
end
# Represents writing to a global variable in a context that doesn't have an explicit value.
#
# $foo, $bar = baz
# ^^^^ ^^^^
class GlobalVariableTargetNode < Node
# attr_reader name: Symbol
attr_reader :name
# def initialize: (name: Symbol, location: Location) -> void
def initialize(name, location)
@name = name
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_global_variable_target_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> GlobalVariableTargetNode
def copy(**params)
GlobalVariableTargetNode.new(
params.fetch(:name) { name },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── name: #{name.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:global_variable_target_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:global_variable_target_node
end
end
# Represents writing to a global variable.
#
# $foo = 1
# ^^^^^^^^
class GlobalVariableWriteNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader value: Node
attr_reader :value
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (name: Symbol, name_loc: Location, value: Node, operator_loc: Location, location: Location) -> void
def initialize(name, name_loc, value, operator_loc, location)
@name = name
@name_loc = name_loc
@value = value
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_global_variable_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, value, operator_loc]
end
# def copy: (**params) -> GlobalVariableWriteNode
def copy(**params)
GlobalVariableWriteNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:value) { value },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, value: value, operator_loc: operator_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── value:\n"
inspector << inspector.child_node(value, "│ ")
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:global_variable_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:global_variable_write_node
end
end
# Represents a hash literal.
#
# { a => b }
# ^^^^^^^^^^
class HashNode < Node
# attr_reader opening_loc: Location
attr_reader :opening_loc
# attr_reader elements: Array[Node]
attr_reader :elements
# attr_reader closing_loc: Location
attr_reader :closing_loc
# def initialize: (opening_loc: Location, elements: Array[Node], closing_loc: Location, location: Location) -> void
def initialize(opening_loc, elements, closing_loc, location)
@opening_loc = opening_loc
@elements = elements
@closing_loc = closing_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_hash_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[*elements]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[*elements]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[opening_loc, *elements, closing_loc]
end
# def copy: (**params) -> HashNode
def copy(**params)
HashNode.new(
params.fetch(:opening_loc) { opening_loc },
params.fetch(:elements) { elements },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ opening_loc: opening_loc, elements: elements, closing_loc: closing_loc, location: location }
end
# def opening: () -> String
def opening
opening_loc.slice
end
# def closing: () -> String
def closing
closing_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "├── elements: #{inspector.list("#{inspector.prefix}│ ", elements)}"
inspector << "└── closing_loc: #{inspector.location(closing_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:hash_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:hash_node
end
end
# Represents a hash pattern in pattern matching.
#
# foo => { a: 1, b: 2 }
# ^^^^^^^^^^^^^^
#
# foo => { a: 1, b: 2, **c }
# ^^^^^^^^^^^^^^^^^^^
class HashPatternNode < Node
# attr_reader constant: Node?
attr_reader :constant
# attr_reader elements: Array[Node]
attr_reader :elements
# attr_reader rest: Node?
attr_reader :rest
# attr_reader opening_loc: Location?
attr_reader :opening_loc
# attr_reader closing_loc: Location?
attr_reader :closing_loc
# def initialize: (constant: Node?, elements: Array[Node], rest: Node?, opening_loc: Location?, closing_loc: Location?, location: Location) -> void
def initialize(constant, elements, rest, opening_loc, closing_loc, location)
@constant = constant
@elements = elements
@rest = rest
@opening_loc = opening_loc
@closing_loc = closing_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_hash_pattern_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[constant, *elements, rest]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << constant if constant
compact.concat(elements)
compact << rest if rest
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*constant, *elements, *rest, *opening_loc, *closing_loc]
end
# def copy: (**params) -> HashPatternNode
def copy(**params)
HashPatternNode.new(
params.fetch(:constant) { constant },
params.fetch(:elements) { elements },
params.fetch(:rest) { rest },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ constant: constant, elements: elements, rest: rest, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
end
# def opening: () -> String?
def opening
opening_loc&.slice
end
# def closing: () -> String?
def closing
closing_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (constant = self.constant).nil?
inspector << "├── constant: ∅\n"
else
inspector << "├── constant:\n"
inspector << constant.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── elements: #{inspector.list("#{inspector.prefix}│ ", elements)}"
if (rest = self.rest).nil?
inspector << "├── rest: ∅\n"
else
inspector << "├── rest:\n"
inspector << rest.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "└── closing_loc: #{inspector.location(closing_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:hash_pattern_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:hash_pattern_node
end
end
# Represents the use of the `if` keyword, either in the block form or the modifier form.
#
# bar if foo
# ^^^^^^^^^^
#
# if foo then bar end
# ^^^^^^^^^^^^^^^^^^^
class IfNode < Node
# attr_reader if_keyword_loc: Location?
attr_reader :if_keyword_loc
# attr_reader predicate: Node
attr_reader :predicate
# attr_reader then_keyword_loc: Location?
attr_reader :then_keyword_loc
# attr_reader statements: StatementsNode?
attr_reader :statements
# attr_reader consequent: Node?
attr_reader :consequent
# attr_reader end_keyword_loc: Location?
attr_reader :end_keyword_loc
# def initialize: (if_keyword_loc: Location?, predicate: Node, then_keyword_loc: Location?, statements: StatementsNode?, consequent: Node?, end_keyword_loc: Location?, location: Location) -> void
def initialize(if_keyword_loc, predicate, then_keyword_loc, statements, consequent, end_keyword_loc, location)
@if_keyword_loc = if_keyword_loc
@predicate = predicate
@then_keyword_loc = then_keyword_loc
@statements = statements
@consequent = consequent
@end_keyword_loc = end_keyword_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_if_node(self)
end
def set_newline_flag(newline_marked) # :nodoc:
predicate.set_newline_flag(newline_marked)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[predicate, statements, consequent]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << predicate
compact << statements if statements
compact << consequent if consequent
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*if_keyword_loc, predicate, *then_keyword_loc, *statements, *consequent, *end_keyword_loc]
end
# def copy: (**params) -> IfNode
def copy(**params)
IfNode.new(
params.fetch(:if_keyword_loc) { if_keyword_loc },
params.fetch(:predicate) { predicate },
params.fetch(:then_keyword_loc) { then_keyword_loc },
params.fetch(:statements) { statements },
params.fetch(:consequent) { consequent },
params.fetch(:end_keyword_loc) { end_keyword_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ if_keyword_loc: if_keyword_loc, predicate: predicate, then_keyword_loc: then_keyword_loc, statements: statements, consequent: consequent, end_keyword_loc: end_keyword_loc, location: location }
end
# def if_keyword: () -> String?
def if_keyword
if_keyword_loc&.slice
end
# def then_keyword: () -> String?
def then_keyword
then_keyword_loc&.slice
end
# def end_keyword: () -> String?
def end_keyword
end_keyword_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── if_keyword_loc: #{inspector.location(if_keyword_loc)}\n"
inspector << "├── predicate:\n"
inspector << inspector.child_node(predicate, "│ ")
inspector << "├── then_keyword_loc: #{inspector.location(then_keyword_loc)}\n"
if (statements = self.statements).nil?
inspector << "├── statements: ∅\n"
else
inspector << "├── statements:\n"
inspector << statements.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
if (consequent = self.consequent).nil?
inspector << "├── consequent: ∅\n"
else
inspector << "├── consequent:\n"
inspector << consequent.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "└── end_keyword_loc: #{inspector.location(end_keyword_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:if_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:if_node
end
end
# Represents an imaginary number literal.
#
# 1.0i
# ^^^^
class ImaginaryNode < Node
# attr_reader numeric: Node
attr_reader :numeric
# def initialize: (numeric: Node, location: Location) -> void
def initialize(numeric, location)
@numeric = numeric
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_imaginary_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[numeric]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[numeric]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[numeric]
end
# def copy: (**params) -> ImaginaryNode
def copy(**params)
ImaginaryNode.new(
params.fetch(:numeric) { numeric },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ numeric: numeric, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── numeric:\n"
inspector << inspector.child_node(numeric, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:imaginary_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:imaginary_node
end
end
# Represents a node that is implicitly being added to the tree but doesn't
# correspond directly to a node in the source.
#
# { foo: }
# ^^^^
#
# { Foo: }
# ^^^^
class ImplicitNode < Node
# attr_reader value: Node
attr_reader :value
# def initialize: (value: Node, location: Location) -> void
def initialize(value, location)
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_implicit_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[value]
end
# def copy: (**params) -> ImplicitNode
def copy(**params)
ImplicitNode.new(
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ value: value, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:implicit_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:implicit_node
end
end
# Represents using a trailing comma to indicate an implicit rest parameter.
#
# foo { |bar,| }
# ^
#
# foo in [bar,]
# ^
#
# for foo, in bar do end
# ^
#
# foo, = bar
# ^
class ImplicitRestNode < Node
# def initialize: (location: Location) -> void
def initialize(location)
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_implicit_rest_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> ImplicitRestNode
def copy(**params)
ImplicitRestNode.new(
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:implicit_rest_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:implicit_rest_node
end
end
# Represents the use of the `in` keyword in a case statement.
#
# case a; in b then c end
# ^^^^^^^^^^^
class InNode < Node
# attr_reader pattern: Node
attr_reader :pattern
# attr_reader statements: StatementsNode?
attr_reader :statements
# attr_reader in_loc: Location
attr_reader :in_loc
# attr_reader then_loc: Location?
attr_reader :then_loc
# def initialize: (pattern: Node, statements: StatementsNode?, in_loc: Location, then_loc: Location?, location: Location) -> void
def initialize(pattern, statements, in_loc, then_loc, location)
@pattern = pattern
@statements = statements
@in_loc = in_loc
@then_loc = then_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_in_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[pattern, statements]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << pattern
compact << statements if statements
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[pattern, *statements, in_loc, *then_loc]
end
# def copy: (**params) -> InNode
def copy(**params)
InNode.new(
params.fetch(:pattern) { pattern },
params.fetch(:statements) { statements },
params.fetch(:in_loc) { in_loc },
params.fetch(:then_loc) { then_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ pattern: pattern, statements: statements, in_loc: in_loc, then_loc: then_loc, location: location }
end
# def in: () -> String
def in
in_loc.slice
end
# def then: () -> String?
def then
then_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── pattern:\n"
inspector << inspector.child_node(pattern, "│ ")
if (statements = self.statements).nil?
inspector << "├── statements: ∅\n"
else
inspector << "├── statements:\n"
inspector << statements.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── in_loc: #{inspector.location(in_loc)}\n"
inspector << "└── then_loc: #{inspector.location(then_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:in_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:in_node
end
end
# Represents the use of the `&&=` operator on a call to the `[]` method.
#
# foo.bar[baz] &&= value
# ^^^^^^^^^^^^^^^^^^^^^^
class IndexAndWriteNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader receiver: Node?
attr_reader :receiver
# attr_reader call_operator_loc: Location?
attr_reader :call_operator_loc
# attr_reader opening_loc: Location
attr_reader :opening_loc
# attr_reader arguments: ArgumentsNode?
attr_reader :arguments
# attr_reader closing_loc: Location
attr_reader :closing_loc
# attr_reader block: Node?
attr_reader :block
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (flags: Integer, receiver: Node?, call_operator_loc: Location?, opening_loc: Location, arguments: ArgumentsNode?, closing_loc: Location, block: Node?, operator_loc: Location, value: Node, location: Location) -> void
def initialize(flags, receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, operator_loc, value, location)
@flags = flags
@receiver = receiver
@call_operator_loc = call_operator_loc
@opening_loc = opening_loc
@arguments = arguments
@closing_loc = closing_loc
@block = block
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_index_and_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[receiver, arguments, block, value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << receiver if receiver
compact << arguments if arguments
compact << block if block
compact << value
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*receiver, *call_operator_loc, opening_loc, *arguments, closing_loc, *block, operator_loc, value]
end
# def copy: (**params) -> IndexAndWriteNode
def copy(**params)
IndexAndWriteNode.new(
params.fetch(:flags) { flags },
params.fetch(:receiver) { receiver },
params.fetch(:call_operator_loc) { call_operator_loc },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:arguments) { arguments },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:block) { block },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, receiver: receiver, call_operator_loc: call_operator_loc, opening_loc: opening_loc, arguments: arguments, closing_loc: closing_loc, block: block, operator_loc: operator_loc, value: value, location: location }
end
# def safe_navigation?: () -> bool
def safe_navigation?
flags.anybits?(CallNodeFlags::SAFE_NAVIGATION)
end
# def variable_call?: () -> bool
def variable_call?
flags.anybits?(CallNodeFlags::VARIABLE_CALL)
end
# def attribute_write?: () -> bool
def attribute_write?
flags.anybits?(CallNodeFlags::ATTRIBUTE_WRITE)
end
# def call_operator: () -> String?
def call_operator
call_operator_loc&.slice
end
# def opening: () -> String
def opening
opening_loc.slice
end
# def closing: () -> String
def closing
closing_loc.slice
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("safe_navigation" if safe_navigation?), ("variable_call" if variable_call?), ("attribute_write" if attribute_write?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
if (receiver = self.receiver).nil?
inspector << "├── receiver: ∅\n"
else
inspector << "├── receiver:\n"
inspector << receiver.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── call_operator_loc: #{inspector.location(call_operator_loc)}\n"
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
if (arguments = self.arguments).nil?
inspector << "├── arguments: ∅\n"
else
inspector << "├── arguments:\n"
inspector << arguments.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
if (block = self.block).nil?
inspector << "├── block: ∅\n"
else
inspector << "├── block:\n"
inspector << block.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:index_and_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:index_and_write_node
end
end
# Represents the use of an assignment operator on a call to `[]`.
#
# foo.bar[baz] += value
# ^^^^^^^^^^^^^^^^^^^^^
class IndexOperatorWriteNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader receiver: Node?
attr_reader :receiver
# attr_reader call_operator_loc: Location?
attr_reader :call_operator_loc
# attr_reader opening_loc: Location
attr_reader :opening_loc
# attr_reader arguments: ArgumentsNode?
attr_reader :arguments
# attr_reader closing_loc: Location
attr_reader :closing_loc
# attr_reader block: Node?
attr_reader :block
# attr_reader operator: Symbol
attr_reader :operator
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (flags: Integer, receiver: Node?, call_operator_loc: Location?, opening_loc: Location, arguments: ArgumentsNode?, closing_loc: Location, block: Node?, operator: Symbol, operator_loc: Location, value: Node, location: Location) -> void
def initialize(flags, receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, operator, operator_loc, value, location)
@flags = flags
@receiver = receiver
@call_operator_loc = call_operator_loc
@opening_loc = opening_loc
@arguments = arguments
@closing_loc = closing_loc
@block = block
@operator = operator
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_index_operator_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[receiver, arguments, block, value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << receiver if receiver
compact << arguments if arguments
compact << block if block
compact << value
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*receiver, *call_operator_loc, opening_loc, *arguments, closing_loc, *block, operator_loc, value]
end
# def copy: (**params) -> IndexOperatorWriteNode
def copy(**params)
IndexOperatorWriteNode.new(
params.fetch(:flags) { flags },
params.fetch(:receiver) { receiver },
params.fetch(:call_operator_loc) { call_operator_loc },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:arguments) { arguments },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:block) { block },
params.fetch(:operator) { operator },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, receiver: receiver, call_operator_loc: call_operator_loc, opening_loc: opening_loc, arguments: arguments, closing_loc: closing_loc, block: block, operator: operator, operator_loc: operator_loc, value: value, location: location }
end
# def safe_navigation?: () -> bool
def safe_navigation?
flags.anybits?(CallNodeFlags::SAFE_NAVIGATION)
end
# def variable_call?: () -> bool
def variable_call?
flags.anybits?(CallNodeFlags::VARIABLE_CALL)
end
# def attribute_write?: () -> bool
def attribute_write?
flags.anybits?(CallNodeFlags::ATTRIBUTE_WRITE)
end
# def call_operator: () -> String?
def call_operator
call_operator_loc&.slice
end
# def opening: () -> String
def opening
opening_loc.slice
end
# def closing: () -> String
def closing
closing_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("safe_navigation" if safe_navigation?), ("variable_call" if variable_call?), ("attribute_write" if attribute_write?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
if (receiver = self.receiver).nil?
inspector << "├── receiver: ∅\n"
else
inspector << "├── receiver:\n"
inspector << receiver.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── call_operator_loc: #{inspector.location(call_operator_loc)}\n"
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
if (arguments = self.arguments).nil?
inspector << "├── arguments: ∅\n"
else
inspector << "├── arguments:\n"
inspector << arguments.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
if (block = self.block).nil?
inspector << "├── block: ∅\n"
else
inspector << "├── block:\n"
inspector << block.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── operator: #{operator.inspect}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:index_operator_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:index_operator_write_node
end
end
# Represents the use of the `||=` operator on a call to `[]`.
#
# foo.bar[baz] ||= value
# ^^^^^^^^^^^^^^^^^^^^^^
class IndexOrWriteNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader receiver: Node?
attr_reader :receiver
# attr_reader call_operator_loc: Location?
attr_reader :call_operator_loc
# attr_reader opening_loc: Location
attr_reader :opening_loc
# attr_reader arguments: ArgumentsNode?
attr_reader :arguments
# attr_reader closing_loc: Location
attr_reader :closing_loc
# attr_reader block: Node?
attr_reader :block
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (flags: Integer, receiver: Node?, call_operator_loc: Location?, opening_loc: Location, arguments: ArgumentsNode?, closing_loc: Location, block: Node?, operator_loc: Location, value: Node, location: Location) -> void
def initialize(flags, receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, operator_loc, value, location)
@flags = flags
@receiver = receiver
@call_operator_loc = call_operator_loc
@opening_loc = opening_loc
@arguments = arguments
@closing_loc = closing_loc
@block = block
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_index_or_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[receiver, arguments, block, value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << receiver if receiver
compact << arguments if arguments
compact << block if block
compact << value
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*receiver, *call_operator_loc, opening_loc, *arguments, closing_loc, *block, operator_loc, value]
end
# def copy: (**params) -> IndexOrWriteNode
def copy(**params)
IndexOrWriteNode.new(
params.fetch(:flags) { flags },
params.fetch(:receiver) { receiver },
params.fetch(:call_operator_loc) { call_operator_loc },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:arguments) { arguments },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:block) { block },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, receiver: receiver, call_operator_loc: call_operator_loc, opening_loc: opening_loc, arguments: arguments, closing_loc: closing_loc, block: block, operator_loc: operator_loc, value: value, location: location }
end
# def safe_navigation?: () -> bool
def safe_navigation?
flags.anybits?(CallNodeFlags::SAFE_NAVIGATION)
end
# def variable_call?: () -> bool
def variable_call?
flags.anybits?(CallNodeFlags::VARIABLE_CALL)
end
# def attribute_write?: () -> bool
def attribute_write?
flags.anybits?(CallNodeFlags::ATTRIBUTE_WRITE)
end
# def call_operator: () -> String?
def call_operator
call_operator_loc&.slice
end
# def opening: () -> String
def opening
opening_loc.slice
end
# def closing: () -> String
def closing
closing_loc.slice
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("safe_navigation" if safe_navigation?), ("variable_call" if variable_call?), ("attribute_write" if attribute_write?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
if (receiver = self.receiver).nil?
inspector << "├── receiver: ∅\n"
else
inspector << "├── receiver:\n"
inspector << receiver.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── call_operator_loc: #{inspector.location(call_operator_loc)}\n"
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
if (arguments = self.arguments).nil?
inspector << "├── arguments: ∅\n"
else
inspector << "├── arguments:\n"
inspector << arguments.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
if (block = self.block).nil?
inspector << "├── block: ∅\n"
else
inspector << "├── block:\n"
inspector << block.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:index_or_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:index_or_write_node
end
end
# Represents assigning to an index.
#
# foo[bar], = 1
# ^^^^^^^^
#
# begin
# rescue => foo[bar]
# ^^^^^^^^
# end
#
# for foo[bar] in baz do end
# ^^^^^^^^
class IndexTargetNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader receiver: Node
attr_reader :receiver
# attr_reader opening_loc: Location
attr_reader :opening_loc
# attr_reader arguments: ArgumentsNode?
attr_reader :arguments
# attr_reader closing_loc: Location
attr_reader :closing_loc
# attr_reader block: Node?
attr_reader :block
# def initialize: (flags: Integer, receiver: Node, opening_loc: Location, arguments: ArgumentsNode?, closing_loc: Location, block: Node?, location: Location) -> void
def initialize(flags, receiver, opening_loc, arguments, closing_loc, block, location)
@flags = flags
@receiver = receiver
@opening_loc = opening_loc
@arguments = arguments
@closing_loc = closing_loc
@block = block
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_index_target_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[receiver, arguments, block]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << receiver
compact << arguments if arguments
compact << block if block
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[receiver, opening_loc, *arguments, closing_loc, *block]
end
# def copy: (**params) -> IndexTargetNode
def copy(**params)
IndexTargetNode.new(
params.fetch(:flags) { flags },
params.fetch(:receiver) { receiver },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:arguments) { arguments },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:block) { block },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, receiver: receiver, opening_loc: opening_loc, arguments: arguments, closing_loc: closing_loc, block: block, location: location }
end
# def safe_navigation?: () -> bool
def safe_navigation?
flags.anybits?(CallNodeFlags::SAFE_NAVIGATION)
end
# def variable_call?: () -> bool
def variable_call?
flags.anybits?(CallNodeFlags::VARIABLE_CALL)
end
# def attribute_write?: () -> bool
def attribute_write?
flags.anybits?(CallNodeFlags::ATTRIBUTE_WRITE)
end
# def opening: () -> String
def opening
opening_loc.slice
end
# def closing: () -> String
def closing
closing_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("safe_navigation" if safe_navigation?), ("variable_call" if variable_call?), ("attribute_write" if attribute_write?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
inspector << "├── receiver:\n"
inspector << inspector.child_node(receiver, "│ ")
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
if (arguments = self.arguments).nil?
inspector << "├── arguments: ∅\n"
else
inspector << "├── arguments:\n"
inspector << arguments.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
if (block = self.block).nil?
inspector << "└── block: ∅\n"
else
inspector << "└── block:\n"
inspector << block.inspect(inspector.child_inspector(" ")).delete_prefix(inspector.prefix)
end
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:index_target_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:index_target_node
end
end
# Represents the use of the `&&=` operator for assignment to an instance variable.
#
# @target &&= value
# ^^^^^^^^^^^^^^^^^
class InstanceVariableAndWriteNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (name: Symbol, name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
def initialize(name, name_loc, operator_loc, value, location)
@name = name
@name_loc = name_loc
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_instance_variable_and_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, operator_loc, value]
end
# def copy: (**params) -> InstanceVariableAndWriteNode
def copy(**params)
InstanceVariableAndWriteNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:instance_variable_and_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:instance_variable_and_write_node
end
end
# Represents assigning to an instance variable using an operator that isn't `=`.
#
# @target += value
# ^^^^^^^^^^^^^^^^
class InstanceVariableOperatorWriteNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# attr_reader operator: Symbol
attr_reader :operator
# def initialize: (name: Symbol, name_loc: Location, operator_loc: Location, value: Node, operator: Symbol, location: Location) -> void
def initialize(name, name_loc, operator_loc, value, operator, location)
@name = name
@name_loc = name_loc
@operator_loc = operator_loc
@value = value
@operator = operator
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_instance_variable_operator_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, operator_loc, value]
end
# def copy: (**params) -> InstanceVariableOperatorWriteNode
def copy(**params)
InstanceVariableOperatorWriteNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:operator) { operator },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, operator_loc: operator_loc, value: value, operator: operator, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "├── value:\n"
inspector << inspector.child_node(value, "│ ")
inspector << "└── operator: #{operator.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:instance_variable_operator_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:instance_variable_operator_write_node
end
end
# Represents the use of the `||=` operator for assignment to an instance variable.
#
# @target ||= value
# ^^^^^^^^^^^^^^^^^
class InstanceVariableOrWriteNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (name: Symbol, name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
def initialize(name, name_loc, operator_loc, value, location)
@name = name
@name_loc = name_loc
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_instance_variable_or_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, operator_loc, value]
end
# def copy: (**params) -> InstanceVariableOrWriteNode
def copy(**params)
InstanceVariableOrWriteNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:instance_variable_or_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:instance_variable_or_write_node
end
end
# Represents referencing an instance variable.
#
# @foo
# ^^^^
class InstanceVariableReadNode < Node
# attr_reader name: Symbol
attr_reader :name
# def initialize: (name: Symbol, location: Location) -> void
def initialize(name, location)
@name = name
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_instance_variable_read_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> InstanceVariableReadNode
def copy(**params)
InstanceVariableReadNode.new(
params.fetch(:name) { name },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── name: #{name.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:instance_variable_read_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:instance_variable_read_node
end
end
# Represents writing to an instance variable in a context that doesn't have an explicit value.
#
# @foo, @bar = baz
# ^^^^ ^^^^
class InstanceVariableTargetNode < Node
# attr_reader name: Symbol
attr_reader :name
# def initialize: (name: Symbol, location: Location) -> void
def initialize(name, location)
@name = name
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_instance_variable_target_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> InstanceVariableTargetNode
def copy(**params)
InstanceVariableTargetNode.new(
params.fetch(:name) { name },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── name: #{name.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:instance_variable_target_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:instance_variable_target_node
end
end
# Represents writing to an instance variable.
#
# @foo = 1
# ^^^^^^^^
class InstanceVariableWriteNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader value: Node
attr_reader :value
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (name: Symbol, name_loc: Location, value: Node, operator_loc: Location, location: Location) -> void
def initialize(name, name_loc, value, operator_loc, location)
@name = name
@name_loc = name_loc
@value = value
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_instance_variable_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, value, operator_loc]
end
# def copy: (**params) -> InstanceVariableWriteNode
def copy(**params)
InstanceVariableWriteNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:value) { value },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, value: value, operator_loc: operator_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── value:\n"
inspector << inspector.child_node(value, "│ ")
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:instance_variable_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:instance_variable_write_node
end
end
# Represents an integer number literal.
#
# 1
# ^
class IntegerNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# def initialize: (flags: Integer, location: Location) -> void
def initialize(flags, location)
@flags = flags
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_integer_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> IntegerNode
def copy(**params)
IntegerNode.new(
params.fetch(:flags) { flags },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, location: location }
end
# def binary?: () -> bool
def binary?
flags.anybits?(IntegerBaseFlags::BINARY)
end
# def decimal?: () -> bool
def decimal?
flags.anybits?(IntegerBaseFlags::DECIMAL)
end
# def octal?: () -> bool
def octal?
flags.anybits?(IntegerBaseFlags::OCTAL)
end
# def hexadecimal?: () -> bool
def hexadecimal?
flags.anybits?(IntegerBaseFlags::HEXADECIMAL)
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("binary" if binary?), ("decimal" if decimal?), ("octal" if octal?), ("hexadecimal" if hexadecimal?)].compact
inspector << "└── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:integer_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:integer_node
end
end
# Represents a regular expression literal that contains interpolation that
# is being used in the predicate of a conditional to implicitly match
# against the last line read by an IO object.
#
# if /foo #{bar} baz/ then end
# ^^^^^^^^^^^^^^^^
class InterpolatedMatchLastLineNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader opening_loc: Location
attr_reader :opening_loc
# attr_reader parts: Array[Node]
attr_reader :parts
# attr_reader closing_loc: Location
attr_reader :closing_loc
# def initialize: (flags: Integer, opening_loc: Location, parts: Array[Node], closing_loc: Location, location: Location) -> void
def initialize(flags, opening_loc, parts, closing_loc, location)
@flags = flags
@opening_loc = opening_loc
@parts = parts
@closing_loc = closing_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_interpolated_match_last_line_node(self)
end
def set_newline_flag(newline_marked) # :nodoc:
first = parts.first
first.set_newline_flag(newline_marked) if first
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[*parts]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[*parts]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[opening_loc, *parts, closing_loc]
end
# def copy: (**params) -> InterpolatedMatchLastLineNode
def copy(**params)
InterpolatedMatchLastLineNode.new(
params.fetch(:flags) { flags },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:parts) { parts },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, opening_loc: opening_loc, parts: parts, closing_loc: closing_loc, location: location }
end
# def ignore_case?: () -> bool
def ignore_case?
flags.anybits?(RegularExpressionFlags::IGNORE_CASE)
end
# def extended?: () -> bool
def extended?
flags.anybits?(RegularExpressionFlags::EXTENDED)
end
# def multi_line?: () -> bool
def multi_line?
flags.anybits?(RegularExpressionFlags::MULTI_LINE)
end
# def once?: () -> bool
def once?
flags.anybits?(RegularExpressionFlags::ONCE)
end
# def euc_jp?: () -> bool
def euc_jp?
flags.anybits?(RegularExpressionFlags::EUC_JP)
end
# def ascii_8bit?: () -> bool
def ascii_8bit?
flags.anybits?(RegularExpressionFlags::ASCII_8BIT)
end
# def windows_31j?: () -> bool
def windows_31j?
flags.anybits?(RegularExpressionFlags::WINDOWS_31J)
end
# def utf_8?: () -> bool
def utf_8?
flags.anybits?(RegularExpressionFlags::UTF_8)
end
# def forced_utf8_encoding?: () -> bool
def forced_utf8_encoding?
flags.anybits?(RegularExpressionFlags::FORCED_UTF8_ENCODING)
end
# def forced_binary_encoding?: () -> bool
def forced_binary_encoding?
flags.anybits?(RegularExpressionFlags::FORCED_BINARY_ENCODING)
end
# def forced_us_ascii_encoding?: () -> bool
def forced_us_ascii_encoding?
flags.anybits?(RegularExpressionFlags::FORCED_US_ASCII_ENCODING)
end
# def opening: () -> String
def opening
opening_loc.slice
end
# def closing: () -> String
def closing
closing_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("ignore_case" if ignore_case?), ("extended" if extended?), ("multi_line" if multi_line?), ("once" if once?), ("euc_jp" if euc_jp?), ("ascii_8bit" if ascii_8bit?), ("windows_31j" if windows_31j?), ("utf_8" if utf_8?), ("forced_utf8_encoding" if forced_utf8_encoding?), ("forced_binary_encoding" if forced_binary_encoding?), ("forced_us_ascii_encoding" if forced_us_ascii_encoding?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "├── parts: #{inspector.list("#{inspector.prefix}│ ", parts)}"
inspector << "└── closing_loc: #{inspector.location(closing_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:interpolated_match_last_line_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:interpolated_match_last_line_node
end
end
# Represents a regular expression literal that contains interpolation.
#
# /foo #{bar} baz/
# ^^^^^^^^^^^^^^^^
class InterpolatedRegularExpressionNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader opening_loc: Location
attr_reader :opening_loc
# attr_reader parts: Array[Node]
attr_reader :parts
# attr_reader closing_loc: Location
attr_reader :closing_loc
# def initialize: (flags: Integer, opening_loc: Location, parts: Array[Node], closing_loc: Location, location: Location) -> void
def initialize(flags, opening_loc, parts, closing_loc, location)
@flags = flags
@opening_loc = opening_loc
@parts = parts
@closing_loc = closing_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_interpolated_regular_expression_node(self)
end
def set_newline_flag(newline_marked) # :nodoc:
first = parts.first
first.set_newline_flag(newline_marked) if first
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[*parts]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[*parts]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[opening_loc, *parts, closing_loc]
end
# def copy: (**params) -> InterpolatedRegularExpressionNode
def copy(**params)
InterpolatedRegularExpressionNode.new(
params.fetch(:flags) { flags },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:parts) { parts },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, opening_loc: opening_loc, parts: parts, closing_loc: closing_loc, location: location }
end
# def ignore_case?: () -> bool
def ignore_case?
flags.anybits?(RegularExpressionFlags::IGNORE_CASE)
end
# def extended?: () -> bool
def extended?
flags.anybits?(RegularExpressionFlags::EXTENDED)
end
# def multi_line?: () -> bool
def multi_line?
flags.anybits?(RegularExpressionFlags::MULTI_LINE)
end
# def once?: () -> bool
def once?
flags.anybits?(RegularExpressionFlags::ONCE)
end
# def euc_jp?: () -> bool
def euc_jp?
flags.anybits?(RegularExpressionFlags::EUC_JP)
end
# def ascii_8bit?: () -> bool
def ascii_8bit?
flags.anybits?(RegularExpressionFlags::ASCII_8BIT)
end
# def windows_31j?: () -> bool
def windows_31j?
flags.anybits?(RegularExpressionFlags::WINDOWS_31J)
end
# def utf_8?: () -> bool
def utf_8?
flags.anybits?(RegularExpressionFlags::UTF_8)
end
# def forced_utf8_encoding?: () -> bool
def forced_utf8_encoding?
flags.anybits?(RegularExpressionFlags::FORCED_UTF8_ENCODING)
end
# def forced_binary_encoding?: () -> bool
def forced_binary_encoding?
flags.anybits?(RegularExpressionFlags::FORCED_BINARY_ENCODING)
end
# def forced_us_ascii_encoding?: () -> bool
def forced_us_ascii_encoding?
flags.anybits?(RegularExpressionFlags::FORCED_US_ASCII_ENCODING)
end
# def opening: () -> String
def opening
opening_loc.slice
end
# def closing: () -> String
def closing
closing_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("ignore_case" if ignore_case?), ("extended" if extended?), ("multi_line" if multi_line?), ("once" if once?), ("euc_jp" if euc_jp?), ("ascii_8bit" if ascii_8bit?), ("windows_31j" if windows_31j?), ("utf_8" if utf_8?), ("forced_utf8_encoding" if forced_utf8_encoding?), ("forced_binary_encoding" if forced_binary_encoding?), ("forced_us_ascii_encoding" if forced_us_ascii_encoding?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "├── parts: #{inspector.list("#{inspector.prefix}│ ", parts)}"
inspector << "└── closing_loc: #{inspector.location(closing_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:interpolated_regular_expression_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:interpolated_regular_expression_node
end
end
# Represents a string literal that contains interpolation.
#
# "foo #{bar} baz"
# ^^^^^^^^^^^^^^^^
class InterpolatedStringNode < Node
# attr_reader opening_loc: Location?
attr_reader :opening_loc
# attr_reader parts: Array[Node]
attr_reader :parts
# attr_reader closing_loc: Location?
attr_reader :closing_loc
# def initialize: (opening_loc: Location?, parts: Array[Node], closing_loc: Location?, location: Location) -> void
def initialize(opening_loc, parts, closing_loc, location)
@opening_loc = opening_loc
@parts = parts
@closing_loc = closing_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_interpolated_string_node(self)
end
def set_newline_flag(newline_marked) # :nodoc:
first = parts.first
first.set_newline_flag(newline_marked) if first
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[*parts]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[*parts]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*opening_loc, *parts, *closing_loc]
end
# def copy: (**params) -> InterpolatedStringNode
def copy(**params)
InterpolatedStringNode.new(
params.fetch(:opening_loc) { opening_loc },
params.fetch(:parts) { parts },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ opening_loc: opening_loc, parts: parts, closing_loc: closing_loc, location: location }
end
# def opening: () -> String?
def opening
opening_loc&.slice
end
# def closing: () -> String?
def closing
closing_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "├── parts: #{inspector.list("#{inspector.prefix}│ ", parts)}"
inspector << "└── closing_loc: #{inspector.location(closing_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:interpolated_string_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:interpolated_string_node
end
end
# Represents a symbol literal that contains interpolation.
#
# :"foo #{bar} baz"
# ^^^^^^^^^^^^^^^^^
class InterpolatedSymbolNode < Node
# attr_reader opening_loc: Location?
attr_reader :opening_loc
# attr_reader parts: Array[Node]
attr_reader :parts
# attr_reader closing_loc: Location?
attr_reader :closing_loc
# def initialize: (opening_loc: Location?, parts: Array[Node], closing_loc: Location?, location: Location) -> void
def initialize(opening_loc, parts, closing_loc, location)
@opening_loc = opening_loc
@parts = parts
@closing_loc = closing_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_interpolated_symbol_node(self)
end
def set_newline_flag(newline_marked) # :nodoc:
first = parts.first
first.set_newline_flag(newline_marked) if first
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[*parts]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[*parts]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*opening_loc, *parts, *closing_loc]
end
# def copy: (**params) -> InterpolatedSymbolNode
def copy(**params)
InterpolatedSymbolNode.new(
params.fetch(:opening_loc) { opening_loc },
params.fetch(:parts) { parts },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ opening_loc: opening_loc, parts: parts, closing_loc: closing_loc, location: location }
end
# def opening: () -> String?
def opening
opening_loc&.slice
end
# def closing: () -> String?
def closing
closing_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "├── parts: #{inspector.list("#{inspector.prefix}│ ", parts)}"
inspector << "└── closing_loc: #{inspector.location(closing_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:interpolated_symbol_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:interpolated_symbol_node
end
end
# Represents an xstring literal that contains interpolation.
#
# `foo #{bar} baz`
# ^^^^^^^^^^^^^^^^
class InterpolatedXStringNode < Node
# attr_reader opening_loc: Location
attr_reader :opening_loc
# attr_reader parts: Array[Node]
attr_reader :parts
# attr_reader closing_loc: Location
attr_reader :closing_loc
# def initialize: (opening_loc: Location, parts: Array[Node], closing_loc: Location, location: Location) -> void
def initialize(opening_loc, parts, closing_loc, location)
@opening_loc = opening_loc
@parts = parts
@closing_loc = closing_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_interpolated_x_string_node(self)
end
def set_newline_flag(newline_marked) # :nodoc:
first = parts.first
first.set_newline_flag(newline_marked) if first
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[*parts]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[*parts]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[opening_loc, *parts, closing_loc]
end
# def copy: (**params) -> InterpolatedXStringNode
def copy(**params)
InterpolatedXStringNode.new(
params.fetch(:opening_loc) { opening_loc },
params.fetch(:parts) { parts },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ opening_loc: opening_loc, parts: parts, closing_loc: closing_loc, location: location }
end
# def opening: () -> String
def opening
opening_loc.slice
end
# def closing: () -> String
def closing
closing_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "├── parts: #{inspector.list("#{inspector.prefix}│ ", parts)}"
inspector << "└── closing_loc: #{inspector.location(closing_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:interpolated_x_string_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:interpolated_x_string_node
end
end
# Represents a hash literal without opening and closing braces.
#
# foo(a: b)
# ^^^^
class KeywordHashNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader elements: Array[Node]
attr_reader :elements
# def initialize: (flags: Integer, elements: Array[Node], location: Location) -> void
def initialize(flags, elements, location)
@flags = flags
@elements = elements
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_keyword_hash_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[*elements]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[*elements]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*elements]
end
# def copy: (**params) -> KeywordHashNode
def copy(**params)
KeywordHashNode.new(
params.fetch(:flags) { flags },
params.fetch(:elements) { elements },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, elements: elements, location: location }
end
# def static_keys?: () -> bool
def static_keys?
flags.anybits?(KeywordHashNodeFlags::STATIC_KEYS)
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("static_keys" if static_keys?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
inspector << "└── elements: #{inspector.list("#{inspector.prefix} ", elements)}"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:keyword_hash_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:keyword_hash_node
end
end
# Represents a keyword rest parameter to a method, block, or lambda definition.
#
# def a(**b)
# ^^^
# end
class KeywordRestParameterNode < Node
# attr_reader name: Symbol?
attr_reader :name
# attr_reader name_loc: Location?
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (name: Symbol?, name_loc: Location?, operator_loc: Location, location: Location) -> void
def initialize(name, name_loc, operator_loc, location)
@name = name
@name_loc = name_loc
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_keyword_rest_parameter_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*name_loc, operator_loc]
end
# def copy: (**params) -> KeywordRestParameterNode
def copy(**params)
KeywordRestParameterNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, operator_loc: operator_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (name = self.name).nil?
inspector << "├── name: ∅\n"
else
inspector << "├── name: #{name.inspect}\n"
end
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:keyword_rest_parameter_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:keyword_rest_parameter_node
end
end
# Represents using a lambda literal (not the lambda method call).
#
# ->(value) { value * 2 }
# ^^^^^^^^^^^^^^^^^^^^^^^
class LambdaNode < Node
# attr_reader locals: Array[Symbol]
attr_reader :locals
# attr_reader locals_body_index: Integer
attr_reader :locals_body_index
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader opening_loc: Location
attr_reader :opening_loc
# attr_reader closing_loc: Location
attr_reader :closing_loc
# attr_reader parameters: Node?
attr_reader :parameters
# attr_reader body: Node?
attr_reader :body
# def initialize: (locals: Array[Symbol], locals_body_index: Integer, operator_loc: Location, opening_loc: Location, closing_loc: Location, parameters: Node?, body: Node?, location: Location) -> void
def initialize(locals, locals_body_index, operator_loc, opening_loc, closing_loc, parameters, body, location)
@locals = locals
@locals_body_index = locals_body_index
@operator_loc = operator_loc
@opening_loc = opening_loc
@closing_loc = closing_loc
@parameters = parameters
@body = body
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_lambda_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[parameters, body]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << parameters if parameters
compact << body if body
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[operator_loc, opening_loc, closing_loc, *parameters, *body]
end
# def copy: (**params) -> LambdaNode
def copy(**params)
LambdaNode.new(
params.fetch(:locals) { locals },
params.fetch(:locals_body_index) { locals_body_index },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:parameters) { parameters },
params.fetch(:body) { body },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ locals: locals, locals_body_index: locals_body_index, operator_loc: operator_loc, opening_loc: opening_loc, closing_loc: closing_loc, parameters: parameters, body: body, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def opening: () -> String
def opening
opening_loc.slice
end
# def closing: () -> String
def closing
closing_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── locals: #{locals.inspect}\n"
inspector << "├── locals_body_index: #{locals_body_index.inspect}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
if (parameters = self.parameters).nil?
inspector << "├── parameters: ∅\n"
else
inspector << "├── parameters:\n"
inspector << parameters.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
if (body = self.body).nil?
inspector << "└── body: ∅\n"
else
inspector << "└── body:\n"
inspector << body.inspect(inspector.child_inspector(" ")).delete_prefix(inspector.prefix)
end
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:lambda_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:lambda_node
end
end
# Represents the use of the `&&=` operator for assignment to a local variable.
#
# target &&= value
# ^^^^^^^^^^^^^^^^
class LocalVariableAndWriteNode < Node
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# attr_reader name: Symbol
attr_reader :name
# attr_reader depth: Integer
attr_reader :depth
# def initialize: (name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer, location: Location) -> void
def initialize(name_loc, operator_loc, value, name, depth, location)
@name_loc = name_loc
@operator_loc = operator_loc
@value = value
@name = name
@depth = depth
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_local_variable_and_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, operator_loc, value]
end
# def copy: (**params) -> LocalVariableAndWriteNode
def copy(**params)
LocalVariableAndWriteNode.new(
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:name) { name },
params.fetch(:depth) { depth },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name_loc: name_loc, operator_loc: operator_loc, value: value, name: name, depth: depth, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "├── value:\n"
inspector << inspector.child_node(value, "│ ")
inspector << "├── name: #{name.inspect}\n"
inspector << "└── depth: #{depth.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:local_variable_and_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:local_variable_and_write_node
end
end
# Represents assigning to a local variable using an operator that isn't `=`.
#
# target += value
# ^^^^^^^^^^^^^^^
class LocalVariableOperatorWriteNode < Node
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# attr_reader name: Symbol
attr_reader :name
# attr_reader operator: Symbol
attr_reader :operator
# attr_reader depth: Integer
attr_reader :depth
# def initialize: (name_loc: Location, operator_loc: Location, value: Node, name: Symbol, operator: Symbol, depth: Integer, location: Location) -> void
def initialize(name_loc, operator_loc, value, name, operator, depth, location)
@name_loc = name_loc
@operator_loc = operator_loc
@value = value
@name = name
@operator = operator
@depth = depth
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_local_variable_operator_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, operator_loc, value]
end
# def copy: (**params) -> LocalVariableOperatorWriteNode
def copy(**params)
LocalVariableOperatorWriteNode.new(
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:name) { name },
params.fetch(:operator) { operator },
params.fetch(:depth) { depth },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name_loc: name_loc, operator_loc: operator_loc, value: value, name: name, operator: operator, depth: depth, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "├── value:\n"
inspector << inspector.child_node(value, "│ ")
inspector << "├── name: #{name.inspect}\n"
inspector << "├── operator: #{operator.inspect}\n"
inspector << "└── depth: #{depth.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:local_variable_operator_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:local_variable_operator_write_node
end
end
# Represents the use of the `||=` operator for assignment to a local variable.
#
# target ||= value
# ^^^^^^^^^^^^^^^^
class LocalVariableOrWriteNode < Node
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# attr_reader name: Symbol
attr_reader :name
# attr_reader depth: Integer
attr_reader :depth
# def initialize: (name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer, location: Location) -> void
def initialize(name_loc, operator_loc, value, name, depth, location)
@name_loc = name_loc
@operator_loc = operator_loc
@value = value
@name = name
@depth = depth
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_local_variable_or_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, operator_loc, value]
end
# def copy: (**params) -> LocalVariableOrWriteNode
def copy(**params)
LocalVariableOrWriteNode.new(
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:name) { name },
params.fetch(:depth) { depth },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name_loc: name_loc, operator_loc: operator_loc, value: value, name: name, depth: depth, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "├── value:\n"
inspector << inspector.child_node(value, "│ ")
inspector << "├── name: #{name.inspect}\n"
inspector << "└── depth: #{depth.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:local_variable_or_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:local_variable_or_write_node
end
end
# Represents reading a local variable. Note that this requires that a local
# variable of the same name has already been written to in the same scope,
# otherwise it is parsed as a method call.
#
# foo
# ^^^
class LocalVariableReadNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader depth: Integer
attr_reader :depth
# def initialize: (name: Symbol, depth: Integer, location: Location) -> void
def initialize(name, depth, location)
@name = name
@depth = depth
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_local_variable_read_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> LocalVariableReadNode
def copy(**params)
LocalVariableReadNode.new(
params.fetch(:name) { name },
params.fetch(:depth) { depth },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, depth: depth, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "└── depth: #{depth.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:local_variable_read_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:local_variable_read_node
end
end
# Represents writing to a local variable in a context that doesn't have an explicit value.
#
# foo, bar = baz
# ^^^ ^^^
class LocalVariableTargetNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader depth: Integer
attr_reader :depth
# def initialize: (name: Symbol, depth: Integer, location: Location) -> void
def initialize(name, depth, location)
@name = name
@depth = depth
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_local_variable_target_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> LocalVariableTargetNode
def copy(**params)
LocalVariableTargetNode.new(
params.fetch(:name) { name },
params.fetch(:depth) { depth },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, depth: depth, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "└── depth: #{depth.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:local_variable_target_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:local_variable_target_node
end
end
# Represents writing to a local variable.
#
# foo = 1
# ^^^^^^^
class LocalVariableWriteNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader depth: Integer
attr_reader :depth
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader value: Node
attr_reader :value
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (name: Symbol, depth: Integer, name_loc: Location, value: Node, operator_loc: Location, location: Location) -> void
def initialize(name, depth, name_loc, value, operator_loc, location)
@name = name
@depth = depth
@name_loc = name_loc
@value = value
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_local_variable_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, value, operator_loc]
end
# def copy: (**params) -> LocalVariableWriteNode
def copy(**params)
LocalVariableWriteNode.new(
params.fetch(:name) { name },
params.fetch(:depth) { depth },
params.fetch(:name_loc) { name_loc },
params.fetch(:value) { value },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, depth: depth, name_loc: name_loc, value: value, operator_loc: operator_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── depth: #{depth.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── value:\n"
inspector << inspector.child_node(value, "│ ")
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:local_variable_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:local_variable_write_node
end
end
# Represents a regular expression literal used in the predicate of a
# conditional to implicitly match against the last line read by an IO
# object.
#
# if /foo/i then end
# ^^^^^^
class MatchLastLineNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader opening_loc: Location
attr_reader :opening_loc
# attr_reader content_loc: Location
attr_reader :content_loc
# attr_reader closing_loc: Location
attr_reader :closing_loc
# attr_reader unescaped: String
attr_reader :unescaped
# def initialize: (flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String, location: Location) -> void
def initialize(flags, opening_loc, content_loc, closing_loc, unescaped, location)
@flags = flags
@opening_loc = opening_loc
@content_loc = content_loc
@closing_loc = closing_loc
@unescaped = unescaped
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_match_last_line_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[opening_loc, content_loc, closing_loc]
end
# def copy: (**params) -> MatchLastLineNode
def copy(**params)
MatchLastLineNode.new(
params.fetch(:flags) { flags },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:content_loc) { content_loc },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:unescaped) { unescaped },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, opening_loc: opening_loc, content_loc: content_loc, closing_loc: closing_loc, unescaped: unescaped, location: location }
end
# def ignore_case?: () -> bool
def ignore_case?
flags.anybits?(RegularExpressionFlags::IGNORE_CASE)
end
# def extended?: () -> bool
def extended?
flags.anybits?(RegularExpressionFlags::EXTENDED)
end
# def multi_line?: () -> bool
def multi_line?
flags.anybits?(RegularExpressionFlags::MULTI_LINE)
end
# def once?: () -> bool
def once?
flags.anybits?(RegularExpressionFlags::ONCE)
end
# def euc_jp?: () -> bool
def euc_jp?
flags.anybits?(RegularExpressionFlags::EUC_JP)
end
# def ascii_8bit?: () -> bool
def ascii_8bit?
flags.anybits?(RegularExpressionFlags::ASCII_8BIT)
end
# def windows_31j?: () -> bool
def windows_31j?
flags.anybits?(RegularExpressionFlags::WINDOWS_31J)
end
# def utf_8?: () -> bool
def utf_8?
flags.anybits?(RegularExpressionFlags::UTF_8)
end
# def forced_utf8_encoding?: () -> bool
def forced_utf8_encoding?
flags.anybits?(RegularExpressionFlags::FORCED_UTF8_ENCODING)
end
# def forced_binary_encoding?: () -> bool
def forced_binary_encoding?
flags.anybits?(RegularExpressionFlags::FORCED_BINARY_ENCODING)
end
# def forced_us_ascii_encoding?: () -> bool
def forced_us_ascii_encoding?
flags.anybits?(RegularExpressionFlags::FORCED_US_ASCII_ENCODING)
end
# def opening: () -> String
def opening
opening_loc.slice
end
# def content: () -> String
def content
content_loc.slice
end
# def closing: () -> String
def closing
closing_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("ignore_case" if ignore_case?), ("extended" if extended?), ("multi_line" if multi_line?), ("once" if once?), ("euc_jp" if euc_jp?), ("ascii_8bit" if ascii_8bit?), ("windows_31j" if windows_31j?), ("utf_8" if utf_8?), ("forced_utf8_encoding" if forced_utf8_encoding?), ("forced_binary_encoding" if forced_binary_encoding?), ("forced_us_ascii_encoding" if forced_us_ascii_encoding?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "├── content_loc: #{inspector.location(content_loc)}\n"
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
inspector << "└── unescaped: #{unescaped.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:match_last_line_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:match_last_line_node
end
end
# Represents the use of the modifier `in` operator.
#
# foo in bar
# ^^^^^^^^^^
class MatchPredicateNode < Node
# attr_reader value: Node
attr_reader :value
# attr_reader pattern: Node
attr_reader :pattern
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (value: Node, pattern: Node, operator_loc: Location, location: Location) -> void
def initialize(value, pattern, operator_loc, location)
@value = value
@pattern = pattern
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_match_predicate_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value, pattern]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value, pattern]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[value, pattern, operator_loc]
end
# def copy: (**params) -> MatchPredicateNode
def copy(**params)
MatchPredicateNode.new(
params.fetch(:value) { value },
params.fetch(:pattern) { pattern },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ value: value, pattern: pattern, operator_loc: operator_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── value:\n"
inspector << inspector.child_node(value, "│ ")
inspector << "├── pattern:\n"
inspector << inspector.child_node(pattern, "│ ")
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:match_predicate_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:match_predicate_node
end
end
# Represents the use of the `=>` operator.
#
# foo => bar
# ^^^^^^^^^^
class MatchRequiredNode < Node
# attr_reader value: Node
attr_reader :value
# attr_reader pattern: Node
attr_reader :pattern
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (value: Node, pattern: Node, operator_loc: Location, location: Location) -> void
def initialize(value, pattern, operator_loc, location)
@value = value
@pattern = pattern
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_match_required_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value, pattern]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value, pattern]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[value, pattern, operator_loc]
end
# def copy: (**params) -> MatchRequiredNode
def copy(**params)
MatchRequiredNode.new(
params.fetch(:value) { value },
params.fetch(:pattern) { pattern },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ value: value, pattern: pattern, operator_loc: operator_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── value:\n"
inspector << inspector.child_node(value, "│ ")
inspector << "├── pattern:\n"
inspector << inspector.child_node(pattern, "│ ")
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:match_required_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:match_required_node
end
end
# Represents writing local variables using a regular expression match with
# named capture groups.
#
# /(?<foo>bar)/ =~ baz
# ^^^^^^^^^^^^^^^^^^^^
class MatchWriteNode < Node
# attr_reader call: CallNode
attr_reader :call
# attr_reader targets: Array[Node]
attr_reader :targets
# def initialize: (call: CallNode, targets: Array[Node], location: Location) -> void
def initialize(call, targets, location)
@call = call
@targets = targets
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_match_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[call, *targets]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[call, *targets]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[call, *targets]
end
# def copy: (**params) -> MatchWriteNode
def copy(**params)
MatchWriteNode.new(
params.fetch(:call) { call },
params.fetch(:targets) { targets },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ call: call, targets: targets, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── call:\n"
inspector << inspector.child_node(call, "│ ")
inspector << "└── targets: #{inspector.list("#{inspector.prefix} ", targets)}"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:match_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:match_write_node
end
end
# Represents a node that is missing from the source and results in a syntax
# error.
class MissingNode < Node
# def initialize: (location: Location) -> void
def initialize(location)
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_missing_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> MissingNode
def copy(**params)
MissingNode.new(
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:missing_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:missing_node
end
end
# Represents a module declaration involving the `module` keyword.
#
# module Foo end
# ^^^^^^^^^^^^^^
class ModuleNode < Node
# attr_reader locals: Array[Symbol]
attr_reader :locals
# attr_reader module_keyword_loc: Location
attr_reader :module_keyword_loc
# attr_reader constant_path: Node
attr_reader :constant_path
# attr_reader body: Node?
attr_reader :body
# attr_reader end_keyword_loc: Location
attr_reader :end_keyword_loc
# attr_reader name: Symbol
attr_reader :name
# def initialize: (locals: Array[Symbol], module_keyword_loc: Location, constant_path: Node, body: Node?, end_keyword_loc: Location, name: Symbol, location: Location) -> void
def initialize(locals, module_keyword_loc, constant_path, body, end_keyword_loc, name, location)
@locals = locals
@module_keyword_loc = module_keyword_loc
@constant_path = constant_path
@body = body
@end_keyword_loc = end_keyword_loc
@name = name
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_module_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[constant_path, body]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << constant_path
compact << body if body
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[module_keyword_loc, constant_path, *body, end_keyword_loc]
end
# def copy: (**params) -> ModuleNode
def copy(**params)
ModuleNode.new(
params.fetch(:locals) { locals },
params.fetch(:module_keyword_loc) { module_keyword_loc },
params.fetch(:constant_path) { constant_path },
params.fetch(:body) { body },
params.fetch(:end_keyword_loc) { end_keyword_loc },
params.fetch(:name) { name },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ locals: locals, module_keyword_loc: module_keyword_loc, constant_path: constant_path, body: body, end_keyword_loc: end_keyword_loc, name: name, location: location }
end
# def module_keyword: () -> String
def module_keyword
module_keyword_loc.slice
end
# def end_keyword: () -> String
def end_keyword
end_keyword_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── locals: #{locals.inspect}\n"
inspector << "├── module_keyword_loc: #{inspector.location(module_keyword_loc)}\n"
inspector << "├── constant_path:\n"
inspector << inspector.child_node(constant_path, "│ ")
if (body = self.body).nil?
inspector << "├── body: ∅\n"
else
inspector << "├── body:\n"
inspector << body.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── end_keyword_loc: #{inspector.location(end_keyword_loc)}\n"
inspector << "└── name: #{name.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:module_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:module_node
end
end
# Represents a multi-target expression.
#
# a, (b, c) = 1, 2, 3
# ^^^^^^
class MultiTargetNode < Node
# attr_reader lefts: Array[Node]
attr_reader :lefts
# attr_reader rest: Node?
attr_reader :rest
# attr_reader rights: Array[Node]
attr_reader :rights
# attr_reader lparen_loc: Location?
attr_reader :lparen_loc
# attr_reader rparen_loc: Location?
attr_reader :rparen_loc
# def initialize: (lefts: Array[Node], rest: Node?, rights: Array[Node], lparen_loc: Location?, rparen_loc: Location?, location: Location) -> void
def initialize(lefts, rest, rights, lparen_loc, rparen_loc, location)
@lefts = lefts
@rest = rest
@rights = rights
@lparen_loc = lparen_loc
@rparen_loc = rparen_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_multi_target_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[*lefts, rest, *rights]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact.concat(lefts)
compact << rest if rest
compact.concat(rights)
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*lefts, *rest, *rights, *lparen_loc, *rparen_loc]
end
# def copy: (**params) -> MultiTargetNode
def copy(**params)
MultiTargetNode.new(
params.fetch(:lefts) { lefts },
params.fetch(:rest) { rest },
params.fetch(:rights) { rights },
params.fetch(:lparen_loc) { lparen_loc },
params.fetch(:rparen_loc) { rparen_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ lefts: lefts, rest: rest, rights: rights, lparen_loc: lparen_loc, rparen_loc: rparen_loc, location: location }
end
# def lparen: () -> String?
def lparen
lparen_loc&.slice
end
# def rparen: () -> String?
def rparen
rparen_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── lefts: #{inspector.list("#{inspector.prefix}│ ", lefts)}"
if (rest = self.rest).nil?
inspector << "├── rest: ∅\n"
else
inspector << "├── rest:\n"
inspector << rest.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── rights: #{inspector.list("#{inspector.prefix}│ ", rights)}"
inspector << "├── lparen_loc: #{inspector.location(lparen_loc)}\n"
inspector << "└── rparen_loc: #{inspector.location(rparen_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:multi_target_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:multi_target_node
end
end
# Represents a write to a multi-target expression.
#
# a, b, c = 1, 2, 3
# ^^^^^^^^^^^^^^^^^
class MultiWriteNode < Node
# attr_reader lefts: Array[Node]
attr_reader :lefts
# attr_reader rest: Node?
attr_reader :rest
# attr_reader rights: Array[Node]
attr_reader :rights
# attr_reader lparen_loc: Location?
attr_reader :lparen_loc
# attr_reader rparen_loc: Location?
attr_reader :rparen_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (lefts: Array[Node], rest: Node?, rights: Array[Node], lparen_loc: Location?, rparen_loc: Location?, operator_loc: Location, value: Node, location: Location) -> void
def initialize(lefts, rest, rights, lparen_loc, rparen_loc, operator_loc, value, location)
@lefts = lefts
@rest = rest
@rights = rights
@lparen_loc = lparen_loc
@rparen_loc = rparen_loc
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_multi_write_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[*lefts, rest, *rights, value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact.concat(lefts)
compact << rest if rest
compact.concat(rights)
compact << value
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*lefts, *rest, *rights, *lparen_loc, *rparen_loc, operator_loc, value]
end
# def copy: (**params) -> MultiWriteNode
def copy(**params)
MultiWriteNode.new(
params.fetch(:lefts) { lefts },
params.fetch(:rest) { rest },
params.fetch(:rights) { rights },
params.fetch(:lparen_loc) { lparen_loc },
params.fetch(:rparen_loc) { rparen_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ lefts: lefts, rest: rest, rights: rights, lparen_loc: lparen_loc, rparen_loc: rparen_loc, operator_loc: operator_loc, value: value, location: location }
end
# def lparen: () -> String?
def lparen
lparen_loc&.slice
end
# def rparen: () -> String?
def rparen
rparen_loc&.slice
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── lefts: #{inspector.list("#{inspector.prefix}│ ", lefts)}"
if (rest = self.rest).nil?
inspector << "├── rest: ∅\n"
else
inspector << "├── rest:\n"
inspector << rest.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── rights: #{inspector.list("#{inspector.prefix}│ ", rights)}"
inspector << "├── lparen_loc: #{inspector.location(lparen_loc)}\n"
inspector << "├── rparen_loc: #{inspector.location(rparen_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:multi_write_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:multi_write_node
end
end
# Represents the use of the `next` keyword.
#
# next 1
# ^^^^^^
class NextNode < Node
# attr_reader arguments: ArgumentsNode?
attr_reader :arguments
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# def initialize: (arguments: ArgumentsNode?, keyword_loc: Location, location: Location) -> void
def initialize(arguments, keyword_loc, location)
@arguments = arguments
@keyword_loc = keyword_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_next_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[arguments]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << arguments if arguments
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*arguments, keyword_loc]
end
# def copy: (**params) -> NextNode
def copy(**params)
NextNode.new(
params.fetch(:arguments) { arguments },
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ arguments: arguments, keyword_loc: keyword_loc, location: location }
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (arguments = self.arguments).nil?
inspector << "├── arguments: ∅\n"
else
inspector << "├── arguments:\n"
inspector << arguments.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "└── keyword_loc: #{inspector.location(keyword_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:next_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:next_node
end
end
# Represents the use of the `nil` keyword.
#
# nil
# ^^^
class NilNode < Node
# def initialize: (location: Location) -> void
def initialize(location)
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_nil_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> NilNode
def copy(**params)
NilNode.new(
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:nil_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:nil_node
end
end
# Represents the use of `**nil` inside method arguments.
#
# def a(**nil)
# ^^^^^
# end
class NoKeywordsParameterNode < Node
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# def initialize: (operator_loc: Location, keyword_loc: Location, location: Location) -> void
def initialize(operator_loc, keyword_loc, location)
@operator_loc = operator_loc
@keyword_loc = keyword_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_no_keywords_parameter_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[operator_loc, keyword_loc]
end
# def copy: (**params) -> NoKeywordsParameterNode
def copy(**params)
NoKeywordsParameterNode.new(
params.fetch(:operator_loc) { operator_loc },
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ operator_loc: operator_loc, keyword_loc: keyword_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── keyword_loc: #{inspector.location(keyword_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:no_keywords_parameter_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:no_keywords_parameter_node
end
end
# Represents an implicit set of parameters through the use of numbered
# parameters within a block or lambda.
#
# -> { _1 + _2 }
# ^^^^^^^^^^^^^^
class NumberedParametersNode < Node
# attr_reader maximum: Integer
attr_reader :maximum
# def initialize: (maximum: Integer, location: Location) -> void
def initialize(maximum, location)
@maximum = maximum
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_numbered_parameters_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> NumberedParametersNode
def copy(**params)
NumberedParametersNode.new(
params.fetch(:maximum) { maximum },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ maximum: maximum, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── maximum: #{maximum.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:numbered_parameters_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:numbered_parameters_node
end
end
# Represents reading a numbered reference to a capture in the previous match.
#
# $1
# ^^
class NumberedReferenceReadNode < Node
# attr_reader number: Integer
attr_reader :number
# def initialize: (number: Integer, location: Location) -> void
def initialize(number, location)
@number = number
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_numbered_reference_read_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> NumberedReferenceReadNode
def copy(**params)
NumberedReferenceReadNode.new(
params.fetch(:number) { number },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ number: number, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── number: #{number.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:numbered_reference_read_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:numbered_reference_read_node
end
end
# Represents an optional keyword parameter to a method, block, or lambda definition.
#
# def a(b: 1)
# ^^^^
# end
class OptionalKeywordParameterNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (name: Symbol, name_loc: Location, value: Node, location: Location) -> void
def initialize(name, name_loc, value, location)
@name = name
@name_loc = name_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_optional_keyword_parameter_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, value]
end
# def copy: (**params) -> OptionalKeywordParameterNode
def copy(**params)
OptionalKeywordParameterNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, value: value, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:optional_keyword_parameter_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:optional_keyword_parameter_node
end
end
# Represents an optional parameter to a method, block, or lambda definition.
#
# def a(b = 1)
# ^^^^^
# end
class OptionalParameterNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader value: Node
attr_reader :value
# def initialize: (name: Symbol, name_loc: Location, operator_loc: Location, value: Node, location: Location) -> void
def initialize(name, name_loc, operator_loc, value, location)
@name = name
@name_loc = name_loc
@operator_loc = operator_loc
@value = value
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_optional_parameter_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[value]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[value]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc, operator_loc, value]
end
# def copy: (**params) -> OptionalParameterNode
def copy(**params)
OptionalParameterNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:value) { value },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, operator_loc: operator_loc, value: value, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "└── value:\n"
inspector << inspector.child_node(value, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:optional_parameter_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:optional_parameter_node
end
end
# Represents the use of the `||` operator or the `or` keyword.
#
# left or right
# ^^^^^^^^^^^^^
class OrNode < Node
# attr_reader left: Node
attr_reader :left
# attr_reader right: Node
attr_reader :right
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (left: Node, right: Node, operator_loc: Location, location: Location) -> void
def initialize(left, right, operator_loc, location)
@left = left
@right = right
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_or_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[left, right]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[left, right]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[left, right, operator_loc]
end
# def copy: (**params) -> OrNode
def copy(**params)
OrNode.new(
params.fetch(:left) { left },
params.fetch(:right) { right },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ left: left, right: right, operator_loc: operator_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── left:\n"
inspector << inspector.child_node(left, "│ ")
inspector << "├── right:\n"
inspector << inspector.child_node(right, "│ ")
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:or_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:or_node
end
end
# Represents the list of parameters on a method, block, or lambda definition.
#
# def a(b, c, d)
# ^^^^^^^
# end
class ParametersNode < Node
# attr_reader requireds: Array[Node]
attr_reader :requireds
# attr_reader optionals: Array[Node]
attr_reader :optionals
# attr_reader rest: Node?
attr_reader :rest
# attr_reader posts: Array[Node]
attr_reader :posts
# attr_reader keywords: Array[Node]
attr_reader :keywords
# attr_reader keyword_rest: Node?
attr_reader :keyword_rest
# attr_reader block: BlockParameterNode?
attr_reader :block
# def initialize: (requireds: Array[Node], optionals: Array[Node], rest: Node?, posts: Array[Node], keywords: Array[Node], keyword_rest: Node?, block: BlockParameterNode?, location: Location) -> void
def initialize(requireds, optionals, rest, posts, keywords, keyword_rest, block, location)
@requireds = requireds
@optionals = optionals
@rest = rest
@posts = posts
@keywords = keywords
@keyword_rest = keyword_rest
@block = block
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_parameters_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[*requireds, *optionals, rest, *posts, *keywords, keyword_rest, block]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact.concat(requireds)
compact.concat(optionals)
compact << rest if rest
compact.concat(posts)
compact.concat(keywords)
compact << keyword_rest if keyword_rest
compact << block if block
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*requireds, *optionals, *rest, *posts, *keywords, *keyword_rest, *block]
end
# def copy: (**params) -> ParametersNode
def copy(**params)
ParametersNode.new(
params.fetch(:requireds) { requireds },
params.fetch(:optionals) { optionals },
params.fetch(:rest) { rest },
params.fetch(:posts) { posts },
params.fetch(:keywords) { keywords },
params.fetch(:keyword_rest) { keyword_rest },
params.fetch(:block) { block },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ requireds: requireds, optionals: optionals, rest: rest, posts: posts, keywords: keywords, keyword_rest: keyword_rest, block: block, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── requireds: #{inspector.list("#{inspector.prefix}│ ", requireds)}"
inspector << "├── optionals: #{inspector.list("#{inspector.prefix}│ ", optionals)}"
if (rest = self.rest).nil?
inspector << "├── rest: ∅\n"
else
inspector << "├── rest:\n"
inspector << rest.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── posts: #{inspector.list("#{inspector.prefix}│ ", posts)}"
inspector << "├── keywords: #{inspector.list("#{inspector.prefix}│ ", keywords)}"
if (keyword_rest = self.keyword_rest).nil?
inspector << "├── keyword_rest: ∅\n"
else
inspector << "├── keyword_rest:\n"
inspector << keyword_rest.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
if (block = self.block).nil?
inspector << "└── block: ∅\n"
else
inspector << "└── block:\n"
inspector << block.inspect(inspector.child_inspector(" ")).delete_prefix(inspector.prefix)
end
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:parameters_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:parameters_node
end
end
# Represents a parenthesized expression
#
# (10 + 34)
# ^^^^^^^^^
class ParenthesesNode < Node
# attr_reader body: Node?
attr_reader :body
# attr_reader opening_loc: Location
attr_reader :opening_loc
# attr_reader closing_loc: Location
attr_reader :closing_loc
# def initialize: (body: Node?, opening_loc: Location, closing_loc: Location, location: Location) -> void
def initialize(body, opening_loc, closing_loc, location)
@body = body
@opening_loc = opening_loc
@closing_loc = closing_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_parentheses_node(self)
end
def set_newline_flag(newline_marked) # :nodoc:
# Never mark ParenthesesNode with a newline flag, mark children instead
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[body]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << body if body
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*body, opening_loc, closing_loc]
end
# def copy: (**params) -> ParenthesesNode
def copy(**params)
ParenthesesNode.new(
params.fetch(:body) { body },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ body: body, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
end
# def opening: () -> String
def opening
opening_loc.slice
end
# def closing: () -> String
def closing
closing_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (body = self.body).nil?
inspector << "├── body: ∅\n"
else
inspector << "├── body:\n"
inspector << body.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "└── closing_loc: #{inspector.location(closing_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:parentheses_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:parentheses_node
end
end
# Represents the use of the `^` operator for pinning an expression in a
# pattern matching expression.
#
# foo in ^(bar)
# ^^^^^^
class PinnedExpressionNode < Node
# attr_reader expression: Node
attr_reader :expression
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader lparen_loc: Location
attr_reader :lparen_loc
# attr_reader rparen_loc: Location
attr_reader :rparen_loc
# def initialize: (expression: Node, operator_loc: Location, lparen_loc: Location, rparen_loc: Location, location: Location) -> void
def initialize(expression, operator_loc, lparen_loc, rparen_loc, location)
@expression = expression
@operator_loc = operator_loc
@lparen_loc = lparen_loc
@rparen_loc = rparen_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_pinned_expression_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[expression]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[expression]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[expression, operator_loc, lparen_loc, rparen_loc]
end
# def copy: (**params) -> PinnedExpressionNode
def copy(**params)
PinnedExpressionNode.new(
params.fetch(:expression) { expression },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:lparen_loc) { lparen_loc },
params.fetch(:rparen_loc) { rparen_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ expression: expression, operator_loc: operator_loc, lparen_loc: lparen_loc, rparen_loc: rparen_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def lparen: () -> String
def lparen
lparen_loc.slice
end
# def rparen: () -> String
def rparen
rparen_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── expression:\n"
inspector << inspector.child_node(expression, "│ ")
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "├── lparen_loc: #{inspector.location(lparen_loc)}\n"
inspector << "└── rparen_loc: #{inspector.location(rparen_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:pinned_expression_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:pinned_expression_node
end
end
# Represents the use of the `^` operator for pinning a variable in a pattern
# matching expression.
#
# foo in ^bar
# ^^^^
class PinnedVariableNode < Node
# attr_reader variable: Node
attr_reader :variable
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (variable: Node, operator_loc: Location, location: Location) -> void
def initialize(variable, operator_loc, location)
@variable = variable
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_pinned_variable_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[variable]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[variable]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[variable, operator_loc]
end
# def copy: (**params) -> PinnedVariableNode
def copy(**params)
PinnedVariableNode.new(
params.fetch(:variable) { variable },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ variable: variable, operator_loc: operator_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── variable:\n"
inspector << inspector.child_node(variable, "│ ")
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:pinned_variable_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:pinned_variable_node
end
end
# Represents the use of the `END` keyword.
#
# END { foo }
# ^^^^^^^^^^^
class PostExecutionNode < Node
# attr_reader statements: StatementsNode?
attr_reader :statements
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# attr_reader opening_loc: Location
attr_reader :opening_loc
# attr_reader closing_loc: Location
attr_reader :closing_loc
# def initialize: (statements: StatementsNode?, keyword_loc: Location, opening_loc: Location, closing_loc: Location, location: Location) -> void
def initialize(statements, keyword_loc, opening_loc, closing_loc, location)
@statements = statements
@keyword_loc = keyword_loc
@opening_loc = opening_loc
@closing_loc = closing_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_post_execution_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[statements]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << statements if statements
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*statements, keyword_loc, opening_loc, closing_loc]
end
# def copy: (**params) -> PostExecutionNode
def copy(**params)
PostExecutionNode.new(
params.fetch(:statements) { statements },
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ statements: statements, keyword_loc: keyword_loc, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def opening: () -> String
def opening
opening_loc.slice
end
# def closing: () -> String
def closing
closing_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (statements = self.statements).nil?
inspector << "├── statements: ∅\n"
else
inspector << "├── statements:\n"
inspector << statements.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── keyword_loc: #{inspector.location(keyword_loc)}\n"
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "└── closing_loc: #{inspector.location(closing_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:post_execution_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:post_execution_node
end
end
# Represents the use of the `BEGIN` keyword.
#
# BEGIN { foo }
# ^^^^^^^^^^^^^
class PreExecutionNode < Node
# attr_reader statements: StatementsNode?
attr_reader :statements
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# attr_reader opening_loc: Location
attr_reader :opening_loc
# attr_reader closing_loc: Location
attr_reader :closing_loc
# def initialize: (statements: StatementsNode?, keyword_loc: Location, opening_loc: Location, closing_loc: Location, location: Location) -> void
def initialize(statements, keyword_loc, opening_loc, closing_loc, location)
@statements = statements
@keyword_loc = keyword_loc
@opening_loc = opening_loc
@closing_loc = closing_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_pre_execution_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[statements]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << statements if statements
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*statements, keyword_loc, opening_loc, closing_loc]
end
# def copy: (**params) -> PreExecutionNode
def copy(**params)
PreExecutionNode.new(
params.fetch(:statements) { statements },
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ statements: statements, keyword_loc: keyword_loc, opening_loc: opening_loc, closing_loc: closing_loc, location: location }
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def opening: () -> String
def opening
opening_loc.slice
end
# def closing: () -> String
def closing
closing_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (statements = self.statements).nil?
inspector << "├── statements: ∅\n"
else
inspector << "├── statements:\n"
inspector << statements.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── keyword_loc: #{inspector.location(keyword_loc)}\n"
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "└── closing_loc: #{inspector.location(closing_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:pre_execution_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:pre_execution_node
end
end
# The top level node of any parse tree.
class ProgramNode < Node
# attr_reader locals: Array[Symbol]
attr_reader :locals
# attr_reader statements: StatementsNode
attr_reader :statements
# def initialize: (locals: Array[Symbol], statements: StatementsNode, location: Location) -> void
def initialize(locals, statements, location)
@locals = locals
@statements = statements
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_program_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[statements]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[statements]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[statements]
end
# def copy: (**params) -> ProgramNode
def copy(**params)
ProgramNode.new(
params.fetch(:locals) { locals },
params.fetch(:statements) { statements },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ locals: locals, statements: statements, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── locals: #{locals.inspect}\n"
inspector << "└── statements:\n"
inspector << inspector.child_node(statements, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:program_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:program_node
end
end
# Represents the use of the `..` or `...` operators.
#
# 1..2
# ^^^^
#
# c if a =~ /left/ ... b =~ /right/
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
class RangeNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader left: Node?
attr_reader :left
# attr_reader right: Node?
attr_reader :right
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (flags: Integer, left: Node?, right: Node?, operator_loc: Location, location: Location) -> void
def initialize(flags, left, right, operator_loc, location)
@flags = flags
@left = left
@right = right
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_range_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[left, right]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << left if left
compact << right if right
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*left, *right, operator_loc]
end
# def copy: (**params) -> RangeNode
def copy(**params)
RangeNode.new(
params.fetch(:flags) { flags },
params.fetch(:left) { left },
params.fetch(:right) { right },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, left: left, right: right, operator_loc: operator_loc, location: location }
end
# def exclude_end?: () -> bool
def exclude_end?
flags.anybits?(RangeFlags::EXCLUDE_END)
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("exclude_end" if exclude_end?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
if (left = self.left).nil?
inspector << "├── left: ∅\n"
else
inspector << "├── left:\n"
inspector << left.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
if (right = self.right).nil?
inspector << "├── right: ∅\n"
else
inspector << "├── right:\n"
inspector << right.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:range_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:range_node
end
end
# Represents a rational number literal.
#
# 1.0r
# ^^^^
class RationalNode < Node
# attr_reader numeric: Node
attr_reader :numeric
# def initialize: (numeric: Node, location: Location) -> void
def initialize(numeric, location)
@numeric = numeric
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_rational_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[numeric]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[numeric]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[numeric]
end
# def copy: (**params) -> RationalNode
def copy(**params)
RationalNode.new(
params.fetch(:numeric) { numeric },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ numeric: numeric, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── numeric:\n"
inspector << inspector.child_node(numeric, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:rational_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:rational_node
end
end
# Represents the use of the `redo` keyword.
#
# redo
# ^^^^
class RedoNode < Node
# def initialize: (location: Location) -> void
def initialize(location)
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_redo_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> RedoNode
def copy(**params)
RedoNode.new(
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:redo_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:redo_node
end
end
# Represents a regular expression literal with no interpolation.
#
# /foo/i
# ^^^^^^
class RegularExpressionNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader opening_loc: Location
attr_reader :opening_loc
# attr_reader content_loc: Location
attr_reader :content_loc
# attr_reader closing_loc: Location
attr_reader :closing_loc
# attr_reader unescaped: String
attr_reader :unescaped
# def initialize: (flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String, location: Location) -> void
def initialize(flags, opening_loc, content_loc, closing_loc, unescaped, location)
@flags = flags
@opening_loc = opening_loc
@content_loc = content_loc
@closing_loc = closing_loc
@unescaped = unescaped
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_regular_expression_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[opening_loc, content_loc, closing_loc]
end
# def copy: (**params) -> RegularExpressionNode
def copy(**params)
RegularExpressionNode.new(
params.fetch(:flags) { flags },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:content_loc) { content_loc },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:unescaped) { unescaped },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, opening_loc: opening_loc, content_loc: content_loc, closing_loc: closing_loc, unescaped: unescaped, location: location }
end
# def ignore_case?: () -> bool
def ignore_case?
flags.anybits?(RegularExpressionFlags::IGNORE_CASE)
end
# def extended?: () -> bool
def extended?
flags.anybits?(RegularExpressionFlags::EXTENDED)
end
# def multi_line?: () -> bool
def multi_line?
flags.anybits?(RegularExpressionFlags::MULTI_LINE)
end
# def once?: () -> bool
def once?
flags.anybits?(RegularExpressionFlags::ONCE)
end
# def euc_jp?: () -> bool
def euc_jp?
flags.anybits?(RegularExpressionFlags::EUC_JP)
end
# def ascii_8bit?: () -> bool
def ascii_8bit?
flags.anybits?(RegularExpressionFlags::ASCII_8BIT)
end
# def windows_31j?: () -> bool
def windows_31j?
flags.anybits?(RegularExpressionFlags::WINDOWS_31J)
end
# def utf_8?: () -> bool
def utf_8?
flags.anybits?(RegularExpressionFlags::UTF_8)
end
# def forced_utf8_encoding?: () -> bool
def forced_utf8_encoding?
flags.anybits?(RegularExpressionFlags::FORCED_UTF8_ENCODING)
end
# def forced_binary_encoding?: () -> bool
def forced_binary_encoding?
flags.anybits?(RegularExpressionFlags::FORCED_BINARY_ENCODING)
end
# def forced_us_ascii_encoding?: () -> bool
def forced_us_ascii_encoding?
flags.anybits?(RegularExpressionFlags::FORCED_US_ASCII_ENCODING)
end
# def opening: () -> String
def opening
opening_loc.slice
end
# def content: () -> String
def content
content_loc.slice
end
# def closing: () -> String
def closing
closing_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("ignore_case" if ignore_case?), ("extended" if extended?), ("multi_line" if multi_line?), ("once" if once?), ("euc_jp" if euc_jp?), ("ascii_8bit" if ascii_8bit?), ("windows_31j" if windows_31j?), ("utf_8" if utf_8?), ("forced_utf8_encoding" if forced_utf8_encoding?), ("forced_binary_encoding" if forced_binary_encoding?), ("forced_us_ascii_encoding" if forced_us_ascii_encoding?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "├── content_loc: #{inspector.location(content_loc)}\n"
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
inspector << "└── unescaped: #{unescaped.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:regular_expression_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:regular_expression_node
end
end
# Represents a required keyword parameter to a method, block, or lambda definition.
#
# def a(b: )
# ^^
# end
class RequiredKeywordParameterNode < Node
# attr_reader name: Symbol
attr_reader :name
# attr_reader name_loc: Location
attr_reader :name_loc
# def initialize: (name: Symbol, name_loc: Location, location: Location) -> void
def initialize(name, name_loc, location)
@name = name
@name_loc = name_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_required_keyword_parameter_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[name_loc]
end
# def copy: (**params) -> RequiredKeywordParameterNode
def copy(**params)
RequiredKeywordParameterNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── name: #{name.inspect}\n"
inspector << "└── name_loc: #{inspector.location(name_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:required_keyword_parameter_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:required_keyword_parameter_node
end
end
# Represents a required parameter to a method, block, or lambda definition.
#
# def a(b)
# ^
# end
class RequiredParameterNode < Node
# attr_reader name: Symbol
attr_reader :name
# def initialize: (name: Symbol, location: Location) -> void
def initialize(name, location)
@name = name
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_required_parameter_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> RequiredParameterNode
def copy(**params)
RequiredParameterNode.new(
params.fetch(:name) { name },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── name: #{name.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:required_parameter_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:required_parameter_node
end
end
# Represents an expression modified with a rescue.
#
# foo rescue nil
# ^^^^^^^^^^^^^^
class RescueModifierNode < Node
# attr_reader expression: Node
attr_reader :expression
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# attr_reader rescue_expression: Node
attr_reader :rescue_expression
# def initialize: (expression: Node, keyword_loc: Location, rescue_expression: Node, location: Location) -> void
def initialize(expression, keyword_loc, rescue_expression, location)
@expression = expression
@keyword_loc = keyword_loc
@rescue_expression = rescue_expression
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_rescue_modifier_node(self)
end
def set_newline_flag(newline_marked) # :nodoc:
expression.set_newline_flag(newline_marked)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[expression, rescue_expression]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[expression, rescue_expression]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[expression, keyword_loc, rescue_expression]
end
# def copy: (**params) -> RescueModifierNode
def copy(**params)
RescueModifierNode.new(
params.fetch(:expression) { expression },
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:rescue_expression) { rescue_expression },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ expression: expression, keyword_loc: keyword_loc, rescue_expression: rescue_expression, location: location }
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── expression:\n"
inspector << inspector.child_node(expression, "│ ")
inspector << "├── keyword_loc: #{inspector.location(keyword_loc)}\n"
inspector << "└── rescue_expression:\n"
inspector << inspector.child_node(rescue_expression, " ")
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:rescue_modifier_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:rescue_modifier_node
end
end
# Represents a rescue statement.
#
# begin
# rescue Foo, *splat, Bar => ex
# foo
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# end
#
# `Foo, *splat, Bar` are in the `exceptions` field.
# `ex` is in the `exception` field.
class RescueNode < Node
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# attr_reader exceptions: Array[Node]
attr_reader :exceptions
# attr_reader operator_loc: Location?
attr_reader :operator_loc
# attr_reader reference: Node?
attr_reader :reference
# attr_reader statements: StatementsNode?
attr_reader :statements
# attr_reader consequent: RescueNode?
attr_reader :consequent
# def initialize: (keyword_loc: Location, exceptions: Array[Node], operator_loc: Location?, reference: Node?, statements: StatementsNode?, consequent: RescueNode?, location: Location) -> void
def initialize(keyword_loc, exceptions, operator_loc, reference, statements, consequent, location)
@keyword_loc = keyword_loc
@exceptions = exceptions
@operator_loc = operator_loc
@reference = reference
@statements = statements
@consequent = consequent
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_rescue_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[*exceptions, reference, statements, consequent]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact.concat(exceptions)
compact << reference if reference
compact << statements if statements
compact << consequent if consequent
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[keyword_loc, *exceptions, *operator_loc, *reference, *statements, *consequent]
end
# def copy: (**params) -> RescueNode
def copy(**params)
RescueNode.new(
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:exceptions) { exceptions },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:reference) { reference },
params.fetch(:statements) { statements },
params.fetch(:consequent) { consequent },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ keyword_loc: keyword_loc, exceptions: exceptions, operator_loc: operator_loc, reference: reference, statements: statements, consequent: consequent, location: location }
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def operator: () -> String?
def operator
operator_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── keyword_loc: #{inspector.location(keyword_loc)}\n"
inspector << "├── exceptions: #{inspector.list("#{inspector.prefix}│ ", exceptions)}"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
if (reference = self.reference).nil?
inspector << "├── reference: ∅\n"
else
inspector << "├── reference:\n"
inspector << reference.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
if (statements = self.statements).nil?
inspector << "├── statements: ∅\n"
else
inspector << "├── statements:\n"
inspector << statements.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
if (consequent = self.consequent).nil?
inspector << "└── consequent: ∅\n"
else
inspector << "└── consequent:\n"
inspector << consequent.inspect(inspector.child_inspector(" ")).delete_prefix(inspector.prefix)
end
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:rescue_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:rescue_node
end
end
# Represents a rest parameter to a method, block, or lambda definition.
#
# def a(*b)
# ^^
# end
class RestParameterNode < Node
# attr_reader name: Symbol?
attr_reader :name
# attr_reader name_loc: Location?
attr_reader :name_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# def initialize: (name: Symbol?, name_loc: Location?, operator_loc: Location, location: Location) -> void
def initialize(name, name_loc, operator_loc, location)
@name = name
@name_loc = name_loc
@operator_loc = operator_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_rest_parameter_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*name_loc, operator_loc]
end
# def copy: (**params) -> RestParameterNode
def copy(**params)
RestParameterNode.new(
params.fetch(:name) { name },
params.fetch(:name_loc) { name_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ name: name, name_loc: name_loc, operator_loc: operator_loc, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
if (name = self.name).nil?
inspector << "├── name: ∅\n"
else
inspector << "├── name: #{name.inspect}\n"
end
inspector << "├── name_loc: #{inspector.location(name_loc)}\n"
inspector << "└── operator_loc: #{inspector.location(operator_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:rest_parameter_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:rest_parameter_node
end
end
# Represents the use of the `retry` keyword.
#
# retry
# ^^^^^
class RetryNode < Node
# def initialize: (location: Location) -> void
def initialize(location)
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_retry_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> RetryNode
def copy(**params)
RetryNode.new(
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:retry_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:retry_node
end
end
# Represents the use of the `return` keyword.
#
# return 1
# ^^^^^^^^
class ReturnNode < Node
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# attr_reader arguments: ArgumentsNode?
attr_reader :arguments
# def initialize: (keyword_loc: Location, arguments: ArgumentsNode?, location: Location) -> void
def initialize(keyword_loc, arguments, location)
@keyword_loc = keyword_loc
@arguments = arguments
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_return_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[arguments]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << arguments if arguments
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[keyword_loc, *arguments]
end
# def copy: (**params) -> ReturnNode
def copy(**params)
ReturnNode.new(
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:arguments) { arguments },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ keyword_loc: keyword_loc, arguments: arguments, location: location }
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── keyword_loc: #{inspector.location(keyword_loc)}\n"
if (arguments = self.arguments).nil?
inspector << "└── arguments: ∅\n"
else
inspector << "└── arguments:\n"
inspector << arguments.inspect(inspector.child_inspector(" ")).delete_prefix(inspector.prefix)
end
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:return_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:return_node
end
end
# Represents the `self` keyword.
#
# self
# ^^^^
class SelfNode < Node
# def initialize: (location: Location) -> void
def initialize(location)
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_self_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> SelfNode
def copy(**params)
SelfNode.new(
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:self_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:self_node
end
end
# Represents a singleton class declaration involving the `class` keyword.
#
# class << self end
# ^^^^^^^^^^^^^^^^^
class SingletonClassNode < Node
# attr_reader locals: Array[Symbol]
attr_reader :locals
# attr_reader class_keyword_loc: Location
attr_reader :class_keyword_loc
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader expression: Node
attr_reader :expression
# attr_reader body: Node?
attr_reader :body
# attr_reader end_keyword_loc: Location
attr_reader :end_keyword_loc
# def initialize: (locals: Array[Symbol], class_keyword_loc: Location, operator_loc: Location, expression: Node, body: Node?, end_keyword_loc: Location, location: Location) -> void
def initialize(locals, class_keyword_loc, operator_loc, expression, body, end_keyword_loc, location)
@locals = locals
@class_keyword_loc = class_keyword_loc
@operator_loc = operator_loc
@expression = expression
@body = body
@end_keyword_loc = end_keyword_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_singleton_class_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[expression, body]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << expression
compact << body if body
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[class_keyword_loc, operator_loc, expression, *body, end_keyword_loc]
end
# def copy: (**params) -> SingletonClassNode
def copy(**params)
SingletonClassNode.new(
params.fetch(:locals) { locals },
params.fetch(:class_keyword_loc) { class_keyword_loc },
params.fetch(:operator_loc) { operator_loc },
params.fetch(:expression) { expression },
params.fetch(:body) { body },
params.fetch(:end_keyword_loc) { end_keyword_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ locals: locals, class_keyword_loc: class_keyword_loc, operator_loc: operator_loc, expression: expression, body: body, end_keyword_loc: end_keyword_loc, location: location }
end
# def class_keyword: () -> String
def class_keyword
class_keyword_loc.slice
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def end_keyword: () -> String
def end_keyword
end_keyword_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── locals: #{locals.inspect}\n"
inspector << "├── class_keyword_loc: #{inspector.location(class_keyword_loc)}\n"
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
inspector << "├── expression:\n"
inspector << inspector.child_node(expression, "│ ")
if (body = self.body).nil?
inspector << "├── body: ∅\n"
else
inspector << "├── body:\n"
inspector << body.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "└── end_keyword_loc: #{inspector.location(end_keyword_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:singleton_class_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:singleton_class_node
end
end
# Represents the use of the `__ENCODING__` keyword.
#
# __ENCODING__
# ^^^^^^^^^^^^
class SourceEncodingNode < Node
# def initialize: (location: Location) -> void
def initialize(location)
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_source_encoding_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> SourceEncodingNode
def copy(**params)
SourceEncodingNode.new(
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:source_encoding_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:source_encoding_node
end
end
# Represents the use of the `__FILE__` keyword.
#
# __FILE__
# ^^^^^^^^
class SourceFileNode < Node
# attr_reader filepath: String
attr_reader :filepath
# def initialize: (filepath: String, location: Location) -> void
def initialize(filepath, location)
@filepath = filepath
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_source_file_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> SourceFileNode
def copy(**params)
SourceFileNode.new(
params.fetch(:filepath) { filepath },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ filepath: filepath, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── filepath: #{filepath.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:source_file_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:source_file_node
end
end
# Represents the use of the `__LINE__` keyword.
#
# __LINE__
# ^^^^^^^^
class SourceLineNode < Node
# def initialize: (location: Location) -> void
def initialize(location)
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_source_line_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> SourceLineNode
def copy(**params)
SourceLineNode.new(
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:source_line_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:source_line_node
end
end
# Represents the use of the splat operator.
#
# [*a]
# ^^
class SplatNode < Node
# attr_reader operator_loc: Location
attr_reader :operator_loc
# attr_reader expression: Node?
attr_reader :expression
# def initialize: (operator_loc: Location, expression: Node?, location: Location) -> void
def initialize(operator_loc, expression, location)
@operator_loc = operator_loc
@expression = expression
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_splat_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[expression]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << expression if expression
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[operator_loc, *expression]
end
# def copy: (**params) -> SplatNode
def copy(**params)
SplatNode.new(
params.fetch(:operator_loc) { operator_loc },
params.fetch(:expression) { expression },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ operator_loc: operator_loc, expression: expression, location: location }
end
# def operator: () -> String
def operator
operator_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── operator_loc: #{inspector.location(operator_loc)}\n"
if (expression = self.expression).nil?
inspector << "└── expression: ∅\n"
else
inspector << "└── expression:\n"
inspector << expression.inspect(inspector.child_inspector(" ")).delete_prefix(inspector.prefix)
end
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:splat_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:splat_node
end
end
# Represents a set of statements contained within some scope.
#
# foo; bar; baz
# ^^^^^^^^^^^^^
class StatementsNode < Node
# attr_reader body: Array[Node]
attr_reader :body
# def initialize: (body: Array[Node], location: Location) -> void
def initialize(body, location)
@body = body
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_statements_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[*body]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[*body]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*body]
end
# def copy: (**params) -> StatementsNode
def copy(**params)
StatementsNode.new(
params.fetch(:body) { body },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ body: body, location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "└── body: #{inspector.list("#{inspector.prefix} ", body)}"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:statements_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:statements_node
end
end
# Represents a string literal, a string contained within a `%w` list, or
# plain string content within an interpolated string.
#
# "foo"
# ^^^^^
#
# %w[foo]
# ^^^
#
# "foo #{bar} baz"
# ^^^^ ^^^^
class StringNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader opening_loc: Location?
attr_reader :opening_loc
# attr_reader content_loc: Location
attr_reader :content_loc
# attr_reader closing_loc: Location?
attr_reader :closing_loc
# attr_reader unescaped: String
attr_reader :unescaped
# def initialize: (flags: Integer, opening_loc: Location?, content_loc: Location, closing_loc: Location?, unescaped: String, location: Location) -> void
def initialize(flags, opening_loc, content_loc, closing_loc, unescaped, location)
@flags = flags
@opening_loc = opening_loc
@content_loc = content_loc
@closing_loc = closing_loc
@unescaped = unescaped
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_string_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*opening_loc, content_loc, *closing_loc]
end
# def copy: (**params) -> StringNode
def copy(**params)
StringNode.new(
params.fetch(:flags) { flags },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:content_loc) { content_loc },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:unescaped) { unescaped },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, opening_loc: opening_loc, content_loc: content_loc, closing_loc: closing_loc, unescaped: unescaped, location: location }
end
# def forced_utf8_encoding?: () -> bool
def forced_utf8_encoding?
flags.anybits?(StringFlags::FORCED_UTF8_ENCODING)
end
# def forced_binary_encoding?: () -> bool
def forced_binary_encoding?
flags.anybits?(StringFlags::FORCED_BINARY_ENCODING)
end
# def frozen?: () -> bool
def frozen?
flags.anybits?(StringFlags::FROZEN)
end
# def opening: () -> String?
def opening
opening_loc&.slice
end
# def content: () -> String
def content
content_loc.slice
end
# def closing: () -> String?
def closing
closing_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("forced_utf8_encoding" if forced_utf8_encoding?), ("forced_binary_encoding" if forced_binary_encoding?), ("frozen" if frozen?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "├── content_loc: #{inspector.location(content_loc)}\n"
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
inspector << "└── unescaped: #{unescaped.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:string_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:string_node
end
end
# Represents the use of the `super` keyword with parentheses or arguments.
#
# super()
# ^^^^^^^
#
# super foo, bar
# ^^^^^^^^^^^^^^
class SuperNode < Node
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# attr_reader lparen_loc: Location?
attr_reader :lparen_loc
# attr_reader arguments: ArgumentsNode?
attr_reader :arguments
# attr_reader rparen_loc: Location?
attr_reader :rparen_loc
# attr_reader block: Node?
attr_reader :block
# def initialize: (keyword_loc: Location, lparen_loc: Location?, arguments: ArgumentsNode?, rparen_loc: Location?, block: Node?, location: Location) -> void
def initialize(keyword_loc, lparen_loc, arguments, rparen_loc, block, location)
@keyword_loc = keyword_loc
@lparen_loc = lparen_loc
@arguments = arguments
@rparen_loc = rparen_loc
@block = block
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_super_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[arguments, block]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << arguments if arguments
compact << block if block
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[keyword_loc, *lparen_loc, *arguments, *rparen_loc, *block]
end
# def copy: (**params) -> SuperNode
def copy(**params)
SuperNode.new(
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:lparen_loc) { lparen_loc },
params.fetch(:arguments) { arguments },
params.fetch(:rparen_loc) { rparen_loc },
params.fetch(:block) { block },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ keyword_loc: keyword_loc, lparen_loc: lparen_loc, arguments: arguments, rparen_loc: rparen_loc, block: block, location: location }
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def lparen: () -> String?
def lparen
lparen_loc&.slice
end
# def rparen: () -> String?
def rparen
rparen_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── keyword_loc: #{inspector.location(keyword_loc)}\n"
inspector << "├── lparen_loc: #{inspector.location(lparen_loc)}\n"
if (arguments = self.arguments).nil?
inspector << "├── arguments: ∅\n"
else
inspector << "├── arguments:\n"
inspector << arguments.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "├── rparen_loc: #{inspector.location(rparen_loc)}\n"
if (block = self.block).nil?
inspector << "└── block: ∅\n"
else
inspector << "└── block:\n"
inspector << block.inspect(inspector.child_inspector(" ")).delete_prefix(inspector.prefix)
end
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:super_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:super_node
end
end
# Represents a symbol literal or a symbol contained within a `%i` list.
#
# :foo
# ^^^^
#
# %i[foo]
# ^^^
class SymbolNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader opening_loc: Location?
attr_reader :opening_loc
# attr_reader value_loc: Location?
attr_reader :value_loc
# attr_reader closing_loc: Location?
attr_reader :closing_loc
# attr_reader unescaped: String
attr_reader :unescaped
# def initialize: (flags: Integer, opening_loc: Location?, value_loc: Location?, closing_loc: Location?, unescaped: String, location: Location) -> void
def initialize(flags, opening_loc, value_loc, closing_loc, unescaped, location)
@flags = flags
@opening_loc = opening_loc
@value_loc = value_loc
@closing_loc = closing_loc
@unescaped = unescaped
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_symbol_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*opening_loc, *value_loc, *closing_loc]
end
# def copy: (**params) -> SymbolNode
def copy(**params)
SymbolNode.new(
params.fetch(:flags) { flags },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:value_loc) { value_loc },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:unescaped) { unescaped },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, opening_loc: opening_loc, value_loc: value_loc, closing_loc: closing_loc, unescaped: unescaped, location: location }
end
# def forced_utf8_encoding?: () -> bool
def forced_utf8_encoding?
flags.anybits?(SymbolFlags::FORCED_UTF8_ENCODING)
end
# def forced_binary_encoding?: () -> bool
def forced_binary_encoding?
flags.anybits?(SymbolFlags::FORCED_BINARY_ENCODING)
end
# def forced_us_ascii_encoding?: () -> bool
def forced_us_ascii_encoding?
flags.anybits?(SymbolFlags::FORCED_US_ASCII_ENCODING)
end
# def opening: () -> String?
def opening
opening_loc&.slice
end
# def value: () -> String?
def value
value_loc&.slice
end
# def closing: () -> String?
def closing
closing_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("forced_utf8_encoding" if forced_utf8_encoding?), ("forced_binary_encoding" if forced_binary_encoding?), ("forced_us_ascii_encoding" if forced_us_ascii_encoding?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "├── value_loc: #{inspector.location(value_loc)}\n"
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
inspector << "└── unescaped: #{unescaped.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:symbol_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:symbol_node
end
end
# Represents the use of the literal `true` keyword.
#
# true
# ^^^^
class TrueNode < Node
# def initialize: (location: Location) -> void
def initialize(location)
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_true_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[]
end
# def copy: (**params) -> TrueNode
def copy(**params)
TrueNode.new(
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ location: location }
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:true_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:true_node
end
end
# Represents the use of the `undef` keyword.
#
# undef :foo, :bar, :baz
# ^^^^^^^^^^^^^^^^^^^^^^
class UndefNode < Node
# attr_reader names: Array[Node]
attr_reader :names
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# def initialize: (names: Array[Node], keyword_loc: Location, location: Location) -> void
def initialize(names, keyword_loc, location)
@names = names
@keyword_loc = keyword_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_undef_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[*names]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[*names]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[*names, keyword_loc]
end
# def copy: (**params) -> UndefNode
def copy(**params)
UndefNode.new(
params.fetch(:names) { names },
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ names: names, keyword_loc: keyword_loc, location: location }
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── names: #{inspector.list("#{inspector.prefix}│ ", names)}"
inspector << "└── keyword_loc: #{inspector.location(keyword_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:undef_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:undef_node
end
end
# Represents the use of the `unless` keyword, either in the block form or the modifier form.
#
# bar unless foo
# ^^^^^^^^^^^^^^
#
# unless foo then bar end
# ^^^^^^^^^^^^^^^^^^^^^^^
class UnlessNode < Node
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# attr_reader predicate: Node
attr_reader :predicate
# attr_reader then_keyword_loc: Location?
attr_reader :then_keyword_loc
# attr_reader statements: StatementsNode?
attr_reader :statements
# attr_reader consequent: ElseNode?
attr_reader :consequent
# attr_reader end_keyword_loc: Location?
attr_reader :end_keyword_loc
# def initialize: (keyword_loc: Location, predicate: Node, then_keyword_loc: Location?, statements: StatementsNode?, consequent: ElseNode?, end_keyword_loc: Location?, location: Location) -> void
def initialize(keyword_loc, predicate, then_keyword_loc, statements, consequent, end_keyword_loc, location)
@keyword_loc = keyword_loc
@predicate = predicate
@then_keyword_loc = then_keyword_loc
@statements = statements
@consequent = consequent
@end_keyword_loc = end_keyword_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_unless_node(self)
end
def set_newline_flag(newline_marked) # :nodoc:
predicate.set_newline_flag(newline_marked)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[predicate, statements, consequent]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << predicate
compact << statements if statements
compact << consequent if consequent
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[keyword_loc, predicate, *then_keyword_loc, *statements, *consequent, *end_keyword_loc]
end
# def copy: (**params) -> UnlessNode
def copy(**params)
UnlessNode.new(
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:predicate) { predicate },
params.fetch(:then_keyword_loc) { then_keyword_loc },
params.fetch(:statements) { statements },
params.fetch(:consequent) { consequent },
params.fetch(:end_keyword_loc) { end_keyword_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ keyword_loc: keyword_loc, predicate: predicate, then_keyword_loc: then_keyword_loc, statements: statements, consequent: consequent, end_keyword_loc: end_keyword_loc, location: location }
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def then_keyword: () -> String?
def then_keyword
then_keyword_loc&.slice
end
# def end_keyword: () -> String?
def end_keyword
end_keyword_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── keyword_loc: #{inspector.location(keyword_loc)}\n"
inspector << "├── predicate:\n"
inspector << inspector.child_node(predicate, "│ ")
inspector << "├── then_keyword_loc: #{inspector.location(then_keyword_loc)}\n"
if (statements = self.statements).nil?
inspector << "├── statements: ∅\n"
else
inspector << "├── statements:\n"
inspector << statements.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
if (consequent = self.consequent).nil?
inspector << "├── consequent: ∅\n"
else
inspector << "├── consequent:\n"
inspector << consequent.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "└── end_keyword_loc: #{inspector.location(end_keyword_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:unless_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:unless_node
end
end
# Represents the use of the `until` keyword, either in the block form or the modifier form.
#
# bar until foo
# ^^^^^^^^^^^^^
#
# until foo do bar end
# ^^^^^^^^^^^^^^^^^^^^
class UntilNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# attr_reader closing_loc: Location?
attr_reader :closing_loc
# attr_reader predicate: Node
attr_reader :predicate
# attr_reader statements: StatementsNode?
attr_reader :statements
# def initialize: (flags: Integer, keyword_loc: Location, closing_loc: Location?, predicate: Node, statements: StatementsNode?, location: Location) -> void
def initialize(flags, keyword_loc, closing_loc, predicate, statements, location)
@flags = flags
@keyword_loc = keyword_loc
@closing_loc = closing_loc
@predicate = predicate
@statements = statements
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_until_node(self)
end
def set_newline_flag(newline_marked) # :nodoc:
predicate.set_newline_flag(newline_marked)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[predicate, statements]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << predicate
compact << statements if statements
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[keyword_loc, *closing_loc, predicate, *statements]
end
# def copy: (**params) -> UntilNode
def copy(**params)
UntilNode.new(
params.fetch(:flags) { flags },
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:predicate) { predicate },
params.fetch(:statements) { statements },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, keyword_loc: keyword_loc, closing_loc: closing_loc, predicate: predicate, statements: statements, location: location }
end
# def begin_modifier?: () -> bool
def begin_modifier?
flags.anybits?(LoopFlags::BEGIN_MODIFIER)
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def closing: () -> String?
def closing
closing_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("begin_modifier" if begin_modifier?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
inspector << "├── keyword_loc: #{inspector.location(keyword_loc)}\n"
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
inspector << "├── predicate:\n"
inspector << inspector.child_node(predicate, "│ ")
if (statements = self.statements).nil?
inspector << "└── statements: ∅\n"
else
inspector << "└── statements:\n"
inspector << statements.inspect(inspector.child_inspector(" ")).delete_prefix(inspector.prefix)
end
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:until_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:until_node
end
end
# Represents the use of the `when` keyword within a case statement.
#
# case true
# when true
# ^^^^^^^^^
# end
class WhenNode < Node
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# attr_reader conditions: Array[Node]
attr_reader :conditions
# attr_reader statements: StatementsNode?
attr_reader :statements
# def initialize: (keyword_loc: Location, conditions: Array[Node], statements: StatementsNode?, location: Location) -> void
def initialize(keyword_loc, conditions, statements, location)
@keyword_loc = keyword_loc
@conditions = conditions
@statements = statements
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_when_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[*conditions, statements]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact.concat(conditions)
compact << statements if statements
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[keyword_loc, *conditions, *statements]
end
# def copy: (**params) -> WhenNode
def copy(**params)
WhenNode.new(
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:conditions) { conditions },
params.fetch(:statements) { statements },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ keyword_loc: keyword_loc, conditions: conditions, statements: statements, location: location }
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── keyword_loc: #{inspector.location(keyword_loc)}\n"
inspector << "├── conditions: #{inspector.list("#{inspector.prefix}│ ", conditions)}"
if (statements = self.statements).nil?
inspector << "└── statements: ∅\n"
else
inspector << "└── statements:\n"
inspector << statements.inspect(inspector.child_inspector(" ")).delete_prefix(inspector.prefix)
end
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:when_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:when_node
end
end
# Represents the use of the `while` keyword, either in the block form or the modifier form.
#
# bar while foo
# ^^^^^^^^^^^^^
#
# while foo do bar end
# ^^^^^^^^^^^^^^^^^^^^
class WhileNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# attr_reader closing_loc: Location?
attr_reader :closing_loc
# attr_reader predicate: Node
attr_reader :predicate
# attr_reader statements: StatementsNode?
attr_reader :statements
# def initialize: (flags: Integer, keyword_loc: Location, closing_loc: Location?, predicate: Node, statements: StatementsNode?, location: Location) -> void
def initialize(flags, keyword_loc, closing_loc, predicate, statements, location)
@flags = flags
@keyword_loc = keyword_loc
@closing_loc = closing_loc
@predicate = predicate
@statements = statements
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_while_node(self)
end
def set_newline_flag(newline_marked) # :nodoc:
predicate.set_newline_flag(newline_marked)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[predicate, statements]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << predicate
compact << statements if statements
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[keyword_loc, *closing_loc, predicate, *statements]
end
# def copy: (**params) -> WhileNode
def copy(**params)
WhileNode.new(
params.fetch(:flags) { flags },
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:predicate) { predicate },
params.fetch(:statements) { statements },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, keyword_loc: keyword_loc, closing_loc: closing_loc, predicate: predicate, statements: statements, location: location }
end
# def begin_modifier?: () -> bool
def begin_modifier?
flags.anybits?(LoopFlags::BEGIN_MODIFIER)
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def closing: () -> String?
def closing
closing_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("begin_modifier" if begin_modifier?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
inspector << "├── keyword_loc: #{inspector.location(keyword_loc)}\n"
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
inspector << "├── predicate:\n"
inspector << inspector.child_node(predicate, "│ ")
if (statements = self.statements).nil?
inspector << "└── statements: ∅\n"
else
inspector << "└── statements:\n"
inspector << statements.inspect(inspector.child_inspector(" ")).delete_prefix(inspector.prefix)
end
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:while_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:while_node
end
end
# Represents an xstring literal with no interpolation.
#
# `foo`
# ^^^^^
class XStringNode < Node
# attr_reader flags: Integer
private attr_reader :flags
# attr_reader opening_loc: Location
attr_reader :opening_loc
# attr_reader content_loc: Location
attr_reader :content_loc
# attr_reader closing_loc: Location
attr_reader :closing_loc
# attr_reader unescaped: String
attr_reader :unescaped
# def initialize: (flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String, location: Location) -> void
def initialize(flags, opening_loc, content_loc, closing_loc, unescaped, location)
@flags = flags
@opening_loc = opening_loc
@content_loc = content_loc
@closing_loc = closing_loc
@unescaped = unescaped
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_x_string_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
[]
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[opening_loc, content_loc, closing_loc]
end
# def copy: (**params) -> XStringNode
def copy(**params)
XStringNode.new(
params.fetch(:flags) { flags },
params.fetch(:opening_loc) { opening_loc },
params.fetch(:content_loc) { content_loc },
params.fetch(:closing_loc) { closing_loc },
params.fetch(:unescaped) { unescaped },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ flags: flags, opening_loc: opening_loc, content_loc: content_loc, closing_loc: closing_loc, unescaped: unescaped, location: location }
end
# def forced_utf8_encoding?: () -> bool
def forced_utf8_encoding?
flags.anybits?(EncodingFlags::FORCED_UTF8_ENCODING)
end
# def forced_binary_encoding?: () -> bool
def forced_binary_encoding?
flags.anybits?(EncodingFlags::FORCED_BINARY_ENCODING)
end
# def opening: () -> String
def opening
opening_loc.slice
end
# def content: () -> String
def content
content_loc.slice
end
# def closing: () -> String
def closing
closing_loc.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
flags = [("forced_utf8_encoding" if forced_utf8_encoding?), ("forced_binary_encoding" if forced_binary_encoding?)].compact
inspector << "├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n"
inspector << "├── opening_loc: #{inspector.location(opening_loc)}\n"
inspector << "├── content_loc: #{inspector.location(content_loc)}\n"
inspector << "├── closing_loc: #{inspector.location(closing_loc)}\n"
inspector << "└── unescaped: #{unescaped.inspect}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:x_string_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:x_string_node
end
end
# Represents the use of the `yield` keyword.
#
# yield 1
# ^^^^^^^
class YieldNode < Node
# attr_reader keyword_loc: Location
attr_reader :keyword_loc
# attr_reader lparen_loc: Location?
attr_reader :lparen_loc
# attr_reader arguments: ArgumentsNode?
attr_reader :arguments
# attr_reader rparen_loc: Location?
attr_reader :rparen_loc
# def initialize: (keyword_loc: Location, lparen_loc: Location?, arguments: ArgumentsNode?, rparen_loc: Location?, location: Location) -> void
def initialize(keyword_loc, lparen_loc, arguments, rparen_loc, location)
@keyword_loc = keyword_loc
@lparen_loc = lparen_loc
@arguments = arguments
@rparen_loc = rparen_loc
@location = location
end
# def accept: (visitor: Visitor) -> void
def accept(visitor)
visitor.visit_yield_node(self)
end
# def child_nodes: () -> Array[nil | Node]
def child_nodes
[arguments]
end
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
compact = []
compact << arguments if arguments
compact
end
# def comment_targets: () -> Array[Node | Location]
def comment_targets
[keyword_loc, *lparen_loc, *arguments, *rparen_loc]
end
# def copy: (**params) -> YieldNode
def copy(**params)
YieldNode.new(
params.fetch(:keyword_loc) { keyword_loc },
params.fetch(:lparen_loc) { lparen_loc },
params.fetch(:arguments) { arguments },
params.fetch(:rparen_loc) { rparen_loc },
params.fetch(:location) { location },
)
end
# def deconstruct: () -> Array[nil | Node]
alias deconstruct child_nodes
# def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location]
def deconstruct_keys(keys)
{ keyword_loc: keyword_loc, lparen_loc: lparen_loc, arguments: arguments, rparen_loc: rparen_loc, location: location }
end
# def keyword: () -> String
def keyword
keyword_loc.slice
end
# def lparen: () -> String?
def lparen
lparen_loc&.slice
end
# def rparen: () -> String?
def rparen
rparen_loc&.slice
end
# def inspect(inspector: NodeInspector) -> String
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
inspector << "├── keyword_loc: #{inspector.location(keyword_loc)}\n"
inspector << "├── lparen_loc: #{inspector.location(lparen_loc)}\n"
if (arguments = self.arguments).nil?
inspector << "├── arguments: ∅\n"
else
inspector << "├── arguments:\n"
inspector << arguments.inspect(inspector.child_inspector("│ ")).delete_prefix(inspector.prefix)
end
inspector << "└── rparen_loc: #{inspector.location(rparen_loc)}\n"
inspector.to_str
end
# Sometimes you want to check an instance of a node against a list of
# classes to see what kind of behavior to perform. Usually this is done by
# calling `[cls1, cls2].include?(node.class)` or putting the node into a
# case statement and doing `case node; when cls1; when cls2; end`. Both of
# these approaches are relatively slow because of the constant lookups,
# method calls, and/or array allocations.
#
# Instead, you can call #type, which will return to you a symbol that you
# can use for comparison. This is faster than the other approaches because
# it uses a single integer comparison, but also because if you're on CRuby
# you can take advantage of the fact that case statements with all symbol
# keys will use a jump table.
#
# def type: () -> Symbol
def type
:yield_node
end
# Similar to #type, this method returns a symbol that you can use for
# splitting on the type of the node without having to do a long === chain.
# Note that like #type, it will still be slower than using == for a single
# class, but should be faster in a case statement or an array comparison.
#
# def self.type: () -> Symbol
def self.type
:yield_node
end
end
# Flags for arguments nodes.
module ArgumentsNodeFlags
# if arguments contain keyword splat
CONTAINS_KEYWORD_SPLAT = 1 << 0
end
# Flags for array nodes.
module ArrayNodeFlags
# if array contains splat nodes
CONTAINS_SPLAT = 1 << 0
end
# Flags for call nodes.
module CallNodeFlags
# &. operator
SAFE_NAVIGATION = 1 << 0
# a call that could have been a local variable
VARIABLE_CALL = 1 << 1
# a call that is an attribute write, so the value being written should be returned
ATTRIBUTE_WRITE = 1 << 2
end
# Flags for nodes that have unescaped content.
module EncodingFlags
# internal bytes forced the encoding to UTF-8
FORCED_UTF8_ENCODING = 1 << 0
# internal bytes forced the encoding to binary
FORCED_BINARY_ENCODING = 1 << 1
end
# Flags for integer nodes that correspond to the base of the integer.
module IntegerBaseFlags
# 0b prefix
BINARY = 1 << 0
# 0d or no prefix
DECIMAL = 1 << 1
# 0o or 0 prefix
OCTAL = 1 << 2
# 0x prefix
HEXADECIMAL = 1 << 3
end
# Flags for keyword hash nodes.
module KeywordHashNodeFlags
# a keyword hash which only has `AssocNode` elements all with static literal keys, which means the elements can be treated as keyword arguments
STATIC_KEYS = 1 << 0
end
# Flags for while and until loop nodes.
module LoopFlags
# a loop after a begin statement, so the body is executed first before the condition
BEGIN_MODIFIER = 1 << 0
end
# Flags for range and flip-flop nodes.
module RangeFlags
# ... operator
EXCLUDE_END = 1 << 0
end
# Flags for regular expression and match last line nodes.
module RegularExpressionFlags
# i - ignores the case of characters when matching
IGNORE_CASE = 1 << 0
# x - ignores whitespace and allows comments in regular expressions
EXTENDED = 1 << 1
# m - allows $ to match the end of lines within strings
MULTI_LINE = 1 << 2
# o - only interpolates values into the regular expression once
ONCE = 1 << 3
# e - forces the EUC-JP encoding
EUC_JP = 1 << 4
# n - forces the ASCII-8BIT encoding
ASCII_8BIT = 1 << 5
# s - forces the Windows-31J encoding
WINDOWS_31J = 1 << 6
# u - forces the UTF-8 encoding
UTF_8 = 1 << 7
# internal bytes forced the encoding to UTF-8
FORCED_UTF8_ENCODING = 1 << 8
# internal bytes forced the encoding to binary
FORCED_BINARY_ENCODING = 1 << 9
# internal bytes forced the encoding to US-ASCII
FORCED_US_ASCII_ENCODING = 1 << 10
end
# Flags for string nodes.
module StringFlags
# internal bytes forced the encoding to UTF-8
FORCED_UTF8_ENCODING = 1 << 0
# internal bytes forced the encoding to binary
FORCED_BINARY_ENCODING = 1 << 1
# frozen by virtue of a `frozen_string_literal` comment
FROZEN = 1 << 2
end
# Flags for symbol nodes.
module SymbolFlags
# internal bytes forced the encoding to UTF-8
FORCED_UTF8_ENCODING = 1 << 0
# internal bytes forced the encoding to binary
FORCED_BINARY_ENCODING = 1 << 1
# internal bytes forced the encoding to US-ASCII
FORCED_US_ASCII_ENCODING = 1 << 2
end
end
Zerion Mini Shell 1.0