EA-21694 - NPE: SelectionModelImpl.getSelectionStart

Refactored the code in order to exclude variables visibilities problems in case of access from concurrent threads
This commit is contained in:
Denis Zhdanov
2010-08-30 16:10:27 +04:00
parent a7f14e657d
commit bfe13eaebb
@@ -55,12 +55,13 @@ import java.awt.*;
import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.StringSelection;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicReference;
public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentListener { public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentListener {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.SelectionModelImpl"); private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.SelectionModelImpl");
private final CopyOnWriteArrayList<SelectionListener> mySelectionListeners = ContainerUtil.createEmptyCOWList(); private final CopyOnWriteArrayList<SelectionListener> mySelectionListeners = ContainerUtil.createEmptyCOWList();
private MyRangeMarker mySelectionMarker = null; private final AtomicReference<MyRangeMarker> mySelectionMarker = new AtomicReference<MyRangeMarker>();
private final EditorImpl myEditor; private final EditorImpl myEditor;
private int myLastSelectionStart; private int myLastSelectionStart;
private LogicalPosition myBlockStart; private LogicalPosition myBlockStart;
@@ -90,7 +91,7 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
if (!isValid()) { if (!isValid()) {
myLastSelectionStart = myEditor.getCaretModel().getOffset(); myLastSelectionStart = myEditor.getCaretModel().getOffset();
release(); release();
mySelectionMarker = null; mySelectionMarker.set(null);
fireSelectionChanged(startBefore, endBefore, myLastSelectionStart, myLastSelectionStart); fireSelectionChanged(startBefore, endBefore, myLastSelectionStart, myLastSelectionStart);
return; return;
} }
@@ -111,8 +112,9 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
public void documentChanged(DocumentEvent event) { public void documentChanged(DocumentEvent event) {
if (myIsInUpdate == event) { if (myIsInUpdate == event) {
myIsInUpdate = null; myIsInUpdate = null;
if (mySelectionMarker != null && mySelectionMarker.isValid()) { MyRangeMarker marker = mySelectionMarker.get();
mySelectionMarker.documentChanged(event); if (marker != null && marker.isValid()) {
marker.documentChanged(event);
} }
} }
} }
@@ -127,8 +129,13 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
public int getSelectionStart() { public int getSelectionStart() {
validateContext(false); validateContext(false);
if (!hasSelection()) return myEditor.getCaretModel().getOffset(); if (hasSelection()) {
return mySelectionMarker.getStartOffset(); MyRangeMarker marker = mySelectionMarker.get();
if (marker != null) {
return marker.getStartOffset();
}
}
return myEditor.getCaretModel().getOffset();
} }
private void validateContext(boolean isWrite) { private void validateContext(boolean isWrite) {
@@ -146,17 +153,23 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
public int getSelectionEnd() { public int getSelectionEnd() {
validateContext(false); validateContext(false);
if (!hasSelection()) return myEditor.getCaretModel().getOffset(); if (hasSelection()) {
return mySelectionMarker.getEndOffset(); MyRangeMarker marker = mySelectionMarker.get();
if (marker != null) {
return marker.getEndOffset();
}
}
return myEditor.getCaretModel().getOffset();
} }
public boolean hasSelection() { public boolean hasSelection() {
validateContext(false); validateContext(false);
if (mySelectionMarker != null && !mySelectionMarker.isValid()) { MyRangeMarker marker = mySelectionMarker.get();
if (marker != null && !marker.isValid()) {
removeSelection(); removeSelection();
} }
return mySelectionMarker != null; return marker != null;
} }
public void setSelection(int startOffset, int endOffset) { public void setSelection(int startOffset, int endOffset) {
@@ -189,19 +202,20 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
int oldSelectionEnd; int oldSelectionEnd;
if (hasSelection()) { if (hasSelection()) {
oldSelectionStart = mySelectionMarker.getStartOffset(); oldSelectionStart = getSelectionStart();
oldSelectionEnd = mySelectionMarker.getEndOffset(); oldSelectionEnd = getSelectionEnd();
if (oldSelectionStart == startOffset && oldSelectionEnd == endOffset) return; if (oldSelectionStart == startOffset && oldSelectionEnd == endOffset) return;
} }
else { else {
oldSelectionStart = oldSelectionEnd = myEditor.getCaretModel().getOffset(); oldSelectionStart = oldSelectionEnd = myEditor.getCaretModel().getOffset();
} }
if (mySelectionMarker != null) { MyRangeMarker marker = mySelectionMarker.get();
mySelectionMarker.release(); if (marker != null) {
marker.release();
} }
mySelectionMarker = new MyRangeMarker((DocumentEx)doc, startOffset, endOffset); mySelectionMarker.set(new MyRangeMarker((DocumentEx)doc, startOffset, endOffset));
fireSelectionChanged(oldSelectionStart, oldSelectionEnd, startOffset, endOffset); fireSelectionChanged(oldSelectionStart, oldSelectionEnd, startOffset, endOffset);
@@ -273,11 +287,12 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
validateContext(true); validateContext(true);
removeBlockSelection(); removeBlockSelection();
myLastSelectionStart = myEditor.getCaretModel().getOffset(); myLastSelectionStart = myEditor.getCaretModel().getOffset();
if (mySelectionMarker != null) { MyRangeMarker marker = mySelectionMarker.get();
int startOffset = mySelectionMarker.getStartOffset(); if (marker != null) {
int endOffset = mySelectionMarker.getEndOffset(); int startOffset = marker.getStartOffset();
mySelectionMarker.release(); int endOffset = marker.getEndOffset();
mySelectionMarker = null; marker.release();
mySelectionMarker.set(null);
fireSelectionChanged(startOffset, endOffset, myLastSelectionStart, myLastSelectionStart); fireSelectionChanged(startOffset, endOffset, myLastSelectionStart, myLastSelectionStart);
} }
} }
@@ -435,11 +450,20 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
public int getLeadSelectionOffset() { public int getLeadSelectionOffset() {
validateContext(false); validateContext(false);
int caretOffset = myEditor.getCaretModel().getOffset(); int caretOffset = myEditor.getCaretModel().getOffset();
if (!hasSelection()) return caretOffset; if (hasSelection()) {
int startOffset = mySelectionMarker.getStartOffset(); MyRangeMarker marker = mySelectionMarker.get();
int endOffset = mySelectionMarker.getEndOffset(); if (marker != null) {
if (caretOffset == endOffset) return startOffset; int startOffset = marker.getStartOffset();
return endOffset; int endOffset = marker.getEndOffset();
if (caretOffset == endOffset) {
return startOffset;
}
else {
return endOffset;
}
}
}
return caretOffset;
} }
public void selectLineAtCaret() { public void selectLineAtCaret() {