super_diff 0.5.3 → 0.8.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 (209) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +46 -20
  3. data/lib/super_diff.rb +46 -7
  4. data/lib/super_diff/active_record.rb +7 -7
  5. data/lib/super_diff/active_record/differs/active_record_relation.rb +3 -13
  6. data/lib/super_diff/active_record/object_inspection.rb +2 -6
  7. data/lib/super_diff/active_record/object_inspection/inspection_tree_builders.rb +16 -0
  8. data/lib/super_diff/active_record/object_inspection/{inspectors → inspection_tree_builders}/active_record_model.rb +19 -20
  9. data/lib/super_diff/active_record/object_inspection/{inspectors → inspection_tree_builders}/active_record_relation.rb +9 -8
  10. data/lib/super_diff/active_record/operation_tree_flatteners.rb +10 -0
  11. data/lib/super_diff/active_record/operation_tree_flatteners/active_record_relation.rb +17 -0
  12. data/lib/super_diff/active_record/operation_trees/active_record_relation.rb +8 -7
  13. data/lib/super_diff/active_support.rb +8 -8
  14. data/lib/super_diff/active_support/differs/hash_with_indifferent_access.rb +3 -13
  15. data/lib/super_diff/active_support/object_inspection.rb +2 -6
  16. data/lib/super_diff/active_support/object_inspection/{inspectors.rb → inspection_tree_builders.rb} +2 -2
  17. data/lib/super_diff/active_support/object_inspection/inspection_tree_builders/hash_with_indifferent_access.rb +37 -0
  18. data/lib/super_diff/active_support/operation_tree_builders/hash_with_indifferent_access.rb +17 -0
  19. data/lib/super_diff/active_support/operation_tree_flatteners.rb +10 -0
  20. data/lib/super_diff/active_support/operation_tree_flatteners/hash_with_indifferent_access.rb +17 -0
  21. data/lib/super_diff/active_support/operation_trees/hash_with_indifferent_access.rb +4 -7
  22. data/lib/super_diff/colorized_document_extensions.rb +9 -6
  23. data/lib/super_diff/configuration.rb +102 -19
  24. data/lib/super_diff/csi.rb +1 -1
  25. data/lib/super_diff/csi/four_bit_color.rb +0 -2
  26. data/lib/super_diff/diff_formatters/collection.rb +2 -2
  27. data/lib/super_diff/diff_formatters/multiline_string.rb +4 -4
  28. data/lib/super_diff/differs/array.rb +1 -1
  29. data/lib/super_diff/differs/base.rb +3 -21
  30. data/lib/super_diff/differs/custom_object.rb +1 -1
  31. data/lib/super_diff/differs/default_object.rb +1 -1
  32. data/lib/super_diff/differs/hash.rb +1 -1
  33. data/lib/super_diff/differs/main.rb +1 -7
  34. data/lib/super_diff/differs/multiline_string.rb +1 -1
  35. data/lib/super_diff/differs/time_like.rb +1 -1
  36. data/lib/super_diff/equality_matchers/array.rb +4 -4
  37. data/lib/super_diff/equality_matchers/default.rb +4 -4
  38. data/lib/super_diff/equality_matchers/hash.rb +4 -4
  39. data/lib/super_diff/equality_matchers/multiline_string.rb +4 -4
  40. data/lib/super_diff/equality_matchers/primitive.rb +6 -9
  41. data/lib/super_diff/equality_matchers/singleline_string.rb +4 -4
  42. data/lib/super_diff/gem_version.rb +45 -0
  43. data/lib/super_diff/helpers.rb +52 -2
  44. data/lib/super_diff/line.rb +83 -0
  45. data/lib/super_diff/object_inspection.rb +12 -9
  46. data/lib/super_diff/object_inspection/inspection_tree.rb +183 -81
  47. data/lib/super_diff/object_inspection/inspection_tree_builders.rb +44 -0
  48. data/lib/super_diff/object_inspection/inspection_tree_builders/array.rb +38 -0
  49. data/lib/super_diff/object_inspection/inspection_tree_builders/base.rb +27 -0
  50. data/lib/super_diff/object_inspection/inspection_tree_builders/custom_object.rb +37 -0
  51. data/lib/super_diff/object_inspection/inspection_tree_builders/default_object.rb +63 -0
  52. data/lib/super_diff/object_inspection/{inspectors → inspection_tree_builders}/defaults.rb +1 -2
  53. data/lib/super_diff/object_inspection/inspection_tree_builders/hash.rb +46 -0
  54. data/lib/super_diff/object_inspection/{inspectors → inspection_tree_builders}/main.rb +5 -10
  55. data/lib/super_diff/object_inspection/inspection_tree_builders/primitive.rb +21 -0
  56. data/lib/super_diff/object_inspection/inspection_tree_builders/time_like.rb +64 -0
  57. data/lib/super_diff/object_inspection/nodes.rb +33 -32
  58. data/lib/super_diff/object_inspection/nodes/as_lines_when_rendering_to_lines.rb +97 -0
  59. data/lib/super_diff/object_inspection/nodes/as_prefix_when_rendering_to_lines.rb +27 -0
  60. data/lib/super_diff/object_inspection/nodes/as_prelude_when_rendering_to_lines.rb +27 -0
  61. data/lib/super_diff/object_inspection/nodes/as_single_line.rb +33 -0
  62. data/lib/super_diff/object_inspection/nodes/base.rb +55 -20
  63. data/lib/super_diff/object_inspection/nodes/inspection.rb +47 -7
  64. data/lib/super_diff/object_inspection/nodes/nesting.rb +16 -5
  65. data/lib/super_diff/object_inspection/nodes/only_when.rb +54 -0
  66. data/lib/super_diff/object_inspection/nodes/text.rb +16 -2
  67. data/lib/super_diff/object_inspection/nodes/when_empty.rb +21 -6
  68. data/lib/super_diff/object_inspection/nodes/when_non_empty.rb +20 -5
  69. data/lib/super_diff/object_inspection/nodes/when_rendering_to_lines.rb +27 -0
  70. data/lib/super_diff/object_inspection/nodes/when_rendering_to_string.rb +27 -0
  71. data/lib/super_diff/object_inspection/prefix_for_next_node.rb +6 -0
  72. data/lib/super_diff/object_inspection/prelude_for_next_node.rb +6 -0
  73. data/lib/super_diff/operation_tree_builders/array.rb +7 -10
  74. data/lib/super_diff/operation_tree_builders/base.rb +6 -6
  75. data/lib/super_diff/operation_tree_builders/custom_object.rb +5 -2
  76. data/lib/super_diff/operation_tree_builders/default_object.rb +1 -1
  77. data/lib/super_diff/operation_tree_builders/defaults.rb +1 -1
  78. data/lib/super_diff/operation_tree_builders/hash.rb +1 -8
  79. data/lib/super_diff/operation_tree_builders/multiline_string.rb +2 -6
  80. data/lib/super_diff/operation_tree_builders/time_like.rb +2 -2
  81. data/lib/super_diff/operation_tree_flatteners.rb +20 -0
  82. data/lib/super_diff/operation_tree_flatteners/array.rb +15 -0
  83. data/lib/super_diff/operation_tree_flatteners/base.rb +54 -0
  84. data/lib/super_diff/operation_tree_flatteners/collection.rb +139 -0
  85. data/lib/super_diff/operation_tree_flatteners/custom_object.rb +28 -0
  86. data/lib/super_diff/operation_tree_flatteners/default_object.rb +32 -0
  87. data/lib/super_diff/operation_tree_flatteners/hash.rb +41 -0
  88. data/lib/super_diff/operation_tree_flatteners/multiline_string.rb +17 -0
  89. data/lib/super_diff/operation_trees/array.rb +4 -7
  90. data/lib/super_diff/operation_trees/base.rb +39 -16
  91. data/lib/super_diff/operation_trees/custom_object.rb +4 -8
  92. data/lib/super_diff/operation_trees/default_object.rb +28 -13
  93. data/lib/super_diff/operation_trees/hash.rb +4 -7
  94. data/lib/super_diff/operation_trees/main.rb +1 -1
  95. data/lib/super_diff/operation_trees/multiline_string.rb +4 -7
  96. data/lib/super_diff/operations/binary_operation.rb +1 -6
  97. data/lib/super_diff/operations/unary_operation.rb +2 -30
  98. data/lib/super_diff/recursion_guard.rb +3 -3
  99. data/lib/super_diff/rspec.rb +41 -13
  100. data/lib/super_diff/rspec/differs/collection_including.rb +4 -2
  101. data/lib/super_diff/rspec/differs/hash_including.rb +4 -2
  102. data/lib/super_diff/rspec/matcher_text_builders/base.rb +7 -7
  103. data/lib/super_diff/rspec/matcher_text_builders/be_predicate.rb +6 -6
  104. data/lib/super_diff/rspec/matcher_text_builders/contain_exactly.rb +1 -1
  105. data/lib/super_diff/rspec/matcher_text_builders/have_predicate.rb +4 -4
  106. data/lib/super_diff/rspec/matcher_text_builders/raise_error.rb +1 -1
  107. data/lib/super_diff/rspec/matcher_text_builders/respond_to.rb +5 -5
  108. data/lib/super_diff/rspec/monkey_patches.rb +353 -306
  109. data/lib/super_diff/rspec/object_inspection.rb +4 -1
  110. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders.rb +44 -0
  111. data/lib/super_diff/rspec/object_inspection/{inspectors → inspection_tree_builders}/collection_containing_exactly.rb +9 -8
  112. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/collection_including.rb +34 -0
  113. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/double.rb +103 -0
  114. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/hash_including.rb +36 -0
  115. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/instance_of.rb +26 -0
  116. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/kind_of.rb +26 -0
  117. data/lib/super_diff/rspec/object_inspection/{inspectors → inspection_tree_builders}/object_having_attributes.rb +10 -12
  118. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/primitive.rb +10 -0
  119. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/value_within.rb +33 -0
  120. data/lib/super_diff/rspec/operation_tree_builders/collection_containing_exactly.rb +12 -4
  121. data/lib/super_diff/rspec/operation_tree_builders/collection_including.rb +10 -3
  122. data/lib/super_diff/rspec/operation_tree_builders/hash_including.rb +10 -3
  123. data/lib/super_diff/tiered_lines.rb +4 -0
  124. data/lib/super_diff/tiered_lines_elider.rb +490 -0
  125. data/lib/super_diff/tiered_lines_formatter.rb +79 -0
  126. data/lib/super_diff/version.rb +1 -1
  127. data/spec/examples.txt +407 -5
  128. data/spec/integration/rails/active_support_spec.rb +19 -0
  129. data/spec/integration/rspec/be_falsey_matcher_spec.rb +10 -10
  130. data/spec/integration/rspec/be_matcher_spec.rb +100 -100
  131. data/spec/integration/rspec/be_nil_matcher_spec.rb +10 -10
  132. data/spec/integration/rspec/be_predicate_matcher_spec.rb +103 -103
  133. data/spec/integration/rspec/be_truthy_matcher_spec.rb +10 -10
  134. data/spec/integration/rspec/contain_exactly_matcher_spec.rb +113 -107
  135. data/spec/integration/rspec/eq_matcher_spec.rb +223 -277
  136. data/spec/integration/rspec/have_attributes_matcher_spec.rb +138 -129
  137. data/spec/integration/rspec/have_predicate_matcher_spec.rb +65 -65
  138. data/spec/integration/rspec/include_matcher_spec.rb +73 -73
  139. data/spec/integration/rspec/match_array_matcher_spec.rb +126 -119
  140. data/spec/integration/rspec/match_matcher_spec.rb +362 -274
  141. data/spec/integration/rspec/raise_error_matcher_spec.rb +86 -86
  142. data/spec/integration/rspec/respond_to_matcher_spec.rb +240 -240
  143. data/spec/integration/rspec/third_party_matcher_spec.rb +8 -8
  144. data/spec/integration/rspec/unhandled_errors_spec.rb +5 -5
  145. data/spec/spec_helper.rb +33 -13
  146. data/spec/support/command_runner.rb +15 -25
  147. data/spec/support/helpers.rb +21 -0
  148. data/spec/support/integration/helpers.rb +8 -2
  149. data/spec/support/integration/matchers/produce_output_when_run_matcher.rb +4 -4
  150. data/spec/support/integration/test_programs/base.rb +38 -10
  151. data/spec/support/integration/test_programs/rspec_active_record.rb +1 -1
  152. data/spec/support/integration/test_programs/rspec_active_support.rb +17 -0
  153. data/spec/support/integration/test_programs/rspec_rails.rb +1 -1
  154. data/spec/support/shared_examples/active_record.rb +109 -108
  155. data/spec/support/shared_examples/active_support.rb +65 -0
  156. data/spec/support/shared_examples/elided_diffs.rb +914 -0
  157. data/spec/support/shared_examples/hash_with_indifferent_access.rb +196 -232
  158. data/spec/support/unit/helpers.rb +15 -0
  159. data/spec/support/unit/matchers/match_output.rb +41 -0
  160. data/spec/unit/active_record/object_inspection_spec.rb +273 -0
  161. data/spec/unit/equality_matchers/main_spec.rb +445 -465
  162. data/spec/unit/helpers_spec.rb +61 -0
  163. data/spec/unit/operation_tree_flatteners/array_spec.rb +604 -0
  164. data/spec/unit/operation_tree_flatteners/custom_object_spec.rb +667 -0
  165. data/spec/unit/operation_tree_flatteners/default_object_spec.rb +687 -0
  166. data/spec/unit/operation_tree_flatteners/hash_spec.rb +632 -0
  167. data/spec/unit/operation_tree_flatteners/multiline_string_spec.rb +121 -0
  168. data/spec/unit/rspec/object_inspection_spec.rb +446 -0
  169. data/spec/unit/super_diff_spec.rb +1958 -0
  170. data/spec/unit/tiered_lines_elider_spec.rb +6356 -0
  171. data/spec/unit/tiered_lines_formatter_spec.rb +193 -0
  172. data/super_diff.gemspec +1 -1
  173. metadata +95 -50
  174. data/lib/super_diff/active_record/diff_formatters.rb +0 -10
  175. data/lib/super_diff/active_record/diff_formatters/active_record_relation.rb +0 -23
  176. data/lib/super_diff/active_record/object_inspection/inspectors.rb +0 -16
  177. data/lib/super_diff/active_support/diff_formatters.rb +0 -10
  178. data/lib/super_diff/active_support/diff_formatters/hash_with_indifferent_access.rb +0 -36
  179. data/lib/super_diff/active_support/object_inspection/inspectors/hash_with_indifferent_access.rb +0 -28
  180. data/lib/super_diff/diff_formatters.rb +0 -14
  181. data/lib/super_diff/diff_formatters/array.rb +0 -21
  182. data/lib/super_diff/diff_formatters/base.rb +0 -33
  183. data/lib/super_diff/diff_formatters/custom_object.rb +0 -30
  184. data/lib/super_diff/diff_formatters/default_object.rb +0 -46
  185. data/lib/super_diff/diff_formatters/defaults.rb +0 -10
  186. data/lib/super_diff/diff_formatters/hash.rb +0 -34
  187. data/lib/super_diff/diff_formatters/main.rb +0 -41
  188. data/lib/super_diff/object_inspection/inspectors.rb +0 -23
  189. data/lib/super_diff/object_inspection/inspectors/array.rb +0 -32
  190. data/lib/super_diff/object_inspection/inspectors/base.rb +0 -36
  191. data/lib/super_diff/object_inspection/inspectors/custom_object.rb +0 -37
  192. data/lib/super_diff/object_inspection/inspectors/default_object.rb +0 -61
  193. data/lib/super_diff/object_inspection/inspectors/hash.rb +0 -32
  194. data/lib/super_diff/object_inspection/inspectors/primitive.rb +0 -28
  195. data/lib/super_diff/object_inspection/inspectors/string.rb +0 -23
  196. data/lib/super_diff/object_inspection/inspectors/time_like.rb +0 -23
  197. data/lib/super_diff/object_inspection/nodes/break.rb +0 -15
  198. data/lib/super_diff/object_inspection/nodes/when_multiline.rb +0 -22
  199. data/lib/super_diff/object_inspection/nodes/when_singleline.rb +0 -24
  200. data/lib/super_diff/rspec/object_inspection/inspectors.rb +0 -40
  201. data/lib/super_diff/rspec/object_inspection/inspectors/collection_including.rb +0 -28
  202. data/lib/super_diff/rspec/object_inspection/inspectors/hash_including.rb +0 -31
  203. data/lib/super_diff/rspec/object_inspection/inspectors/instance_of.rb +0 -23
  204. data/lib/super_diff/rspec/object_inspection/inspectors/kind_of.rb +0 -23
  205. data/lib/super_diff/rspec/object_inspection/inspectors/primitive.rb +0 -13
  206. data/lib/super_diff/rspec/object_inspection/inspectors/value_within.rb +0 -29
  207. data/spec/support/object_id.rb +0 -27
  208. data/spec/support/ruby_versions.rb +0 -11
  209. data/spec/unit/object_inspection_spec.rb +0 -1168
