Class: DeepCover::CoveredCode
- Inherits:
-
Object
- Object
- DeepCover::CoveredCode
- Defined in:
- lib/deep_cover/covered_code.rb
Instance Attribute Summary collapse
-
#buffer ⇒ Object
Returns the value of attribute buffer.
-
#local_var ⇒ Object
Returns the value of attribute local_var.
-
#path ⇒ Object
Returns the value of attribute path.
Class Method Summary collapse
Instance Method Summary collapse
- #allocate_trackers(nb_needed) ⇒ Object
- #char_cover(**options) ⇒ Object
- #comments ⇒ Object
- #compile ⇒ Object
- #compile_or_warn ⇒ Object
- #covered_ast ⇒ Object
- #covered_source ⇒ Object
- #each_node(*args, &block) ⇒ Object
- #execute_code(binding: DeepCover::GLOBAL_BINDING.dup) ⇒ Object
- #execute_code_or_warn(*args) ⇒ Object
- #freeze ⇒ Object
- #increment_tracker_source(tracker_id) ⇒ Object
-
#initialize(path: nil, source: nil, lineno: 1, local_var: '_temp', tracker_hits: nil) ⇒ CoveredCode
constructor
A new instance of CoveredCode.
- #inspect ⇒ Object (also: #to_s)
- #instrument_source ⇒ Object
- #line_coverage(**options) ⇒ Object
- #lineno ⇒ Object
- #nb_lines ⇒ Object
- #root ⇒ Object
- #setup_tracking_source ⇒ Object
- #tracker_hits ⇒ Object
-
#warn_instead_of_syntax_error ⇒ Object
&block.
Constructor Details
#initialize(path: nil, source: nil, lineno: 1, local_var: '_temp', tracker_hits: nil) ⇒ CoveredCode
Returns a new instance of CoveredCode.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/deep_cover/covered_code.rb', line 10 def initialize( path: nil, source: nil, lineno: 1, local_var: '_temp', tracker_hits: nil ) raise 'Must provide either path or source' unless path || source @path = path &&= Pathname(path) @buffer = Parser::Source::Buffer.new('', lineno) @buffer.source = source || path.read @index = nil # Set in #instrument_source @local_var = local_var @covered_source = nil # Set in #covered_source @tracker_hits = tracker_hits # Loaded from global in #tracker_hits, or when received right away when loading data @nb_allocated_trackers = 0 # We parse the code now so that problems happen early covered_ast @tracker_hits = Array.new(@nb_allocated_trackers, 0) if @tracker_hits == :zeroes end |
Instance Attribute Details
#buffer ⇒ Object
Returns the value of attribute buffer.
8 9 10 |
# File 'lib/deep_cover/covered_code.rb', line 8 def buffer @buffer end |
#local_var ⇒ Object
Returns the value of attribute local_var.
8 9 10 |
# File 'lib/deep_cover/covered_code.rb', line 8 def local_var @local_var end |
#path ⇒ Object
Returns the value of attribute path.
8 9 10 |
# File 'lib/deep_cover/covered_code.rb', line 8 def path @path end |
Class Method Details
.next_global_index ⇒ Object
168 169 170 171 |
# File 'lib/deep_cover/covered_code.rb', line 168 def self.next_global_index @last_allocated_global_index ||= -1 @last_allocated_global_index += 1 end |
Instance Method Details
#allocate_trackers(nb_needed) ⇒ Object
94 95 96 97 98 99 |
# File 'lib/deep_cover/covered_code.rb', line 94 def allocate_trackers(nb_needed) return @nb_allocated_trackers...@nb_allocated_trackers if nb_needed == 0 prev = @nb_allocated_trackers @nb_allocated_trackers += nb_needed prev...@nb_allocated_trackers end |
#char_cover(**options) ⇒ Object
60 61 62 |
# File 'lib/deep_cover/covered_code.rb', line 60 def char_cover(**) Analyser::PerChar.new(self, **).results end |
#comments ⇒ Object
68 69 70 71 |
# File 'lib/deep_cover/covered_code.rb', line 68 def comments root @comments end |
#compile ⇒ Object
133 134 135 |
# File 'lib/deep_cover/covered_code.rb', line 133 def compile RubyVM::InstructionSequence.compile(covered_source, path.to_s, path.to_s) end |
#compile_or_warn ⇒ Object
137 138 139 140 141 |
# File 'lib/deep_cover/covered_code.rb', line 137 def compile_or_warn warn_instead_of_syntax_error do compile end end |
#covered_ast ⇒ Object
64 65 66 |
# File 'lib/deep_cover/covered_code.rb', line 64 def covered_ast root.main end |
#covered_source ⇒ Object
114 115 116 |
# File 'lib/deep_cover/covered_code.rb', line 114 def covered_source @covered_source ||= instrument_source end |
#each_node(*args, &block) ⇒ Object
80 81 82 |
# File 'lib/deep_cover/covered_code.rb', line 80 def each_node(*args, &block) covered_ast.each_node(*args, &block) end |
#execute_code(binding: DeepCover::GLOBAL_BINDING.dup) ⇒ Object
45 46 47 48 |
# File 'lib/deep_cover/covered_code.rb', line 45 def execute_code(binding: DeepCover::GLOBAL_BINDING.dup) eval(covered_source, binding, (@path || '<raw_code>').to_s, lineno) # rubocop:disable Security/Eval self end |
#execute_code_or_warn(*args) ⇒ Object
50 51 52 53 54 |
# File 'lib/deep_cover/covered_code.rb', line 50 def execute_code_or_warn(*args) warn_instead_of_syntax_error do execute_code(*args) end end |
#freeze ⇒ Object
143 144 145 146 147 148 149 150 |
# File 'lib/deep_cover/covered_code.rb', line 143 def freeze unless frozen? # Guard against reentrance tracker_hits super root.each_node(&:freeze) end self end |
#increment_tracker_source(tracker_id) ⇒ Object
90 91 92 |
# File 'lib/deep_cover/covered_code.rb', line 90 def increment_tracker_source(tracker_id) "#{DeepCover.config.tracker_global}[#{@index}][#{tracker_id}]+=1" end |
#inspect ⇒ Object Also known as: to_s
152 153 154 |
# File 'lib/deep_cover/covered_code.rb', line 152 def inspect %{#<DeepCover::CoveredCode "#{path}">} end |
#instrument_source ⇒ Object
118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/deep_cover/covered_code.rb', line 118 def instrument_source @index ||= self.class.next_global_index rewriter = Parser::Source::TreeRewriter.new(@buffer) covered_ast.each_node do |node| node.rewriting_rules.each do |range, rule| prefix, _node, suffix = rule.partition('%{node}') prefix = yield prefix, node, range.begin, :prefix if block_given? && !prefix.empty? suffix = yield suffix, node, range.end, :suffix if block_given? && !suffix.empty? rewriter.wrap(range, prefix, suffix) end end rewriter.process end |
#line_coverage(**options) ⇒ Object
56 57 58 |
# File 'lib/deep_cover/covered_code.rb', line 56 def line_coverage(**) Analyser::PerLine.new(self, **).results end |
#lineno ⇒ Object
32 33 34 |
# File 'lib/deep_cover/covered_code.rb', line 32 def lineno @buffer.first_line end |
#nb_lines ⇒ Object
36 37 38 39 40 41 42 43 |
# File 'lib/deep_cover/covered_code.rb', line 36 def nb_lines lines = buffer.source_lines if lines.empty? 0 else lines.size - (lines.last.empty? ? 1 : 0) end end |
#root ⇒ Object
73 74 75 76 77 78 |
# File 'lib/deep_cover/covered_code.rb', line 73 def root @root ||= begin ast, @comments = parser.parse_with_comments(@buffer) Node::Root.new(ast, self) end end |
#setup_tracking_source ⇒ Object
84 85 86 87 88 |
# File 'lib/deep_cover/covered_code.rb', line 84 def setup_tracking_source src = "(#{DeepCover.config.tracker_global}||={})[#{@index}]||=Array.new(#{@nb_allocated_trackers},0)" src += ";(#{DeepCover.config.tracker_global}_p||={})[#{@index}]=#{path.to_s.inspect}" if path src end |
#tracker_hits ⇒ Object
101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/deep_cover/covered_code.rb', line 101 def tracker_hits return @tracker_hits if @tracker_hits global_trackers = DeepCover::GlobalVariables.trackers[@index] return unless global_trackers if global_trackers.size != @nb_allocated_trackers raise "Cannot sync path: #{path.inspect}, global[#{@index}] is of size #{global_trackers.size} instead of expected #{@nb_allocated_trackers}" end @tracker_hits = global_trackers end |
#warn_instead_of_syntax_error ⇒ Object
&block
157 158 159 160 161 162 163 164 165 166 |
# File 'lib/deep_cover/covered_code.rb', line 157 def warn_instead_of_syntax_error # &block yield rescue ::SyntaxError => e warn Tools.strip_heredoc(<<-MSG) DeepCover is getting confused with the file #{path} and it won't be instrumented. Please report this error and provide the source code around the following lines: #{e} MSG nil end |