mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
VCS: Show Diff from annotation: speed up; test for lines splitting; debug info for bug added
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.openapi.vcs.actions;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author irengrig
|
||||
* Date: 4/27/11
|
||||
* Time: 3:42 PM
|
||||
*/
|
||||
public class ContentsLines {
|
||||
private final static Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.actions.ContentsLines");
|
||||
|
||||
private final SplittingIterator mySplittingIterator;
|
||||
private final List<Integer> myLinesStartOffsets;
|
||||
private final String myContents;
|
||||
private boolean myLineEndsFinished;
|
||||
|
||||
public ContentsLines(final String contents) {
|
||||
myContents = contents;
|
||||
mySplittingIterator = new SplittingIterator(contents);
|
||||
myLinesStartOffsets = new ArrayList<Integer>();
|
||||
}
|
||||
|
||||
public String getLineContents(final int number) {
|
||||
assert !myLineEndsFinished || myLinesStartOffsets.size() > number;
|
||||
|
||||
// we need to know end
|
||||
if (myLineEndsFinished || (myLinesStartOffsets.size() > (number + 1))) {
|
||||
return extractCalculated(number);
|
||||
}
|
||||
while (((myLinesStartOffsets.size() - 1) < (number + 1)) && (!myLineEndsFinished) && mySplittingIterator.hasNext()) {
|
||||
final Integer nextStart = mySplittingIterator.next();
|
||||
myLinesStartOffsets.add(nextStart);
|
||||
}
|
||||
myLineEndsFinished = myLinesStartOffsets.size() < (number + 1);
|
||||
return extractCalculated(number);
|
||||
}
|
||||
|
||||
private String extractCalculated(int number) {
|
||||
try {
|
||||
String text = myContents.substring(myLinesStartOffsets.get(number),
|
||||
(number + 1 >= myLinesStartOffsets.size())
|
||||
? myContents.length()
|
||||
: myLinesStartOffsets.get(number + 1));
|
||||
text = text.endsWith("\r\n") ? text.substring(0, text.length() - 2) : text;
|
||||
text = (text.endsWith("\r") || text.endsWith("\n")) ? text.substring(0, text.length() - 1) : text;
|
||||
return text;
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
LOG.error("Loaded contents lines: " + StringUtil.getLineBreakCount(myContents), e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLineEndsFinished() {
|
||||
return myLineEndsFinished;
|
||||
}
|
||||
|
||||
public int getKnownLinesNumber() {
|
||||
return myLineEndsFinished ? myLinesStartOffsets.size() : -1;
|
||||
}
|
||||
}
|
||||
+5
-102
@@ -42,10 +42,7 @@ import com.intellij.util.containers.CacheOneStepIterator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
@@ -162,7 +159,7 @@ class ShowDiffFromAnnotation extends AnAction implements LineNumberListener {
|
||||
|
||||
// for current line number
|
||||
private DiffNavigationContext createDiffNavigationContext(final int actualLine) {
|
||||
final MyContentsLines contentsLines = new MyContentsLines(myFileAnnotation.getAnnotatedContent());
|
||||
final ContentsLines contentsLines = new ContentsLines(myFileAnnotation.getAnnotatedContent());
|
||||
|
||||
final Pair<Integer, String> pair = correctActualLineIfTextEmpty(contentsLines, actualLine);
|
||||
return new DiffNavigationContext(new Iterable<String>() {
|
||||
@@ -175,7 +172,7 @@ class ShowDiffFromAnnotation extends AnAction implements LineNumberListener {
|
||||
|
||||
private final static int ourVicinity = 5;
|
||||
|
||||
private Pair<Integer, String> correctActualLineIfTextEmpty(final MyContentsLines contentsLines, final int actualLine) {
|
||||
private Pair<Integer, String> correctActualLineIfTextEmpty(final ContentsLines contentsLines, final int actualLine) {
|
||||
final VcsRevisionNumber revision = myFileAnnotation.getLineRevisionNumber(actualLine);
|
||||
|
||||
for (int i = actualLine; (i < (actualLine + ourVicinity)) && (!contentsLines.isLineEndsFinished()); i++) {
|
||||
@@ -196,105 +193,11 @@ class ShowDiffFromAnnotation extends AnAction implements LineNumberListener {
|
||||
return new Pair<Integer, String>(actualLine, contentsLines.getLineContents(actualLine));
|
||||
}
|
||||
|
||||
private static class MySplittingIterator implements Iterator<Integer> {
|
||||
private final String myContents;
|
||||
// always at the beginning of the _next_ line
|
||||
private int myOffset;
|
||||
|
||||
private MySplittingIterator(final String contents) {
|
||||
myContents = contents;
|
||||
myOffset = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return myOffset < myContents.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer next() {
|
||||
final int start = myOffset;
|
||||
while (myOffset < myContents.length()) {
|
||||
// \r, \n, or \r\n
|
||||
final char c = myContents.charAt(myOffset);
|
||||
if ('\n' == c) {
|
||||
++myOffset;
|
||||
break;
|
||||
}
|
||||
else if ('\r' == c) {
|
||||
if (myOffset + 1 == myContents.length()) {
|
||||
// at the end
|
||||
++myOffset;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
myOffset += (('\n' == myContents.charAt(myOffset + 1)) ? 2 : 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
++myOffset;
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyContentsLines {
|
||||
private final MySplittingIterator mySplittingIterator;
|
||||
private final List<Integer> myLinesStartOffsets;
|
||||
private final String myContents;
|
||||
private boolean myLineEndsFinished;
|
||||
|
||||
private MyContentsLines(final String contents) {
|
||||
myContents = contents;
|
||||
mySplittingIterator = new MySplittingIterator(contents);
|
||||
myLinesStartOffsets = new LinkedList<Integer>();
|
||||
}
|
||||
|
||||
public String getLineContents(final int number) {
|
||||
assert !myLineEndsFinished || myLinesStartOffsets.size() > number;
|
||||
|
||||
// we need to know end
|
||||
if (myLineEndsFinished || (myLinesStartOffsets.size() > (number + 1))) {
|
||||
return extractCalculated(number);
|
||||
}
|
||||
while (((myLinesStartOffsets.size() - 1) < (number + 1)) && (!myLineEndsFinished) && mySplittingIterator.hasNext()) {
|
||||
final Integer nextStart = mySplittingIterator.next();
|
||||
myLinesStartOffsets.add(nextStart);
|
||||
}
|
||||
myLineEndsFinished = myLinesStartOffsets.size() < (number + 1);
|
||||
return extractCalculated(number);
|
||||
}
|
||||
|
||||
private String extractCalculated(int number) {
|
||||
String text = myContents.substring(myLinesStartOffsets.get(number),
|
||||
(number + 1 >= myLinesStartOffsets.size())
|
||||
? myContents.length()
|
||||
: myLinesStartOffsets.get(number + 1));
|
||||
text = text.endsWith("\r\n") ? text.substring(0, text.length() - 2) : text;
|
||||
text = (text.endsWith("\r") || text.endsWith("\n")) ? text.substring(0, text.length() - 1) : text;
|
||||
return text;
|
||||
}
|
||||
|
||||
public boolean isLineEndsFinished() {
|
||||
return myLineEndsFinished;
|
||||
}
|
||||
|
||||
public int getKnownLinesNumber() {
|
||||
return myLineEndsFinished ? myLinesStartOffsets.size() : -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Slightly break the contract: can return null from next() while had claimed hasNext()
|
||||
*/
|
||||
private static class ContextLineIterator implements Iterator<String> {
|
||||
private final MyContentsLines myContentsLines;
|
||||
private final ContentsLines myContentsLines;
|
||||
|
||||
private final VcsRevisionNumber myRevisionNumber;
|
||||
private final FileAnnotation myAnnotation;
|
||||
@@ -302,7 +205,7 @@ class ShowDiffFromAnnotation extends AnAction implements LineNumberListener {
|
||||
// we assume file has at least one line ;)
|
||||
private int myCurrentLine; // to start looking for next line with revision from
|
||||
|
||||
private ContextLineIterator(final MyContentsLines contentLines, final FileAnnotation annotation, final int stopAtLine) {
|
||||
private ContextLineIterator(final ContentsLines contentLines, final FileAnnotation annotation, final int stopAtLine) {
|
||||
myAnnotation = annotation;
|
||||
myRevisionNumber = myAnnotation.originalRevision(stopAtLine);
|
||||
myStopAtLine = stopAtLine;
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.openapi.vcs.actions;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* @author irengrig
|
||||
* Date: 4/27/11
|
||||
* Time: 3:42 PM
|
||||
*/
|
||||
public class SplittingIterator implements Iterator<Integer> {
|
||||
private final String myContents;
|
||||
// always at the beginning of the _next_ line
|
||||
private int myOffset;
|
||||
|
||||
public SplittingIterator(final String contents) {
|
||||
myContents = contents;
|
||||
myOffset = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return myOffset < myContents.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer next() {
|
||||
final int start = myOffset;
|
||||
while (myOffset < myContents.length()) {
|
||||
// \r, \n, or \r\n
|
||||
final char c = myContents.charAt(myOffset);
|
||||
if ('\n' == c) {
|
||||
++myOffset;
|
||||
break;
|
||||
}
|
||||
else if ('\r' == c) {
|
||||
if (myOffset + 1 == myContents.length()) {
|
||||
// at the end
|
||||
++myOffset;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
myOffset += (('\n' == myContents.charAt(myOffset + 1)) ? 2 : 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
++myOffset;
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user