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,11 +1,56 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # TODO: must handle circular requires
2
4
 
3
5
  module DeepCover
4
6
  class CustomRequirer
5
- attr_reader :load_path, :loaded_features
6
- def initialize(load_path=$LOAD_PATH, loaded_features=$LOADED_FEATURES)
7
- @load_path = load_path
7
+ class LoadPathsSubset
8
+ def initialize(load_paths: raise, lookup_paths: raise)
9
+ @original_load_paths = load_paths
10
+ @cached_load_paths_subset = []
11
+ @cached_load_paths_hash = nil
12
+ @lookup_paths = lookup_paths.map { |p| File.expand_path(p) }
13
+ end
14
+
15
+ def load_paths
16
+ if @cached_load_paths_hash != (h = @original_load_paths.hash)
17
+ @cached_load_paths_subset = compute_subset
18
+ @cached_load_paths_hash = h
19
+ end
20
+ @cached_load_paths_subset
21
+ end
22
+
23
+ # E.g. '/a/b/' => true if a lookup path is '/a/b/c/', because '/a/b/' + 'c/ok' is within lookup.
24
+ def potentially_within_lookup?(full_dir_path)
25
+ @lookup_paths.any? { |p| p.start_with? full_dir_path }
26
+ end
27
+
28
+ # E.g. '/a/b' => true when a lookup path is '/a/'
29
+ def within_lookup?(full_path)
30
+ @lookup_paths.any? { |p| full_path.start_with? p }
31
+ end
32
+
33
+ def exist?(full_path)
34
+ within_lookup?(full_path) && File.exist?(full_path)
35
+ end
36
+
37
+ private
38
+
39
+ def compute_subset
40
+ @original_load_paths.map { |p| File.expand_path(p) }
41
+ .select { |p| within_lookup?(p) || potentially_within_lookup?(p) }
42
+ .freeze
43
+ end
44
+ end
45
+
46
+ attr_reader :load_paths, :loaded_features, :filter
47
+ def initialize(load_paths: $LOAD_PATH, loaded_features: $LOADED_FEATURES, lookup_paths: nil, &filter)
48
+ @load_paths = load_paths
49
+ lookup_paths ||= Dir.getwd
50
+ lookup_paths = Array(lookup_paths)
51
+ @load_paths_subset = LoadPathsSubset.new(load_paths: load_paths, lookup_paths: lookup_paths) unless lookup_paths.include? '/'
8
52
  @loaded_features = loaded_features
53
+ @filter = filter
9
54
  end
10
55
 
11
56
  # Returns a path to an existing file or nil if none can be found.
@@ -14,46 +59,46 @@ module DeepCover
14
59
  # An absolute path is returned directly if it exists, otherwise nil
15
60
  # is returned without searching anywhere else.
16
61
  def resolve_path(path)
17
- path = File.absolute_path(path) if path.start_with?('./') || path.start_with?('../')
18
-
19
- if Pathname.new(path).absolute?
20
- return path if File.exist?(path)
21
- return nil
22
- end
23
-
24
- @load_path.each do |load_path|
25
- possible_path = File.absolute_path(path, load_path)
26
- return possible_path if File.exist?(possible_path)
62
+ path = File.absolute_path(path) if path.start_with?('./', '../')
63
+
64
+ abs_path = File.absolute_path(path)
65
+ if path == abs_path
66
+ path if (@load_paths_subset || File).exist?(path)
67
+ else
68
+ (@load_paths_subset || self).load_paths.each do |load_path|
69
+ possible_path = File.absolute_path(path, load_path)
70
+ return possible_path if (@load_paths_subset || File).exist?(possible_path)
71
+ end
72
+ nil
27
73
  end
28
-
29
- nil
30
74
  end
31
75
 
32
76
  # Homemade #require to be able to instrument the code before it gets executed.
33
77
  # Returns true when everything went right. (Same as regular ruby)