@@ -0,0 +1,27 @@
1
+ module SuperDiff
2
+ module ObjectInspection
3
+ module Nodes
4
+ class WhenRenderingToLines < Base
5
+ def self.node_name
6
+ :when_rendering_to_lines
7
+ end
8
+
9
+ def self.method_name
10
+ :when_rendering_to_lines
11
+ end
12
+
13
+ def render_to_string(*)
14
+ ""
15
+ end
16
+
17
+ def render_to_lines(object, type:, indentation_level:)
18
+ render_to_lines_in_subtree(
19
+ object,
20
+ type: type,
21
+ indentation_level: indentation_level,
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ module SuperDiff
2
+ module ObjectInspection
3
+ module Nodes
4
+ class WhenRenderingToString < Base
5
+ def self.node_name
6
+ :when_rendering_to_string
7
+ end
8
+
9
+ def self.method_name
10
+ :when_rendering_to_string
11
+ end
12
+
13
+ def render_to_string(object)
14
+ if block
15
+ render_to_string_in_subtree(object)
16
+ else
17
+ immediate_value.to_s
18
+ end
19
+ end
20
+
21
+ def render_to_lines(*, **)
22
+ []
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,6 @@
1
+ module SuperDiff
2
+ module ObjectInspection
3
+ class PrefixForNextNode < String
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module SuperDiff
2
+ module ObjectInspection
3
+ class PreludeForNextNode < String
4
+ end
5
+ end
6
+ end
@@ -17,7 +17,7 @@ module SuperDiff
17
17
  operation_tree: operation_tree,
18
18
  expected: expected,
19
19
  actual: actual,
20
- sequence: method(:sequence),
20
+ compare: method(:compare),
21
21
  )
