super_diff 0.6.2 → 0.9.0

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 (186) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -1
  3. data/lib/super_diff/active_record/differs/active_record_relation.rb +3 -13
  4. data/lib/super_diff/active_record/object_inspection/{inspectors → inspection_tree_builders}/active_record_model.rb +19 -20
  5. data/lib/super_diff/active_record/object_inspection/{inspectors → inspection_tree_builders}/active_record_relation.rb +9 -8
  6. data/lib/super_diff/active_record/object_inspection/inspection_tree_builders.rb +16 -0
  7. data/lib/super_diff/active_record/object_inspection.rb +2 -6
  8. data/lib/super_diff/active_record/operation_tree_flatteners/active_record_relation.rb +17 -0
  9. data/lib/super_diff/active_record/operation_tree_flatteners.rb +10 -0
  10. data/lib/super_diff/active_record/operation_trees/active_record_relation.rb +8 -7
  11. data/lib/super_diff/active_record.rb +7 -7
  12. data/lib/super_diff/active_support/differs/hash_with_indifferent_access.rb +3 -13
  13. data/lib/super_diff/active_support/object_inspection/inspection_tree_builders/hash_with_indifferent_access.rb +37 -0
  14. data/lib/super_diff/active_support/object_inspection/{inspectors.rb → inspection_tree_builders.rb} +2 -2
  15. data/lib/super_diff/active_support/object_inspection.rb +2 -6
  16. data/lib/super_diff/active_support/operation_tree_builders/hash_with_indifferent_access.rb +17 -0
  17. data/lib/super_diff/active_support/operation_tree_flatteners/hash_with_indifferent_access.rb +17 -0
  18. data/lib/super_diff/active_support/operation_tree_flatteners.rb +10 -0
  19. data/lib/super_diff/active_support/operation_trees/hash_with_indifferent_access.rb +4 -7
  20. data/lib/super_diff/active_support.rb +8 -8
  21. data/lib/super_diff/colorized_document_extensions.rb +9 -6
  22. data/lib/super_diff/configuration.rb +81 -8
  23. data/lib/super_diff/csi/four_bit_color.rb +0 -2
  24. data/lib/super_diff/csi.rb +1 -2
  25. data/lib/super_diff/differs/array.rb +1 -1
  26. data/lib/super_diff/differs/base.rb +3 -21
  27. data/lib/super_diff/differs/custom_object.rb +1 -1
  28. data/lib/super_diff/differs/default_object.rb +1 -1
  29. data/lib/super_diff/differs/hash.rb +1 -1
  30. data/lib/super_diff/differs/main.rb +1 -7
  31. data/lib/super_diff/differs/multiline_string.rb +1 -1
  32. data/lib/super_diff/differs/time_like.rb +1 -1
  33. data/lib/super_diff/equality_matchers/array.rb +2 -2
  34. data/lib/super_diff/equality_matchers/default.rb +2 -2
  35. data/lib/super_diff/equality_matchers/hash.rb +2 -2
  36. data/lib/super_diff/equality_matchers/multiline_string.rb +2 -2
  37. data/lib/super_diff/equality_matchers/primitive.rb +4 -7
  38. data/lib/super_diff/equality_matchers/singleline_string.rb +2 -2
  39. data/lib/super_diff/helpers.rb +56 -2
  40. data/lib/super_diff/line.rb +83 -0
  41. data/lib/super_diff/object_inspection/inspection_tree.rb +183 -81
  42. data/lib/super_diff/object_inspection/inspection_tree_builders/array.rb +38 -0
  43. data/lib/super_diff/object_inspection/inspection_tree_builders/base.rb +27 -0
  44. data/lib/super_diff/object_inspection/inspection_tree_builders/custom_object.rb +37 -0
  45. data/lib/super_diff/object_inspection/inspection_tree_builders/default_object.rb +63 -0
  46. data/lib/super_diff/object_inspection/{inspectors → inspection_tree_builders}/defaults.rb +1 -2
  47. data/lib/super_diff/object_inspection/inspection_tree_builders/hash.rb +46 -0
  48. data/lib/super_diff/object_inspection/{inspectors → inspection_tree_builders}/main.rb +5 -10
  49. data/lib/super_diff/object_inspection/inspection_tree_builders/primitive.rb +21 -0
  50. data/lib/super_diff/object_inspection/inspection_tree_builders/time_like.rb +64 -0
  51. data/lib/super_diff/object_inspection/inspection_tree_builders.rb +44 -0
  52. data/lib/super_diff/object_inspection/nodes/as_lines_when_rendering_to_lines.rb +97 -0
  53. data/lib/super_diff/object_inspection/nodes/as_prefix_when_rendering_to_lines.rb +27 -0
  54. data/lib/super_diff/object_inspection/nodes/as_prelude_when_rendering_to_lines.rb +27 -0
  55. data/lib/super_diff/object_inspection/nodes/as_single_line.rb +33 -0
  56. data/lib/super_diff/object_inspection/nodes/base.rb +55 -20
  57. data/lib/super_diff/object_inspection/nodes/inspection.rb +47 -7
  58. data/lib/super_diff/object_inspection/nodes/nesting.rb +16 -5
  59. data/lib/super_diff/object_inspection/nodes/only_when.rb +54 -0
  60. data/lib/super_diff/object_inspection/nodes/text.rb +16 -2
  61. data/lib/super_diff/object_inspection/nodes/when_empty.rb +21 -6
  62. data/lib/super_diff/object_inspection/nodes/when_non_empty.rb +20 -5
  63. data/lib/super_diff/object_inspection/nodes/when_rendering_to_lines.rb +27 -0
  64. data/lib/super_diff/object_inspection/nodes/when_rendering_to_string.rb +27 -0
  65. data/lib/super_diff/object_inspection/nodes.rb +33 -32
  66. data/lib/super_diff/object_inspection/prefix_for_next_node.rb +6 -0
  67. data/lib/super_diff/object_inspection/prelude_for_next_node.rb +6 -0
  68. data/lib/super_diff/object_inspection.rb +12 -1
  69. data/lib/super_diff/operation_tree_builders/array.rb +7 -10
  70. data/lib/super_diff/operation_tree_builders/base.rb +6 -6
  71. data/lib/super_diff/operation_tree_builders/custom_object.rb +5 -2
  72. data/lib/super_diff/operation_tree_builders/default_object.rb +1 -1
  73. data/lib/super_diff/operation_tree_builders/defaults.rb +1 -1
  74. data/lib/super_diff/operation_tree_builders/hash.rb +1 -8
  75. data/lib/super_diff/operation_tree_builders/multiline_string.rb +2 -6
  76. data/lib/super_diff/operation_tree_builders/time_like.rb +2 -2
  77. data/lib/super_diff/operation_tree_flatteners/array.rb +15 -0
  78. data/lib/super_diff/operation_tree_flatteners/base.rb +54 -0
  79. data/lib/super_diff/operation_tree_flatteners/collection.rb +139 -0
  80. data/lib/super_diff/operation_tree_flatteners/custom_object.rb +28 -0
  81. data/lib/super_diff/operation_tree_flatteners/default_object.rb +32 -0
  82. data/lib/super_diff/operation_tree_flatteners/hash.rb +41 -0
  83. data/lib/super_diff/operation_tree_flatteners/multiline_string.rb +17 -0
  84. data/lib/super_diff/operation_tree_flatteners.rb +20 -0
  85. data/lib/super_diff/operation_trees/array.rb +4 -7
  86. data/lib/super_diff/operation_trees/base.rb +39 -16
  87. data/lib/super_diff/operation_trees/custom_object.rb +4 -8
  88. data/lib/super_diff/operation_trees/default_object.rb +28 -13
  89. data/lib/super_diff/operation_trees/hash.rb +4 -7
  90. data/lib/super_diff/operation_trees/main.rb +1 -1
  91. data/lib/super_diff/operation_trees/multiline_string.rb +4 -7
  92. data/lib/super_diff/operations/binary_operation.rb +1 -6
  93. data/lib/super_diff/operations/unary_operation.rb +2 -30
  94. data/lib/super_diff/recursion_guard.rb +3 -3
  95. data/lib/super_diff/rspec/differs/collection_including.rb +4 -2
  96. data/lib/super_diff/rspec/differs/hash_including.rb +4 -2
  97. data/lib/super_diff/rspec/monkey_patches.rb +2 -2
  98. data/lib/super_diff/rspec/object_inspection/{inspectors → inspection_tree_builders}/collection_containing_exactly.rb +9 -8
  99. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/collection_including.rb +34 -0
  100. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/double.rb +103 -0
  101. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/hash_including.rb +36 -0
  102. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/instance_of.rb +26 -0
  103. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/kind_of.rb +26 -0
  104. data/lib/super_diff/rspec/object_inspection/{inspectors → inspection_tree_builders}/object_having_attributes.rb +10 -12
  105. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/primitive.rb +10 -0
  106. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/value_within.rb +33 -0
  107. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders.rb +44 -0
  108. data/lib/super_diff/rspec/object_inspection.rb +4 -1
  109. data/lib/super_diff/rspec/operation_tree_builders/collection_containing_exactly.rb +0 -3
  110. data/lib/super_diff/rspec/operation_tree_builders/collection_including.rb +10 -3
  111. data/lib/super_diff/rspec/operation_tree_builders/hash_including.rb +10 -3
  112. data/lib/super_diff/rspec.rb +34 -13
  113. data/lib/super_diff/tiered_lines.rb +4 -0
  114. data/lib/super_diff/tiered_lines_elider.rb +490 -0
  115. data/lib/super_diff/tiered_lines_formatter.rb +79 -0
  116. data/lib/super_diff/version.rb +1 -1
  117. data/lib/super_diff.rb +28 -6
  118. data/spec/examples.txt +482 -403
  119. data/spec/integration/rails/active_support_spec.rb +19 -0
  120. data/spec/integration/rspec/contain_exactly_matcher_spec.rb +12 -6
  121. data/spec/integration/rspec/eq_matcher_spec.rb +33 -87
  122. data/spec/integration/rspec/have_attributes_matcher_spec.rb +17 -8
  123. data/spec/integration/rspec/match_array_matcher_spec.rb +14 -7
  124. data/spec/integration/rspec/match_matcher_spec.rb +93 -5
  125. data/spec/spec_helper.rb +4 -1
  126. data/spec/support/command_runner.rb +15 -25
  127. data/spec/support/helpers.rb +21 -0
  128. data/spec/support/integration/helpers.rb +2 -0
  129. data/spec/support/integration/matchers/produce_output_when_run_matcher.rb +3 -3
  130. data/spec/support/integration/test_programs/base.rb +36 -10
  131. data/spec/support/shared_examples/active_record.rb +3 -2
  132. data/spec/support/shared_examples/active_support.rb +65 -0
  133. data/spec/support/shared_examples/elided_diffs.rb +914 -0
  134. data/spec/support/shared_examples/hash_with_indifferent_access.rb +16 -16
  135. data/spec/support/unit/helpers.rb +15 -0
  136. data/spec/support/unit/matchers/match_output.rb +41 -0
  137. data/spec/tmp/warnings_logger/all_warnings.txt +2 -0
  138. data/spec/unit/active_record/object_inspection_spec.rb +273 -0
  139. data/spec/unit/equality_matchers/main_spec.rb +55 -75
  140. data/spec/unit/helpers_spec.rb +75 -0
  141. data/spec/unit/operation_tree_flatteners/array_spec.rb +604 -0
  142. data/spec/unit/operation_tree_flatteners/custom_object_spec.rb +667 -0
  143. data/spec/unit/operation_tree_flatteners/default_object_spec.rb +687 -0
  144. data/spec/unit/operation_tree_flatteners/hash_spec.rb +632 -0
  145. data/spec/unit/operation_tree_flatteners/multiline_string_spec.rb +121 -0
  146. data/spec/unit/rspec/object_inspection_spec.rb +446 -0
  147. data/spec/unit/super_diff_spec.rb +1530 -800
  148. data/spec/unit/tiered_lines_elider_spec.rb +6356 -0
  149. data/spec/unit/tiered_lines_formatter_spec.rb +193 -0
  150. metadata +91 -52
  151. data/lib/super_diff/active_record/diff_formatters/active_record_relation.rb +0 -23
  152. data/lib/super_diff/active_record/diff_formatters.rb +0 -10
  153. data/lib/super_diff/active_record/object_inspection/inspectors.rb +0 -16
  154. data/lib/super_diff/active_support/diff_formatters/hash_with_indifferent_access.rb +0 -36
  155. data/lib/super_diff/active_support/diff_formatters.rb +0 -10
  156. data/lib/super_diff/active_support/object_inspection/inspectors/hash_with_indifferent_access.rb +0 -28
  157. data/lib/super_diff/diff_formatters/array.rb +0 -21
  158. data/lib/super_diff/diff_formatters/base.rb +0 -33
  159. data/lib/super_diff/diff_formatters/custom_object.rb +0 -30
  160. data/lib/super_diff/diff_formatters/default_object.rb +0 -46
  161. data/lib/super_diff/diff_formatters/defaults.rb +0 -10
  162. data/lib/super_diff/diff_formatters/hash.rb +0 -34
  163. data/lib/super_diff/diff_formatters/main.rb +0 -41
  164. data/lib/super_diff/diff_formatters.rb +0 -14
  165. data/lib/super_diff/object_inspection/inspectors/array.rb +0 -32
  166. data/lib/super_diff/object_inspection/inspectors/base.rb +0 -36
  167. data/lib/super_diff/object_inspection/inspectors/custom_object.rb +0 -37
  168. data/lib/super_diff/object_inspection/inspectors/default_object.rb +0 -61
  169. data/lib/super_diff/object_inspection/inspectors/hash.rb +0 -32
  170. data/lib/super_diff/object_inspection/inspectors/primitive.rb +0 -28
  171. data/lib/super_diff/object_inspection/inspectors/string.rb +0 -23
  172. data/lib/super_diff/object_inspection/inspectors/time_like.rb +0 -23
  173. data/lib/super_diff/object_inspection/inspectors.rb +0 -23
  174. data/lib/super_diff/object_inspection/nodes/break.rb +0 -15
  175. data/lib/super_diff/object_inspection/nodes/when_multiline.rb +0 -22
  176. data/lib/super_diff/object_inspection/nodes/when_singleline.rb +0 -24
  177. data/lib/super_diff/rspec/object_inspection/inspectors/collection_including.rb +0 -28
  178. data/lib/super_diff/rspec/object_inspection/inspectors/hash_including.rb +0 -31
  179. data/lib/super_diff/rspec/object_inspection/inspectors/instance_of.rb +0 -23
  180. data/lib/super_diff/rspec/object_inspection/inspectors/kind_of.rb +0 -23
  181. data/lib/super_diff/rspec/object_inspection/inspectors/primitive.rb +0 -13
  182. data/lib/super_diff/rspec/object_inspection/inspectors/value_within.rb +0 -29
  183. data/lib/super_diff/rspec/object_inspection/inspectors.rb +0 -40
  184. data/spec/combustion/Gemfile.lock +0 -173
  185. data/spec/support/object_id.rb +0 -27
  186. data/spec/support/ruby_versions.rb +0 -11