34
78
  # Returns false when the found file was already required. (Same as regular ruby)
35
- # Returns :not_found if the file couldn't be found.
36
- # Caller should delegate to the default #require.
37
- # Returns :cover_failed if DeepCover couldn't apply instrumentation the file found.
38
- # Caller should delegate to the default #require.
39
- # Returns :not_supported for files that are not supported (such as ike .so files)
40
- # Caller should delegate to the default #require.
79
+ # Throws :use_fallback in case caller should delegate to the default #require.
80
+ # Reasons given could be:
81
+ # - :not_found if the file couldn't be found.
82
+ # - :cover_failed if DeepCover couldn't apply instrumentation the file found.
83
+ # - :not_supported for files that are not supported (such as ike .so files)
84
+ # - :skipped if the filter block returned `true`
41
85
  # Exceptions raised by the required code bubble up as normal.
42
86
  # It is *NOT* recommended to simply delegate to the default #require, since it
43
87
  # might not be safe to run part of the code again.
44
88
  def require(path)
45
89
  ext = File.extname(path)
46
- return :not_supported if ext == '.so'
47
- path = path + '.rb' if ext != '.rb'
90
+ throw :use_fallback, :not_supported if ext == '.so'
91
+ path += '.rb' if ext != '.rb'
48
92
  return false if @loaded_features.include?(path)
49
93
 
50
94
  found_path = resolve_path(path)
51
95
 
52
- return :not_found unless found_path
96
+ throw :use_fallback, :not_found unless found_path
53
97
  return false if @loaded_features.include?(found_path)
54
98
 
55
- covered_code = cover_and_execute(found_path)
56
- return covered_code if covered_code.is_a?(Symbol)
99
+ throw :use_fallback, :skipped if filter && filter.call(found_path)
100
+
101
+ cover_and_execute(found_path)
57
102
 
58
103
  @loaded_features << found_path
59
104
  true
@@ -61,7 +106,7 @@ module DeepCover
61
106
 
62
107
  # Homemade #load to be able to instrument the code before it gets executed.
63
108
  # Note, this doesn't support the `wrap` parameter that ruby's #load has.
64
- # Same return/raise as CustomRequirer#require, except:
109
+ # Same return/throw as CustomRequirer#require, except:
65
110
  # Cannot return false since #load doesn't care about a file already being executed.
66
111
  def load(path)
67
112
  found_path = resolve_path(path)
@@ -69,18 +114,18 @@ module DeepCover
69
114
  if found_path.nil?
70
115
  # #load has a final fallback of always trying relative to current work directory of process
71
116
  possible_path = File.absolute_path(path)
72
- found_path = possible_path if File.exist?(possible_path)
117
+ found_path = possible_path if (@load_paths_subset || File).exist?(possible_path)
73
118
  end
74
119
 
75
- return :not_found unless found_path
120
+ throw :use_fallback, :not_found unless found_path
76
121
 
77
- covered_code = cover_and_execute(found_path)
78
- return covered_code if covered_code.is_a?(Symbol)
122
+ cover_and_execute(found_path)
79
123
 
80
124
  true
81
125
  end
82
126
 
83
127
  protected
128
+
84
129
  def cover_and_execute(path)
85
130
  begin
86
131
  covered_code = DeepCover.coverage.covered_code(path)
@@ -90,15 +135,17 @@ module DeepCover
90
135
  else
91
136
  warn "The file #{path} can't be instrumented"
92
137
  end
93
- return :cover_failed
138
+ throw :use_fallback, :cover_failed
94
139
  end
95
140
  DeepCover.autoload_tracker.wrap_require(path) do
96
141
  begin
97
142
  covered_code.execute_code
98
143
  rescue ::SyntaxError => e