22
22
  end
23
23
 
@@ -28,7 +28,7 @@ module SuperDiff
28
28
  class LcsCallbacks
29
29
  extend AttrExtras.mixin
30
30
 
31
- pattr_initialize [:operation_tree!, :expected!, :actual!, :sequence!]
31
+ pattr_initialize [:operation_tree!, :expected!, :actual!, :compare!]
32
32
  public :operation_tree
33
33
 
34
34
  def match(event)
@@ -44,10 +44,10 @@ module SuperDiff
44
44
  end
45
45
 
46
46
  def change(event)
47
- child_operations = sequence.call(event.old_element, event.new_element)
47
+ children = compare.(event.old_element, event.new_element)
48
48
 
49
- if child_operations
50
- add_change_operation(event, child_operations)
49
+ if children
50
+ add_change_operation(event, children)
51
51
  else
52
52
  add_delete_operation(event)
53
53
  add_insert_operation(event)
@@ -63,7 +63,6 @@ module SuperDiff
63
63
  key: event.old_position,
64
64
  value: event.old_element,
65
65
  index: event.old_position,
66
- index_in_collection: expected.index(event.old_element),
67
66
  )
68
67
  end
69
68
 
@@ -74,7 +73,6 @@ module SuperDiff
74
73
  key: event.new_position,
