[vcs] IJPL-157627 Added ability to load inner fragments when 'Highlight lines' mode is enabled.

GitOrigin-RevId: 992ae38f51a3cf97157605dc63d1529cd5821644
This commit is contained in:
Denis Zaichenko
2024-07-09 12:15:49 +02:00
committed by intellij-monorepo-bot
parent 2dc32e7977
commit 75d4f86f62
3 changed files with 69 additions and 32 deletions

View File

@@ -640,6 +640,12 @@ a:com.intellij.diff.lang.LangDiffIgnoredRangeProvider
- pa:accepts(com.intellij.openapi.project.Project,com.intellij.lang.Language):Z
- pa:computeIgnoredRanges(com.intellij.openapi.project.Project,java.lang.CharSequence,com.intellij.lang.Language):java.util.List
- getIgnoredRanges(com.intellij.openapi.project.Project,java.lang.CharSequence,com.intellij.diff.contents.DiffContent):java.util.List
f:com.intellij.diff.merge.ChangeReferenceProcessor
- sf:Companion:com.intellij.diff.merge.ChangeReferenceProcessor$Companion
- <init>(com.intellij.openapi.project.Project,com.intellij.openapi.editor.Editor,java.util.List,java.util.List):V
- f:process(com.intellij.diff.util.ThreeSide,java.util.List,java.util.List):V
f:com.intellij.diff.merge.ChangeReferenceProcessor$Companion
- f:getLOG():com.intellij.openapi.diagnostic.Logger
a:com.intellij.diff.merge.MergeContextEx
- com.intellij.diff.merge.MergeContext
- <init>():V

View File

