mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
LST to use own lock instead of write action
This commit is contained in:
@@ -20,14 +20,13 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.undo.UndoManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.EditorFactory;
|
||||
import com.intellij.openapi.editor.event.DocumentAdapter;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl;
|
||||
import com.intellij.openapi.editor.markup.*;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsBundle;
|
||||
@@ -46,6 +45,7 @@ import java.util.ListIterator;
|
||||
*/
|
||||
public class LineStatusTracker {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.ex.LineStatusTracker");
|
||||
private final Object myLock = new Object();
|
||||
// true -> have contents
|
||||
private BaseLoadState myBaseLoaded;
|
||||
|
||||
@@ -72,36 +72,36 @@ public class LineStatusTracker {
|
||||
}
|
||||
|
||||
public void initialize(@NotNull final String upToDateContent) {
|
||||
ApplicationManager.getApplication().isReadAccessAllowed();
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
LOG.assertTrue(BaseLoadState.LOADING == myBaseLoaded);
|
||||
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
myUpToDateDocument.setReadOnly(false);
|
||||
myUpToDateDocument.replaceString(0, myUpToDateDocument.getTextLength(), upToDateContent);
|
||||
myUpToDateDocument.setReadOnly(true);
|
||||
reinstallRanges();
|
||||
synchronized (myLock) {
|
||||
try {
|
||||
myUpToDateDocument.setReadOnly(false);
|
||||
myUpToDateDocument.replaceString(0, myUpToDateDocument.getTextLength(), upToDateContent);
|
||||
myUpToDateDocument.setReadOnly(true);
|
||||
reinstallRanges();
|
||||
|
||||
if (myDocumentListener == null) {
|
||||
myDocumentListener = new MyDocumentListener();
|
||||
myDocument.addDocumentListener(myDocumentListener);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myBaseLoaded = BaseLoadState.LOADED;
|
||||
if (myDocumentListener == null) {
|
||||
myDocumentListener = new MyDocumentListener();
|
||||
myDocument.addDocumentListener(myDocumentListener);
|
||||
}
|
||||
}
|
||||
});
|
||||
finally {
|
||||
myBaseLoaded = BaseLoadState.LOADED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void reinstallRanges() {
|
||||
myApplication.assertWriteAccessAllowed();
|
||||
myApplication.assertReadAccessAllowed();
|
||||
|
||||
removeHighlightersFromMarkupModel();
|
||||
myRanges = new RangesBuilder(myDocument, myUpToDateDocument).getRanges();
|
||||
for (final Range range : myRanges) {
|
||||
range.setHighlighter(createHighlighter(range));
|
||||
synchronized (myLock) {
|
||||
removeHighlightersFromMarkupModel();
|
||||
myRanges = new RangesBuilder(myDocument, myUpToDateDocument).getRanges();
|
||||
for (final Range range : myRanges) {
|
||||
range.setHighlighter(createHighlighter(range));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,16 +137,13 @@ public class LineStatusTracker {
|
||||
}
|
||||
|
||||
public void release() {
|
||||
myApplication.runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myDocumentListener != null) {
|
||||
myDocument.removeDocumentListener(myDocumentListener);
|
||||
}
|
||||
removeHighlightersFromMarkupModel();
|
||||
myRanges.clear();
|
||||
synchronized (myLock) {
|
||||
if (myDocumentListener != null) {
|
||||
myDocument.removeDocumentListener(myDocumentListener);
|
||||
}
|
||||
});
|
||||
removeHighlightersFromMarkupModel();
|
||||
myRanges.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public Document getDocument() {
|
||||
@@ -160,39 +157,38 @@ public class LineStatusTracker {
|
||||
public List<Range> getRanges() {
|
||||
myApplication.assertReadAccessAllowed();
|
||||
|
||||
return myRanges;
|
||||
synchronized (myLock) {
|
||||
return myRanges;
|
||||
}
|
||||
}
|
||||
|
||||
public Document getUpToDateDocument() {
|
||||
myApplication.assertIsDispatchThread();
|
||||
return myUpToDateDocument;
|
||||
}
|
||||
|
||||
public void startBulkUpdate() {
|
||||
myApplication.runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myBulkUpdate = true;
|
||||
removeHighlightersFromMarkupModel();
|
||||
myRanges.clear();
|
||||
}
|
||||
});
|
||||
synchronized (myLock) {
|
||||
myBulkUpdate = true;
|
||||
removeHighlightersFromMarkupModel();
|
||||
myRanges.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void removeHighlightersFromMarkupModel() {
|
||||
final MarkupModel markupModel = myDocument.getMarkupModel(myProject);
|
||||
for (Range range : myRanges) {
|
||||
markupModel.removeHighlighter(range.getHighlighter());
|
||||
synchronized (myLock) {
|
||||
for (Range range : myRanges) {
|
||||
markupModel.removeHighlighter(range.getHighlighter());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void finishBulkUpdate() {
|
||||
myApplication.runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myBulkUpdate = false;
|
||||
reinstallRanges();
|
||||
}
|
||||
});
|
||||
synchronized (myLock) {
|
||||
myBulkUpdate = false;
|
||||
reinstallRanges();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,24 +196,18 @@ public class LineStatusTracker {
|
||||
* false -> load was already started; after contents is loaded,
|
||||
*/
|
||||
public boolean resetForBaseRevisionLoad() {
|
||||
return myApplication.runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
if (BaseLoadState.LOADING == myBaseLoaded) return false;
|
||||
return myApplication.runWriteAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
myUpToDateDocument.setReadOnly(false);
|
||||
myUpToDateDocument.setText("");
|
||||
myUpToDateDocument.setReadOnly(true);
|
||||
removeHighlightersFromMarkupModel();
|
||||
myRanges.clear();
|
||||
myBaseLoaded = BaseLoadState.LOADING;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
myApplication.assertReadAccessAllowed();
|
||||
|
||||
synchronized (myLock) {
|
||||
if (BaseLoadState.LOADING == myBaseLoaded) return false;
|
||||
myUpToDateDocument.setReadOnly(false);
|
||||
myUpToDateDocument.setText("");
|
||||
myUpToDateDocument.setReadOnly(true);
|
||||
removeHighlightersFromMarkupModel();
|
||||
myRanges.clear();
|
||||
myBaseLoaded = BaseLoadState.LOADING;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class MyDocumentListener extends DocumentAdapter {
|
||||
@@ -231,39 +221,41 @@ public class LineStatusTracker {
|
||||
if (myBulkUpdate || (BaseLoadState.LOADED != myBaseLoaded)) return;
|
||||
myApplication.assertWriteAccessAllowed();
|
||||
|
||||
try {
|
||||
myFirstChangedLine = myDocument.getLineNumber(e.getOffset());
|
||||
myLastChangedLine = myDocument.getLineNumber(e.getOffset() + e.getOldLength());
|
||||
if (StringUtil.endsWithChar(e.getOldFragment(), '\n')) myLastChangedLine++;
|
||||
synchronized (myLock) {
|
||||
try {
|
||||
myFirstChangedLine = myDocument.getLineNumber(e.getOffset());
|
||||
myLastChangedLine = myDocument.getLineNumber(e.getOffset() + e.getOldLength());
|
||||
if (StringUtil.endsWithChar(e.getOldFragment(), '\n')) myLastChangedLine++;
|
||||
|
||||
myLinesBeforeChange = myDocument.getLineNumber(e.getOffset() + e.getOldLength()) - myDocument.getLineNumber(e.getOffset());
|
||||
myLinesBeforeChange = myDocument.getLineNumber(e.getOffset() + e.getOldLength()) - myDocument.getLineNumber(e.getOffset());
|
||||
|
||||
Range firstChangedRange = getLastRangeBeforeLine(myFirstChangedLine);
|
||||
Range firstChangedRange = getLastRangeBeforeLine(myFirstChangedLine);
|
||||
|
||||
if (firstChangedRange == null) {
|
||||
myUpToDateFirstLine = myFirstChangedLine;
|
||||
}
|
||||
else if (firstChangedRange.containsLine(myFirstChangedLine)) {
|
||||
myFirstChangedLine = firstChangedRange.getOffset1();
|
||||
myUpToDateFirstLine = firstChangedRange.getUOffset1();
|
||||
}
|
||||
else {
|
||||
myUpToDateFirstLine = firstChangedRange.getUOffset2() + (myFirstChangedLine - firstChangedRange.getOffset2());
|
||||
}
|
||||
if (firstChangedRange == null) {
|
||||
myUpToDateFirstLine = myFirstChangedLine;
|
||||
}
|
||||
else if (firstChangedRange.containsLine(myFirstChangedLine)) {
|
||||
myFirstChangedLine = firstChangedRange.getOffset1();
|
||||
myUpToDateFirstLine = firstChangedRange.getUOffset1();
|
||||
}
|
||||
else {
|
||||
myUpToDateFirstLine = firstChangedRange.getUOffset2() + (myFirstChangedLine - firstChangedRange.getOffset2());
|
||||
}
|
||||
|
||||
Range myLastChangedRange = getLastRangeBeforeLine(myLastChangedLine);
|
||||
Range myLastChangedRange = getLastRangeBeforeLine(myLastChangedLine);
|
||||
|
||||
if (myLastChangedRange == null) {
|
||||
myUpToDateLastLine = myLastChangedLine;
|
||||
if (myLastChangedRange == null) {
|
||||
myUpToDateLastLine = myLastChangedLine;
|
||||
}
|
||||
else if (myLastChangedRange.containsLine(myLastChangedLine)) {
|
||||
myUpToDateLastLine = myLastChangedRange.getUOffset2();
|
||||
myLastChangedLine = myLastChangedRange.getOffset2();
|
||||
}
|
||||
else {
|
||||
myUpToDateLastLine = myLastChangedRange.getUOffset2() + (myLastChangedLine - myLastChangedRange.getOffset2());
|
||||
}
|
||||
} catch (ProcessCanceledException ignore) {
|
||||
}
|
||||
else if (myLastChangedRange.containsLine(myLastChangedLine)) {
|
||||
myUpToDateLastLine = myLastChangedRange.getUOffset2();
|
||||
myLastChangedLine = myLastChangedRange.getOffset2();
|
||||
}
|
||||
else {
|
||||
myUpToDateLastLine = myLastChangedRange.getUOffset2() + (myLastChangedLine - myLastChangedRange.getOffset2());
|
||||
}
|
||||
} catch (ProcessCanceledException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,47 +273,49 @@ public class LineStatusTracker {
|
||||
if (myBulkUpdate || (BaseLoadState.LOADED != myBaseLoaded)) return;
|
||||
myApplication.assertWriteAccessAllowed();
|
||||
|
||||
try {
|
||||
synchronized (myLock) {
|
||||
try {
|
||||
|
||||
int line = myDocument.getLineNumber(e.getOffset() + e.getNewLength());
|
||||
int linesAfterChange = line - myDocument.getLineNumber(e.getOffset());
|
||||
int linesShift = linesAfterChange - myLinesBeforeChange;
|
||||
int line = myDocument.getLineNumber(e.getOffset() + e.getNewLength());
|
||||
int linesAfterChange = line - myDocument.getLineNumber(e.getOffset());
|
||||
int linesShift = linesAfterChange - myLinesBeforeChange;
|
||||
|
||||
List<Range> rangesAfterChange = getRangesAfter(myRanges, myLastChangedLine);
|
||||
List<Range> rangesBeforeChange = getRangesBefore(myRanges, myFirstChangedLine);
|
||||
List<Range> rangesAfterChange = getRangesAfter(myRanges, myLastChangedLine);
|
||||
List<Range> rangesBeforeChange = getRangesBefore(myRanges, myFirstChangedLine);
|
||||
|
||||
List<Range> changedRanges = getChangedRanges(myFirstChangedLine, myLastChangedLine);
|
||||
List<Range> changedRanges = getChangedRanges(myFirstChangedLine, myLastChangedLine);
|
||||
|
||||
int newSize = rangesBeforeChange.size() + changedRanges.size() + rangesAfterChange.size();
|
||||
if (myRanges.size() != newSize) {
|
||||
LOG.info("Ranges: " + myRanges + "; first changed line: " + myFirstChangedLine + "; last changed line: " + myLastChangedLine);
|
||||
LOG.assertTrue(false);
|
||||
}
|
||||
|
||||
|
||||
myLastChangedLine += linesShift;
|
||||
|
||||
|
||||
List<Range> newChangedRanges = getNewChangedRanges();
|
||||
|
||||
shiftRanges(rangesAfterChange, linesShift);
|
||||
|
||||
if (!changedRanges.equals(newChangedRanges)) {
|
||||
replaceRanges(changedRanges, newChangedRanges);
|
||||
|
||||
myRanges = new ArrayList<Range>();
|
||||
|
||||
myRanges.addAll(rangesBeforeChange);
|
||||
myRanges.addAll(newChangedRanges);
|
||||
myRanges.addAll(rangesAfterChange);
|
||||
|
||||
myRanges = mergeRanges(myRanges);
|
||||
|
||||
for (Range range : myRanges) {
|
||||
if (!range.hasHighlighter()) range.setHighlighter(createHighlighter(range));
|
||||
int newSize = rangesBeforeChange.size() + changedRanges.size() + rangesAfterChange.size();
|
||||
if (myRanges.size() != newSize) {
|
||||
LOG.info("Ranges: " + myRanges + "; first changed line: " + myFirstChangedLine + "; last changed line: " + myLastChangedLine);
|
||||
LOG.assertTrue(false);
|
||||
}
|
||||
|
||||
|
||||
myLastChangedLine += linesShift;
|
||||
|
||||
|
||||
List<Range> newChangedRanges = getNewChangedRanges();
|
||||
|
||||
shiftRanges(rangesAfterChange, linesShift);
|
||||
|
||||
if (!changedRanges.equals(newChangedRanges)) {
|
||||
replaceRanges(changedRanges, newChangedRanges);
|
||||
|
||||
myRanges = new ArrayList<Range>();
|
||||
|
||||
myRanges.addAll(rangesBeforeChange);
|
||||
myRanges.addAll(newChangedRanges);
|
||||
myRanges.addAll(rangesAfterChange);
|
||||
|
||||
myRanges = mergeRanges(myRanges);
|
||||
|
||||
for (Range range : myRanges) {
|
||||
if (!range.hasHighlighter()) range.setHighlighter(createHighlighter(range));
|
||||
}
|
||||
}
|
||||
} catch (ProcessCanceledException ignore) {
|
||||
}
|
||||
} catch (ProcessCanceledException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,49 +384,57 @@ public class LineStatusTracker {
|
||||
|
||||
@Nullable
|
||||
Range getNextRange(final Range range) {
|
||||
final int index = myRanges.indexOf(range);
|
||||
if (index == myRanges.size() - 1) return null;
|
||||
return myRanges.get(index + 1);
|
||||
synchronized (myLock) {
|
||||
final int index = myRanges.indexOf(range);
|
||||
if (index == myRanges.size() - 1) return null;
|
||||
return myRanges.get(index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Range getPrevRange(final Range range) {
|
||||
final int index = myRanges.indexOf(range);
|
||||
if (index <= 0) return null;
|
||||
return myRanges.get(index - 1);
|
||||
synchronized (myLock) {
|
||||
final int index = myRanges.indexOf(range);
|
||||
if (index <= 0) return null;
|
||||
return myRanges.get(index - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Range getNextRange(final int line) {
|
||||
final Range currentRange = getRangeForLine(line);
|
||||
if (currentRange != null) {
|
||||
return getNextRange(currentRange);
|
||||
}
|
||||
|
||||
for (final Range range : myRanges) {
|
||||
if (line > range.getOffset1() || line > range.getOffset2()) {
|
||||
continue;
|
||||
synchronized (myLock) {
|
||||
final Range currentRange = getRangeForLine(line);
|
||||
if (currentRange != null) {
|
||||
return getNextRange(currentRange);
|
||||
}
|
||||
return range;
|
||||
|
||||
for (final Range range : myRanges) {
|
||||
if (line > range.getOffset1() || line > range.getOffset2()) {
|
||||
continue;
|
||||
}
|
||||
return range;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Range getPrevRange(final int line) {
|
||||
final Range currentRange = getRangeForLine(line);
|
||||
if (currentRange != null) {
|
||||
return getPrevRange(currentRange);
|
||||
}
|
||||
|
||||
for (ListIterator<Range> iterator = myRanges.listIterator(myRanges.size()); iterator.hasPrevious();) {
|
||||
final Range range = iterator.previous();
|
||||
if (range.getOffset1() > line) {
|
||||
continue;
|
||||
synchronized (myLock) {
|
||||
final Range currentRange = getRangeForLine(line);
|
||||
if (currentRange != null) {
|
||||
return getPrevRange(currentRange);
|
||||
}
|
||||
return range;
|
||||
|
||||
for (ListIterator<Range> iterator = myRanges.listIterator(myRanges.size()); iterator.hasPrevious();) {
|
||||
final Range range = iterator.previous();
|
||||
if (range.getOffset1() > line) {
|
||||
continue;
|
||||
}
|
||||
return range;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<Range> getRangesBefore(List<Range> ranges, int line) {
|
||||
@@ -455,43 +457,49 @@ public class LineStatusTracker {
|
||||
|
||||
@Nullable
|
||||
public Range getRangeForLine(final int line) {
|
||||
for (final Range range : myRanges) {
|
||||
if (range.getType() == Range.DELETED && line == range.getOffset1()) {
|
||||
return range;
|
||||
}
|
||||
else if (line >= range.getOffset1() && line < range.getOffset2()) {
|
||||
return range;
|
||||
synchronized (myLock) {
|
||||
for (final Range range : myRanges) {
|
||||
if (range.getType() == Range.DELETED && line == range.getOffset1()) {
|
||||
return range;
|
||||
}
|
||||
else if (line >= range.getOffset1() && line < range.getOffset2()) {
|
||||
return range;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void rollbackChanges(final Range range) {
|
||||
myApplication.assertWriteAccessAllowed();
|
||||
|
||||
TextRange currentTextRange = getCurrentTextRange(range);
|
||||
synchronized (myLock) {
|
||||
TextRange currentTextRange = getCurrentTextRange(range);
|
||||
|
||||
if (range.getType() == Range.INSERTED) {
|
||||
myDocument
|
||||
.replaceString(currentTextRange.getStartOffset(), Math.min(currentTextRange.getEndOffset() + 1, myDocument.getTextLength()), "");
|
||||
}
|
||||
else if (range.getType() == Range.DELETED) {
|
||||
String upToDateContent = getUpToDateContent(range);
|
||||
myDocument.insertString(currentTextRange.getStartOffset(), upToDateContent);
|
||||
}
|
||||
else {
|
||||
if (range.getType() == Range.INSERTED) {
|
||||
myDocument
|
||||
.replaceString(currentTextRange.getStartOffset(), Math.min(currentTextRange.getEndOffset() + 1, myDocument.getTextLength()), "");
|
||||
}
|
||||
else if (range.getType() == Range.DELETED) {
|
||||
String upToDateContent = getUpToDateContent(range);
|
||||
myDocument.insertString(currentTextRange.getStartOffset(), upToDateContent);
|
||||
}
|
||||
else {
|
||||
|
||||
String upToDateContent = getUpToDateContent(range);
|
||||
myDocument.replaceString(currentTextRange.getStartOffset(), Math.min(currentTextRange.getEndOffset() + 1, myDocument.getTextLength()),
|
||||
upToDateContent);
|
||||
String upToDateContent = getUpToDateContent(range);
|
||||
myDocument.replaceString(currentTextRange.getStartOffset(), Math.min(currentTextRange.getEndOffset() + 1, myDocument.getTextLength()),
|
||||
upToDateContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getUpToDateContent(Range range) {
|
||||
TextRange textRange = getUpToDateRange(range);
|
||||
final int startOffset = textRange.getStartOffset();
|
||||
final int endOffset = Math.min(textRange.getEndOffset() + 1, myUpToDateDocument.getTextLength());
|
||||
return myUpToDateDocument.getCharsSequence().subSequence(startOffset, endOffset).toString();
|
||||
synchronized (myLock) {
|
||||
TextRange textRange = getUpToDateRange(range);
|
||||
final int startOffset = textRange.getStartOffset();
|
||||
final int endOffset = Math.min(textRange.getEndOffset() + 1, myUpToDateDocument.getTextLength());
|
||||
return myUpToDateDocument.getCharsSequence().subSequence(startOffset, endOffset).toString();
|
||||
}
|
||||
}
|
||||
|
||||
Project getProject() {
|
||||
@@ -539,7 +547,7 @@ public class LineStatusTracker {
|
||||
}
|
||||
|
||||
public static LineStatusTracker createOn(final Document doc, final Project project) {
|
||||
final Document document = EditorFactory.getInstance().createDocument("");
|
||||
final Document document = new DocumentImpl(true);
|
||||
return new LineStatusTracker(doc, document, project);
|
||||
}
|
||||
|
||||
@@ -548,8 +556,9 @@ public class LineStatusTracker {
|
||||
}
|
||||
|
||||
public void baseRevisionLoadFailed() {
|
||||
myApplication.assertWriteAccessAllowed();
|
||||
myBaseLoaded = BaseLoadState.FAILED;
|
||||
synchronized (myLock) {
|
||||
myBaseLoaded = BaseLoadState.FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
public static enum BaseLoadState {
|
||||
|
||||
@@ -42,7 +42,6 @@ import com.intellij.openapi.editor.ex.DocumentBulkUpdateListener;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -68,6 +67,7 @@ import java.util.Map;
|
||||
|
||||
public class LineStatusTrackerManager implements ProjectComponent, LineStatusTrackerManagerI {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.impl.LineStatusTrackerManager");
|
||||
public final Object myLock = new Object();
|
||||
|
||||
public static LineStatusTrackerManagerI getInstance(final Project project) {
|
||||
if (System.getProperty(IGNORE_CHANGEMARKERS_KEY) != null) {
|
||||
@@ -116,15 +116,17 @@ public class LineStatusTrackerManager implements ProjectComponent, LineStatusTra
|
||||
myDisposable = new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
final Collection<LineStatusTracker> trackers = myLineStatusTrackers.values();
|
||||
final LineStatusTracker[] lineStatusTrackers = trackers.toArray(new LineStatusTracker[trackers.size()]);
|
||||
for (final LineStatusTracker tracker : lineStatusTrackers) {
|
||||
releaseTracker(tracker.getDocument());
|
||||
}
|
||||
synchronized (myLock) {
|
||||
final Collection<LineStatusTracker> trackers = myLineStatusTrackers.values();
|
||||
final LineStatusTracker[] lineStatusTrackers = trackers.toArray(new LineStatusTracker[trackers.size()]);
|
||||
for (final LineStatusTracker tracker : lineStatusTrackers) {
|
||||
releaseTracker(tracker.getDocument());
|
||||
}
|
||||
|
||||
myLineStatusTrackers.clear();
|
||||
assert myLineStatusUpdateAlarms.isEmpty();
|
||||
myLineStatusUpdateAlarms.clear();
|
||||
myLineStatusTrackers.clear();
|
||||
assert myLineStatusUpdateAlarms.isEmpty();
|
||||
myLineStatusUpdateAlarms.clear();
|
||||
}
|
||||
}
|
||||
};
|
||||
Disposer.register(myProject, myDisposable);
|
||||
@@ -178,12 +180,15 @@ public class LineStatusTrackerManager implements ProjectComponent, LineStatusTra
|
||||
@Override
|
||||
public LineStatusTracker getLineStatusTracker(final Document document) {
|
||||
myApplication.assertReadAccessAllowed();
|
||||
|
||||
if ((! myProject.isOpen()) || myProject.isDisposed()) return null;
|
||||
return myLineStatusTrackers.get(document);
|
||||
|
||||
synchronized (myLock) {
|
||||
return myLineStatusTrackers.get(document);
|
||||
}
|
||||
}
|
||||
|
||||
private void resetTracker(@NotNull final VirtualFile virtualFile) {
|
||||
myApplication.assertReadAccessAllowed();
|
||||
if ((! myProject.isOpen()) || myProject.isDisposed()) return;
|
||||
|
||||
final Document document = FileDocumentManager.getInstance().getCachedDocument(virtualFile);
|
||||
@@ -194,49 +199,43 @@ public class LineStatusTrackerManager implements ProjectComponent, LineStatusTra
|
||||
|
||||
log("resetting tracker for file " + virtualFile.getPath());
|
||||
|
||||
final LineStatusTracker tracker = myLineStatusTrackers.get(document);
|
||||
final boolean editorOpened = myFileEditorManager.isFileOpen(virtualFile);
|
||||
final boolean shouldBeInstalled = shouldBeInstalled(virtualFile) && editorOpened;
|
||||
|
||||
if (tracker == null && (! shouldBeInstalled)) return;
|
||||
synchronized (myLock) {
|
||||
final LineStatusTracker tracker = myLineStatusTrackers.get(document);
|
||||
|
||||
myApplication.runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// remove ?
|
||||
if (tracker != null) {
|
||||
if (! shouldBeInstalled) {
|
||||
releaseTracker(document);
|
||||
return;
|
||||
} else if ((LineStatusTracker.BaseLoadState.LOADING == tracker.getBaseLoaded())) {
|
||||
return; // will be recalculated
|
||||
} else {
|
||||
tracker.resetForBaseRevisionLoad();
|
||||
startAlarm(document, virtualFile);
|
||||
}
|
||||
} else if (shouldBeInstalled) {
|
||||
installTracker(virtualFile, document);
|
||||
if (tracker == null && (! shouldBeInstalled)) return;
|
||||
|
||||
if (tracker != null) {
|
||||
if (! shouldBeInstalled) {
|
||||
releaseTracker(document);
|
||||
return;
|
||||
} else if ((LineStatusTracker.BaseLoadState.LOADING == tracker.getBaseLoaded())) {
|
||||
return; // will be recalculated
|
||||
} else {
|
||||
tracker.resetForBaseRevisionLoad();
|
||||
startAlarm(document, virtualFile);
|
||||
}
|
||||
} else if (shouldBeInstalled) {
|
||||
installTracker(virtualFile, document);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void releaseTracker(final Document document) {
|
||||
if ((! myProject.isOpen()) || myProject.isDisposed()) return;
|
||||
|
||||
myApplication.runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Alarm alarm = myLineStatusUpdateAlarms.remove(document);
|
||||
if (alarm != null) {
|
||||
alarm.cancelAllRequests();
|
||||
}
|
||||
final LineStatusTracker tracker = myLineStatusTrackers.remove(document);
|
||||
if (tracker != null) {
|
||||
tracker.release();
|
||||
}
|
||||
synchronized (myLock) {
|
||||
final Alarm alarm = myLineStatusUpdateAlarms.remove(document);
|
||||
if (alarm != null) {
|
||||
alarm.cancelAllRequests();
|
||||
}
|
||||
});
|
||||
final LineStatusTracker tracker = myLineStatusTrackers.remove(document);
|
||||
if (tracker != null) {
|
||||
tracker.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldBeInstalled(final VirtualFile virtualFile) {
|
||||
@@ -261,25 +260,24 @@ public class LineStatusTrackerManager implements ProjectComponent, LineStatusTra
|
||||
}
|
||||
|
||||
private void installTracker(final VirtualFile virtualFile, final Document document) {
|
||||
myApplication.runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myLineStatusTrackers.containsKey(document)) return;
|
||||
assert !myLineStatusUpdateAlarms.containsKey(document);
|
||||
synchronized (myLock) {
|
||||
if (myLineStatusTrackers.containsKey(document)) return;
|
||||
assert !myLineStatusUpdateAlarms.containsKey(document);
|
||||
|
||||
final LineStatusTracker tracker = LineStatusTracker.createOn(document, myProject);
|
||||
myLineStatusTrackers.put(document, tracker);
|
||||
final LineStatusTracker tracker = LineStatusTracker.createOn(document, myProject);
|
||||
myLineStatusTrackers.put(document, tracker);
|
||||
|
||||
startAlarm(document, virtualFile);
|
||||
}
|
||||
});
|
||||
startAlarm(document, virtualFile);
|
||||
}
|
||||
}
|
||||
|
||||
private void startAlarm(final Document document, final VirtualFile virtualFile) {
|
||||
myApplication.assertWriteAccessAllowed();
|
||||
myApplication.assertReadAccessAllowed();
|
||||
|
||||
final Alarm alarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
|
||||
myLineStatusUpdateAlarms.put(document, alarm);
|
||||
synchronized (myLock) {
|
||||
myLineStatusUpdateAlarms.put(document, alarm);
|
||||
}
|
||||
alarm.addRequest(new BaseRevisionLoader(alarm, document, virtualFile), 10);
|
||||
}
|
||||
|
||||
@@ -297,14 +295,12 @@ public class LineStatusTrackerManager implements ProjectComponent, LineStatusTra
|
||||
@Override
|
||||
public void run() {
|
||||
myAlarm.cancelAllRequests();
|
||||
final Boolean removed = myApplication.runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
final Alarm removed = myLineStatusUpdateAlarms.remove(myDocument);
|
||||
return removed != null;
|
||||
synchronized (myLock) {
|
||||
final Alarm removed = myLineStatusUpdateAlarms.remove(myDocument);
|
||||
if (removed == null) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
if (! Boolean.TRUE.equals(removed)) return;
|
||||
}
|
||||
if ((! myProject.isOpen()) || myProject.isDisposed()) return;
|
||||
|
||||
if (! myVirtualFile.isValid()) {
|
||||
@@ -323,15 +319,13 @@ public class LineStatusTrackerManager implements ProjectComponent, LineStatusTra
|
||||
final String converted = StringUtil.convertLineSeparators(lastUpToDateContent);
|
||||
myApplication.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
log("initializing tracker for file " + myVirtualFile.getPath());
|
||||
final LineStatusTracker tracker = myLineStatusTrackers.get(myDocument);
|
||||
if (tracker != null) {
|
||||
tracker.initialize(converted);
|
||||
}
|
||||
synchronized (myLock) {
|
||||
log("initializing tracker for file " + myVirtualFile.getPath());
|
||||
final LineStatusTracker tracker = myLineStatusTrackers.get(myDocument);
|
||||
if (tracker != null) {
|
||||
tracker.initialize(converted);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}, new Condition() {
|
||||
@Override
|
||||
@@ -342,24 +336,13 @@ public class LineStatusTrackerManager implements ProjectComponent, LineStatusTra
|
||||
}
|
||||
|
||||
private void reportTrackerBaseLoadFailed() {
|
||||
myApplication.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
log("base revision load failed for file " + myVirtualFile.getPath());
|
||||
final LineStatusTracker tracker = myLineStatusTrackers.get(myDocument);
|
||||
if (tracker != null) {
|
||||
tracker.baseRevisionLoadFailed();
|
||||
}
|
||||
}
|
||||
});
|
||||
synchronized (myLock) {
|
||||
log("base revision load failed for file " + myVirtualFile.getPath());
|
||||
final LineStatusTracker tracker = myLineStatusTrackers.get(myDocument);
|
||||
if (tracker != null) {
|
||||
tracker.baseRevisionLoadFailed();
|
||||
}
|
||||
}, new Condition() {
|
||||
@Override
|
||||
public boolean value(final Object ignore) {
|
||||
return (! myProject.isOpen()) || myProject.isDisposed();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,7 +352,6 @@ public class LineStatusTrackerManager implements ProjectComponent, LineStatusTra
|
||||
|
||||
final VirtualFile[] openFiles = myFileEditorManager.getOpenFiles();
|
||||
for(final VirtualFile openFile: openFiles) {
|
||||
// write action inside is sufficient level
|
||||
resetTracker(openFile);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user