deep-cover 0.1.14 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +227 -0
  3. data/Gemfile +5 -2
  4. data/Rakefile +9 -6
  5. data/bin/console +3 -3
  6. data/bin/cov +8 -8
  7. data/bin/gemcov +2 -2
  8. data/bin/selfcov +5 -5
  9. data/bin/test_gems +11 -10
  10. data/bin/testall +6 -6
  11. data/deep_cover.gemspec +26 -21
  12. data/exe/deep-cover +1 -0
  13. data/lib/deep-cover.rb +2 -0
  14. data/lib/deep_cover.rb +3 -0
  15. data/lib/deep_cover/analyser.rb +2 -0
  16. data/lib/deep_cover/analyser/base.rb +2 -0
  17. data/lib/deep_cover/analyser/branch.rb +4 -2
  18. data/lib/deep_cover/analyser/covered_code_source.rb +3 -1
  19. data/lib/deep_cover/analyser/function.rb +3 -1
  20. data/lib/deep_cover/analyser/ignore_uncovered.rb +6 -4
  21. data/lib/deep_cover/analyser/node.rb +3 -0
  22. data/lib/deep_cover/analyser/optionally_covered.rb +12 -7
  23. data/lib/deep_cover/analyser/per_char.rb +7 -6
  24. data/lib/deep_cover/analyser/per_line.rb +9 -8
  25. data/lib/deep_cover/analyser/statement.rb +2 -0
  26. data/lib/deep_cover/analyser/subset.rb +4 -1
  27. data/lib/deep_cover/auto_run.rb +3 -0
  28. data/lib/deep_cover/autoload_tracker.rb +6 -3
  29. data/lib/deep_cover/backports.rb +2 -0
  30. data/lib/deep_cover/base.rb +11 -2
  31. data/lib/deep_cover/builtin_takeover.rb +2 -0
  32. data/lib/deep_cover/cli/debugger.rb +55 -30
  33. data/lib/deep_cover/cli/deep_cover.rb +17 -11
  34. data/lib/deep_cover/cli/instrumented_clone_reporter.rb +16 -14
  35. data/lib/deep_cover/config.rb +29 -16
  36. data/lib/deep_cover/core_ext/autoload_overrides.rb +2 -0
  37. data/lib/deep_cover/core_ext/coverage_replacement.rb +2 -0
  38. data/lib/deep_cover/core_ext/load_overrides.rb +5 -6
  39. data/lib/deep_cover/core_ext/require_overrides.rb +6 -7
  40. data/lib/deep_cover/coverage.rb +21 -18
  41. data/lib/deep_cover/covered_code.rb +22 -12
  42. data/lib/deep_cover/custom_requirer.rb +82 -35
  43. data/lib/deep_cover/memoize.rb +48 -0
  44. data/lib/deep_cover/module_override.rb +2 -0
  45. data/lib/deep_cover/node.rb +14 -1
  46. data/lib/deep_cover/node/arguments.rb +2 -0
  47. data/lib/deep_cover/node/assignments.rb +32 -30
  48. data/lib/deep_cover/node/base.rb +30 -29
  49. data/lib/deep_cover/node/begin.rb +3 -1
  50. data/lib/deep_cover/node/block.rb +5 -2
  51. data/lib/deep_cover/node/branch.rb +2 -1
  52. data/lib/deep_cover/node/case.rb +15 -13
  53. data/lib/deep_cover/node/collections.rb +2 -0
  54. data/lib/deep_cover/node/const.rb +2 -0
  55. data/lib/deep_cover/node/def.rb +10 -8
  56. data/lib/deep_cover/node/empty_body.rb +2 -0
  57. data/lib/deep_cover/node/exceptions.rb +3 -1
  58. data/lib/deep_cover/node/if.rb +3 -1
  59. data/lib/deep_cover/node/keywords.rb +4 -2
  60. data/lib/deep_cover/node/literals.rb +2 -0
  61. data/lib/deep_cover/node/loops.rb +5 -3
  62. data/lib/deep_cover/node/mixin/can_augment_children.rb +8 -7
  63. data/lib/deep_cover/node/mixin/check_completion.rb +3 -1
  64. data/lib/deep_cover/node/mixin/child_can_be_empty.rb +4 -2
  65. data/lib/deep_cover/node/mixin/executed_after_children.rb +2 -0
  66. data/lib/deep_cover/node/mixin/execution_location.rb +4 -2
  67. data/lib/deep_cover/node/mixin/flow_accounting.rb +2 -0
  68. data/lib/deep_cover/node/mixin/has_child.rb +22 -18
  69. data/lib/deep_cover/node/mixin/has_child_handler.rb +10 -8
  70. data/lib/deep_cover/node/mixin/has_tracker.rb +4 -2
  71. data/lib/deep_cover/node/mixin/is_statement.rb +3 -1
  72. data/lib/deep_cover/node/mixin/rewriting.rb +5 -3
  73. data/lib/deep_cover/node/mixin/wrapper.rb +2 -0
  74. data/lib/deep_cover/node/module.rb +11 -9
  75. data/lib/deep_cover/node/root.rb +2 -0
  76. data/lib/deep_cover/node/send.rb +4 -2
  77. data/lib/deep_cover/node/short_circuit.rb +4 -2
  78. data/lib/deep_cover/node/splat.rb +2 -0
  79. data/lib/deep_cover/node/variables.rb +2 -0
  80. data/lib/deep_cover/parser_ext/range.rb +3 -1
  81. data/lib/deep_cover/problem_with_diagnostic.rb +11 -9
  82. data/lib/deep_cover/reporter.rb +2 -0
  83. data/lib/deep_cover/reporter/istanbul.rb +28 -24
  84. data/lib/deep_cover/tools.rb +2 -0
  85. data/lib/deep_cover/tools/builtin_coverage.rb +6 -4
  86. data/lib/deep_cover/tools/camelize.rb +3 -1
  87. data/lib/deep_cover/tools/dasherize.rb +3 -1
  88. data/lib/deep_cover/tools/dump_covered_code.rb +7 -6
  89. data/lib/deep_cover/tools/execute_sample.rb +13 -13
  90. data/lib/deep_cover/tools/format.rb +3 -1
  91. data/lib/deep_cover/tools/format_char_cover.rb +4 -2
  92. data/lib/deep_cover/tools/format_generated_code.rb +3 -1
  93. data/lib/deep_cover/tools/number_lines.rb +2 -0
  94. data/lib/deep_cover/tools/our_coverage.rb +5 -3
  95. data/lib/deep_cover/tools/profiling.rb +66 -0
  96. data/lib/deep_cover/tools/require_relative_dir.rb +3 -1
  97. data/lib/deep_cover/tools/silence_warnings.rb +4 -1
  98. data/lib/deep_cover/tools/slice.rb +3 -1
  99. data/lib/deep_cover/tools/truncate_backtrace.rb +2 -0
  100. data/lib/deep_cover/version.rb +3 -1
  101. metadata +47 -30
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeepCover
2
4
  module Node::Mixin
