mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
diff: allow to create LineOffsets from Document
This commit is contained in:
committed by
Aleksey Pivovarov
parent
924b76e03d
commit
6ba9ed4eaf
@@ -36,6 +36,7 @@ import com.intellij.diff.tools.util.base.HighlightPolicy;
|
||||
import com.intellij.diff.tools.util.base.IgnorePolicy;
|
||||
import com.intellij.diff.tools.util.base.TextDiffViewerUtil;
|
||||
import com.intellij.diff.tools.util.text.LineOffsets;
|
||||
import com.intellij.diff.tools.util.text.LineOffsetsUtil;
|
||||
import com.intellij.diff.tools.util.text.MergeInnerDifferences;
|
||||
import com.intellij.diff.tools.util.text.TextDiffProviderBase;
|
||||
import com.intellij.diff.util.*;
|
||||
@@ -406,7 +407,7 @@ public class TextMergeViewer implements MergeTool.MergeViewer {
|
||||
indicator.checkCanceled();
|
||||
return ContainerUtil.map(contents, content -> content.getDocument().getImmutableCharSequence());
|
||||
});
|
||||
List<LineOffsets> lineOffsets = ContainerUtil.map(sequences, LineOffsets::create);
|
||||
List<LineOffsets> lineOffsets = ContainerUtil.map(sequences, LineOffsetsUtil::create);
|
||||
|
||||
ComparisonManager manager = ComparisonManager.getInstance();
|
||||
List<MergeLineFragment> lineFragments = manager.compareLines(sequences.get(0), sequences.get(1), sequences.get(2),
|
||||
|
||||
@@ -15,61 +15,14 @@
|
||||
*/
|
||||
package com.intellij.diff.tools.util.text;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import gnu.trove.TIntArrayList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
public interface LineOffsets {
|
||||
int getLineStart(int line);
|
||||
|
||||
public class LineOffsets {
|
||||
private final int[] myLineEnds;
|
||||
private final int myTextLength;
|
||||
int getLineEnd(int line);
|
||||
|
||||
private LineOffsets(int[] ends, int length) {
|
||||
myLineEnds = ends;
|
||||
myTextLength = length;
|
||||
}
|
||||
int getLineNumber(int offset);
|
||||
|
||||
public int getLineStart(int line) {
|
||||
checkLineIndex(line);
|
||||
if (line == 0) return 0;
|
||||
return myLineEnds[line - 1] + 1;
|
||||
}
|
||||
int getLineCount();
|
||||
|
||||
public int getLineEnd(int line) {
|
||||
checkLineIndex(line);
|
||||
return myLineEnds[line];
|
||||
}
|
||||
|
||||
public int getLineCount() {
|
||||
return myLineEnds.length;
|
||||
}
|
||||
|
||||
public int getTextLength() {
|
||||
return myTextLength;
|
||||
}
|
||||
|
||||
private void checkLineIndex(int index) {
|
||||
if (index < 0 || index >= getLineCount()) {
|
||||
throw new IndexOutOfBoundsException("Wrong line: " + index + ". Available lines count: " + getLineCount());
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static LineOffsets create(@NotNull CharSequence text) {
|
||||
TIntArrayList ends = new TIntArrayList();
|
||||
|
||||
int index = 0;
|
||||
while (true) {
|
||||
int lineEnd = StringUtil.indexOf(text, '\n', index);
|
||||
if (lineEnd != -1) {
|
||||
ends.add(lineEnd);
|
||||
index = lineEnd + 1;
|
||||
}
|
||||
else {
|
||||
ends.add(text.length());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new LineOffsets(ends.toNativeArray(), text.length());
|
||||
}
|
||||
int getTextLength();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.diff.tools.util.text;
|
||||
|
||||
import com.intellij.diff.util.DiffUtil;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import gnu.trove.TIntArrayList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class LineOffsetsUtil {
|
||||
public static LineOffsets create(@NotNull Document document) {
|
||||
return new LineOffsetsDocumentWrapper(document);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static LineOffsets create(@NotNull CharSequence text) {
|
||||
TIntArrayList ends = new TIntArrayList();
|
||||
|
||||
int index = 0;
|
||||
while (true) {
|
||||
int lineEnd = StringUtil.indexOf(text, '\n', index);
|
||||
if (lineEnd != -1) {
|
||||
ends.add(lineEnd);
|
||||
index = lineEnd + 1;
|
||||
}
|
||||
else {
|
||||
ends.add(text.length());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new LineOffsetsImpl(ends.toNativeArray(), text.length());
|
||||
}
|
||||
|
||||
private static class LineOffsetsImpl implements LineOffsets {
|
||||
private final int[] myLineEnds;
|
||||
private final int myTextLength;
|
||||
|
||||
private LineOffsetsImpl(int[] lineEnds, int textLength) {
|
||||
myLineEnds = lineEnds;
|
||||
myTextLength = textLength;
|
||||
}
|
||||
|
||||
public int getLineStart(int line) {
|
||||
checkLineIndex(line);
|
||||
if (line == 0) return 0;
|
||||
return myLineEnds[line - 1] + 1;
|
||||
}
|
||||
|
||||
public int getLineEnd(int line) {
|
||||
checkLineIndex(line);
|
||||
return myLineEnds[line];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineNumber(int offset) {
|
||||
if (offset < 0 || offset > getTextLength()) {
|
||||
throw new IndexOutOfBoundsException("Wrong offset: " + offset + ". Available text length: " + getTextLength());
|
||||
}
|
||||
if (offset == 0) return 0;
|
||||
if (offset == getTextLength()) return getLineCount() - 1;
|
||||
|
||||
int bsResult = Arrays.binarySearch(myLineEnds, offset);
|
||||
return bsResult >= 0 ? bsResult : -bsResult - 1;
|
||||
}
|
||||
|
||||
public int getLineCount() {
|
||||
return myLineEnds.length;
|
||||
}
|
||||
|
||||
public int getTextLength() {
|
||||
return myTextLength;
|
||||
}
|
||||
|
||||
private void checkLineIndex(int index) {
|
||||
if (index < 0 || index >= getLineCount()) {
|
||||
throw new IndexOutOfBoundsException("Wrong line: " + index + ". Available lines count: " + getLineCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class LineOffsetsDocumentWrapper implements LineOffsets {
|
||||
@NotNull private final Document myDocument;
|
||||
|
||||
public LineOffsetsDocumentWrapper(@NotNull Document document) {
|
||||
myDocument = document;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineStart(int line) {
|
||||
return myDocument.getLineStartOffset(line);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineEnd(int line) {
|
||||
return myDocument.getLineEndOffset(line);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineNumber(int offset) {
|
||||
return myDocument.getLineNumber(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineCount() {
|
||||
return DiffUtil.getLineCount(myDocument);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTextLength() {
|
||||
return myDocument.getTextLength();
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -57,7 +57,7 @@ public class SimpleThreesideTextDiffProvider extends TextDiffProviderBase {
|
||||
ComparisonPolicy comparisonPolicy = ignorePolicy.getComparisonPolicy();
|
||||
|
||||
List<CharSequence> sequences = ContainerUtil.list(text1, text2, text3);
|
||||
List<LineOffsets> lineOffsets = ContainerUtil.map(sequences, LineOffsets::create);
|
||||
List<LineOffsets> lineOffsets = ContainerUtil.map(sequences, LineOffsetsUtil::create);
|
||||
|
||||
indicator.checkCanceled();
|
||||
List<MergeLineFragment> lineFragments = ComparisonManager.getInstance().compareLines(text1, text2, text3, comparisonPolicy, indicator);
|
||||
|
||||
@@ -858,16 +858,7 @@ public class DiffUtil {
|
||||
|
||||
@NotNull
|
||||
public static TextRange getLinesRange(@NotNull Document document, int line1, int line2, boolean includeNewline) {
|
||||
if (line1 == line2) {
|
||||
int lineStartOffset = line1 < getLineCount(document) ? document.getLineStartOffset(line1) : document.getTextLength();
|
||||
return new TextRange(lineStartOffset, lineStartOffset);
|
||||
}
|
||||
else {
|
||||
int startOffset = document.getLineStartOffset(line1);
|
||||
int endOffset = document.getLineEndOffset(line2 - 1);
|
||||
if (includeNewline && endOffset < document.getTextLength()) endOffset++;
|
||||
return new TextRange(startOffset, endOffset);
|
||||
}
|
||||
return getLinesRange(LineOffsetsUtil.create(document), line1, line2, includeNewline);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package com.intellij.diff.util
|
||||
|
||||
import com.intellij.diff.DiffTestCase
|
||||
import com.intellij.diff.tools.util.text.LineOffsets
|
||||
import com.intellij.diff.tools.util.text.LineOffsetsUtil
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl
|
||||
|
||||
class LineOffsetsTest : DiffTestCase() {
|
||||
@@ -40,26 +40,34 @@ class LineOffsetsTest : DiffTestCase() {
|
||||
}
|
||||
|
||||
private fun checkSameAsDocument(text: String) {
|
||||
val lineOffsets = LineOffsets.create(text)
|
||||
val document = DocumentImpl(text)
|
||||
val lineOffsets1 = LineOffsetsUtil.create(DocumentImpl(text))
|
||||
val lineOffsets2 = LineOffsetsUtil.create(text)
|
||||
|
||||
assertEquals(lineOffsets.lineCount, getLineCount(document))
|
||||
assertEquals(lineOffsets.textLength, document.textLength)
|
||||
assertEquals(lineOffsets1.lineCount, lineOffsets2.lineCount)
|
||||
assertEquals(lineOffsets1.textLength, lineOffsets2.textLength)
|
||||
|
||||
for (i in 0 until lineOffsets.lineCount) {
|
||||
assertEquals(lineOffsets.getLineStart(i), document.getLineStartOffset(i))
|
||||
assertEquals(lineOffsets.getLineEnd(i), document.getLineEndOffset(i))
|
||||
for (i in 0 until lineOffsets1.lineCount) {
|
||||
assertEquals(lineOffsets1.getLineStart(i), lineOffsets2.getLineStart(i))
|
||||
assertEquals(lineOffsets1.getLineEnd(i), lineOffsets2.getLineEnd(i))
|
||||
}
|
||||
|
||||
for (i in 0..lineOffsets1.textLength) {
|
||||
assertEquals(lineOffsets1.getLineNumber(i), lineOffsets2.getLineNumber(i))
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkOffsets(text: String, vararg offsets: IntPair) {
|
||||
val lineOffsets = LineOffsets.create(text)
|
||||
val lineOffsets = LineOffsetsUtil.create(text)
|
||||
|
||||
assertEquals(offsets.size, lineOffsets.lineCount)
|
||||
|
||||
offsets.forEachIndexed { i, value ->
|
||||
assertEquals(lineOffsets.getLineStart(i), value.val1)
|
||||
assertEquals(lineOffsets.getLineEnd(i), value.val2)
|
||||
offsets.forEachIndexed { line, value ->
|
||||
assertEquals(lineOffsets.getLineStart(line), value.val1)
|
||||
assertEquals(lineOffsets.getLineEnd(line), value.val2)
|
||||
|
||||
for (offset in lineOffsets.getLineStart(line)..lineOffsets.getLineEnd(line)) {
|
||||
assertEquals(line, lineOffsets.getLineNumber(offset))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user