class DeepCover::Node
Base
class to handle covered nodes.
Constants
- CLASSES
Reopened in base
- Complex
- Cvasgn
- Dsym
- Erange
- Float
- Int
- Ivar
- Kwarg
- Kwoptarg
- Kwrestarg
- OrAsgn
- Rational
- Sym
- True
- Zsuper
Attributes
base_node[R]
children[R]
index[R]
next_sibling[RW]
parent[R]
previous_sibling[RW]
Public Class Methods
[](source)
click to toggle source
Shortcut to create a node from source code
# File lib/deep_cover/node/base.rb, line 72 def self.[](source) CoveredCode.new(source: source).execute_code.covered_ast end
atom(type)
click to toggle source
Atoms
# File lib/deep_cover/node/literals.rb, line 26 def self.atom(type) ::Class.new(StaticLiteral) do has_child value: type end end
define_module_class() { || ... }
click to toggle source
# File lib/deep_cover/node/module.rb, line 24 def self.define_module_class check_completion has_tracker :body_entry yield has_child body: Node, can_be_empty: -> { base_node.loc.end.begin }, rewrite: '%{body_entry_tracker};%{node}', is_statement: true, flow_entry_count: :body_entry_tracker_hits executed_loc_keys :keyword class_eval do def execution_count # Overrides ExecutedAfterChildren body_entry_tracker_hits end end end
has_evaluated_segments()
click to toggle source
Dynamic
# File lib/deep_cover/node/literals.rb, line 74 def self.has_evaluated_segments has_extra_children constituents: [Str, Begin, Ivar, Cvar, Gvar, Dstr, NthRef] end
inherited(parent)
click to toggle source
Calls superclass method
# File lib/deep_cover/node.rb, line 10 def self.inherited(parent) CLASSES << parent super end
new(base_node, parent:, index: 0, base_children: base_node.children)
click to toggle source
Calls superclass method
DeepCover::Node::Mixin::HasChild::new
# File lib/deep_cover/node/base.rb, line 22 def initialize(base_node, parent:, index: 0, base_children: base_node.children) @base_node = base_node @parent = parent @index = index @children = [] begin @children = augment_children(base_children) initialize_siblings super() rescue StandardError => e diagnose(e) end end
Public Instance Methods
[](lookup)
click to toggle source
Shortcut to access children
# File lib/deep_cover/node/base.rb, line 55 def [](lookup) if lookup.is_a?(Integer) children.fetch(lookup) else found = find_all(lookup) case found.size when 1 found.first when 0 raise "No children of type #{lookup}" else raise "Ambiguous lookup #{lookup}, found #{found}." end end end
children_nodes()
click to toggle source
# File lib/deep_cover/node/base.rb, line 76 def children_nodes children.select { |c| c.is_a? Node } end
Also aliased as: children_nodes_in_flow_order
covered_code()
click to toggle source
Internal API
# File lib/deep_cover/node/base.rb, line 112 def covered_code parent.covered_code end
each_node() { |self| ... }
click to toggle source
Yields its children and itself
# File lib/deep_cover/node/base.rb, line 122 def each_node(&block) return to_enum :each_node unless block_given? children_nodes.each do |child| child.each_node(&block) end yield self self end
execution_count()
click to toggle source
# File lib/deep_cover/node/module.rb, line 36 def execution_count # Overrides ExecutedAfterChildren body_entry_tracker_hits end
fancy_type()
click to toggle source
# File lib/deep_cover/node/base.rb, line 131 def fancy_type class_name = self.class.to_s.gsub(/^DeepCover::/, '').gsub(/^Node::/, '') t = type.to_s t.casecmp(class_name) == 0 ? t : "#{t}[#{class_name}]" end
find_all(lookup)
click to toggle source
Search self and descendants for a particular Class
or type
# File lib/deep_cover/node/base.rb, line 39 def find_all(lookup) case lookup when ::Module each_node.grep(lookup) when ::Symbol each_node.find_all { |n| n.type == lookup } when ::String each_node.find_all { |n| n.source == lookup } when ::Regexp each_node.find_all { |n| n.source =~ lookup } else raise ::TypeError, "Expected class or symbol, got #{lookup.class}: #{lookup.inspect}" end end
simple_literal?()
click to toggle source
# File lib/deep_cover/node/literals.rb, line 8 def simple_literal? false end
to_s(indent = 0)
click to toggle source
Adapted from github.com/whitequark/ast/blob/master/lib/ast/node.rb
# File lib/deep_cover/node/base.rb, line 93 def to_s(indent = 0) [ ' ' * indent, '(', fancy_type, *children.map do |child, idx| if child.is_a?(Node) "\n#{child.to_s(indent + 1)}" else " #{child.inspect}" end end, ')', ].join end
Also aliased as: inspect
type()
click to toggle source
# File lib/deep_cover/node/base.rb, line 116 def type return base_node.type if base_node self.class.name.split('::').last.to_sym end
Private Instance Methods
diagnose(exception)
click to toggle source
# File lib/deep_cover/node/base.rb, line 139 def diagnose(exception) msg = if self.class == Node "Unknown node type encountered: #{base_node.type}" else "Node class #{self.class} incorrectly defined" end warn [msg, 'Attempting to continue, but this node will not be handled properly', ('Its subnodes will be ignored' if children.empty?), 'Source:', expression, 'Original exception:', exception.inspect, ].join("\n") end
initialize_siblings()
click to toggle source
# File lib/deep_cover/node/base.rb, line 84 def initialize_siblings children_nodes_in_flow_order.each_cons(2) do |child, next_child| child.next_sibling = next_child next_child.previous_sibling = child end end