super_diff 0.11.0 → 0.12.1

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 (231) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +19 -166
  3. data/lib/super_diff/active_record/differs/active_record_relation.rb +1 -1
  4. data/lib/super_diff/active_record/inspection_tree_builders/active_record_model.rb +57 -0
  5. data/lib/super_diff/active_record/inspection_tree_builders/active_record_relation.rb +34 -0
  6. data/lib/super_diff/active_record/inspection_tree_builders.rb +14 -0
  7. data/lib/super_diff/active_record/monkey_patches.rb +6 -3
  8. data/lib/super_diff/active_record/object_inspection.rb +16 -4
  9. data/lib/super_diff/active_record/operation_tree_builders/active_record_model.rb +6 -2
  10. data/lib/super_diff/active_record/operation_tree_builders/active_record_relation.rb +1 -1
  11. data/lib/super_diff/active_record/operation_tree_flatteners/active_record_relation.rb +1 -1
  12. data/lib/super_diff/active_record/operation_trees/active_record_relation.rb +1 -1
  13. data/lib/super_diff/active_record.rb +12 -16
  14. data/lib/super_diff/active_support/differs/hash_with_indifferent_access.rb +1 -1
  15. data/lib/super_diff/active_support/inspection_tree_builders/hash_with_indifferent_access.rb +44 -0
  16. data/lib/super_diff/active_support/inspection_tree_builders/ordered_options.rb +44 -0
  17. data/lib/super_diff/active_support/inspection_tree_builders.rb +14 -0
  18. data/lib/super_diff/active_support/object_inspection.rb +16 -4
  19. data/lib/super_diff/active_support/operation_tree_builders/hash_with_indifferent_access.rb +1 -1
  20. data/lib/super_diff/active_support/operation_tree_flatteners/hash_with_indifferent_access.rb +1 -1
  21. data/lib/super_diff/active_support/operation_trees/hash_with_indifferent_access.rb +1 -1
  22. data/lib/super_diff/active_support.rb +11 -15
  23. data/lib/super_diff/basic/diff_formatters/collection.rb +135 -0
  24. data/lib/super_diff/basic/diff_formatters/multiline_string.rb +34 -0
  25. data/lib/super_diff/basic/diff_formatters.rb +11 -0
  26. data/lib/super_diff/basic/differs/array.rb +17 -0
  27. data/lib/super_diff/basic/differs/custom_object.rb +19 -0
  28. data/lib/super_diff/basic/differs/date_like.rb +17 -0
  29. data/lib/super_diff/basic/differs/default_object.rb +24 -0
  30. data/lib/super_diff/basic/differs/hash.rb +17 -0
  31. data/lib/super_diff/basic/differs/multiline_string.rb +18 -0
  32. data/lib/super_diff/basic/differs/time_like.rb +17 -0
  33. data/lib/super_diff/basic/differs.rb +24 -0
  34. data/lib/super_diff/{object_inspection → basic}/inspection_tree_builders/array.rb +3 -3
  35. data/lib/super_diff/{object_inspection → basic}/inspection_tree_builders/custom_object.rb +3 -3
  36. data/lib/super_diff/{object_inspection → basic}/inspection_tree_builders/date_like.rb +3 -3
  37. data/lib/super_diff/{object_inspection → basic}/inspection_tree_builders/default_object.rb +5 -7
  38. data/lib/super_diff/{object_inspection → basic}/inspection_tree_builders/hash.rb +3 -3
  39. data/lib/super_diff/{object_inspection → basic}/inspection_tree_builders/primitive.rb +3 -3
  40. data/lib/super_diff/{object_inspection → basic}/inspection_tree_builders/time_like.rb +3 -3
  41. data/lib/super_diff/basic/inspection_tree_builders.rb +20 -0
  42. data/lib/super_diff/basic/operation_tree_builders/array.rb +111 -0
  43. data/lib/super_diff/basic/operation_tree_builders/custom_object.rb +42 -0
  44. data/lib/super_diff/basic/operation_tree_builders/date_like.rb +17 -0
  45. data/lib/super_diff/basic/operation_tree_builders/default_object.rb +117 -0
  46. data/lib/super_diff/basic/operation_tree_builders/hash.rb +222 -0
  47. data/lib/super_diff/basic/operation_tree_builders/multiline_string.rb +90 -0
  48. data/lib/super_diff/basic/operation_tree_builders/time_like.rb +26 -0
  49. data/lib/super_diff/basic/operation_tree_builders.rb +34 -0
  50. data/lib/super_diff/basic/operation_tree_flatteners/array.rb +17 -0
  51. data/lib/super_diff/basic/operation_tree_flatteners/collection.rb +140 -0
  52. data/lib/super_diff/basic/operation_tree_flatteners/custom_object.rb +30 -0
  53. data/lib/super_diff/basic/operation_tree_flatteners/default_object.rb +32 -0
  54. data/lib/super_diff/basic/operation_tree_flatteners/hash.rb +35 -0
  55. data/lib/super_diff/basic/operation_tree_flatteners/multiline_string.rb +20 -0
  56. data/lib/super_diff/basic/operation_tree_flatteners.rb +24 -0
  57. data/lib/super_diff/basic/operation_trees/array.rb +17 -0
  58. data/lib/super_diff/basic/operation_trees/custom_object.rb +17 -0
  59. data/lib/super_diff/basic/operation_trees/default_object.rb +42 -0
  60. data/lib/super_diff/basic/operation_trees/hash.rb +17 -0
  61. data/lib/super_diff/basic/operation_trees/multiline_string.rb +17 -0
  62. data/lib/super_diff/basic/operation_trees.rb +25 -0
  63. data/lib/super_diff/basic.rb +48 -0
  64. data/lib/super_diff/{differs/base.rb → core/abstract_differ.rb} +2 -2
  65. data/lib/super_diff/core/abstract_inspection_tree_builder.rb +26 -0
  66. data/lib/super_diff/{operation_trees/base.rb → core/abstract_operation_tree.rb} +6 -2
  67. data/lib/super_diff/{operation_tree_builders/base.rb → core/abstract_operation_tree_builder.rb} +4 -8
  68. data/lib/super_diff/{operation_tree_flatteners/base.rb → core/abstract_operation_tree_flattener.rb} +2 -2
  69. data/lib/super_diff/{operations → core}/binary_operation.rb +1 -1
  70. data/lib/super_diff/core/colorized_document_extensions.rb +20 -0
  71. data/lib/super_diff/core/configuration.rb +192 -0
  72. data/lib/super_diff/core/differ_dispatcher.rb +31 -0
  73. data/lib/super_diff/core/gem_version.rb +47 -0
  74. data/lib/super_diff/core/helpers.rb +88 -0
  75. data/lib/super_diff/core/implementation_checks.rb +21 -0
  76. data/lib/super_diff/{object_inspection → core}/inspection_tree.rb +7 -6
  77. data/lib/super_diff/core/inspection_tree_builder_dispatcher.rb +23 -0
  78. data/lib/super_diff/{object_inspection/nodes → core/inspection_tree_nodes}/as_lines_when_rendering_to_lines.rb +9 -3
  79. data/lib/super_diff/{object_inspection/nodes → core/inspection_tree_nodes}/as_prefix_when_rendering_to_lines.rb +3 -3
  80. data/lib/super_diff/{object_inspection/nodes → core/inspection_tree_nodes}/as_prelude_when_rendering_to_lines.rb +3 -3
  81. data/lib/super_diff/{object_inspection/nodes → core/inspection_tree_nodes}/as_single_line.rb +3 -3
  82. data/lib/super_diff/{object_inspection/nodes → core/inspection_tree_nodes}/base.rb +2 -2
  83. data/lib/super_diff/{object_inspection/nodes → core/inspection_tree_nodes}/inspection.rb +7 -11
  84. data/lib/super_diff/{object_inspection/nodes → core/inspection_tree_nodes}/nesting.rb +2 -2
  85. data/lib/super_diff/{object_inspection/nodes → core/inspection_tree_nodes}/only_when.rb +2 -2
  86. data/lib/super_diff/{object_inspection/nodes → core/inspection_tree_nodes}/text.rb +2 -2
  87. data/lib/super_diff/{object_inspection/nodes → core/inspection_tree_nodes}/when_empty.rb +2 -2
  88. data/lib/super_diff/{object_inspection/nodes → core/inspection_tree_nodes}/when_non_empty.rb +2 -2
  89. data/lib/super_diff/{object_inspection/nodes → core/inspection_tree_nodes}/when_rendering_to_lines.rb +2 -2
  90. data/lib/super_diff/{object_inspection/nodes → core/inspection_tree_nodes}/when_rendering_to_string.rb +2 -2
  91. data/lib/super_diff/core/inspection_tree_nodes.rb +55 -0
  92. data/lib/super_diff/core/line.rb +85 -0
  93. data/lib/super_diff/{errors → core}/no_differ_available_error.rb +1 -1
  94. data/lib/super_diff/core/no_inspection_tree_builder_available_error.rb +21 -0
  95. data/lib/super_diff/core/no_operation_tree_available_error.rb +20 -0
  96. data/lib/super_diff/core/no_operation_tree_builder_available_error.rb +24 -0
  97. data/lib/super_diff/{operation_tree_builders/main.rb → core/operation_tree_builder_dispatcher.rb} +9 -13
  98. data/lib/super_diff/core/operation_tree_finder.rb +27 -0
  99. data/lib/super_diff/core/prefix_for_next_inspection_tree_node.rb +6 -0
  100. data/lib/super_diff/core/prelude_for_next_inspection_tree_node.rb +6 -0
  101. data/lib/super_diff/core/recursion_guard.rb +52 -0
  102. data/lib/super_diff/core/tiered_lines.rb +6 -0
  103. data/lib/super_diff/core/tiered_lines_elider.rb +472 -0
  104. data/lib/super_diff/core/tiered_lines_formatter.rb +77 -0
  105. data/lib/super_diff/{operations → core}/unary_operation.rb +1 -1
  106. data/lib/super_diff/core.rb +69 -0
  107. data/lib/super_diff/differs.rb +19 -12
  108. data/lib/super_diff/equality_matchers/array.rb +3 -3
  109. data/lib/super_diff/equality_matchers/default.rb +8 -3
  110. data/lib/super_diff/equality_matchers/hash.rb +3 -3
  111. data/lib/super_diff/equality_matchers/multiline_string.rb +3 -3
  112. data/lib/super_diff/equality_matchers/primitive.rb +3 -3
  113. data/lib/super_diff/equality_matchers/singleline_string.rb +2 -2
  114. data/lib/super_diff/errors.rb +12 -8
  115. data/lib/super_diff/object_inspection.rb +63 -14
  116. data/lib/super_diff/operation_tree_builders.rb +19 -15
  117. data/lib/super_diff/operation_tree_flatteners.rb +19 -16
  118. data/lib/super_diff/operation_trees.rb +19 -9
  119. data/lib/super_diff/operations.rb +12 -2
  120. data/lib/super_diff/rspec/augmented_matcher.rb +1 -1
  121. data/lib/super_diff/rspec/differ.rb +4 -5
  122. data/lib/super_diff/rspec/differs/collection_containing_exactly.rb +1 -1
  123. data/lib/super_diff/rspec/differs/collection_including.rb +1 -1
  124. data/lib/super_diff/rspec/differs/hash_including.rb +1 -1
  125. data/lib/super_diff/rspec/differs/object_having_attributes.rb +1 -1
  126. data/lib/super_diff/rspec/inspection_tree_builders/collection_containing_exactly.rb +34 -0
  127. data/lib/super_diff/rspec/inspection_tree_builders/collection_including.rb +40 -0
  128. data/lib/super_diff/rspec/inspection_tree_builders/double.rb +100 -0
  129. data/lib/super_diff/rspec/inspection_tree_builders/generic_describable_matcher.rb +17 -0
  130. data/lib/super_diff/rspec/inspection_tree_builders/hash_including.rb +40 -0
  131. data/lib/super_diff/rspec/inspection_tree_builders/instance_of.rb +25 -0
  132. data/lib/super_diff/rspec/inspection_tree_builders/kind_of.rb +25 -0
  133. data/lib/super_diff/rspec/inspection_tree_builders/object_having_attributes.rb +34 -0
  134. data/lib/super_diff/rspec/inspection_tree_builders/primitive.rb +9 -0
  135. data/lib/super_diff/rspec/inspection_tree_builders/value_within.rb +30 -0
  136. data/lib/super_diff/rspec/inspection_tree_builders.rb +40 -0
  137. data/lib/super_diff/rspec/object_inspection.rb +14 -4
  138. data/lib/super_diff/rspec/operation_tree_builders/collection_containing_exactly.rb +4 -4
  139. data/lib/super_diff/rspec/operation_tree_builders/collection_including.rb +1 -1
  140. data/lib/super_diff/rspec/operation_tree_builders/hash_including.rb +1 -1
  141. data/lib/super_diff/rspec/operation_tree_builders/object_having_attributes.rb +2 -2
  142. data/lib/super_diff/rspec.rb +20 -18
  143. data/lib/super_diff/version.rb +1 -1
  144. data/lib/super_diff.rb +69 -21
  145. data/spec/examples.txt +704 -543
  146. data/spec/support/integration/helpers.rb +4 -1
  147. data/spec/support/integration/matchers/produce_output_when_run_matcher.rb +1 -1
  148. data/spec/support/models/active_record/person.rb +8 -1
  149. data/spec/support/shared_examples/active_record.rb +5 -5
  150. data/spec/support/unit/helpers.rb +12 -1
  151. data/spec/support/unit/matchers/be_deprecated_in_favor_of.rb +39 -0
  152. data/spec/unit/active_record/object_inspection_spec.rb +5 -5
  153. data/spec/unit/{operation_tree_flatteners → basic/operation_tree_flatteners}/array_spec.rb +8 -8
  154. data/spec/unit/{operation_tree_flatteners → basic/operation_tree_flatteners}/custom_object_spec.rb +9 -9
  155. data/spec/unit/{operation_tree_flatteners → basic/operation_tree_flatteners}/default_object_spec.rb +9 -9
  156. data/spec/unit/{operation_tree_flatteners → basic/operation_tree_flatteners}/hash_spec.rb +8 -8
  157. data/spec/unit/{operation_tree_flatteners → basic/operation_tree_flatteners}/multiline_string_spec.rb +4 -4
  158. data/spec/unit/{helpers_spec.rb → core/helpers_spec.rb} +2 -2
  159. data/spec/unit/{tiered_lines_elider_spec.rb → core/tiered_lines_elider_spec.rb} +2 -2
  160. data/spec/unit/{tiered_lines_formatter_spec.rb → core/tiered_lines_formatter_spec.rb} +1 -1
  161. data/spec/unit/deprecations_spec.rb +176 -0
  162. data/spec/unit/equality_matchers/main_spec.rb +5 -5
  163. data/super_diff.gemspec +6 -0
  164. metadata +127 -115
  165. data/lib/super_diff/active_record/object_inspection/inspection_tree_builders/active_record_model.rb +0 -51
  166. data/lib/super_diff/active_record/object_inspection/inspection_tree_builders/active_record_relation.rb +0 -36
  167. data/lib/super_diff/active_record/object_inspection/inspection_tree_builders.rb +0 -16
  168. data/lib/super_diff/active_support/object_inspection/inspection_tree_builders/hash_with_indifferent_access.rb +0 -46
  169. data/lib/super_diff/active_support/object_inspection/inspection_tree_builders/ordered_options.rb +0 -46
  170. data/lib/super_diff/active_support/object_inspection/inspection_tree_builders.rb +0 -16
  171. data/lib/super_diff/colorized_document_extensions.rb +0 -18
  172. data/lib/super_diff/configuration.rb +0 -149
  173. data/lib/super_diff/diff_formatters/collection.rb +0 -132
  174. data/lib/super_diff/diff_formatters/multiline_string.rb +0 -31
  175. data/lib/super_diff/differs/array.rb +0 -15
  176. data/lib/super_diff/differs/custom_object.rb +0 -17
  177. data/lib/super_diff/differs/date_like.rb +0 -15
  178. data/lib/super_diff/differs/default_object.rb +0 -19
  179. data/lib/super_diff/differs/defaults.rb +0 -13
  180. data/lib/super_diff/differs/empty.rb +0 -13
  181. data/lib/super_diff/differs/hash.rb +0 -15
  182. data/lib/super_diff/differs/main.rb +0 -31
  183. data/lib/super_diff/differs/multiline_string.rb +0 -16
  184. data/lib/super_diff/differs/time_like.rb +0 -15
  185. data/lib/super_diff/gem_version.rb +0 -45
  186. data/lib/super_diff/helpers.rb +0 -86
  187. data/lib/super_diff/implementation_checks.rb +0 -19
  188. data/lib/super_diff/line.rb +0 -83
  189. data/lib/super_diff/object_inspection/inspection_tree_builders/base.rb +0 -27
  190. data/lib/super_diff/object_inspection/inspection_tree_builders/defaults.rb +0 -15
  191. data/lib/super_diff/object_inspection/inspection_tree_builders/main.rb +0 -30
  192. data/lib/super_diff/object_inspection/inspection_tree_builders.rb +0 -48
  193. data/lib/super_diff/object_inspection/nodes.rb +0 -50
  194. data/lib/super_diff/object_inspection/prefix_for_next_node.rb +0 -6
  195. data/lib/super_diff/object_inspection/prelude_for_next_node.rb +0 -6
  196. data/lib/super_diff/operation_tree_builders/array.rb +0 -107
  197. data/lib/super_diff/operation_tree_builders/custom_object.rb +0 -40
  198. data/lib/super_diff/operation_tree_builders/date_like.rb +0 -15
  199. data/lib/super_diff/operation_tree_builders/default_object.rb +0 -119
  200. data/lib/super_diff/operation_tree_builders/defaults.rb +0 -5
  201. data/lib/super_diff/operation_tree_builders/hash.rb +0 -218
  202. data/lib/super_diff/operation_tree_builders/multiline_string.rb +0 -86
  203. data/lib/super_diff/operation_tree_builders/time_like.rb +0 -24
  204. data/lib/super_diff/operation_tree_flatteners/array.rb +0 -15
  205. data/lib/super_diff/operation_tree_flatteners/collection.rb +0 -136
  206. data/lib/super_diff/operation_tree_flatteners/custom_object.rb +0 -28
  207. data/lib/super_diff/operation_tree_flatteners/default_object.rb +0 -31
  208. data/lib/super_diff/operation_tree_flatteners/hash.rb +0 -33
  209. data/lib/super_diff/operation_tree_flatteners/multiline_string.rb +0 -18
  210. data/lib/super_diff/operation_trees/array.rb +0 -15
  211. data/lib/super_diff/operation_trees/custom_object.rb +0 -15
  212. data/lib/super_diff/operation_trees/default_object.rb +0 -40
  213. data/lib/super_diff/operation_trees/defaults.rb +0 -5
  214. data/lib/super_diff/operation_trees/hash.rb +0 -15
  215. data/lib/super_diff/operation_trees/main.rb +0 -35
  216. data/lib/super_diff/operation_trees/multiline_string.rb +0 -15
  217. data/lib/super_diff/recursion_guard.rb +0 -50
  218. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/collection_containing_exactly.rb +0 -36
  219. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/collection_including.rb +0 -42
  220. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/double.rb +0 -102
  221. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/generic_describable_matcher.rb +0 -19
  222. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/hash_including.rb +0 -42
  223. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/instance_of.rb +0 -27
  224. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/kind_of.rb +0 -27
  225. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/object_having_attributes.rb +0 -36
  226. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/primitive.rb +0 -10
  227. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/value_within.rb +0 -32
  228. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders.rb +0 -48
  229. data/lib/super_diff/tiered_lines.rb +0 -4
  230. data/lib/super_diff/tiered_lines_elider.rb +0 -462
  231. data/lib/super_diff/tiered_lines_formatter.rb +0 -75