@@ -3,7 +3,8 @@ module SuperDiff
3
3
  class InspectionTree
4
4
  include Enumerable
5
5
 
6
- def initialize(&block)
6
+ def initialize(disallowed_node_names: [], &block)
7
+ @disallowed_node_names = disallowed_node_names
7
8
  @nodes = []
8
9
 
9
10
  if block
@@ -11,6 +12,12 @@ module SuperDiff
11
12
  end
12
13
  end
13
14
 
15
+ Nodes.registry.each do |node_class|
16
+ define_method(node_class.method_name) do |*args, **options, &block|
17
+ add_node(node_class, *args, **options, &block)
18
+ end
19
+ end
20
+
14
21
  def each(&block)
15
22
  nodes.each(&block)
16
23
  end
@@ -19,129 +26,224 @@ module SuperDiff
19
26
  @_before_each_callbacks ||= Hash.new { |h, k| h[k] = [] }
20
27
  end
21
28
 
22
- def evaluate(object, as_single_line:, indent_level:)
23
- nodes.reduce("") do |str, node|
24
- str << node.evaluate(
25
- object,
26
- as_single_line: as_single_line,
27
- indent_level: indent_level,
28
- )
29
+ def render_to_string(object)
30
+ nodes.reduce("") do |string, node|
31
+ result = node.render_to_string(object)
32
+ string + result
29
33
  end