@@ -4,18 +4,26 @@ package com.intellij.diff.merge
import com.intellij.codeInsight.editorActions.CopyPastePostProcessor
import com.intellij.codeInsight.editorActions.ReferenceCopyPasteProcessor
import com.intellij.codeInsight.editorActions.TextBlockTransferableData
import com.intellij.diff.comparison.ComparisonPolicy
import com.intellij.diff.tools.util.text.MergeInnerDifferences
import com.intellij.diff.util.DiffUtil
import com.intellij.diff.util.Side
import com.intellij.diff.util.ThreeSide
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.editor.Document
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.RangeMarker
import com.intellij.openapi.progress.DumbProgressIndicator
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Ref
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiFile
import java.util.concurrent.ConcurrentHashMap
class ChangeReferenceProcessor(val project: Project, private val editor: Editor, val files: List<PsiFile>) {
class ChangeReferenceProcessor(private val project: Project, private val editor: Editor, private val files: List<PsiFile>, private val documents: List<Document>) {
private val innerDifferencesCache: MutableMap<TextMergeChange, MergeInnerDifferences?> = ConcurrentHashMap()
fun process(
side: ThreeSide,
@@ -51,39 +59,59 @@ class ChangeReferenceProcessor(val project: Project, private val editor: Editor,
processInnerFragments: Boolean,
) {
val sourceThreeSide = sourceSide.select(ThreeSide.LEFT, ThreeSide.RIGHT) ?: return
val sourceDocument = sourceThreeSide.select(documents) ?: return
val psiFile = sourceSide.select(files[0], files[2]) ?: return
val sourceDocument = psiFile.fileDocument
val startOffset = sourceDocument.getLineStartOffset(change.getStartLine(sourceThreeSide))
val endOffset = sourceDocument.getLineEndOffset(change.getEndLine(sourceThreeSide) - 1)
val sourceRange = DiffUtil.getLinesRange(sourceDocument, change.getStartLine(sourceThreeSide), change.getEndLine(sourceThreeSide))
if (!processInnerFragments) {
val data = createReferenceData(psiFile, startOffset, endOffset)
if (change.getStartLine(sourceThreeSide) == change.getEndLine(sourceThreeSide)) return
if (processInnerFragments) {
val innerDifferences = change.innerFragments ?: compareInner(change) ?: return
innerDifferences.get(sourceThreeSide)?.forEach {
if (it.isEmpty) return@forEach
val text = editor.document.getText(rangeMarker.textRange)
val fragmentStartOffset = sourceRange.startOffset + it.startOffset
val rangeInDocument = TextRange(fragmentStartOffset, fragmentStartOffset + it.length)
val fragmentText = sourceDocument.getText(rangeInDocument)
if (fragmentText.isBlank()) return@forEach
val offset = text.indexOf(fragmentText)
if (offset == -1) return@forEach
val data = createReferenceData(psiFile, rangeInDocument.startOffset, rangeInDocument.endOffset)
val marker = sourceDocument.createRangeMarker(
rangeMarker.startOffset + offset,
rangeMarker.startOffset + offset + fragmentText.length
)
data.forEach { processorData ->
processorData.process(project, editor, marker, 0, Ref(false))
}
}
}
else {
val data = createReferenceData(psiFile, sourceRange.startOffset, sourceRange.endOffset)
data.forEach { processorData ->
processorData.process(project, editor, rangeMarker, 0, Ref(false))
}
return
}
}
val innerFragments = change.innerFragments
innerFragments?.get(sourceThreeSide)?.forEach {
if (it.isEmpty) return@forEach
private fun getSequences(change: TextMergeChange): List<CharSequence?> {
return ThreeSide.map {
if (!change.isChange(it)) return@map null
val startLine = change.getStartLine(it)
val endLine = change.getEndLine(it)
if (startLine == endLine) return@map null
return@map DiffUtil.getLinesContent(it.select(documents), startLine, endLine)
}
}
val text = editor.document.getText(rangeMarker.textRange)
val fragmentStartOffset = startOffset + it.startOffset
val rangeInDocument = TextRange(fragmentStartOffset, fragmentStartOffset + it.length)
val fragmentText = sourceDocument.getText(rangeInDocument)
val offset = text.indexOf(fragmentText)
if (offset == -1) return@forEach
val data = createReferenceData(psiFile, rangeInDocument.startOffset, rangeInDocument.endOffset)
val marker = sourceDocument.createRangeMarker(
rangeMarker.startOffset + offset,
rangeInDocument.startOffset + offset + it.length
)
data.forEach { processorData ->
processorData.process(project, editor, marker, 0, Ref(false))
}
private fun compareInner(change: TextMergeChange): MergeInnerDifferences? {
return innerDifferencesCache.computeIfAbsent(change) {
return@computeIfAbsent DiffUtil.compareThreesideInner(getSequences(change), ComparisonPolicy.DEFAULT, DumbProgressIndicator.INSTANCE)
}
}

View File

@@ -1,9 +1,6 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.diff.merge;
import com.intellij.codeInsight.editorActions.CopyPastePostProcessor;
import com.intellij.codeInsight.editorActions.ReferenceCopyPasteProcessor;
import com.intellij.codeInsight.editorActions.TextBlockTransferableData;
import com.intellij.diff.DiffContext;
import com.intellij.diff.DiffDialogHints;
import com.intellij.diff.DiffManager;
@@ -59,7 +56,10 @@ import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageDialogBuilder;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.LineTokenizer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.ex.Range;
@@ -409,7 +409,6 @@ public class MergeThreesideViewer extends ThreesideTextDiffViewerEx {
sequences.addAll(ContainerUtil.map(contents, content -> content.getDocument().getImmutableCharSequence()));
if (getTextSettings().isAutoResolveImportConflicts()) {
initPsiFiles();
myChangeReferenceProcessor = new ChangeReferenceProcessor(myProject, getEditor(), myPsiFiles);
return MergeImportUtil.getImportMergeRange(myProject, myPsiFiles);
}
return null;
@@ -535,6 +534,9 @@ public class MergeThreesideViewer extends ThreesideTextDiffViewerEx {
);
if (myResolveImportConflicts) {
myChangeReferenceProcessor =
new ChangeReferenceProcessor(myProject, getEditor(), myPsiFiles,
ContainerUtil.map(myMergeRequest.getContents(), content -> content.getDocument()));
List<TextMergeChange> importChanges = ContainerUtil.filter(getChanges(), change -> change.isImportChange());
if (importChanges.size() != fragmentsWithMetadata.getFragments().size()) {
for (TextMergeChange importChange : importChanges) {
@@ -1104,8 +1106,9 @@ public class MergeThreesideViewer extends ThreesideTextDiffViewerEx {
if (myResolveImportConflicts && myPsiFiles.size() == 3) {
Document document = getContent(ThreeSide.BASE).getDocument();
List<RangeMarker> markers = ContainerUtil.map(newRanges, range ->
document.createRangeMarker(document.getLineStartOffset(range.start), document.getLineEndOffset(range.end)));
document.createRangeMarker(DiffUtil.getLinesRange(document, range.start, range.end)));
myChangeReferenceProcessor.process(side, changes, markers);
markers.forEach(RangeMarker::dispose);
}
}