99
- warn "DeepCover is getting confused with the file #{path} and it won't be instrumented.\n" +
100
- "Please report this error and provide the source code around the following:\n#{e}"
101
- return :cover_failed
144
+ warn ["DeepCover is getting confused with the file #{path} and it won't be instrumented.",
145
+ 'Please report this error and provide the source code around the following:',
146
+ e,
147
+ ].join("\n")
148
+ throw :use_fallback, :cover_failed
102
149
  end
103
150
  end
104
151
  covered_code
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ # Memoize is a quick way to prepend a module that defines
5
+ # the memoized methods as `@_cache ||= super.freeze`
6
+ # It also refines `freeze` to precache memoized methods
7
+ #
8
+ module Memoize
9
+ def self.included(base)
10
+ base.extend ClassMethods
11
+ end
12
+
13
+ def freeze
14
+ self.class.memoized.each do |method|
15
+ send method
16
+ end
17
+ super
18
+ end
19
+
20
+ module ClassMethods
21
+ def memoized
22
+ @memoized ||= [].freeze
23
+ end
24
+
25
+ def memoizer_module
26
+ @memoizer_module ||= begin
27
+ mod = const_set(:Memoizer, Module.new)
28
+ prepend mod
29
+ mod
30
+ end
31
+ end
32
+
33
+ def memoize(*methods)
34
+ @memoized ||= []
35
+ @memoized |= methods
36
+ @memoized.freeze
37
+
38
+ methods.each do |method|
39
+ memoizer_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
40
+ def #{method} # def foo
41
+ @_#{method} ||= super.freeze # @_foo ||= super.freeze
42
+ end # end
43
+ RUBY
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeepCover
2
4
  # Helps redefine methods in overriden_modules.
3
5
  # For each methods in Mod, this defines `<method>_with{out}_deep_cover`.
@@ -1,8 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeepCover
2
- class Node
4
+ class Node
3
5
  # Reopened in base
6
+ CLASSES = []
7
+ def self.inherited(parent)
8
+ CLASSES << parent
9
+ super
10
+ end
4
11
  end
5
12
  require_relative_dir 'node/mixin'
6
13
  require_relative 'node/base'
7
14
  require_relative_dir 'node'
15
+
16
+ require_relative 'memoize'
17
+ Node.include Memoize
18
+ Node::CLASSES.freeze.each do |klass|
19
+ klass.memoize :flow_entry_count, :flow_completion_count, :execution_count, :loc_hash
20
+ end
8
21
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'assignments'
2
4
 
3
5
  module DeepCover
@@ -1,5 +1,7 @@
1
- require_relative "const"
2
- require_relative "literals"
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'const'
4
+ require_relative 'literals'
3
5
 
4
6
  module DeepCover
5
7
  class Node
@@ -88,17 +90,17 @@ module DeepCover
88
90
  if method_name == :[]=
89
91
  selector = base[:selector]
90
92
  {
91
- expression: base[:expression],
92
- selector_begin: selector.resize(1),
93
- # The = is implicit, so only backtrack the end by one
94
- selector_end: Parser::Source::Range.new(selector.source_buffer, selector.end_pos - 1, selector.end_pos),
93
+ expression: base[:expression],
94
+ selector_begin: selector.resize(1),
95
+ # The = is implicit, so only backtrack the end by one
96
+ selector_end: Parser::Source::Range.new(selector.source_buffer, selector.end_pos - 1, selector.end_pos),
95
97
  }
96
98
  else
97
99
  {
98
- dot: base[:dot],
99
- expression: base[:expression],
100
- selector_begin: base[:selector],
101
- selector_end: nil#,
100
+ dot: base[:dot],
101
+ expression: base[:expression],
102
+ selector_begin: base[:selector],
103
+ selector_end: nil, # ,
102
104
  }
103
105
  end
104
106
  end
@@ -134,11 +136,11 @@ module DeepCover
134
136
  end
135
137
 