30
34
  end
31
35
 
32
- def evaluate_block(object, &block)
33
- instance_exec(object, &block)
34
- end
35
-
36
- def add_text(*args, &block)
37
- add_node :text, *args, &block
38
- end
39
-
40
- def when_multiline(&block)
41
- add_node :when_multiline, &block
42
- end
43
-
44
- def when_singleline(&block)
45
- add_node :when_singleline, &block
46
- end
47
-
48
- def add_break(*args, &block)
49
- add_node :break, *args, &block
50
- end
51
-
52
- def nested(&block)
53
- add_node :nesting, &block
54
- end
55
-
56
- def when_empty(&block)
57
- add_node :when_empty, &block
36
+ def render_to_lines(object, type:, indentation_level:)
37
+ nodes.
38
+ each_with_index.
39
+ reduce([TieredLines.new, "", ""]) do |
40
+ (tiered_lines, prelude, prefix),
41
+ (node, index)
42
+ |
43
+ UpdateTieredLines.call(
44
+ object: object,
45
+ type: type,
46
+ indentation_level: indentation_level,
47
+ nodes: nodes,
48
+ tiered_lines: tiered_lines,
49
+ prelude: prelude,
50
+ prefix: prefix,
51
+ node: node,
52
+ index: index,
53
+ )
54
+ end.
55
+ first
58
56
  end
