super_diff 0.11.0 → 0.12.1

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