@@ -0,0 +1,472 @@
1
+ module SuperDiff
2
+ module Core
3
+ class TieredLinesElider
4
+ SIZE_OF_ELISION = 1
5
+
6
+ extend AttrExtras.mixin
7
+ include Helpers
8
+
9
+ method_object :lines
10
+
11
+ def call
12
+ all_lines_are_changed_or_unchanged? ? lines : elided_lines
13
+ end
14
+
15
+ private
16
+
17
+ def all_lines_are_changed_or_unchanged?
18
+ panes.size == 1 && panes.first.range == Range.new(0, lines.length - 1)
19
+ end
20
+
21
+ def elided_lines
22
+ boxes_to_elide
23
+ .reverse
24
+ .reduce(lines) do |lines_with_elisions, box|
25
+ with_box_elided(box, lines_with_elisions)
26
+ end
27
+ end
28
+
29
+ def boxes_to_elide
30
+ @_boxes_to_elide ||=
31
+ panes_to_consider_for_eliding.reduce([]) do |array, pane|
32
+ array + (find_boxes_to_elide_within(pane) || [])
33
+ end
34
+ end
35
+
36
+ def panes_to_consider_for_eliding
37
+ panes.select { |pane| pane.type == :clean && pane.range.size > maximum }
38
+ end
39
+
40
+ def panes
41
+ @_panes ||=
42
+ BuildPanes.call(dirty_panes: padded_dirty_panes, lines: lines)
43
+ end
44
+
45
+ def padded_dirty_panes
46
+ @_padded_dirty_panes ||=
47
+ combine_congruent_panes(
48
+ dirty_panes
49
+ .map(&:padded)
50
+ .map { |pane| pane.capped_to(0, lines.size - 1) }
51
+ )
52
+ end
53
+
54
+ def dirty_panes
55
+ @_dirty_panes ||=
56
+ lines
57
+ .each_with_index
58
+ .select { |line, index| line.type != :noop }
59
+ .reduce([]) do |panes, (_, index)|
60
+ if !panes.empty? && panes.last.range.end == index - 1
61
+ panes[0..-2] + [panes[-1].extended_to(index)]
62
+ else
63
+ panes + [Pane.new(type: :dirty, range: index..index)]
64
+ end
65
+ end
66
+ end
67
+
68
+ def with_box_elided(box, lines)
69
+ box_at_start_of_lines =
70
+ if lines.first.complete_bookend?
71
+ box.range.begin == 1
72
+ else
73
+ box.range.begin == 0
74
+ end
75
+
76
+ box_at_end_of_lines =
77
+ if lines.last.complete_bookend?
78
+ box.range.end == lines.size - 2
79
+ else
80
+ box.range.end == lines.size - 1
81
+ end
82
+
83
+ if one_dimensional_line_tree? && outermost_box?(box)
84
+ if box_at_start_of_lines
85
+ with_start_of_box_elided(box, lines)
86
+ elsif box_at_end_of_lines
87
+ with_end_of_box_elided(box, lines)
88
+ else
89
+ with_middle_of_box_elided(box, lines)
90
+ end
91
+ else
92
+ with_subset_of_lines_elided(
93
+ lines,
94
+ range: box.range,
95
+ indentation_level: box.indentation_level
96
+ )
97
+ end
98
+ end
99
+
100
+ def outermost_box?(box)
101
+ box.indentation_level == all_indentation_levels.min
102
+ end
103
+
104
+ def one_dimensional_line_tree?
105
+ all_indentation_levels.size == 1
106
+ end
107
+
108
+ def all_indentation_levels
109
+ lines
110
+ .map(&:indentation_level)
111
+ .select { |indentation_level| indentation_level > 0 }
112
+ .uniq
113
+ end
114
+
115
+ def find_boxes_to_elide_within(pane)
116
+ set_of_boxes =
117
+ normalized_box_groups_at_decreasing_indentation_levels_within(pane)
118
+
119
+ total_size_before_eliding =
120
+ lines[pane.range].reject(&:complete_bookend?).size
121
+
122
+ if total_size_before_eliding > maximum
123
+ if maximum > 0
124
+ set_of_boxes.find do |boxes|
125
+ total_size_after_eliding =
126
+ total_size_before_eliding -
127
+ boxes.sum { |box| box.range.size - SIZE_OF_ELISION }
128
+ total_size_after_eliding <= maximum
129
+ end
130
+ else
131
+ set_of_boxes[-1]
132
+ end
133
+ else
134
+ []
135
+ end
136
+ end
137
+
138
+ def normalized_box_groups_at_decreasing_indentation_levels_within(pane)
139
+ box_groups_at_decreasing_indentation_levels_within(pane).map(
140
+ &method(:filter_out_boxes_fully_contained_in_others)
141
+ ).map(&method(:combine_congruent_boxes))
142
+ end
143
+
144
+ def box_groups_at_decreasing_indentation_levels_within(pane)
145
+ boxes_within_pane = boxes.select { |box| box.fits_fully_within?(pane) }
146
+
147
+ possible_indentation_levels =
148
+ boxes_within_pane
149
+ .map(&:indentation_level)
150
+ .select { |indentation_level| indentation_level > 0 }
151
+ .uniq
152
+ .sort
153
+ .reverse
154
+
155
+ possible_indentation_levels.map do |indentation_level|
156
+ boxes_within_pane.select do |box|
157
+ box.indentation_level >= indentation_level
158
+ end
159
+ end
160
+ end
161
+
162
+ def filter_out_boxes_fully_contained_in_others(boxes)
163
+ sorted_boxes =
164
+ boxes.sort_by do |box|
165
+ [box.indentation_level, box.range.begin, box.range.end]
166
+ end
167
+
168
+ boxes.reject do |box2|
169
+ sorted_boxes.any? do |box1|
170
+ !box1.equal?(box2) && box1.fully_contains?(box2)
171
+ end
172
+ end
173
+ end
174
+
175
+ def combine_congruent_boxes(boxes)
176
+ combine(boxes, on: :indentation_level)
177
+ end
178
+
179
+ def combine_congruent_panes(panes)
180
+ combine(panes, on: :type)
181
+ end
182
+
183
+ def combine(spannables, on:)
184
+ criterion = on
185
+ spannables.reduce([]) do |combined_spannables, spannable|
186
+ if (
187
+ !combined_spannables.empty? &&
188
+ spannable.range.begin <=
189
+ combined_spannables.last.range.end + 1 &&
190
+ spannable.public_send(criterion) ==
191
+ combined_spannables.last.public_send(criterion)
192
+ )
193
+ combined_spannables[0..-2] +
194
+ [combined_spannables[-1].extended_to(spannable.range.end)]
195
+ else
196
+ combined_spannables + [spannable]
197
+ end
198
+ end
199
+ end
200
+
201
+ def boxes
202
+ @_boxes ||= BuildBoxes.call(lines)
203
+ end
204
+
205
+ def with_start_of_box_elided(box, lines)
206
+ amount_to_elide =
207
+ if maximum > 0
208
+ box.range.size - maximum + SIZE_OF_ELISION
209
+ else
210
+ box.range.size
211
+ end
212
+
213
+ with_subset_of_lines_elided(
214
+ lines,
215
+ range:
216
+ Range.new(box.range.begin, box.range.begin + amount_to_elide - 1),
217
+ indentation_level: box.indentation_level
218
+ )
219
+ end
220
+
221
+ def with_end_of_box_elided(box, lines)
222
+ amount_to_elide =
223
+ if maximum > 0
224
+ box.range.size - maximum + SIZE_OF_ELISION
225
+ else
226
+ box.range.size
227
+ end
228
+
229
+ range =
230
+ if amount_to_elide > 0
231
+ Range.new(box.range.end - amount_to_elide + 1, box.range.end)
232
+ else
233
+ box.range
234
+ end
235
+
236
+ with_subset_of_lines_elided(
237
+ lines,
238
+ range: range,
239
+ indentation_level: box.indentation_level
240
+ )
241
+ end
242
+
243
+ def with_middle_of_box_elided(box, lines)
244
+ half_of_maximum, remainder =
245
+ if maximum > 0
246
+ (maximum - SIZE_OF_ELISION).divmod(2)
247
+ else
248
+ [0, 0]
249
+ end
250
+
251
+ opening_length, closing_length =
252
+ half_of_maximum,
253
+ half_of_maximum + remainder
254
+
255
+ with_subset_of_lines_elided(
256
+ lines,
257
+ range:
258
+ Range.new(
259
+ box.range.begin + opening_length,
260
+ box.range.end - closing_length
261
+ ),
262
+ indentation_level: box.indentation_level
263
+ )
264
+ end
265
+
266
+ def with_subset_of_lines_elided(lines, range:, indentation_level:)
267
+ with_slice_of_array_replaced(
268
+ lines,
269
+ range,
270
+ Elision.new(
271
+ indentation_level: indentation_level,
272
+ children: lines[range].map(&:as_elided)
273
+ )
274
+ )
275
+ end
276
+
277
+ def maximum
278
+ SuperDiff.configuration.diff_elision_maximum || 0
279
+ end
280
+
281
+ class BuildPanes
282
+ extend AttrExtras.mixin
283
+
284
+ method_object %i[dirty_panes! lines!]
285
+
286
+ def call
287
+ beginning + middle + ending
288
+ end
289
+
290
+ private
291
+
292
+ def beginning
293
+ if (dirty_panes.empty? || dirty_panes.first.range.begin == 0)
294
+ []
295
+ else
296
+ [
297
+ Pane.new(
298
+ type: :clean,
299
+ range: Range.new(0, dirty_panes.first.range.begin - 1)
300
+ )
301
+ ]
302
+ end
303
+ end
304
+
305
+ def middle
306
+ if dirty_panes.size == 1
307
+ dirty_panes
308
+ else
309
+ dirty_panes
310
+ .each_with_index
311
+ .each_cons(2)
312
+ .reduce([]) do |panes, ((pane1, _), (pane2, index2))|
313
+ panes +
314
+ [
315
+ pane1,
316
+ Pane.new(
317
+ type: :clean,
318
+ range:
319
+ Range.new(pane1.range.end + 1, pane2.range.begin - 1)
320
+ )
321
+ ] + (index2 == dirty_panes.size - 1 ? [pane2] : [])
322
+ end
323
+ end
324
+ end
325
+
326
+ def ending
327
+ if (
328
+ dirty_panes.empty? ||
329
+ dirty_panes.last.range.end >= lines.size - 1
330
+ )
331
+ []
332
+ else
333
+ [
334
+ Pane.new(
335
+ type: :clean,
336
+ range: Range.new(dirty_panes.last.range.end + 1, lines.size - 1)
337
+ )
338
+ ]
339
+ end
340
+ end
341
+ end
342
+
343
+ class Pane
344
+ extend AttrExtras.mixin
345
+
346
+ rattr_initialize %i[type! range!]
347
+
348
+ def extended_to(new_end)
349
+ self.class.new(type: type, range: range.begin..new_end)
350
+ end
351
+
352
+ def padded
353
+ self.class.new(type: type, range: Range.new(range.begin, range.end))
354
+ end
355
+
356
+ def capped_to(beginning, ending)
357
+ new_beginning = range.begin < beginning ? beginning : range.begin
358
+ new_ending = range.end > ending ? ending : range.end
359
+ self.class.new(
360
+ type: type,
361
+ range: Range.new(new_beginning, new_ending)
362
+ )
363
+ end
364
+ end
365
+
366
+ class BuildBoxes
367
+ def self.call(lines)
368
+ builder = new(lines)
369
+ builder.build
370
+ builder.final_boxes
371
+ end
372
+
373
+ attr_reader :final_boxes
374
+
375
+ def initialize(lines)
376
+ @lines = lines
377
+
378
+ @open_collection_boxes = []
379
+ @final_boxes = []
380
+ end
381
+
382
+ def build
383
+ lines.each_with_index do |line, index|
384
+ if line.opens_collection?
385
+ open_new_collection_box(line, index)
386
+ elsif line.closes_collection?
387
+ extend_working_collection_box(index)
388
+ close_working_collection_box
389
+ else
390
+ extend_working_collection_box(index) if open_collection_boxes.any?
391
+ record_item_box(line, index)
392
+ end
393
+ end
394
+ end
395
+
396
+ private
397
+
398
+ attr_reader :lines, :open_collection_boxes
399
+
400
+ def extend_working_collection_box(index)
401
+ open_collection_boxes.last.extend_to(index)
402
+ end
403
+
404
+ def close_working_collection_box
405
+ final_boxes << open_collection_boxes.pop
406
+ end
407
+
408
+ def open_new_collection_box(line, index)
409
+ open_collection_boxes << Box.new(
410
+ indentation_level: line.indentation_level,
411
+ range: index..index
412
+ )
413
+ end
414
+
415
+ def record_item_box(line, index)
416
+ final_boxes << Box.new(
417
+ indentation_level: line.indentation_level,
418
+ range: index..index
419
+ )
420
+ end
421
+ end
422
+
423
+ class Box
424
+ extend AttrExtras.mixin
425
+
426
+ rattr_initialize %i[indentation_level! range!]
427
+
428
+ def fully_contains?(other)
429
+ range.begin <= other.range.begin && range.end >= other.range.end
430
+ end
431
+
432
+ def fits_fully_within?(other)
433
+ other.range.begin <= range.begin && other.range.end >= range.end
434
+ end
435
+
436
+ def extended_to(new_end)
437
+ dup.tap { |clone| clone.extend_to(new_end) }
438
+ end
439
+
440
+ def extend_to(new_end)
441
+ @range = range.begin..new_end
442
+ end
443
+ end
444
+
445
+ class Elision
446
+ extend AttrExtras.mixin
447
+
448
+ rattr_initialize %i[indentation_level! children!]
449
+
450
+ def type
451
+ :elision
452
+ end
453
+
454
+ def prefix
455
+ ""
456
+ end
457
+
458
+ def value
459
+ "# ..."
460
+ end
461
+
462
+ def elided?
463
+ true
464
+ end
465
+
466
+ def add_comma?
467
+ false
468
+ end
469
+ end
470
+ end
471
+ end
472
+ end
@@ -0,0 +1,77 @@
1
+ module SuperDiff
2
+ module Core
3
+ class TieredLinesFormatter
4
+ extend AttrExtras.mixin
5
+
6
+ method_object :tiered_lines
7
+
8
+ def call
9
+ colorized_document.to_s.chomp
10
+ end
11
+
12
+ private
13
+
14
+ def colorized_document
15
+ Helpers.style do |doc|
16
+ formattable_lines.each do |formattable_line|
17
+ doc.public_send(
18
+ "#{formattable_line.color}_line",
19
+ formattable_line.content
20
+ )
21
+ end
22
+ end
23
+ end
24
+
25
+ def formattable_lines
26
+ tiered_lines.map { |line| FormattableLine.new(line) }
27
+ end
28
+
29
+ class FormattableLine
30
+ extend AttrExtras.mixin
31
+
32
+ INDENTATION_UNIT = " ".freeze
33
+ ICONS = { delete: "-", insert: "+", elision: " ", noop: " " }.freeze
34
+ COLORS = {
35
+ delete: :expected,
36
+ insert: :actual,
37
+ elision: :elision_marker,
38
+ noop: :plain
39
+ }.freeze
40
+
41
+ pattr_initialize :line
42
+
43
+ def content
44
+ icon + " " + indentation + line.prefix + line.value + possible_comma
45
+ end
46
+
47
+ def color
48
+ COLORS.fetch(line.type) do
49
+ raise(
50
+ KeyError,
51
+ "Couldn't find color for line type #{line.type.inspect}!"
52
+ )
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def icon
59
+ ICONS.fetch(line.type) do
60
+ raise(
61
+ KeyError,
62
+ "Couldn't find icon for line type #{line.type.inspect}!"
63
+ )
64
+ end
65
+ end
66
+
67
+ def indentation
68
+ INDENTATION_UNIT * line.indentation_level
69
+ end
70
+
71
+ def possible_comma
72
+ line.add_comma? ? "," : ""
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -1,5 +1,5 @@
1
1
  module SuperDiff