59
57
 
60
- def when_non_empty(&block)
61
- add_node :when_non_empty, &block
58
+ def evaluate_block(object, &block)
59
+ instance_exec(object, &block)
62
60
  end
63
61
 
64
62
  def insert_array_inspection_of(array)
65
- # FIXME: why must this be inside the `nested`?
66
- add_break
67
-
68
63
  insert_separated_list(array) do |value|
69
- add_inspection_of value
64
+ # Have to do these shenanigans so that if value is a hash, Ruby
65
+ # doesn't try to interpret it as keyword args
66
+ if SuperDiff::Helpers.ruby_version_matches?(">= 2.7.1")
67
+ add_inspection_of(value, **{})
68
+ else
69
+ add_inspection_of(*[value, {}])
70
+ end
70
71
  end
71
72
  end
72
73
 
73
- def insert_hash_inspection_of(hash, initial_break: " ")
74
- # FIXME: why must this be inside the `nested`?
75
- add_break initial_break
74
+ def insert_hash_inspection_of(hash)
75
+ keys = hash.keys
76
76
 
77
- format_keys_as_kwargs = hash.keys.all? do |key|
77
+ format_keys_as_kwargs = keys.all? do |key|
78
78
  key.is_a?(Symbol)
79
79
  end
80
80
 