136
138
  BASE_MAP = {
137
- cvasgn: VariableAssignment, gvasgn: VariableAssignment,
138
- ivasgn: VariableAssignment, lvasgn: VariableAssignment,
139
- casgn: ConstantAssignment,
140
- send: Setter,
141
- }
139
+ cvasgn: VariableAssignment, gvasgn: VariableAssignment,
140
+ ivasgn: VariableAssignment, lvasgn: VariableAssignment,
141
+ casgn: ConstantAssignment,
142
+ send: Setter,
143
+ }.freeze
142
144
  class Splat < Node
143
145
  include BackwardsStrategy
144
146
  has_child rest_arg: [nil], remap: BASE_MAP
@@ -148,10 +150,10 @@ module DeepCover
148
150
  class LeftSide < Node
149
151
  include BackwardsStrategy
150
152
  has_extra_children receivers: {
151
- splat: Splat,
152
- mlhs: LeftSide,
153
- **BASE_MAP,
154
- }
153
+ splat: Splat,
154
+ mlhs: LeftSide,
155
+ **BASE_MAP,
156
+ }
155
157
  executed_loc_keys # none
156
158
 
157
159
  def flow_completion_count
@@ -195,7 +197,7 @@ module DeepCover
195
197
 
196
198
  def loc_hash
197
199
  base = super
198
- hash = { expression: base[:expression], begin: base[:begin], end: base[:end], dot: base[:dot]}
200
+ hash = {expression: base[:expression], begin: base[:begin], end: base[:end], dot: base[:dot]}
199
201
  selector = base[:selector]
200
202
 
201
203
  if [:[], :[]=].include?(method_name)
@@ -214,11 +216,11 @@ module DeepCover
214
216
  check_completion
215
217
  has_tracker :reader
216
218
  has_child receiver: {
217
- lvasgn: VariableOperatorAssign, ivasgn: VariableOperatorAssign,
218
- cvasgn: VariableOperatorAssign, gvasgn: VariableOperatorAssign,
219
- casgn: Casgn, # TODO
220
- send: SendOperatorAssign,
221
- }
219
+ lvasgn: VariableOperatorAssign, ivasgn: VariableOperatorAssign,
220
+ cvasgn: VariableOperatorAssign, gvasgn: VariableOperatorAssign,
221
+ casgn: Casgn, # TODO
222
+ send: SendOperatorAssign,
223
+ }
222
224
  has_child operator: Symbol
223
225
  has_child value: Node, rewrite: '(%{reader_tracker};%{node})', flow_entry_count: :reader_tracker_hits
224
226
  executed_loc_keys :operator
@@ -233,11 +235,11 @@ module DeepCover
233
235
  check_completion
234
236
  has_tracker :long_branch
235
237
  has_child receiver: {
236
- lvasgn: VariableOperatorAssign, ivasgn: VariableOperatorAssign,
237
- cvasgn: VariableOperatorAssign, gvasgn: VariableOperatorAssign,
238
- casgn: ConstantOperatorAssign,
239
- send: SendOperatorAssign,
240
- }
238
+ lvasgn: VariableOperatorAssign, ivasgn: VariableOperatorAssign,
239
+ cvasgn: VariableOperatorAssign, gvasgn: VariableOperatorAssign,
240
+ casgn: ConstantOperatorAssign,
241
+ send: SendOperatorAssign,
242
+ }
241
243
  has_child value: Node, rewrite: '(%{long_branch_tracker};%{node})', flow_entry_count: :long_branch_tracker_hits
242
244
  executed_loc_keys :operator
243
245
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeepCover
2
4
  # Base class to handle covered nodes.
3
5
  class Node
@@ -22,6 +24,7 @@ module DeepCover
22
24
  @children = []
23
25
  begin
24
26
  @children = augment_children(base_children)
27
+ initialize_siblings
25
28
  super()
26
29
  rescue StandardError => e
27
30
  diagnose(e)
@@ -36,11 +39,11 @@ module DeepCover
36
39
  when ::Class
