mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-77478 diff: support by-character diff highlighting
This commit is contained in:
+3
-1
@@ -5,6 +5,7 @@ import com.intellij.diff.DiffContentFactory;
|
||||
import com.intellij.diff.DiffManager;
|
||||
import com.intellij.diff.DiffRequestPanel;
|
||||
import com.intellij.diff.comparison.ComparisonManagerImpl;
|
||||
import com.intellij.diff.comparison.InnerFragmentsPolicy;
|
||||
import com.intellij.diff.contents.DocumentContent;
|
||||
import com.intellij.diff.fragments.LineFragment;
|
||||
import com.intellij.diff.tools.fragmented.UnifiedDiffTool;
|
||||
@@ -389,13 +390,14 @@ class PreviewDiffPanel extends BorderLayoutPanel implements Disposable, PreviewT
|
||||
@NotNull
|
||||
private static DiffUserDataKeysEx.DiffComputer getDiffComputer(@NotNull Collection<? extends Range> ranges) {
|
||||
return (text1, text2, policy, innerChanges, indicator) -> {
|
||||
InnerFragmentsPolicy fragmentsPolicy = innerChanges ? InnerFragmentsPolicy.WORDS : InnerFragmentsPolicy.NONE;
|
||||
LineOffsets offsets1 = LineOffsetsUtil.create(text1);
|
||||
LineOffsets offsets2 = LineOffsetsUtil.create(text2);
|
||||
|
||||
List<LineFragment> result = new ArrayList<>();
|
||||
ComparisonManagerImpl comparisonManager = ComparisonManagerImpl.getInstanceImpl();
|
||||
for (Range range : ranges) {
|
||||
result.addAll(comparisonManager.compareLinesInner(range, text1, text2, offsets1, offsets2, policy, innerChanges, indicator));
|
||||
result.addAll(comparisonManager.compareLinesInner(range, text1, text2, offsets1, offsets2, policy, fragmentsPolicy, indicator));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.diff.comparison;
|
||||
|
||||
public enum InnerFragmentsPolicy {
|
||||
NONE,
|
||||
WORDS,
|
||||
CHARS
|
||||
}
|
||||
@@ -16,7 +16,9 @@
|
||||
package com.intellij.diff.comparison;
|
||||
|
||||
import com.intellij.diff.comparison.iterables.DiffIterable;
|
||||
import com.intellij.diff.comparison.iterables.DiffIterableUtil;
|
||||
import com.intellij.diff.comparison.iterables.FairDiffIterable;
|
||||
import com.intellij.diff.util.IntPair;
|
||||
import com.intellij.diff.util.Range;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import gnu.trove.TIntArrayList;
|
||||
@@ -55,6 +57,32 @@ public class ByChar {
|
||||
return matchAdjustmentSpaces(chars1, chars2, text1, text2, nonSpaceChanges, indicator);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DiffIterable compareTrimWhitespaces(@NotNull CharSequence text1,
|
||||
@NotNull CharSequence text2,
|
||||
@NotNull ProgressIndicator indicator) {
|
||||
FairDiffIterable iterable = compareTwoStep(text1, text2, indicator);
|
||||
|
||||
IntPair trim1 = TrimUtil.trim(text1, 0, text1.length());
|
||||
IntPair trim2 = TrimUtil.trim(text2, 0, text2.length());
|
||||
|
||||
List<Range> ranges = new ArrayList<>();
|
||||
for (Range ch : iterable.iterateChanges()) {
|
||||
int start1 = Math.max(ch.start1, trim1.val1);
|
||||
int end1 = Math.min(ch.end1, trim1.val2);
|
||||
int start2 = Math.max(ch.start2, trim2.val1);
|
||||
int end2 = Math.min(ch.end2, trim2.val2);
|
||||
|
||||
if (end1 < start1) start1 = end1 = ch.start1;
|
||||
if (end2 < start2) start2 = end2 = ch.start2;
|
||||
|
||||
if (start1 != end1 || start2 != end2) {
|
||||
ranges.add(new Range(start1, end1, start2, end2));
|
||||
}
|
||||
}
|
||||
return DiffIterableUtil.create(ranges, text1.length(), text2.length());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DiffIterable compareIgnoreWhitespaces(@NotNull CharSequence text1,
|
||||
@NotNull CharSequence text2,
|
||||
|
||||
@@ -127,7 +127,7 @@ public class ComparisonManagerImpl extends ComparisonManager {
|
||||
@NotNull ComparisonPolicy policy,
|
||||
@NotNull ProgressIndicator indicator) throws DiffTooBigException {
|
||||
List<LineFragment> lineFragments = compareLines(text1, text2, policy, indicator);
|
||||
return createInnerFragments(lineFragments, text1, text2, policy, indicator);
|
||||
return createInnerFragments(lineFragments, text1, text2, policy, InnerFragmentsPolicy.WORDS, indicator);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -136,11 +136,11 @@ public class ComparisonManagerImpl extends ComparisonManager {
|
||||
@NotNull LineOffsets lineOffsets1,
|
||||
@NotNull LineOffsets lineOffsets2,
|
||||
@NotNull ComparisonPolicy policy,
|
||||
boolean innerFragments,
|
||||
@NotNull InnerFragmentsPolicy fragmentsPolicy,
|
||||
@NotNull ProgressIndicator indicator) throws DiffTooBigException {
|
||||
List<LineFragment> lineFragments = compareLines(text1, text2, lineOffsets1, lineOffsets2, policy, indicator);
|
||||
if (innerFragments) {
|
||||
return createInnerFragments(lineFragments, text1, text2, policy, indicator);
|
||||
if (fragmentsPolicy != InnerFragmentsPolicy.NONE) {
|
||||
return createInnerFragments(lineFragments, text1, text2, policy, fragmentsPolicy, indicator);
|
||||
}
|
||||
else {
|
||||
return lineFragments;
|
||||
@@ -154,11 +154,11 @@ public class ComparisonManagerImpl extends ComparisonManager {
|
||||
@NotNull LineOffsets lineOffsets1,
|
||||
@NotNull LineOffsets lineOffsets2,
|
||||
@NotNull ComparisonPolicy policy,
|
||||
boolean innerFragments,
|
||||
@NotNull InnerFragmentsPolicy fragmentsPolicy,
|
||||
@NotNull ProgressIndicator indicator) throws DiffTooBigException {
|
||||
List<LineFragment> lineFragments = compareLines(range, text1, text2, lineOffsets1, lineOffsets2, policy, indicator);
|
||||
if (innerFragments) {
|
||||
return createInnerFragments(lineFragments, text1, text2, policy, indicator);
|
||||
if (fragmentsPolicy != InnerFragmentsPolicy.NONE) {
|
||||
return createInnerFragments(lineFragments, text1, text2, policy, fragmentsPolicy, indicator);
|
||||
}
|
||||
else {
|
||||
return lineFragments;
|
||||
@@ -169,6 +169,7 @@ public class ComparisonManagerImpl extends ComparisonManager {
|
||||
@NotNull CharSequence text1,
|
||||
@NotNull CharSequence text2,
|
||||
@NotNull ComparisonPolicy policy,
|
||||
@NotNull InnerFragmentsPolicy fragmentsPolicy,
|
||||
@NotNull ProgressIndicator indicator) {
|
||||
List<LineFragment> result = new ArrayList<>(lineFragments.size());
|
||||
|
||||
@@ -179,7 +180,7 @@ public class ComparisonManagerImpl extends ComparisonManager {
|
||||
try {
|
||||
// Do not try to build fine blocks after few fails
|
||||
boolean tryComputeDifferences = tooBigChunksCount < FilesTooBigForDiffException.MAX_BAD_LINES;
|
||||
result.addAll(createInnerFragments(fragment, text1, text2, policy, indicator, tryComputeDifferences));
|
||||
result.addAll(createInnerFragments(fragment, text1, text2, policy, fragmentsPolicy, indicator, tryComputeDifferences));
|
||||
}
|
||||
catch (DiffTooBigException e) {
|
||||
result.add(fragment);
|
||||
@@ -195,8 +196,13 @@ public class ComparisonManagerImpl extends ComparisonManager {
|
||||
@NotNull CharSequence text1,
|
||||
@NotNull CharSequence text2,
|
||||
@NotNull ComparisonPolicy policy,
|
||||
@NotNull InnerFragmentsPolicy fragmentsPolicy,
|
||||
@NotNull ProgressIndicator indicator,
|
||||
boolean tryComputeDifferences) throws DiffTooBigException {
|
||||
if (fragmentsPolicy == InnerFragmentsPolicy.NONE) {
|
||||
return singletonList(fragment);
|
||||
}
|
||||
|
||||
CharSequence subSequence1 = text1.subSequence(fragment.getStartOffset1(), fragment.getEndOffset1());
|
||||
CharSequence subSequence2 = text2.subSequence(fragment.getStartOffset2(), fragment.getEndOffset2());
|
||||
|
||||
@@ -212,6 +218,23 @@ public class ComparisonManagerImpl extends ComparisonManager {
|
||||
|
||||
if (!tryComputeDifferences) return singletonList(fragment);
|
||||
|
||||
if (fragmentsPolicy == InnerFragmentsPolicy.WORDS) {
|
||||
return createInnerWordFragments(fragment, subSequence1, subSequence2, policy, indicator);
|
||||
}
|
||||
else if (fragmentsPolicy == InnerFragmentsPolicy.CHARS) {
|
||||
return createInnerCharFragments(fragment, subSequence1, subSequence2, policy, indicator);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(fragmentsPolicy.name());
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<LineFragment> createInnerWordFragments(@NotNull LineFragment fragment,
|
||||
@NotNull CharSequence subSequence1,
|
||||
@NotNull CharSequence subSequence2,
|
||||
@NotNull ComparisonPolicy policy,
|
||||
@NotNull ProgressIndicator indicator) throws DiffTooBigException {
|
||||
List<ByWord.LineBlock> lineBlocks = ByWord.compareAndSplit(subSequence1, subSequence2, policy, indicator);
|
||||
assert lineBlocks.size() != 0;
|
||||
|
||||
@@ -241,6 +264,27 @@ public class ComparisonManagerImpl extends ComparisonManager {
|
||||
return chunks;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<LineFragment> createInnerCharFragments(@NotNull LineFragment fragment,
|
||||
@NotNull CharSequence subSequence1,
|
||||
@NotNull CharSequence subSequence2,
|
||||
@NotNull ComparisonPolicy policy,
|
||||
@NotNull ProgressIndicator indicator) throws DiffTooBigException {
|
||||
DiffIterable iterable;
|
||||
if (policy == ComparisonPolicy.DEFAULT) {
|
||||
iterable = ByChar.compareTwoStep(subSequence1, subSequence2, indicator);
|
||||
}
|
||||
else if (policy == ComparisonPolicy.TRIM_WHITESPACES) {
|
||||
iterable = ByChar.compareTrimWhitespaces(subSequence1, subSequence2, indicator);
|
||||
}
|
||||
else {
|
||||
iterable = ByChar.compareIgnoreWhitespaces(subSequence1, subSequence2, indicator);
|
||||
}
|
||||
|
||||
List<DiffFragment> innerChanges = convertIntoDiffFragments(iterable);
|
||||
return singletonList(new LineFragmentImpl(fragment, innerChanges));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@Deprecated
|
||||
@@ -532,12 +576,12 @@ public class ComparisonManagerImpl extends ComparisonManager {
|
||||
@NotNull LineOffsets lineOffsets2,
|
||||
@NotNull BitSet ignored1,
|
||||
@NotNull BitSet ignored2,
|
||||
boolean innerFragments,
|
||||
@NotNull InnerFragmentsPolicy fragmentsPolicy,
|
||||
@NotNull ProgressIndicator indicator) throws DiffTooBigException {
|
||||
Range range = new Range(0, lineOffsets1.getLineCount(),
|
||||
0, lineOffsets2.getLineCount());
|
||||
return compareLinesWithIgnoredRanges(range, text1, text2, lineOffsets1, lineOffsets2, ignored1, ignored2,
|
||||
innerFragments, indicator);
|
||||
fragmentsPolicy, indicator);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -551,7 +595,7 @@ public class ComparisonManagerImpl extends ComparisonManager {
|
||||
@NotNull LineOffsets lineOffsets2,
|
||||
@NotNull BitSet ignored1,
|
||||
@NotNull BitSet ignored2,
|
||||
boolean innerFragments,
|
||||
@NotNull InnerFragmentsPolicy fragmentsPolicy,
|
||||
@NotNull ProgressIndicator indicator) throws DiffTooBigException {
|
||||
List<CharSequence> lineTexts1 = getNotIgnoredLineContents(range.start1, range.end1, text1, lineOffsets1, ignored1);
|
||||
List<CharSequence> lineTexts2 = getNotIgnoredLineContents(range.start2, range.end2, text2, lineOffsets2, ignored2);
|
||||
@@ -566,8 +610,8 @@ public class ComparisonManagerImpl extends ComparisonManager {
|
||||
|
||||
List<LineFragment> lineFragments = convertIntoLineFragments(range, lineOffsets1, lineOffsets2, trimmedIterable);
|
||||
|
||||
if (innerFragments) {
|
||||
lineFragments = createInnerFragments(lineFragments, text1, text2, ComparisonPolicy.DEFAULT, indicator);
|
||||
if (fragmentsPolicy != InnerFragmentsPolicy.NONE) {
|
||||
lineFragments = createInnerFragments(lineFragments, text1, text2, ComparisonPolicy.DEFAULT, fragmentsPolicy, indicator);
|
||||
}
|
||||
|
||||
return ContainerUtil.mapNotNull(lineFragments, fragment -> {
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
*/
|
||||
package com.intellij.diff.tools.util.base;
|
||||
|
||||
import com.intellij.diff.comparison.InnerFragmentsPolicy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public enum HighlightPolicy {
|
||||
BY_LINE("Highlight lines"),
|
||||
BY_WORD("Highlight words"),
|
||||
BY_WORD_SPLIT("Highlight split changes"),
|
||||
BY_CHAR("Highlight symbols"),
|
||||
DO_NOT_HIGHLIGHT("Do not highlight");
|
||||
|
||||
@NotNull private final String myText;
|
||||
@@ -39,10 +41,26 @@ public enum HighlightPolicy {
|
||||
}
|
||||
|
||||
public boolean isFineFragments() {
|
||||
return this == BY_WORD || this == BY_WORD_SPLIT;
|
||||
return getFragmentsPolicy() != InnerFragmentsPolicy.NONE;
|
||||
}
|
||||
|
||||
public boolean isShouldSquash() {
|
||||
return this == BY_WORD || this == BY_LINE;
|
||||
return this != BY_WORD_SPLIT;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public InnerFragmentsPolicy getFragmentsPolicy() {
|
||||
switch (this) {
|
||||
case BY_WORD:
|
||||
case BY_WORD_SPLIT:
|
||||
return InnerFragmentsPolicy.WORDS;
|
||||
case BY_CHAR:
|
||||
return InnerFragmentsPolicy.CHARS;
|
||||
case BY_LINE:
|
||||
case DO_NOT_HIGHLIGHT:
|
||||
return InnerFragmentsPolicy.NONE;
|
||||
default:
|
||||
throw new IllegalArgumentException(this.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-6
@@ -17,6 +17,7 @@ package com.intellij.diff.tools.util.text;
|
||||
|
||||
import com.intellij.diff.comparison.ComparisonManagerImpl;
|
||||
import com.intellij.diff.comparison.ComparisonPolicy;
|
||||
import com.intellij.diff.comparison.InnerFragmentsPolicy;
|
||||
import com.intellij.diff.fragments.LineFragment;
|
||||
import com.intellij.diff.tools.util.base.HighlightPolicy;
|
||||
import com.intellij.diff.tools.util.base.IgnorePolicy;
|
||||
@@ -41,7 +42,8 @@ public class SimpleTextDiffProvider extends TwosideTextDiffProviderBase implemen
|
||||
private static final Logger LOG = Logger.getInstance(SimpleTextDiffProvider.class);
|
||||
|
||||
private static final IgnorePolicy[] IGNORE_POLICIES = {DEFAULT, TRIM_WHITESPACES, IGNORE_WHITESPACES, IGNORE_WHITESPACES_CHUNKS};
|
||||
private static final HighlightPolicy[] HIGHLIGHT_POLICIES = {BY_LINE, BY_WORD, BY_WORD_SPLIT, DO_NOT_HIGHLIGHT};
|
||||
private static final HighlightPolicy[] HIGHLIGHT_POLICIES = {BY_LINE, BY_WORD, BY_WORD_SPLIT, BY_CHAR, DO_NOT_HIGHLIGHT};
|
||||
private static final HighlightPolicy[] CUSTOM_COMPUTER_HIGHLIGHT_POLICIES = {BY_LINE, BY_WORD, BY_WORD_SPLIT, DO_NOT_HIGHLIGHT};
|
||||
|
||||
@Nullable private final DiffComputer myDiffComputer;
|
||||
|
||||
@@ -55,7 +57,8 @@ public class SimpleTextDiffProvider extends TwosideTextDiffProviderBase implemen
|
||||
@NotNull Runnable rediff,
|
||||
@NotNull Disposable disposable,
|
||||
@Nullable DiffComputer diffComputer) {
|
||||
this(settings, rediff, disposable, diffComputer, IGNORE_POLICIES, HIGHLIGHT_POLICIES);
|
||||
this(settings, rediff, disposable, diffComputer, IGNORE_POLICIES,
|
||||
diffComputer != null ? CUSTOM_COMPUTER_HIGHLIGHT_POLICIES : HIGHLIGHT_POLICIES);
|
||||
}
|
||||
|
||||
private SimpleTextDiffProvider(@NotNull TextDiffSettings settings,
|
||||
@@ -92,7 +95,7 @@ public class SimpleTextDiffProvider extends TwosideTextDiffProviderBase implemen
|
||||
@NotNull HighlightPolicy highlightPolicy,
|
||||
@NotNull ProgressIndicator indicator) {
|
||||
ComparisonPolicy policy = ignorePolicy.getComparisonPolicy();
|
||||
boolean innerFragments = highlightPolicy.isFineFragments();
|
||||
InnerFragmentsPolicy fragmentsPolicy = highlightPolicy.getFragmentsPolicy();
|
||||
|
||||
if (diffComputer != null && linesRanges != null) {
|
||||
LOG.error(new Throwable("Unsupported operation: ranged diff with custom DiffComputer - " + diffComputer));
|
||||
@@ -101,12 +104,12 @@ public class SimpleTextDiffProvider extends TwosideTextDiffProviderBase implemen
|
||||
ComparisonManagerImpl comparisonManager = ComparisonManagerImpl.getInstanceImpl();
|
||||
if (linesRanges == null) {
|
||||
if (diffComputer != null) {
|
||||
List<LineFragment> fragments = diffComputer.compute(text1, text2, policy, innerFragments, indicator);
|
||||
List<LineFragment> fragments = diffComputer.compute(text1, text2, policy, fragmentsPolicy != InnerFragmentsPolicy.NONE, indicator);
|
||||
return Collections.singletonList(fragments);
|
||||
}
|
||||
else {
|
||||
List<LineFragment> fragments = comparisonManager.compareLinesInner(text1, text2, lineOffsets1, lineOffsets2,
|
||||
policy, innerFragments, indicator);
|
||||
policy, fragmentsPolicy, indicator);
|
||||
return Collections.singletonList(fragments);
|
||||
}
|
||||
}
|
||||
@@ -114,7 +117,7 @@ public class SimpleTextDiffProvider extends TwosideTextDiffProviderBase implemen
|
||||
List<List<LineFragment>> result = new ArrayList<>();
|
||||
for (Range range : linesRanges) {
|
||||
result.add(comparisonManager.compareLinesInner(range, text1, text2, lineOffsets1, lineOffsets2,
|
||||
policy, innerFragments, indicator));
|
||||
policy, fragmentsPolicy, indicator));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.diff.tools.util.text;
|
||||
|
||||
import com.intellij.diff.comparison.ComparisonManagerImpl;
|
||||
import com.intellij.diff.comparison.InnerFragmentsPolicy;
|
||||
import com.intellij.diff.contents.DiffContent;
|
||||
import com.intellij.diff.fragments.LineFragment;
|
||||
import com.intellij.diff.lang.DiffIgnoredRangeProvider;
|
||||
@@ -44,7 +45,7 @@ import static com.intellij.diff.tools.util.base.IgnorePolicy.*;
|
||||
|
||||
public class SmartTextDiffProvider extends TwosideTextDiffProviderBase implements TwosideTextDiffProvider {
|
||||
private static final IgnorePolicy[] IGNORE_POLICIES = {DEFAULT, TRIM_WHITESPACES, IGNORE_WHITESPACES, IGNORE_WHITESPACES_CHUNKS, FORMATTING};
|
||||
private static final HighlightPolicy[] HIGHLIGHT_POLICIES = {BY_LINE, BY_WORD, BY_WORD_SPLIT, DO_NOT_HIGHLIGHT};
|
||||
private static final HighlightPolicy[] HIGHLIGHT_POLICIES = {BY_LINE, BY_WORD, BY_WORD_SPLIT, BY_CHAR, DO_NOT_HIGHLIGHT};
|
||||
|
||||
@Nullable private final Project myProject;
|
||||
@NotNull private final DiffContent myContent1;
|
||||
@@ -137,7 +138,7 @@ public class SmartTextDiffProvider extends TwosideTextDiffProviderBase implement
|
||||
@Nullable List<Range> linesRanges,
|
||||
@NotNull HighlightPolicy highlightPolicy,
|
||||
@NotNull ProgressIndicator indicator) {
|
||||
boolean innerFragments = highlightPolicy.isFineFragments();
|
||||
InnerFragmentsPolicy fragmentsPolicy = highlightPolicy.getFragmentsPolicy();
|
||||
|
||||
List<TextRange> ignoredRanges1 = myProvider.getIgnoredRanges(myProject, text1, myContent1);
|
||||
List<TextRange> ignoredRanges2 = myProvider.getIgnoredRanges(myProject, text2, myContent2);
|
||||
@@ -148,14 +149,14 @@ public class SmartTextDiffProvider extends TwosideTextDiffProviderBase implement
|
||||
ComparisonManagerImpl comparisonManager = ComparisonManagerImpl.getInstanceImpl();
|
||||
if (linesRanges == null) {
|
||||
List<LineFragment> fragments = comparisonManager.compareLinesWithIgnoredRanges(text1, text2, lineOffsets1, lineOffsets2,
|
||||
ignored1, ignored2, innerFragments, indicator);
|
||||
ignored1, ignored2, fragmentsPolicy, indicator);
|
||||
return Collections.singletonList(fragments);
|
||||
}
|
||||
else {
|
||||
List<List<LineFragment>> result = new ArrayList<>();
|
||||
for (Range range : linesRanges) {
|
||||
result.add(comparisonManager.compareLinesWithIgnoredRanges(range, text1, text2, lineOffsets1, lineOffsets2,
|
||||
ignored1, ignored2, innerFragments, indicator));
|
||||
ignored1, ignored2, fragmentsPolicy, indicator));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.diff.fragments.MergeLineFragment
|
||||
import com.intellij.diff.fragments.MergeWordFragment
|
||||
import com.intellij.diff.tools.util.base.HighlightPolicy
|
||||
import com.intellij.diff.tools.util.base.IgnorePolicy
|
||||
import com.intellij.diff.tools.util.text.LineOffsetsUtil
|
||||
import com.intellij.diff.util.DiffUtil
|
||||
import com.intellij.diff.util.Range
|
||||
import com.intellij.diff.util.ThreeSide
|
||||
@@ -69,78 +70,90 @@ class ComparisonUtilAutoTest : HeavyDiffTestCase() {
|
||||
}
|
||||
|
||||
private fun doTestLine(seed: Long, runs: Int, maxLength: Int) {
|
||||
val policies = listOf(ComparisonPolicy.DEFAULT, ComparisonPolicy.TRIM_WHITESPACES, ComparisonPolicy.IGNORE_WHITESPACES)
|
||||
val ignorePolicies = listOf(ComparisonPolicy.DEFAULT, ComparisonPolicy.TRIM_WHITESPACES, ComparisonPolicy.IGNORE_WHITESPACES)
|
||||
val fragmentsPolicies = listOf(InnerFragmentsPolicy.WORDS, InnerFragmentsPolicy.CHARS)
|
||||
|
||||
doTest(seed, runs, maxLength, policies) { text1, text2, policy, debugData ->
|
||||
doTest(seed, runs, maxLength, ignorePolicies, fragmentsPolicies) { text1, text2, ignorePolicy, fragmentsPolicy, debugData ->
|
||||
val sequence1 = text1.charsSequence
|
||||
val sequence2 = text2.charsSequence
|
||||
|
||||
val fragments = MANAGER.compareLinesInner(sequence1, sequence2, policy, INDICATOR)
|
||||
val lineOffsets1 = LineOffsetsUtil.create(sequence1)
|
||||
val lineOffsets2 = LineOffsetsUtil.create(sequence2)
|
||||
|
||||
val fragments = MANAGER.compareLinesInner(sequence1, sequence2, lineOffsets1, lineOffsets2, ignorePolicy, fragmentsPolicy, INDICATOR)
|
||||
debugData.put("Fragments", fragments)
|
||||
|
||||
checkResultLine(text1, text2, fragments, policy, true)
|
||||
checkResultLine(text1, text2, fragments, ignorePolicy, true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun doTestLineSquashed(seed: Long, runs: Int, maxLength: Int) {
|
||||
val policies = listOf(ComparisonPolicy.DEFAULT, ComparisonPolicy.TRIM_WHITESPACES, ComparisonPolicy.IGNORE_WHITESPACES)
|
||||
val ignorePolicies = listOf(ComparisonPolicy.DEFAULT, ComparisonPolicy.TRIM_WHITESPACES, ComparisonPolicy.IGNORE_WHITESPACES)
|
||||
val fragmentsPolicies = listOf(InnerFragmentsPolicy.WORDS, InnerFragmentsPolicy.CHARS)
|
||||
|
||||
doTest(seed, runs, maxLength, policies) { text1, text2, policy, debugData ->
|
||||
doTest(seed, runs, maxLength, ignorePolicies, fragmentsPolicies) { text1, text2, ignorePolicy, fragmentsPolicy, debugData ->
|
||||
val sequence1 = text1.charsSequence
|
||||
val sequence2 = text2.charsSequence
|
||||
|
||||
val fragments = MANAGER.compareLinesInner(sequence1, sequence2, policy, INDICATOR)
|
||||
val lineOffsets1 = LineOffsetsUtil.create(sequence1)
|
||||
val lineOffsets2 = LineOffsetsUtil.create(sequence2)
|
||||
|
||||
val fragments = MANAGER.compareLinesInner(sequence1, sequence2, lineOffsets1, lineOffsets2, ignorePolicy, fragmentsPolicy, INDICATOR)
|
||||
debugData.put("Fragments", fragments)
|
||||
|
||||
val squashedFragments = MANAGER.squash(fragments)
|
||||
debugData.put("Squashed Fragments", squashedFragments)
|
||||
|
||||
checkResultLine(text1, text2, squashedFragments, policy, false)
|
||||
checkResultLine(text1, text2, squashedFragments, ignorePolicy, false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun doTestLineTrimSquashed(seed: Long, runs: Int, maxLength: Int) {
|
||||
val policies = listOf(ComparisonPolicy.DEFAULT, ComparisonPolicy.TRIM_WHITESPACES, ComparisonPolicy.IGNORE_WHITESPACES)
|
||||
val ignorePolicies = listOf(ComparisonPolicy.DEFAULT, ComparisonPolicy.TRIM_WHITESPACES, ComparisonPolicy.IGNORE_WHITESPACES)
|
||||
val fragmentsPolicies = listOf(InnerFragmentsPolicy.WORDS, InnerFragmentsPolicy.CHARS)
|
||||
|
||||
doTest(seed, runs, maxLength, policies) { text1, text2, policy, debugData ->
|
||||
doTest(seed, runs, maxLength, ignorePolicies, fragmentsPolicies) { text1, text2, ignorePolicy, fragmentsPolicy, debugData ->
|
||||
val sequence1 = text1.charsSequence
|
||||
val sequence2 = text2.charsSequence
|
||||
|
||||
val fragments = MANAGER.compareLinesInner(sequence1, sequence2, policy, INDICATOR)
|
||||
val lineOffsets1 = LineOffsetsUtil.create(sequence1)
|
||||
val lineOffsets2 = LineOffsetsUtil.create(sequence2)
|
||||
|
||||
val fragments = MANAGER.compareLinesInner(sequence1, sequence2, lineOffsets1, lineOffsets2, ignorePolicy, fragmentsPolicy, INDICATOR)
|
||||
debugData.put("Fragments", fragments)
|
||||
|
||||
val processed = MANAGER.processBlocks(fragments, sequence1, sequence2, policy, true, true)
|
||||
val processed = MANAGER.processBlocks(fragments, sequence1, sequence2, ignorePolicy, true, true)
|
||||
debugData.put("Processed Fragments", processed)
|
||||
|
||||
checkResultLine(text1, text2, processed, policy, false)
|
||||
checkResultLine(text1, text2, processed, ignorePolicy, false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun doTestChar(seed: Long, runs: Int, maxLength: Int) {
|
||||
val policies = listOf(ComparisonPolicy.DEFAULT, ComparisonPolicy.IGNORE_WHITESPACES)
|
||||
val ignorePolicies = listOf(ComparisonPolicy.DEFAULT, ComparisonPolicy.IGNORE_WHITESPACES)
|
||||
|
||||
doTest(seed, runs, maxLength, policies) { text1, text2, policy, debugData ->
|
||||
doTest(seed, runs, maxLength, ignorePolicies) { text1, text2, ignorePolicy, debugData ->
|
||||
val sequence1 = text1.charsSequence
|
||||
val sequence2 = text2.charsSequence
|
||||
|
||||
val fragments = MANAGER.compareChars(sequence1, sequence2, policy, INDICATOR)
|
||||
val fragments = MANAGER.compareChars(sequence1, sequence2, ignorePolicy, INDICATOR)
|
||||
debugData.put("Fragments", fragments)
|
||||
|
||||
checkResultChar(sequence1, sequence2, fragments, policy)
|
||||
checkResultChar(sequence1, sequence2, fragments, ignorePolicy)
|
||||
}
|
||||
}
|
||||
|
||||
private fun doTestWord(seed: Long, runs: Int, maxLength: Int) {
|
||||
val policies = listOf(ComparisonPolicy.DEFAULT, ComparisonPolicy.TRIM_WHITESPACES, ComparisonPolicy.IGNORE_WHITESPACES)
|
||||
val ignorePolicies = listOf(ComparisonPolicy.DEFAULT, ComparisonPolicy.TRIM_WHITESPACES, ComparisonPolicy.IGNORE_WHITESPACES)
|
||||
|
||||
doTest(seed, runs, maxLength, policies) { text1, text2, policy, debugData ->
|
||||
doTest(seed, runs, maxLength, ignorePolicies) { text1, text2, ignorePolicy, debugData ->
|
||||
val sequence1 = text1.charsSequence
|
||||
val sequence2 = text2.charsSequence
|
||||
|
||||
val fragments = MANAGER.compareWords(sequence1, sequence2, policy, INDICATOR)
|
||||
val fragments = MANAGER.compareWords(sequence1, sequence2, ignorePolicy, INDICATOR)
|
||||
debugData.put("Fragments", fragments)
|
||||
|
||||
checkResultWord(sequence1, sequence2, fragments, policy)
|
||||
checkResultWord(sequence1, sequence2, fragments, ignorePolicy)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,12 +231,24 @@ class ComparisonUtilAutoTest : HeavyDiffTestCase() {
|
||||
}
|
||||
|
||||
|
||||
private fun doTest(seed: Long, runs: Int, maxLength: Int, policies: List<ComparisonPolicy>,
|
||||
private fun doTest(seed: Long, runs: Int, maxLength: Int,
|
||||
ignorePolicies: List<ComparisonPolicy>, fragmentsPolicies: List<InnerFragmentsPolicy>,
|
||||
test: (Document, Document, ComparisonPolicy, InnerFragmentsPolicy, DiffTestCase.DebugData) -> Unit) {
|
||||
doTest(seed, runs, maxLength, ignorePolicies) { text1, text2, ignorePolicy, debugData ->
|
||||
for (fragmentsPolicy in fragmentsPolicies) {
|
||||
debugData.put("Inner Policy", fragmentsPolicy)
|
||||
test(text1, text2, ignorePolicy, fragmentsPolicy, debugData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun doTest(seed: Long, runs: Int, maxLength: Int,
|
||||
ignorePolicies: List<ComparisonPolicy>,
|
||||
test: (Document, Document, ComparisonPolicy, DiffTestCase.DebugData) -> Unit) {
|
||||
doTest(seed, runs, maxLength) { text1, text2, debugData ->
|
||||
for (comparisonPolicy in policies) {
|
||||
debugData.put("Policy", comparisonPolicy)
|
||||
test(text1, text2, comparisonPolicy, debugData)
|
||||
for (ignorePolicy in ignorePolicies) {
|
||||
debugData.put("Ignore Policy", ignorePolicy)
|
||||
test(text1, text2, ignorePolicy, debugData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,13 +557,13 @@ class IgnoreComparisonUtilTest : DiffTestCase() {
|
||||
val result1: String = result1.filterNot { it == '.' }
|
||||
val result2: String = result2.filterNot { it == '.' }
|
||||
|
||||
private var inner = true
|
||||
private var innerPolicy = InnerFragmentsPolicy.WORDS
|
||||
private var changedLinesNumber: IntPair? = null
|
||||
private var range: Range? = null
|
||||
private var changedLines: List<Couple<IntPair>>? = null
|
||||
|
||||
fun noInnerChanges(): Test {
|
||||
inner = false
|
||||
innerPolicy = InnerFragmentsPolicy.NONE
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -601,10 +601,10 @@ class IgnoreComparisonUtilTest : DiffTestCase() {
|
||||
val lineOffsets2 = LineOffsetsUtil.create(text2)
|
||||
|
||||
val result = if (range != null) {
|
||||
MANAGER.compareLinesWithIgnoredRanges(range!!, text1, text2, lineOffsets1, lineOffsets2, ignored1, ignored2, inner, INDICATOR)
|
||||
MANAGER.compareLinesWithIgnoredRanges(range!!, text1, text2, lineOffsets1, lineOffsets2, ignored1, ignored2, innerPolicy, INDICATOR)
|
||||
}
|
||||
else {
|
||||
MANAGER.compareLinesWithIgnoredRanges(text1, text2, lineOffsets1, lineOffsets2, ignored1, ignored2, inner, INDICATOR)
|
||||
MANAGER.compareLinesWithIgnoredRanges(text1, text2, lineOffsets1, lineOffsets2, ignored1, ignored2, innerPolicy, INDICATOR)
|
||||
}
|
||||
|
||||
val expected = Couple(parseExpected(result1), parseExpected(result2))
|
||||
|
||||
Reference in New Issue
Block a user