fail when accessing invalid offsets in completion insert handlers

This commit is contained in:
peter
2016-06-24 11:59:44 +02:00
parent 9e9eaac4f1
commit 7c3cd4327b
4 changed files with 20 additions and 10 deletions
@@ -58,7 +58,7 @@ public class ConstructorInsertHandler implements InsertHandler<LookupElementDeco
boolean isAbstract = psiClass.hasModifierProperty(PsiModifier.ABSTRACT);
if (Lookup.REPLACE_SELECT_CHAR == context.getCompletionChar()) {
if (Lookup.REPLACE_SELECT_CHAR == context.getCompletionChar() && context.getOffsetMap().containsOffset(PARAM_LIST_START)) {
final int plStart = context.getOffset(PARAM_LIST_START);
final int plEnd = context.getOffset(PARAM_LIST_END);
if (plStart >= 0 && plEnd >= 0) {
@@ -19,10 +19,10 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -48,10 +48,10 @@ public class OffsetMap implements Disposable {
public int getOffset(OffsetKey key) {
synchronized (myMap) {
final RangeMarker marker = myMap.get(key);
if (marker == null) return -1;
if (marker == null) throw new IllegalArgumentException("Offset " + key + " is not registered");
if (!marker.isValid()) {
removeOffset(key);
return -1;
throw new IllegalStateException("Offset " + key + " is invalid: " + marker);
}
final int endOffset = marker.getEndOffset();
@@ -62,6 +62,11 @@ public class OffsetMap implements Disposable {
}
}
public boolean containsOffset(OffsetKey key) {
final RangeMarker marker = myMap.get(key);
return marker != null && marker.isValid();
}
/**
* Register key-offset binding. Offset will change together with {@link Document} editing operations
* unless an operation replaces completely the offset vicinity.
@@ -108,7 +113,7 @@ public class OffsetMap implements Disposable {
synchronized (myMap) {
ProgressManager.checkCanceled();
assert !myDisposed;
return new ArrayList<OffsetKey>(myMap.keySet());
return ContainerUtil.filter(myMap.keySet(), this::containsOffset);
}
}
@@ -566,10 +566,9 @@ public class CodeCompletionHandlerBase {
final Editor editor = indicator.getEditor();
final int caretOffset = indicator.getCaret().getOffset();
int idEndOffset = indicator.getIdentifierEndOffset();
if (idEndOffset < 0) {
idEndOffset = CompletionInitializationContext.calcDefaultIdentifierEnd(editor, caretOffset);
}
final int idEndOffset = indicator.getOffsetMap().containsOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET) ?
indicator.getIdentifierEndOffset() :
CompletionInitializationContext.calcDefaultIdentifierEnd(editor, caretOffset);
final int idEndOffsetDelta = idEndOffset - caretOffset;
CompletionAssertions.WatchingInsertionContext context;
@@ -462,6 +462,10 @@ public class CompletionLookupArranger extends LookupArranger {
return;
}
if (!context.getOffsetMap().containsOffset(CompletionInitializationContext.START_OFFSET)) {
return;
}
final Document document = context.getDocument();
int startOffset = context.getStartOffset();
int tailOffset = context.getEditor().getCaretModel().getOffset();
@@ -550,7 +554,9 @@ public class CompletionLookupArranger extends LookupArranger {
public void addSparedChars(CompletionProgressIndicator indicator, LookupElement item, InsertionContext context, char completionChar) {
String textInserted;
if (context.getStartOffset() >= 0 && context.getTailOffset() >= context.getStartOffset()) {
if (context.getOffsetMap().containsOffset(CompletionInitializationContext.START_OFFSET) &&
context.getOffsetMap().containsOffset(InsertionContext.TAIL_OFFSET) &&
context.getTailOffset() >= context.getStartOffset()) {
textInserted = context.getDocument().getImmutableCharSequence().subSequence(context.getStartOffset(), context.getTailOffset()).toString();
} else {
textInserted = item.getLookupString();