81
- insert_separated_list(hash) do |(key, value)|
81
+ insert_separated_list(keys) do |key|
82
82
  if format_keys_as_kwargs
83
- add_text key
84
- add_text ": "
83
+ as_prefix_when_rendering_to_lines do
84
+ add_text "#{key}: "
85
+ end
85
86
  else
86
- add_inspection_of key
87
- add_text " => "
87
+ as_prefix_when_rendering_to_lines do
88
+ add_inspection_of key, as_lines: false
89
+ add_text " => "
90
+ end
88
91
  end
89
92
 
90
- add_inspection_of value
93
+ # Have to do these shenanigans so that if hash[key] is a hash, Ruby
94
+ # doesn't try to interpret it as keyword args
95
+ if SuperDiff::Helpers.ruby_version_matches?(">= 2.7.1")
96
+ add_inspection_of(hash[key], **{})
97
+ else
98
+ add_inspection_of(*[hash[key], {}])
99
+ end
91
100
  end
92
101
  end
93
102
 
94
- def insert_separated_list(enumerable, separator: ",")
103
+ def insert_separated_list(enumerable, &block)
95
104
  enumerable.each_with_index do |value, index|
96
- if index > 0
97
- if separator.is_a?(Nodes::Base)
98
- append_node separator
99
- else
100
- add_text separator
105
+ as_lines_when_rendering_to_lines(
106
+ add_comma: index < enumerable.size - 1,
107
+ ) do
108
+ if index > 0
109
+ when_rendering_to_string do
110
+ add_text " "
111
+ end
101
112
  end
102
113
 
103
- add_break " "
114
+ evaluate_block(value, &block)
104
115
  end
105
-
106
- yield value
107
- end
108
- end
109
-
110
- def add_inspection_of(value = nil, &block)
111
- if block
112
- add_node :inspection, &block
113
- else
114
- add_node :inspection, value
115
- end
116
- end
117
-
118
- def apply_tree(tree)
119
- tree.each do |node|
120
- append_node(node.clone_with(tree: self))
121
116
  end
122
117
  end
123
118
 
124
119
  private
125
120
 
126
- attr_reader :nodes
121
+ attr_reader :disallowed_node_names, :nodes
127
122
 
128
- def add_node(type, *args, &block)
129
- append_node(build_node(type, *args, &block))
123
+ def add_node(node_class, *args, **options, &block)
124
+ if disallowed_node_names.include?(node_class.name)
125
+ raise DisallowedNodeError.create(node_name: node_class.name)
126
+ end
127
+
128
+ append_node(build_node(node_class, *args, **options, &block))
130
129
  end
