From 73fadeb963546e938037afce62a19515ba26c97b Mon Sep 17 00:00:00 2001 From: Joe Stein Date: Thu, 26 Mar 2026 11:45:20 -0700 Subject: [PATCH 1/3] Write failing test for multiline op tree builder Specifically, if there is another operation tree builder that can produce an op subtree for each line, the multiline string differ will raise an error. --- .../multiline_string_spec.rb | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/spec/unit/basic/operation_tree_builders/multiline_string_spec.rb b/spec/unit/basic/operation_tree_builders/multiline_string_spec.rb index adc274cf..bfc73f48 100644 --- a/spec/unit/basic/operation_tree_builders/multiline_string_spec.rb +++ b/spec/unit/basic/operation_tree_builders/multiline_string_spec.rb @@ -2,6 +2,41 @@ require 'spec_helper' +class WordOperationTreeBuilder < SuperDiff::Core::AbstractOperationTreeBuilder + def self.applies_to?(expected, actual) + expected.is_a?(::String) && actual.is_a?(::String) + end + + protected + + def unary_operations + expected_words = expected.split + actual_words = actual.split + + Diff::LCS.diff(expected_words, actual_words).flat_map do |change_group| + change_group.map do |change| + SuperDiff::Core::UnaryOperation.new( + name: change.action == '+' ? :insert : :delete, + collection: expected, + key: change.position, + index: change.position, + value: change.element + ) + end + end + end + + def build_operation_tree + SuperDiff::Basic::OperationTrees::Array.new([]) + end + + private + + def should_compare?(_operation, _next_operation) + false + end +end + RSpec.describe SuperDiff, type: :unit do describe '.diff' do subject(:diff) { SuperDiff.diff(expected, actual) } @@ -115,5 +150,33 @@ expect(diff).to eq(expected_output) end end + + context 'when a string operation tree builder exists' do + around do |example| + with_configuration(extra_operation_tree_builder_classes: SuperDiff.configuration.extra_operation_tree_builder_classes + [WordOperationTreeBuilder]) do + example.run + end + end + + let(:actual) { <<~STRING } + This here is a string. + It contains separate lines. + This one is different. + STRING + + it 'does not attempt to diff each line' do + expected_output = + SuperDiff::Core::Helpers + .style(color_enabled: true) do + plain_line ' This here is a string.\\n' + plain_line ' It contains separate lines.\\n' + expected_line '- What else can I say?\\n' + actual_line '+ This one is different.\\n' + end + .to_s + .chomp + expect(diff).to eq(expected_output) + end + end end end From 86965b32cb20842d35659fbabc8ba80aa5689fca Mon Sep 17 00:00:00 2001 From: Joe Stein Date: Thu, 26 Mar 2026 11:47:07 -0700 Subject: [PATCH 2/3] Do not attempt to sub-diff multiline strings --- .../basic/operation_tree_builders/multiline_string.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/super_diff/basic/operation_tree_builders/multiline_string.rb b/lib/super_diff/basic/operation_tree_builders/multiline_string.rb index 714d13d6..43fc44ff 100644 --- a/lib/super_diff/basic/operation_tree_builders/multiline_string.rb +++ b/lib/super_diff/basic/operation_tree_builders/multiline_string.rb @@ -43,6 +43,13 @@ def build_operation_tree attr_reader :sequence_matcher, :original_expected, :original_actual + # override + def should_compare?(_operation, _next_operation) + # Don't try to build a nested operation tree for individual line changes, even if + # there's an applicable string operation tree builder. + false + end + def split_into_lines(string) string.scan(/.*(?:\r|\n|\r\n|\Z)/) end From be171e14016b7057a994ad70c24e43a831b4bb10 Mon Sep 17 00:00:00 2001 From: Joe Stein Date: Thu, 26 Mar 2026 11:55:29 -0700 Subject: [PATCH 3/3] Add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4a5de6a..2088fe1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Support elision for flat line trees. [#300](https://github.com/splitwise/super_diff/pull/300) by [@gschlager](https://github.com/gschlager) - Fix integration snippet indentation. [#299](https://github.com/splitwise/super_diff/pull/299) by [@gschlager](https://github.com/gschlager) - Pin all actions to full commit SHA. [#305](https://github.com/splitwise/super_diff/pull/305) +- Do not attempt to sub-diff multiline strings. [#304](https://github.com/splitwise/super_diff/pull/304) ## 0.18.0 - 2025-12-05