75
74
  value: event.new_element,
76
75
  index: event.new_position,
77
- index_in_collection: actual.index(event.new_element),
78
76
  )
79
77
  end
80
78
 
@@ -85,11 +83,10 @@ module SuperDiff
85
83
  key: event.new_position,
86
84
  value: event.new_element,
87
85
  index: event.new_position,
88
- index_in_collection: actual.index(event.new_element),
89
86
  )
90
87
  end
91
88
 
92
- def add_change_operation(event, child_operations)
89
+ def add_change_operation(event, children)
93
90
  operation_tree << Operations::BinaryOperation.new(
94
91
  name: :change,
95
92
  left_collection: expected,
@@ -100,7 +97,7 @@ module SuperDiff
100
97
  right_value: event.new_element,
101
98
  left_index: event.old_position,
102
99
  right_index: event.new_position,
103
- child_operations: child_operations,
100
+ children: children,
104
101
  )
105
102
  end
106
103
  end
@@ -39,7 +39,7 @@ module SuperDiff
39
39
  )
40
40
  unmatched_delete_operations.delete(delete_operation)
41
41
 
42
- if (child_operations = possible_comparison_of(
42
+ if (children = possible_comparison_of(
43
43
  delete_operation,
44
44
  insert_operation,
45
45
  ))
@@ -52,9 +52,9 @@ module SuperDiff
52
52
  right_key: insert_operation.key,
53
53
  left_value: delete_operation.collection[operation.key],
54
54
  right_value: insert_operation.collection[operation.key],
55
- left_index: delete_operation.index_in_collection,
56
- right_index: insert_operation.index_in_collection,
57
- child_operations: child_operations,
55
+ left_index: delete_operation.index,
56
+ right_index: insert_operation.index,
57
+ children: children,
58
58
  )
59
59
  else
60
60
  operation_tree << insert_operation
@@ -73,7 +73,7 @@ module SuperDiff
73
73
 
74
74
  def possible_comparison_of(operation, next_operation)
75
75
  if should_compare?(operation, next_operation)
76
- sequence(operation.value, next_operation.value)
76
+ compare(operation.value, next_operation.value)
77
77
  else
78
78
  nil
79
79
  end
@@ -86,7 +86,7 @@ module SuperDiff
86
86
  next_operation.key == operation.key
87
87
  end
88
88
 
89
- def sequence(expected, actual)
89
+ def compare(expected, actual)
90
90
  OperationTreeBuilders::Main.call(
91
91
  expected: expected,
92
92
  actual: actual,
@@ -7,9 +7,12 @@ module SuperDiff
7
7
  actual.respond_to?(:attributes_for_super_diff)
8
8
  end
9
9
 
10
+ protected
11
+
10
12
  def build_operation_tree
11
- # XXX This assumes that `expected` and `actual` are the same
12
- OperationTrees::CustomObject.new([], value_class: expected.class)
13
+ # NOTE: It doesn't matter whether we use expected or actual here,
14
+ # because all we care about is the name of the class
15
+ OperationTrees::CustomObject.new([], underlying_object: actual)
13
16
  end
14
17
 
15
18
  def attribute_names
@@ -25,7 +25,7 @@ module SuperDiff
25
25
  def build_operation_tree
26
26
  # XXX This assumes that `expected` and `actual` are the same
27
27
  # TODO: Does this need to be find_operation_tree_for?
28
- OperationTrees::DefaultObject.new([], value_class: expected.class)
28
+ OperationTrees::DefaultObject.new([], underlying_object: actual)
29
29
  end
30
30
 
31
31
  def find_operation_tree_for(value)
@@ -1,5 +1,5 @@
1
1
  module SuperDiff
2
2
  module OperationTreeBuilders
3
- DEFAULTS = [Array, Hash, CustomObject].freeze
3
+ DEFAULTS = [Array, Hash, TimeLike, CustomObject].freeze
4
4
  end
5
5
  end
@@ -53,7 +53,7 @@ module SuperDiff
53
53
  ev2, av2 = expected[ek], actual[ek]
54
54
 
55
55
  if (
56
- (!actual.include?(ek) || ev != av2) &&
56
+ (!actual.include?(ek) || ev2 != av2) &&
57
57
  operations.none? { |operation|
58
58
  [:delete, :noop].include?(operation.name) &&
59
59
  operation.key == ek
@@ -65,7 +65,6 @@ module SuperDiff
65
65
  key: ek,
66
66
  value: ev2,
67
67
  index: ei2,
68
- index_in_collection: ei2,
69
68
  )
70
69
  end
71
70
  end
@@ -77,7 +76,6 @@ module SuperDiff
77
76
  key: ak,
78
77
  value: av,
79
78
  index: ai,
80
- index_in_collection: ai,
81
79
  )
82
80
  else
83
81
  # (If we're here, it probably means that the key in 'actual' isn't
@@ -133,7 +131,6 @@ module SuperDiff
133
131
  key: ek,
134
132
  value: ev,
135
133
  index: ei2,
136
- index_in_collection: ei2,
137
134
  )
138
135
  end
139
136
 
@@ -148,7 +145,6 @@ module SuperDiff
148
145
  key: ak,
149
146
  value: av,
150
147
  index: ai,
151
- index_in_collection: ai,
152
148
  )
