deep-cover 0.1.14 → 0.1.15

Sign up to get free protection for your applications and to get access to all the features.
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