Class: RuboCop::Cop::InternalAffairs::NodePatternGroups::ASTWalker
Relationships & Source Files | |
Namespace Children | |
Classes:
| |
Inherits: | Object |
Defined in: | lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb |
Overview
Walks an AST that has been processed by InternalAffairs::NodePatternGroups::Processor
in order to find node_type
and node_sequence
nodes that can be replaced with a node
group in InternalAffairs/NodePatternGroups
.
Calling #walk sets #node_groups with an array of NodeGroup
structs
that contain metadata about nodes that can be replaced, including location data. That
metadata is used by the cop to register offenses and perform corrections.
Class Method Summary
- .new ⇒ ASTWalker constructor
Instance Attribute Summary
- #node_groups readonly
Instance Method Summary
-
#on_union(node)
Search
union
nodes fornode_type
andnode_sequence
nodes that can be collapsed into a node group. - #reset!
-
#walk(node)
Recursively walk the AST in a depth-first manner.
- #each_child_node(node, *types) private
- #each_node_group(types_to_check) private
- #get_relevant_nodes(node_types, group_name) private
- #node_group_data(name, union, node_types, start_index, other) private
- #sequences_match?(types) ⇒ Boolean private
Constructor Details
.new ⇒ ASTWalker
# File 'lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb', line 30
def initialize reset! end
Instance Attribute Details
#node_groups (readonly)
[ GitHub ]# File 'lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb', line 38
attr_reader :node_groups
Instance Method Details
#each_child_node(node, *types) (private)
[ GitHub ]# File 'lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb', line 75
def each_child_node(node, *types) return to_enum(__method__, node, *types) unless block_given? node.children.each do |child| yield child if types.empty? || types.include?(child.type) end self end
#each_node_group(types_to_check) (private)
[ GitHub ]# File 'lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb', line 85
def each_node_group(types_to_check) # Find all node groups where all of the members are present in the union type_names = types_to_check.map(&:child) NODE_GROUPS.select { |_, group| group & type_names == group }.each_key do |name| nodes = get_relevant_nodes(types_to_check, name) yield name, nodes end end
#get_relevant_nodes(node_types, group_name) (private)
[ GitHub ]# File 'lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb', line 96
def get_relevant_nodes(node_types, group_name) node_types.each_with_object([]) do |node_type, arr| next unless NODE_GROUPS[group_name].include?(node_type.child) arr << node_type end end
#node_group_data(name, union, node_types, start_index, other) (private)
[ GitHub ]# File 'lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb', line 104
def node_group_data(name, union, node_types, start_index, other) NodeGroup.new( name: name, union: union, node_types: node_types, sequence?: node_types.first.type == :node_sequence, start_index: start_index, pipe: union.source_range.source['|'], other_elements?: other ) end
#on_union(node)
Search union
nodes for node_type
and node_sequence
nodes that can be
collapsed into a node group.
* node_type
nodes are nodes with no further configuration (ie. send
)
* node_sequence
nodes are nodes with further configuration (ie. (send …)
)
Each group of types that can be collapsed will have a ASTWalker::NodeGroup
record added
to #node_groups, which is then used by the cop.
# File 'lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb', line 59
def on_union(node) all_node_types = each_child_node(node, :node_type, :node_sequence).to_a each_node_group(all_node_types) do |group_name, node_types| next unless sequences_match?(node_types) node_groups << node_group_data( group_name, node, node_types, all_node_types.index(node_types.first), (node.children - node_types).any? ) end end
#reset!
[ GitHub ]# File 'lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb', line 34
def reset! @node_groups = [] end
#sequences_match?(types) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb', line 116
def sequences_match?(types) # Ensure all given types have the same type and the same sequence # ie. `(send ...)` and `(csend ...) is a match # `(send)` and `(csend ...)` is not a match # `send` and `(csend ...)` is not a match types.each_cons(2).all? do |left, right| left.type == right.type && left.children[1..] == right.children[1..] end end
#walk(node)
Recursively walk the AST in a depth-first manner.
Only union
nodes are handled further.
# File 'lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb', line 42
def walk(node) return if node.nil? on_union(node) if node.type == :union node.child_nodes.each do |child| walk(child) end end