153
149
  end
154
150
  end
@@ -169,7 +165,6 @@ module SuperDiff
169
165
  key: ak,
170
166
  value: expected[ak],
171
167
  index: ei,
172
- index_in_collection: ei,
173
168
  )
174
169
  end
175
170
 
@@ -184,7 +179,6 @@ module SuperDiff
184
179
  key: ak,
185
180
  value: av,
186
181
  index: ai,
187
- index_in_collection: ai,
188
182
  )
189
183
  end
190
184
  end
@@ -207,7 +201,6 @@ module SuperDiff
207
201
  key: ek,
208
202
  value: ev,
209
203
  index: ei,
210
- index_in_collection: ei,
211
204
  )
212
205
  end
213
206
 
@@ -38,12 +38,8 @@ module SuperDiff
38
38
 
39
39
  attr_reader :sequence_matcher, :original_expected, :original_actual
40
40
 
41
- def split_into_lines(str)
42
- str.
43
- split(/(\r?\n)/).
44
- each_slice(2).
45
- map(&:join).
46
- map { |line| line.inspect[1..-2] }
41
+ def split_into_lines(string)
42
+ string.scan(/.+(?:\r|\n|\r\n|\Z)/)
47
43
  end
48
44
 
49
45
  def opcodes
@@ -15,9 +15,9 @@ module SuperDiff
15
15
  "hour",