131
130
 
132
131
  def append_node(node)
133
132
  nodes.push(node)
134
133
  end
135
134
 
136
- def build_node(type, *args, &block)
137
- Nodes.fetch(type).new(self, *args, &block)
135
+ def build_node(node_class, *args, **options, &block)
136
+ node_class.new(self, *args, **options, &block)
138
137
  end
139
138
 
140
- class BlockArgument
139
+ class UpdateTieredLines
141
140
  extend AttrExtras.mixin
142
141
 
143
- rattr_initialize [:object!, :as_single_line!]
144
- attr_query :as_single_line?
142
+ method_object [
143
+ :object!,
144
+ :type!,
145
+ :indentation_level!,
146
+ :nodes!,
147
+ :tiered_lines!,
148
+ :prelude!,
149
+ :prefix!,
150
+ :node!,
151
+ :index!
152
+ ]
153
+
154
+ def call
155
+ if rendering.is_a?(Array)
156
+ concat_with_lines
157
+ elsif rendering.is_a?(PrefixForNextNode)
158
+ add_to_prefix
159
+ elsif tiered_lines.any?
160
+ add_to_last_line
161
+ elsif index < nodes.size - 1 || rendering.is_a?(PreludeForNextNode)
162
+ add_to_prelude
163
+ else
164
+ add_to_lines
165
+ end
166
+ end
167
+
168
+ private
169
+
170
+ def concat_with_lines
171
+ additional_lines = prefix_with(
172
+ prefix,
173
+ prepend_with(prelude, rendering),
174
+ )
175
+ [tiered_lines + additional_lines, "", ""]
176
+ end
177
+
178
+ def prefix_with(prefix, text)
179
+ if prefix.empty?
180
+ text
181
+ else
182
+ [text[0].prefixed_with(prefix)] + text[1..-1]
183
+ end
184
+ end
185
+
186
+ def prepend_with(prelude, text)
187
+ if prelude.empty?
188
+ text
189
+ else
190
+ [text[0].with_value_prepended(prelude)] + text[1..-1]
191
+ end
192
+ end
193
+
194
+ def add_to_prefix
195
+ [tiered_lines, prelude, rendering + prefix]
196
+ end
197
+
198
+ def add_to_last_line
199
+ new_lines = tiered_lines[0..-2] + [
200
+ tiered_lines[-1].with_value_appended(rendering),
201
+ ]
202
+ [new_lines, prelude, prefix]
203
+ end
204
+
205
+ def add_to_prelude
206
+ [tiered_lines, prelude + rendering, prefix]
207
+ end
208
+
209
+ def add_to_lines
210
+ new_lines = tiered_lines + [
211
+ Line.new(
212
+ type: type,
213
+ indentation_level: indentation_level,
214
+ value: rendering,
215
+ ),
216
+ ]
217
+ [new_lines, prelude, prefix]
218
+ end
219
+
220
+ def rendering
221
+ if defined?(@_rendering)
222
+ @_rendering
223
+ else
224
+ @_rendering = node.render(
225
+ object,
226
+ preferably_as_lines: true,
227
+ type: type,
228
+ indentation_level: indentation_level,
229
+ )
230
+ end
231
+ end
232
+ end
233
+
234
+ class DisallowedNodeError < StandardError
235
+ def self.create(node_name:)
236
+ allocate.tap do |error|
237
+ error.node_name = node_name
238
+ error.__send__(:initialize)
239
+ end
240
+ end
241
+
242
+ attr_accessor :node_name
243
+
244
+ def initialize(_message = nil)
245
+ super("#{node_name} is not allowed to be used here!")
246
+ end
145
247
  end
146
248
  end
147
249
  end
