Linux premium180.web-hosting.com 4.18.0-553.54.1.lve.el8.x86_64 #1 SMP Wed Jun 4 13:01:13 UTC 2025 x86_64
LiteSpeed
: 162.0.209.168 | : 216.73.216.187
Cant Read [ /etc/named.conf ]
8.3.30
nortrmdp
www.github.com/MadExploits
Terminal
AUTO ROOT
Adminer
Backdoor Destroyer
Linux Exploit
Lock Shell
Lock File
Create User
CREATE RDP
PHP Mailer
BACKCONNECT
UNLOCK SHELL
HASH IDENTIFIER
CPANEL RESET
CREATE WP USER
BLACK DEFEND!
README
+ Create Folder
+ Create File
/
opt /
alt /
ruby33 /
share /
ruby /
prism /
[ HOME SHELL ]
Name
Size
Permission
Action
parse_result
[ DIR ]
drwxr-xr-x
compiler.rb
14.88
KB
-rw-r--r--
debug.rb
6.12
KB
-rw-r--r--
desugar_compiler.rb
5.71
KB
-rw-r--r--
dispatcher.rb
108.9
KB
-rw-r--r--
dsl.rb
31.99
KB
-rw-r--r--
ffi.rb
10.27
KB
-rw-r--r--
lex_compat.rb
31.04
KB
-rw-r--r--
mutation_compiler.rb
20.81
KB
-rw-r--r--
node.rb
575.41
KB
-rw-r--r--
node_ext.rb
5.01
KB
-rw-r--r--
node_inspector.rb
2.06
KB
-rw-r--r--
pack.rb
5.77
KB
-rw-r--r--
parse_result.rb
13.43
KB
-rw-r--r--
pattern.rb
7.56
KB
-rw-r--r--
ripper_compat.rb
5.95
KB
-rw-r--r--
serialize.rb
56.71
KB
-rw-r--r--
visitor.rb
15.02
KB
-rw-r--r--
Delete
Unzip
Zip
${this.title}
Close
Code Editor : node.rb
# 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
Close