3
5
  module HasChildHandler
@@ -5,9 +7,9 @@ module DeepCover
5
7
  base.extend ClassMethods
6
8
  end
7
9
 
8
- def call_child_handler template, child, child_name = nil
9
- child_name ||= self.class.child_index_to_name(child.index, children.size) rescue binding.pry
10
- method_name = template % {name: child_name}
10
+ def call_child_handler(template, child, child_name = nil)
11
+ child_name ||= self.class.child_index_to_name(child.index, children.size)
12
+ method_name = format(template, name: child_name)
11
13
  if respond_to?(method_name)
12
14
  args = [child, child_name]
13
15
  arity = method(method_name).arity
@@ -22,10 +24,10 @@ module DeepCover
22
24
 
23
25
  module ClassMethods
24
26
  def has_child_handler(template)
25
- child_method_name = template % {name: 'child'}
27
+ child_method_name = format(template, name: 'child')
26
28
  action = template.gsub(/_%{name}/, '').gsub(/%{name}_/, '')
27
29
  const_name = "#{Tools.camelize(action)}Handler"
28
- class_eval <<-end_eval, __FILE__, __LINE__
30
+ class_eval <<-EVAL, __FILE__, __LINE__ + 1
29
31
  module #{const_name} # module RewriteHandler
30
32
  module ClassMethods # module ClassMethods
