From bfe13eaebb6fca384bdc9d9db81ebdb9a9c1a3ce Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Mon, 30 Aug 2010 16:09:06 +0400 Subject: [PATCH] EA-21694 - NPE: SelectionModelImpl.getSelectionStart Refactored the code in order to exclude variables visibilities problems in case of access from concurrent threads --- .../editor/impl/SelectionModelImpl.java | 74 ++++++++++++------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java index 7c3ff3f102e0..49d9dac78b89 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java @@ -55,12 +55,13 @@ import java.awt.*; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.StringSelection; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicReference; public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentListener { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.SelectionModelImpl"); private final CopyOnWriteArrayList mySelectionListeners = ContainerUtil.createEmptyCOWList(); - private MyRangeMarker mySelectionMarker = null; + private final AtomicReference mySelectionMarker = new AtomicReference(); private final EditorImpl myEditor; private int myLastSelectionStart; private LogicalPosition myBlockStart; @@ -90,7 +91,7 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi if (!isValid()) { myLastSelectionStart = myEditor.getCaretModel().getOffset(); release(); - mySelectionMarker = null; + mySelectionMarker.set(null); fireSelectionChanged(startBefore, endBefore, myLastSelectionStart, myLastSelectionStart); return; } @@ -111,8 +112,9 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi public void documentChanged(DocumentEvent event) { if (myIsInUpdate == event) { myIsInUpdate = null; - if (mySelectionMarker != null && mySelectionMarker.isValid()) { - mySelectionMarker.documentChanged(event); + MyRangeMarker marker = mySelectionMarker.get(); + if (marker != null && marker.isValid()) { + marker.documentChanged(event); } } } @@ -127,8 +129,13 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi public int getSelectionStart() { validateContext(false); - if (!hasSelection()) return myEditor.getCaretModel().getOffset(); - return mySelectionMarker.getStartOffset(); + if (hasSelection()) { + MyRangeMarker marker = mySelectionMarker.get(); + if (marker != null) { + return marker.getStartOffset(); + } + } + return myEditor.getCaretModel().getOffset(); } private void validateContext(boolean isWrite) { @@ -146,17 +153,23 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi public int getSelectionEnd() { validateContext(false); - if (!hasSelection()) return myEditor.getCaretModel().getOffset(); - return mySelectionMarker.getEndOffset(); + if (hasSelection()) { + MyRangeMarker marker = mySelectionMarker.get(); + if (marker != null) { + return marker.getEndOffset(); + } + } + return myEditor.getCaretModel().getOffset(); } public boolean hasSelection() { validateContext(false); - if (mySelectionMarker != null && !mySelectionMarker.isValid()) { + MyRangeMarker marker = mySelectionMarker.get(); + if (marker != null && !marker.isValid()) { removeSelection(); } - return mySelectionMarker != null; + return marker != null; } public void setSelection(int startOffset, int endOffset) { @@ -189,19 +202,20 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi int oldSelectionEnd; if (hasSelection()) { - oldSelectionStart = mySelectionMarker.getStartOffset(); - oldSelectionEnd = mySelectionMarker.getEndOffset(); + oldSelectionStart = getSelectionStart(); + oldSelectionEnd = getSelectionEnd(); if (oldSelectionStart == startOffset && oldSelectionEnd == endOffset) return; } else { oldSelectionStart = oldSelectionEnd = myEditor.getCaretModel().getOffset(); } - if (mySelectionMarker != null) { - mySelectionMarker.release(); + MyRangeMarker marker = mySelectionMarker.get(); + 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); @@ -273,11 +287,12 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi validateContext(true); removeBlockSelection(); myLastSelectionStart = myEditor.getCaretModel().getOffset(); - if (mySelectionMarker != null) { - int startOffset = mySelectionMarker.getStartOffset(); - int endOffset = mySelectionMarker.getEndOffset(); - mySelectionMarker.release(); - mySelectionMarker = null; + MyRangeMarker marker = mySelectionMarker.get(); + if (marker != null) { + int startOffset = marker.getStartOffset(); + int endOffset = marker.getEndOffset(); + marker.release(); + mySelectionMarker.set(null); fireSelectionChanged(startOffset, endOffset, myLastSelectionStart, myLastSelectionStart); } } @@ -435,11 +450,20 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi public int getLeadSelectionOffset() { validateContext(false); int caretOffset = myEditor.getCaretModel().getOffset(); - if (!hasSelection()) return caretOffset; - int startOffset = mySelectionMarker.getStartOffset(); - int endOffset = mySelectionMarker.getEndOffset(); - if (caretOffset == endOffset) return startOffset; - return endOffset; + if (hasSelection()) { + MyRangeMarker marker = mySelectionMarker.get(); + if (marker != null) { + int startOffset = marker.getStartOffset(); + int endOffset = marker.getEndOffset(); + if (caretOffset == endOffset) { + return startOffset; + } + else { + return endOffset; + } + } + } + return caretOffset; } public void selectLineAtCaret() {