2
- module Operations
2
+ module Core
3
3
  class UnaryOperation
4
4
  extend AttrExtras.mixin
5
5
 
@@ -0,0 +1,69 @@
1
+ module SuperDiff
2
+ module Core
3
+ autoload :AbstractDiffer, "super_diff/core/abstract_differ"
4
+ autoload(
5
+ :AbstractInspectionTreeBuilder,
6
+ "super_diff/core/abstract_inspection_tree_builder"
7
+ )
8
+ autoload :AbstractOperationTree, "super_diff/core/abstract_operation_tree"
9
+ autoload(
10
+ :AbstractOperationTreeBuilder,
11
+ "super_diff/core/abstract_operation_tree_builder"
12
+ )
13
+ autoload(
14
+ :AbstractOperationTreeFlattener,
15
+ "super_diff/core/abstract_operation_tree_flattener"
16
+ )
17
+ autoload :BinaryOperation, "super_diff/core/binary_operation"
18
+ autoload(
19
+ :ColorizedDocumentExtensions,
20
+ "super_diff/core/colorized_document_extensions"
21
+ )
22
+ autoload :Configuration, "super_diff/core/configuration"
23
+ autoload :DifferDispatcher, "super_diff/core/differ_dispatcher"
24
+ autoload :GemVersion, "super_diff/core/gem_version"
25
+ autoload :Helpers, "super_diff/core/helpers"
26
+ autoload :ImplementationChecks, "super_diff/core/implementation_checks"
27
+ autoload :InspectionTree, "super_diff/core/inspection_tree"
28
+ autoload(
29
+ :InspectionTreeBuilderDispatcher,
30
+ "super_diff/core/inspection_tree_builder_dispatcher"
31
+ )
32
+ autoload :InspectionTreeNodes, "super_diff/core/inspection_tree_nodes"
33
+ autoload :Line, "super_diff/core/line"
34
+ autoload(
35
+ :OperationTreeBuilderDispatcher,
36
+ "super_diff/core/operation_tree_builder_dispatcher"
37
+ )
38
+ autoload(
39
+ :NoDifferAvailableError,
40
+ "super_diff/core/no_differ_available_error"
41
+ )
42
+ autoload(
43
+ :NoInspectionTreeAvailableError,
44
+ "super_diff/core/no_inspection_tree_builder_available_error"
45
+ )
46
+ autoload(
47
+ :NoOperationTreeBuilderAvailableError,
48
+ "super_diff/core/no_operation_tree_builder_available_error"
49
+ )
50
+ autoload(
51
+ :NoOperationTreeAvailableError,
52
+ "super_diff/core/no_operation_tree_available_error"
53
+ )
54
+ autoload :OperationTreeFinder, "super_diff/core/operation_tree_finder"
55
+ autoload(
56
+ :PrefixForNextInspectionTreeNode,
57
+ "super_diff/core/prefix_for_next_inspection_tree_node"
58
+ )
59
+ autoload(
60
+ :PreludeForNextInspectionTreeNode,
61
+ "super_diff/core/prelude_for_next_inspection_tree_node"
62
+ )
63
+ autoload :RecursionGuard, "super_diff/core/recursion_guard"
64
+ autoload :TieredLines, "super_diff/core/tiered_lines"
65
+ autoload :TieredLinesElider, "super_diff/core/tiered_lines_elider"
66
+ autoload :TieredLinesFormatter, "super_diff/core/tiered_lines_formatter"
67
+ autoload :UnaryOperation, "super_diff/core/unary_operation"
68
+ end
69
+ end
@@ -1,16 +1,23 @@
1
1
  module SuperDiff