31
33
  def has_child(#{action}: nil, **h) # def has_child(rewrite: nil, **h)
@@ -43,11 +45,11 @@ module DeepCover
43
45
  end # end
44
46
  include #{const_name} # include RewriteHandler
45
47
  singleton_class.prepend #{const_name}::ClassMethods # singleton_class.prepend RewriteHandler::ClassMethods
46
- end_eval
48
+ EVAL
47
49
  end
48
50
 
49
51
  def define_child_handler(template, name, action)
50
- method_name = template % {name: name}
52
+ method_name = format(template, name: name)
51
53
  case action
52
54
  when nil
53
55
  # Nothing to do
@@ -63,7 +65,7 @@ module DeepCover
63
65
  when Proc
64
66
  define_method(method_name, &action)
65
67
  else
66
- define_method(method_name) {|*| action }
68
+ define_method(method_name) { |*| action }
67
69
  end
68
70
  end
69
71
  private :define_child_handler
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeepCover
2
4
  module Node::Mixin
3
5
  module HasTracker
@@ -25,14 +27,14 @@ module DeepCover
25
27
 
26
28
  def has_tracker(name)
27
29
  i = self::TRACKERS[name] = self::TRACKERS.size
28
- class_eval <<-end_eval, __FILE__, __LINE__ + 1
30
+ class_eval <<-EVAL, __FILE__, __LINE__ + 1
29
31
  def #{name}_tracker_source
30
32
  covered_code.tracker_source(@tracker_offset + #{i})
31
33
  end
32
34
  def #{name}_tracker_hits
33
35
  covered_code.tracker_hits(@tracker_offset + #{i})
34
36
  end
35
- end_eval
37
+ EVAL
36
38
  end
37
39
  end
38
40
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeepCover
2
4
  module Node::Mixin
3
5
  module IsStatement
@@ -10,7 +12,7 @@ module DeepCover
10
12
  end
11
13
 
12
14
  # Default child rewriting rule
13
- def is_child_statement(child, name=nil)
15
+ def is_child_statement(child, name = nil)
14
16
  :if_incompatible
15
17
  end
16
18
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeepCover
2
4
  module Node::Mixin
3
5
  module Rewriting
@@ -10,14 +12,14 @@ module DeepCover
10
12
  end
11
13
 
12
14
  # Default child rewriting rule
13
- def rewrite_child(child, name=nil)
15
+ def rewrite_child(child, name = nil)
14
16
  end
15
17
 
16
18
  # Replaces all the '%{local}' or '%{some_tracker}' in rewriting rules
17
19
  def resolve_rewrite(rule, context)
18
20
  return if rule == nil
19
21
  sources = context.tracker_sources
20
- rule % {local: covered_code.local_var, node: '%{node}', **sources}
22
+ format(rule, local: covered_code.local_var, node: '%{node}', **sources)
21
23
  end
22
24
 
23
25
  # Returns an array of [range, rule], where rule is a string containing '%{node}'
@@ -26,7 +28,7 @@ module DeepCover
26
28
  [
27
29
  resolve_rewrite(rewrite, self),
28
30
  resolve_rewrite(parent.rewrite_child(self), parent),
29
- ].compact.map{|rule| [expression, rule]}
31
+ ].compact.map { |rule| [expression, rule] }
30
32
  end
31
33
  end
32
34
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeepCover
2
4
  module Node::Mixin
3
5
  module Wrapper
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'const'
2
4
 
3
5
  module DeepCover
@@ -24,10 +26,10 @@ module DeepCover
24
26
  has_tracker :body_entry
25
27
  has_child const: {const: ModuleName}
26
28
  has_child body: Node,
27
- can_be_empty: -> { base_node.loc.end.begin },
28
- rewrite: '%{body_entry_tracker};%{local}=nil;%{node}',
29
- is_statement: true,
30
- flow_entry_count: :body_entry_tracker_hits
29
+ can_be_empty: -> { base_node.loc.end.begin },
30
+ rewrite: '%{body_entry_tracker};%{local}=nil;%{node}',
31
+ is_statement: true,
32
+ flow_entry_count: :body_entry_tracker_hits
31
33
  executed_loc_keys :keyword
32
34
 
33
35
  def execution_count
@@ -39,12 +41,12 @@ module DeepCover
39
41
  check_completion
40
42
  has_tracker :body_entry
41
43
  has_child const: {const: ModuleName}
42
- has_child inherit: [Node, nil] # TODO
44
+ has_child inherit: [Node, nil] # TODO
43
45
  has_child body: Node,
44
- can_be_empty: -> { base_node.loc.end.begin },
45
- rewrite: '%{body_entry_tracker};%{node}',
46
- is_statement: true,
47
- flow_entry_count: :body_entry_tracker_hits
46
+ can_be_empty: -> { base_node.loc.end.begin },
47
+ rewrite: '%{body_entry_tracker};%{node}',
48
+ is_statement: true,
49
+ flow_entry_count: :body_entry_tracker_hits
48
50
  executed_loc_keys :keyword
49
51
 
50
52
  def execution_count
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeepCover
2
4
  class Node::Root < Node
3
5
  has_tracker :root
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'literals'
2
4
  require_relative 'branch'
3
5
 
@@ -90,8 +92,8 @@ module DeepCover
90
92
  end
91
93
 
92
94
  def branches
93
- [ actual_send,
94
- TrivialBranch.new(condition: receiver, other_branch: actual_send)
95
+ [actual_send,
96
+ TrivialBranch.new(condition: receiver, other_branch: actual_send),
95
97
  ]
96
98
  end
97
99
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'branch'
2
4
 
3
5
  module DeepCover
@@ -7,12 +9,12 @@ module DeepCover
7
9
  has_tracker :conditional
8
10
  has_child lhs: Node
9
11
  has_child conditional: Node, flow_entry_count: :conditional_tracker_hits,
10
- rewrite: '((%{conditional_tracker};%{node}))'
12
+ rewrite: '((%{conditional_tracker};%{node}))'
11
13
 
12
14
  def branches
13
15
  [
14
16
  conditional,
15
- TrivialBranch.new(condition: lhs, other_branch: conditional)
17
+ TrivialBranch.new(condition: lhs, other_branch: conditional),
16
18
  ]
17
19
  end
18
20
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeepCover
2
4
  class Node
3
5
  class Splat < Node
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeepCover
2
4
  class Node
3
5
  class Variable < Node
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Parser::Source::Range
2
4
  def with(begin_pos: @begin_pos, end_pos: @end_pos)
3
5
  Parser::Source::Range.new(@source_buffer, begin_pos, end_pos)
@@ -9,7 +11,7 @@ class Parser::Source::Range
9
11
  inner_ranges.sort_by!(&:begin_pos)
10
12
  [self.begin, *inner_ranges, self.end]
11
13
  .each_cons(2)
12
- .map{|i, j| with(begin_pos: i.end_pos, end_pos: j.begin_pos)}
14
+ .map { |i, j| with(begin_pos: i.end_pos, end_pos: j.begin_pos) }
13
15
  .reject(&:empty?)
14
16
  end
15
17
 
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeepCover
2
4
  class ProblemWithDiagnostic < StandardError
3
5
  attr_reader :covered_code, :line_range, :original_exception
4
6
 
5
- def initialize(covered_code, line_range, original_exception=nil)
7
+ def initialize(covered_code, line_range, original_exception = nil)
6
8
  @covered_code = covered_code
7
9
  if line_range.is_a?(Parser::Source::Range)
8
10
  @line_range = line_range.line..line_range.last_line
@@ -14,11 +16,11 @@ module DeepCover
14
16
 
15
17
  def message
16
18
  msg = []
17
- msg << "You found a problem with DeepCover!"
18
- msg << "Please open an issue at https://github.com/deep-cover/deep-cover/issues"
19
- msg << "and include the following diagnostic information:"
19
+ msg << 'You found a problem with DeepCover!'
20
+ msg << 'Please open an issue at https://github.com/deep-cover/deep-cover/issues'
21
+ msg << 'and include the following diagnostic information:'
20
22
  extra = begin
21
- diagnostic_information_lines.map{|line| "| #{line}"}
23
+ diagnostic_information_lines.map { |line| "| #{line}" }
22
24
  rescue ProblemWithDiagnostic
23
25
  ["Oh no! We're in deep trouble!!!"]
24
26
  rescue Exception => e
@@ -32,13 +34,13 @@ module DeepCover
32
34
  lines = []
33
35
  lines << "Source file: #{covered_code.path}"
34
36
  lines << "Line numbers: #{line_range}"
35
- lines << "Source lines around location:"
36
- lines.concat source_lines.map{|line| " #{line}" }
37
+ lines << 'Source lines around location:'
38
+ lines.concat(source_lines.map { |line| " #{line}" })
37
39
  if original_exception
38
- lines << "Original exception:"
40
+ lines << 'Original exception:'
39
41
  lines << " #{original_exception.class.name}: #{original_exception.message}"
40
42
  backtrace = Tools.truncate_backtrace(original_exception)
41
- lines.concat backtrace.map{|line| " #{line}"}
43
+ lines.concat(backtrace.map { |line| " #{line}" })
42
44
  end
43
45
  lines
44
46
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeepCover
2
4
  module Reporter
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
 
3
5
  module DeepCover
@@ -6,20 +8,20 @@ module DeepCover
6
8
  # Converters has no dependency on the including class.
7
9
  module Converters
8
10
  def convert_range(range)
9
- { start: {
10
- line: range.line,
11
- column: range.column,
12
- },
13
- end: {
14
- line: range.last_line,
15
- column: range.last_column-1, # Our ranges are exclusive, Istanbul's are inclusive
16
- },
11
+ {start: {
12
+ line: range.line,
13
+ column: range.column,
14
+ },
15
+ end: {
16
+ line: range.last_line,
17
+ column: range.last_column - 1, # Our ranges are exclusive, Istanbul's are inclusive
18
+ },
17
19
  }
18
20
  end
19
21
 
20
22
  # [:a, :b, :c] => {'1': :a, '2': :b, '3': :c}
21
23
  def convert_list(list)
22
- list.map.with_index{ |val, i| [i.succ.to_s, val] }.to_h
24
+ list.map.with_index { |val, i| [i.succ.to_s, val] }.to_h
23
25
  end
24
26
 
25
27
  def convert_def(node)
@@ -31,7 +33,7 @@ module DeepCover
31
33
  def convert_block(node)
32
34
  decl = node.loc_hash[:begin]
33
35
  if (args = node.args.expression)
34
- decl = decl.join(args) rescue binding.pry
36
+ decl = decl.join(args)
35
37
  end
36
38
  _convert_function(node, '(block)', decl)
37
39
  end
@@ -50,11 +52,12 @@ module DeepCover
50
52
  loc: convert_range(node.expression),
51
53
  type: node.type,
52
54
  line: node.expression.line,
53
- locations: branches.map{|n| convert_range(n.expression || node.expression)}
55
+ locations: branches.map { |n| convert_range(n.expression || node.expression) },
54
56
  }
55
57
  end
56
58
 
57
59
  private
60
+
58
61
  def _convert_function(node, name, decl)
59
62
  loc = node.body ? node.body.expression : decl.end
60
63
  {
@@ -95,15 +98,15 @@ module DeepCover
95
98
 
96
99
  # Istanbul doesn't understand how to ignore a branch...
97
100
  def zero_to_something(values)
98
- values.map{|v| v || 1}
101
+ values.map { |v| v || 1 }
99
102
  end
100
103
 
101
104
  def branch_runs
102
- branches.values.map{|r| zero_to_something(r.values) }
105
+ branches.values.map { |r| zero_to_something(r.values) }
103
106
  end
104
107
 
105
108
  def statement_map
106
- statements.keys.map{ |range| convert_range(range) }
109
+ statements.keys.map { |range| convert_range(range) }
107
110
  end
108
111
 
109
112
  def statement_runs
@@ -111,7 +114,7 @@ module DeepCover
111
114
  end
112
115
 
113
116
  def function_map
114
- functions.keys.map{|n| convert_function(n) }
117
+ functions.keys.map { |n| convert_function(n) }
115
118
  end
116
119
 
117
120
  def function_runs
@@ -120,20 +123,21 @@ module DeepCover
120
123
 
121
124
  def data
122
125
  {
123
- statementMap: statement_map ,
126
+ statementMap: statement_map,
124
127
  s: statement_runs,
125
- fnMap: function_map ,
126
- f: function_runs ,
127
- branchMap: branch_map ,
128
- b: branch_runs ,
128
+ fnMap: function_map,
129
+ f: function_runs,
130
+ branchMap: branch_map,
131
+ b: branch_runs,
129
132
  }
130
133
  end
131
134
 
132
135
  def convert
133
- { covered_code.name => {
134
- path: covered_code.path,
135
- **data.transform_values{|l| convert_list(l)},
136
- } }
136
+ {covered_code.name => {
137
+ path: covered_code.path,
138
+ **data.transform_values { |l| convert_list(l) },
139
+ },
140
+ }
137
141
  end
138
142
 
139
143
  def report
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeepCover
2
4
  Tools = Module.new
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeepCover
2
4
  module Tools::BuiltinCoverage
3
5
  require 'coverage'
@@ -6,7 +8,7 @@ module DeepCover
6
8
  fn = File.absolute_path(File.expand_path(fn))
7
9
  ::Coverage.start
8
10
  Tools.silence_warnings do
9
- execute_sample ->{ run_with_line_coverage(source, fn, lineno)}
11
+ execute_sample -> { run_with_line_coverage(source, fn, lineno) }
10
12
  end
11
13
  unshift_coverage(::Coverage.result.fetch(fn), lineno)
12
14
  end
@@ -14,7 +16,7 @@ module DeepCover
14
16
  if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
15
17
  # Executes the source as if it was in the specified file while
16
18
  # builtin coverage information is still captured
17
- def run_with_line_coverage(source, fn=nil, lineno=1)
19
+ def run_with_line_coverage(source, fn = nil, lineno = 1)
18
20
  source = shift_source(source, lineno)
19
21
  Object.to_java.getRuntime.executeScript(source, fn)
20
22
  end
@@ -31,7 +33,7 @@ module DeepCover
31
33
 
32
34
  # Executes the source as if it was in the specified file while
33
35
  # builtin coverage information is still captured
34
- def run_with_line_coverage(source, fn=nil, lineno=1)
36
+ def run_with_line_coverage(source, fn = nil, lineno = 1)
35
37
  source = shift_source(source, lineno)
36
38
  RubyVM::InstructionSequence.compile(source, fn).eval
37
39
  end
@@ -44,7 +46,7 @@ module DeepCover
44
46
  end
45
47
 
46
48
  def unshift_coverage(coverage, lineno)
47
- coverage[(lineno-1)..-1]
49
+ coverage[(lineno - 1)..-1]
48
50
  end
49
51
  end
50
52
  end