From e47e0a695ab1fbfdda5b23d80d74248ef885d60e Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 22 Dec 2014 14:27:08 +0300 Subject: [PATCH] diff: ignore replacements with moving of punctuation into another line We do not detect such cases in ByWord diff - so we can't fully rely on inner fragments Squash such blocks into a single one --- .../util/diff/comparison/ComparisonUtil.java | 12 ++++++++---- .../util/diff/comparison/LineFragmentSplitter.java | 13 +++++++++++-- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/platform/diff-api/src/com/intellij/openapi/util/diff/comparison/ComparisonUtil.java b/platform/diff-api/src/com/intellij/openapi/util/diff/comparison/ComparisonUtil.java index 6f7f7bff0547..9187034774db 100644 --- a/platform/diff-api/src/com/intellij/openapi/util/diff/comparison/ComparisonUtil.java +++ b/platform/diff-api/src/com/intellij/openapi/util/diff/comparison/ComparisonUtil.java @@ -255,8 +255,10 @@ public class ComparisonUtil { CharSequenceSubSequence sequence1 = new CharSequenceSubSequence(text1, fragment.getStartOffset1(), fragment.getEndOffset1()); CharSequenceSubSequence sequence2 = new CharSequenceSubSequence(text2, fragment.getStartOffset2(), fragment.getEndOffset2()); - if (fragment.getFineFragments() != null && !fragment.getFineFragments().isEmpty()) break; - if (!StringUtil.equalsIgnoreWhitespaces(sequence1, sequence2)) break; + if ((fragment.getFineFragments() == null || !fragment.getFineFragments().isEmpty()) && + !StringUtil.equalsIgnoreWhitespaces(sequence1, sequence2)) { + break; + } start++; } while (start < end) { @@ -264,8 +266,10 @@ public class ComparisonUtil { CharSequenceSubSequence sequence1 = new CharSequenceSubSequence(text1, fragment.getStartOffset1(), fragment.getEndOffset1()); CharSequenceSubSequence sequence2 = new CharSequenceSubSequence(text2, fragment.getStartOffset2(), fragment.getEndOffset2()); - if (fragment.getFineFragments() != null && !fragment.getFineFragments().isEmpty()) break; - if (!StringUtil.equalsIgnoreWhitespaces(sequence1, sequence2)) break; + if ((fragment.getFineFragments() == null || !fragment.getFineFragments().isEmpty()) && + !StringUtil.equalsIgnoreWhitespaces(sequence1, sequence2)) { + break; + } end--; } } diff --git a/platform/diff-api/src/com/intellij/openapi/util/diff/comparison/LineFragmentSplitter.java b/platform/diff-api/src/com/intellij/openapi/util/diff/comparison/LineFragmentSplitter.java index fb1c5dfe2e15..88ffcb0d0344 100644 --- a/platform/diff-api/src/com/intellij/openapi/util/diff/comparison/LineFragmentSplitter.java +++ b/platform/diff-api/src/com/intellij/openapi/util/diff/comparison/LineFragmentSplitter.java @@ -116,8 +116,7 @@ class LineFragmentSplitter { private boolean shouldMergeBlocks(@NotNull WordBlock lastBlock, @NotNull WordBlock newBlock) { if (!lastHasEqualWords && !hasEqualWords) return true; // combine lines, that matched only by '\n' if (isEqualsIgnoreWhitespace(newBlock) && isEqualsIgnoreWhitespace(lastBlock)) return true; // combine whitespace-only changed lines - // TODO: squash if new/old block contain no words, and non-space characters could be attached to the end of the second one - // TODO: or squash all blocks without words in it ? + if (noWordsInside(lastBlock) || noWordsInside(newBlock)) return true; // squash block without words in it return false; } @@ -151,6 +150,16 @@ class LineFragmentSplitter { return words1.get(index - 1) instanceof NewlineChunk; } + private boolean noWordsInside(@NotNull WordBlock block) { + for (int i = block.words.start1; i < block.words.end1; i++) { + if (!(myWords1.get(i) instanceof NewlineChunk)) return false; + } + for (int i = block.words.start2; i < block.words.end2; i++) { + if (!(myWords2.get(i) instanceof NewlineChunk)) return false; + } + return true; + } + // // Helpers //