Skip to content

Commit 8e410e6

Browse files
authored
Do not attempt to sub-diff multiline strings (#304)
Inspired by @gschlager 's PR; see https://github.com/splitwise/super_diff/pull/301/changes#r2996407601.
1 parent 4215b55 commit 8e410e6

3 files changed

Lines changed: 71 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
- Support elision for flat line trees. [#300](https://github.com/splitwise/super_diff/pull/300) by [@gschlager](https://github.com/gschlager)
1111
- Fix integration snippet indentation. [#299](https://github.com/splitwise/super_diff/pull/299) by [@gschlager](https://github.com/gschlager)
1212
- Pin all actions to full commit SHA. [#305](https://github.com/splitwise/super_diff/pull/305)
13+
- Do not attempt to sub-diff multiline strings. [#304](https://github.com/splitwise/super_diff/pull/304)
1314

1415
## 0.18.0 - 2025-12-05
1516

lib/super_diff/basic/operation_tree_builders/multiline_string.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ def build_operation_tree
4343

4444
attr_reader :sequence_matcher, :original_expected, :original_actual
4545

46+
# override
47+
def should_compare?(_operation, _next_operation)
48+
# Don't try to build a nested operation tree for individual line changes, even if
49+
# there's an applicable string operation tree builder.
50+
false
51+
end
52+
4653
def split_into_lines(string)
4754
string.scan(/.*(?:\r|\n|\r\n|\Z)/)
4855
end

spec/unit/basic/operation_tree_builders/multiline_string_spec.rb

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,41 @@
22

33
require 'spec_helper'
44

5+
class WordOperationTreeBuilder < SuperDiff::Core::AbstractOperationTreeBuilder
6+
def self.applies_to?(expected, actual)
7+
expected.is_a?(::String) && actual.is_a?(::String)
8+
end
9+
10+
protected
11+
12+
def unary_operations
13+
expected_words = expected.split
14+
actual_words = actual.split
15+
16+
Diff::LCS.diff(expected_words, actual_words).flat_map do |change_group|
17+
change_group.map do |change|
18+
SuperDiff::Core::UnaryOperation.new(
19+
name: change.action == '+' ? :insert : :delete,
20+
collection: expected,
21+
key: change.position,
22+
index: change.position,
23+
value: change.element
24+
)
25+
end
26+
end
27+
end
28+
29+
def build_operation_tree
30+
SuperDiff::Basic::OperationTrees::Array.new([])
31+
end
32+
33+
private
34+
35+
def should_compare?(_operation, _next_operation)
36+
false
37+
end
38+
end
39+
540
RSpec.describe SuperDiff, type: :unit do
641
describe '.diff' do
742
subject(:diff) { SuperDiff.diff(expected, actual) }
@@ -115,5 +150,33 @@
115150
expect(diff).to eq(expected_output)
116151
end
117152
end
153+
154+
context 'when a string operation tree builder exists' do
155+
around do |example|
156+
with_configuration(extra_operation_tree_builder_classes: SuperDiff.configuration.extra_operation_tree_builder_classes + [WordOperationTreeBuilder]) do
157+
example.run
158+
end
159+
end
160+
161+
let(:actual) { <<~STRING }
162+
This here is a string.
163+
It contains separate lines.
164+
This one is different.
165+
STRING
166+
167+
it 'does not attempt to diff each line' do
168+
expected_output =
169+
SuperDiff::Core::Helpers
170+
.style(color_enabled: true) do
171+
plain_line ' This here is a string.\\n'
172+
plain_line ' It contains separate lines.\\n'
173+
expected_line '- What else can I say?\\n'
174+
actual_line '+ This one is different.\\n'
175+
end
176+
.to_s
177+
.chomp
178+
expect(diff).to eq(expected_output)
179+
end
180+
end
118181
end
119182
end

0 commit comments

Comments
 (0)