@@ -0,0 +1,38 @@
1
+ module SuperDiff
2
+ module ObjectInspection
3
+ module InspectionTreeBuilders
4
+ class Array < Base
5
+ def self.applies_to?(value)
6
+ value.is_a?(::Array)
7
+ end
8
+
9
+ def call
10
+ empty = -> { object.empty? }
11
+ nonempty = -> { !object.empty? }
12
+
13
+ InspectionTree.new do
14
+ only_when empty do
15
+ as_lines_when_rendering_to_lines do
16
+ add_text "[]"
17
+ end
18
+ end
19
+
20
+ only_when nonempty do
21
+ as_lines_when_rendering_to_lines(collection_bookend: :open) do
22
+ add_text "["
23
+ end
24
+
25
+ nested do |array|
26
+ insert_array_inspection_of(array)
27
+ end
28
+
29
+ as_lines_when_rendering_to_lines(collection_bookend: :close) do
30
+ add_text "]"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,27 @@
1
+ module SuperDiff
2
+ module ObjectInspection
3
+ module InspectionTreeBuilders
4
+ class Base
5
+ extend AttrExtras.mixin
6
+ extend ImplementationChecks
7
+ include ImplementationChecks
8
+
9
+ def self.applies_to?(_value)
10
+ unimplemented_class_method!
11
+ end
12
+
13
+ method_object :object
14
+
15
+ def call
16
+ unimplemented_instance_method!
17
+ end
18
+
19
+ protected
20
+
21
+ def inspection_tree
22
+ unimplemented_instance_method!
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,37 @@
1
+ module SuperDiff
2
+ module ObjectInspection
3
+ module InspectionTreeBuilders
4
+ class CustomObject < Base
5
+ def self.applies_to?(value)
6
+ value.respond_to?(:attributes_for_super_diff)
7
+ end
8
+
9
+ def call
10
+ InspectionTree.new do
11
+ as_lines_when_rendering_to_lines(collection_bookend: :open) do
12
+ add_text do |object|
13
+ "#<#{object.class} "
14
+ end
15
+
16
+ when_rendering_to_lines do
17
+ add_text "{"
18
+ end
19
+ end
20
+
21
+ nested do |object|
22
+ insert_hash_inspection_of(object.attributes_for_super_diff)
23
+ end
24
+
25
+ as_lines_when_rendering_to_lines(collection_bookend: :close) do
26
+ when_rendering_to_lines do
27
+ add_text "}"
28
+ end
29
+
30
+ add_text ">"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,63 @@
1
+ module SuperDiff
2
+ module ObjectInspection
3
+ module InspectionTreeBuilders
4
+ class DefaultObject < Base
5
+ def self.applies_to?(_value)
6
+ true
7
+ end
8
+
9
+ def call
10
+ empty = -> { object.instance_variables.empty? }
11
+ nonempty = -> { !object.instance_variables.empty? }
12
+
13
+ InspectionTree.new do
14
+ only_when empty do
15
+ as_lines_when_rendering_to_lines do
16
+ add_text do |object|
17
+ "#<#{object.class.name}:" +
18
+ SuperDiff::Helpers.object_address_for(object) +
19
+ ">"
20
+ end
21
+ end
22
+ end
23
+
24
+ only_when nonempty do
25
+ as_lines_when_rendering_to_lines(collection_bookend: :open) do
26
+ add_text do |object|
27
+ "#<#{object.class.name}:" +
28
+ SuperDiff::Helpers.object_address_for(object)
29
+ end
30
+
31
+ when_rendering_to_lines do
32
+ add_text " {"
33
+ end
34
+ end
35
+
36
+ when_rendering_to_string do
37
+ add_text " "
38
+ end
39
+
40
+ nested do |object|
41
+ insert_separated_list(object.instance_variables.sort) do |name|
42
+ as_prefix_when_rendering_to_lines do
43
+ add_text "#{name}="
44
+ end
45
+
46
+ add_inspection_of object.instance_variable_get(name)
47
+ end
48
+ end
49
+
50
+ as_lines_when_rendering_to_lines(collection_bookend: :close) do
51
+ when_rendering_to_lines do
52
+ add_text "}"
53
+ end
54
+
55
+ add_text ">"
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -1,12 +1,11 @@
1
1
  module SuperDiff
2
2
  module ObjectInspection
3
- module Inspectors
3
+ module InspectionTreeBuilders
4
4
  DEFAULTS = [
5
5
  CustomObject,
6
6
  Array,
7
7
  Hash,
8
8
  Primitive,
9
- String,
10
9
  TimeLike,
11
10
  DefaultObject,
12
11
  ].freeze