37
40
  each_node.grep(lookup)
38
41
  when ::Symbol
39
- each_node.find_all{|n| n.type == lookup}
42
+ each_node.find_all { |n| n.type == lookup }
40
43
  when ::String
41
- each_node.find_all{|n| n.source == lookup}
44
+ each_node.find_all { |n| n.source == lookup }
42
45
  when ::Regexp
43
- each_node.find_all{|n| n.source =~ lookup}
46
+ each_node.find_all { |n| n.source =~ lookup }
44
47
  else
45
48
  binding.pry
46
49
  raise ::TypeError, "Expected class or symbol, got #{lookup.class}: #{lookup.inspect}"
@@ -70,28 +73,25 @@ module DeepCover
70
73
  end
71
74
 
72
75
  def children_nodes
73
- children.select{|c| c.is_a? Node }
76
+ children.select { |c| c.is_a? Node }
74
77
  end
75
78
  alias_method :children_nodes_in_flow_order, :children_nodes
76
79
 
77
- def next_sibling
78
- parent.children_nodes_in_flow_order.each_cons(2) do |child, next_child|
79
- return next_child if child.equal? self
80
- end
81
- nil
82
- end
83
-
84
- def previous_sibling
85
- parent.children_nodes_in_flow_order.each_cons(2) do |previous_child, child|
86
- return previous_child if child.equal? self
80
+ attr_accessor :next_sibling
81
+ attr_accessor :previous_sibling
82
+ protected :next_sibling=, :previous_sibling=
83
+ def initialize_siblings
84
+ children_nodes_in_flow_order.each_cons(2) do |child, next_child|
85
+ child.next_sibling = next_child
86
+ next_child.previous_sibling = child
87
87
  end
88
- nil
89
88
  end
89
+ private :initialize_siblings
90
90
 
91
91
  # Adapted from https://github.com/whitequark/ast/blob/master/lib/ast/node.rb
92
- def to_s(indent=0)
92
+ def to_s(indent = 0)
93
93
  [
94
- " " * indent,
94
+ ' ' * indent,
95
95
  '(',
96
96
  fancy_type,
97
97
  *children.map do |child, idx|
@@ -101,7 +101,7 @@ module DeepCover
101
101
  " #{child.inspect}"
102
102
  end
103
103
  end,
104
- ')'
104
+ ')',
105
105
  ].join
106
106
  end
107
107
 
@@ -128,25 +128,26 @@ module DeepCover
128
128
  end
129
129
 
130
130
  def fancy_type
131
- class_name = self.class.to_s.gsub(/^DeepCover::/,'').gsub(/^Node::/, '')
131
+ class_name = self.class.to_s.gsub(/^DeepCover::/, '').gsub(/^Node::/, '')
132
132
  t = type.to_s
133
133
  t.casecmp(class_name) == 0 ? t : "#{t}[#{class_name}]"
134
134
  end
135
135
 
136
136
  private
137
+
137
138
  def diagnose(exception)
138
139
  msg = if self.class == Node
139
- "Unknown node type encountered: #{base_node.type}"
140
- else
141
- "Node class #{self.class} incorrectly defined"
142
- end
140
+ "Unknown node type encountered: #{base_node.type}"
141
+ else
142
+ "Node class #{self.class} incorrectly defined"
143
+ end
143
144
  warn [msg,
144
- 'Attempting to continue, but this node will not be handled properly',
145
- ('Its subnodes will be ignored' if children.empty?),
146
- 'Source:',
147
- expression,
148
- "Original exception:",
149
- exception.inspect,
145
+ 'Attempting to continue, but this node will not be handled properly',
146
+ ('Its subnodes will be ignored' if children.empty?),
147
+ 'Source:',
148
+ expression,
149
+ 'Original exception:',
150
+ exception.inspect,
150
151
  ].join("\n")
151
152
  end
152
153
  end