16
16
  "min",
17
17
  "sec",
18
- "nsec",
18
+ "subsec",
19
19
  "zone",
20
- "gmt_offset",
20
+ "utc_offset",
21
21
  ]
22
22
 
23
23
  # If timezones are different, also show a normalized timestamp at the
@@ -0,0 +1,20 @@
1
+ module SuperDiff
2
+ module OperationTreeFlatteners
3
+ autoload :Array, "super_diff/operation_tree_flatteners/array"
4
+ autoload :Base, "super_diff/operation_tree_flatteners/base"
5
+ autoload :Collection, "super_diff/operation_tree_flatteners/collection"
6
+ autoload(
7
+ :CustomObject,
8
+ "super_diff/operation_tree_flatteners/custom_object",
9
+ )
10
+ autoload(
11
+ :DefaultObject,
12
+ "super_diff/operation_tree_flatteners/default_object",
13
+ )
14
+ autoload :Hash, "super_diff/operation_tree_flatteners/hash"
15
+ autoload(
16
+ :MultilineString,
17
+ "super_diff/operation_tree_flatteners/multiline_string",
18
+ )
19
+ end
20
+ end
@@ -0,0 +1,15 @@
1
+ module SuperDiff
2
+ module OperationTreeFlatteners
3
+ class Array < Collection
4
+ protected
5
+
6
+ def open_token
7
+ "["
8
+ end
9
+
10
+ def close_token
11
+ "]"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,54 @@
1
+ module SuperDiff
2
+ module OperationTreeFlatteners
3
+ class Base
4
+ include ImplementationChecks
5
+ extend AttrExtras.mixin
6
+
7
+ method_object :operation_tree, [indentation_level: 0]
8
+
9
+ def call
10
+ beginning_lines + middle_lines + ending_lines
11
+ end
12
+
13
+ protected
14
+
15
+ def build_tiered_lines
16
+ unimplemented_instance_method!
17
+ end
18
+
19
+ private
20
+
21
+ def beginning_lines
22
+ if tiered_lines.empty?
23
+ []
24
+ elsif indentation_level > 0
25
+ [tiered_lines[0]]
26
+ else
27
+ [tiered_lines[0].with_complete_bookend(:open)]
28
+ end
29
+ end
30
+
31
+ def middle_lines
32
+ if tiered_lines.empty?
33
+ []
34
+ else
35
+ tiered_lines[1..-2]
36
+ end
37
+ end
38
+
39
+ def ending_lines
40
+ if tiered_lines.empty?
41
+ []
42
+ elsif indentation_level > 0
43
+ [tiered_lines[-1]]
44
+ else
45
+ [tiered_lines[-1].with_complete_bookend(:close)]
46
+ end
47
+ end
48
+
49
+ def tiered_lines
50
+ @_tiered_lines ||= build_tiered_lines
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,139 @@
1
+ module SuperDiff
2
+ module OperationTreeFlatteners
3
+ class Collection < Base
4
+ protected
5
+
6
+ def build_tiered_lines
7
+ [
8
+ Line.new(
9
+ type: :noop,
10
+ indentation_level: indentation_level,
11
+ value: open_token,
12
+ collection_bookend: :open,
13
+ ),
14
+ *inner_lines,
15
+ Line.new(
16
+ type: :noop,
17
+ indentation_level: indentation_level,
18
+ value: close_token,
19
+ collection_bookend: :close,
20
+ ),
21
+ ]
22
+ end
23
+
24
+ def inner_lines
25
+ @_inner_lines ||= operation_tree.
26
+ flat_map do |operation|
27
+ lines =
28
+ if operation.name == :change
29
+ build_lines_for_change_operation(operation)
30
+ else
31
+ build_lines_for_non_change_operation(operation)
32
+ end
33
+
34
+ maybe_add_prefix_at_beginning_of_lines(
35
+ maybe_add_comma_at_end_of_lines(lines, operation),
36
+ operation,
37
+ )
38
+ end
39
+ end
40
+
41
+ def maybe_add_prefix_at_beginning_of_lines(lines, operation)
42
+ if add_prefix_at_beginning_of_lines?(operation)
43
+ add_prefix_at_beginning_of_lines(lines, operation)
44
+ else
45
+ lines
46
+ end
47
+ end
48
+
49
+ def add_prefix_at_beginning_of_lines?(operation)
50
+ !!item_prefix_for(operation)
51
+ end
52
+
53
+ def add_prefix_at_beginning_of_lines(lines, operation)
54
+ [lines[0].prefixed_with(item_prefix_for(operation))] +
55
+ lines[1..-1]
56
+ end
57
+
58
+ def maybe_add_comma_at_end_of_lines(lines, operation)
59
+ if last_item_in_collection?(operation)
60
+ lines
61
+ else
62
+ add_comma_at_end_of_lines(lines)
63
+ end
64
+ end
65
+
66
+ def last_item_in_collection?(operation)
67
+ if operation.name == :change
68
+ operation.left_index == operation.left_collection.size - 1 &&
69
+ operation.right_index == operation.right_collection.size - 1
70
+ else
71
+ operation.index == operation.collection.size - 1
72
+ end
73
+ end
74
+
75
+ def add_comma_at_end_of_lines(lines)
76
+ lines[0..-2] + [lines[-1].with_comma]
77
+ end
78
+
79
+ def build_lines_for_change_operation(operation)
80
+ SuperDiff::RecursionGuard.guarding_recursion_of(
81
+ operation.left_collection,
82
+ operation.right_collection,
83
+ ) do |already_seen|
84
+ if already_seen
85
+ raise InfiniteRecursionError
86
+ else
87
+ operation.children.flatten(
88
+ indentation_level: indentation_level + 1,
89
+ )
90
+ end
91
+ end
92
+ end
93
+
94
+ def build_lines_for_non_change_operation(operation)
95
+ indentation_level = @indentation_level + 1
96
+
97
+ if recursive_operation?(operation)
98
+ [
99
+ Line.new(
100
+ type: operation.name,
101
+ indentation_level: indentation_level,
102
+ value: SuperDiff::RecursionGuard::PLACEHOLDER,
103
+ ),
104
+ ]
105
+ else
106
+ build_lines_from_inspection_of(
107
+ operation.value,
108
+ type: operation.name,
109
+ indentation_level: indentation_level,
110
+ )
111
+ end
112
+ end
113
+
114
+ def recursive_operation?(operation)
115
+ operation.value.equal?(operation.collection) ||
116
+ SuperDiff::RecursionGuard.already_seen?(operation.value)
117
+ end
118
+
119
+ def item_prefix_for(_operation)
120
+ ""
121
+ end
122
+
123
+ def build_lines_from_inspection_of(value, type:, indentation_level:)
124
+ SuperDiff.inspect_object(
125
+ value,
126
+ as_lines: true,
127
+ type: type,
128
+ indentation_level: indentation_level,
129
+ )
130
+ end
131
+
132
+ class InfiniteRecursionError < StandardError
133
+ def initialize(_message = nil)
134
+ super("Unhandled recursive data structure encountered!")
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end