@@ -0,0 +1,46 @@
1
+ module SuperDiff
2
+ module ObjectInspection
3
+ module InspectionTreeBuilders
4
+ class Hash < Base
5
+ def self.applies_to?(value)
6
+ value.is_a?(::Hash)
7
+ end
8
+
9
+ def call
10
+ empty = -> { object.empty? }
11
+ nonempty = -> { !object.empty? }
12
+
13
+ InspectionTree.new do
14
+ only_when empty do
15
+ as_lines_when_rendering_to_lines do
16
+ add_text "{}"
17
+ end
18
+ end
19
+
20
+ only_when nonempty do
21
+ as_lines_when_rendering_to_lines(collection_bookend: :open) do
22
+ add_text "{"
23
+ end
24
+
25
+ when_rendering_to_string do
26
+ add_text " "
27
+ end
28
+
29
+ nested do |hash|
30
+ insert_hash_inspection_of(hash)
31
+ end
32
+
33
+ when_rendering_to_string do
34
+ add_text " "
35
+ end
36
+
37
+ as_lines_when_rendering_to_lines(collection_bookend: :close) do
38
+ add_text "}"
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,18 +1,14 @@
1
1
  module SuperDiff
2
2
  module ObjectInspection
3
- module Inspectors
3
+ module InspectionTreeBuilders
4
4
  class Main
5
5
  extend AttrExtras.mixin
6
6
 
7
- method_object :object, [:as_single_line!, :indent_level!]
7
+ method_object :object
8
8
 
9
9
  def call
10
10
  if resolved_class
11
- resolved_class.call(
12
- object,
13
- as_single_line: as_single_line?,
14
- indent_level: indent_level,
15
- )
11
+ resolved_class.call(object)
16
12
  else
17
13
  raise NoInspectorAvailableError.create(object)
18
14
  end
@@ -20,14 +16,13 @@ module SuperDiff
20
16
 
21
17
  private
22
18
 
23
- attr_query :as_single_line?
24
-
25
19
  def resolved_class
26
20
  available_classes.find { |klass| klass.applies_to?(object) }
27
21
  end
28
22
 
29
23
  def available_classes
30
- SuperDiff.configuration.extra_inspector_classes + DEFAULTS
24
+ SuperDiff.configuration.extra_inspection_tree_builder_classes +
25
+ DEFAULTS
31
26
  end
32
27
  end
33
28
  end
@@ -0,0 +1,21 @@
1
+ module SuperDiff
2
+ module ObjectInspection
3
+ module InspectionTreeBuilders
4
+ class Primitive < Base
5
+ def self.applies_to?(value)
6
+ SuperDiff.primitive?(value) || value.is_a?(::String)
7
+ end
8
+
9
+ def call
10
+ InspectionTree.new do
11
+ as_lines_when_rendering_to_lines do
12
+ # rubocop:disable Style/SymbolProc
13
+ add_text { |object| object.inspect }
14
+ # rubocop:enable Style/SymbolProc
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,64 @@
1
+ module SuperDiff
2
+ module ObjectInspection
3
+ module InspectionTreeBuilders
4
+ class TimeLike < Base
5
+ def self.applies_to?(value)
6
+ SuperDiff.time_like?(value)
7
+ end
8
+
9
+ def call
10
+ InspectionTree.new do
11
+ as_lines_when_rendering_to_lines(collection_bookend: :open) do
12
+ add_text do |time|
13
+ "#<#{time.class} "
14
+ end
15
+
16
+ when_rendering_to_lines do
17
+ add_text "{"
18
+ end
19
+ end
20
+
21
+ when_rendering_to_string do
22
+ add_text do |time|
23
+ time.strftime("%Y-%m-%d %H:%M:%S") +
24
+ (time.subsec == 0 ? "" : "+#{time.subsec.inspect}") +
25
+ " " + time.strftime("%:z") +
26
+ (time.zone ? " (#{time.zone})" : "")
27
+ end
28
+ end
29
+
30
+ when_rendering_to_lines do
31
+ nested do |time|
32
+ insert_separated_list(
33
+ [
34
+ :year,
35
+ :month,
36
+ :day,
37
+ :hour,
38
+ :min,
39
+ :sec,
40
+ :subsec,
41
+ :zone,
42
+ :utc_offset
43
+ ]
44
+ ) do |name|
45
+ add_text name.to_s
46
+ add_text ": "
47
+ add_inspection_of time.public_send(name)
48
+ end
49
+ end
50
+ end
51
+
52
+ as_lines_when_rendering_to_lines(collection_bookend: :close) do
53
+ when_rendering_to_lines do
54
+ add_text "}"
55
+ end
56
+
57
+ add_text ">"
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end