2
2
  module Differs
3
- autoload :Array, "super_diff/differs/array"
4
- autoload :Base, "super_diff/differs/base"
5
- autoload :CustomObject, "super_diff/differs/custom_object"
6
- autoload :DefaultObject, "super_diff/differs/default_object"
7
- autoload :Empty, "super_diff/differs/empty"
8
- autoload :Hash, "super_diff/differs/hash"
9
- autoload :Main, "super_diff/differs/main"
10
- autoload :MultilineString, "super_diff/differs/multiline_string"
11
- autoload :TimeLike, "super_diff/differs/time_like"
12
- autoload :DateLike, "super_diff/differs/date_like"
3
+ def self.const_missing(missing_const_name)
4
+ if missing_const_name == :Base
5
+ warn <<~EOT
6
+ WARNING: SuperDiff::Differs::#{missing_const_name} is deprecated and will be removed in the next major release.
7
+ Please use SuperDiff::Core::AbstractDiffer instead.
8
+ #{caller_locations.join("\n")}
9
+ EOT
10
+ Core::AbstractDiffer
11
+ elsif Basic::Differs.const_defined?(missing_const_name)
12
+ warn <<~EOT
13
+ WARNING: SuperDiff::Differs::#{missing_const_name} is deprecated and will be removed in the next major release.
14
+ Please use SuperDiff::Basic::Differs::#{missing_const_name} instead.
15
+ #{caller_locations.join("\n")}
16
+ EOT
17
+ Basic::Differs.const_get(missing_const_name)
18
+ else
19
+ super
20
+ end
21
+ end
13
22
  end
14
23
  end
15
-
16
- require "super_diff/differs/defaults"
@@ -10,13 +10,13 @@ module SuperDiff
10
10
  Differing arrays.
11
11
 
12
12
  #{
13
- Helpers.style(
13
+ Core::Helpers.style(
14
14
  :expected,
15
15
  "Expected: " + SuperDiff.inspect_object(expected, as_lines: false)
16
16
  )
17
17
  }
18
18
  #{
19
- Helpers.style(
19
+ Core::Helpers.style(
20
20
  :actual,
21
21
  " Actual: " + SuperDiff.inspect_object(actual, as_lines: false)
22
22
  )
@@ -31,7 +31,7 @@ module SuperDiff
31
31
  protected
32
32
 
33
33
  def diff
34
- Differs::Array.call(expected, actual, indent_level: 0)
34
+ Basic::Differs::Array.call(expected, actual, indent_level: 0)
35
35
  end
36
36
  end
37
37
  end