mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Add API for handling selected item in completion list
This commit is contained in:
+44
-24
@@ -46,6 +46,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -385,25 +386,39 @@ public class CodeCompletionHandlerBase {
|
||||
WatchingInsertionContext context = null;
|
||||
try {
|
||||
StatisticsUpdate update = StatisticsUpdate.collectStatisticChanges(item);
|
||||
context = insertItemHonorBlockSelection(indicator, item, completionChar, items, update);
|
||||
context = insertItemHonorBlockSelection(indicator, item, completionChar, update);
|
||||
update.trackStatistics(context);
|
||||
}
|
||||
finally {
|
||||
afterItemInsertion(indicator, context == null ? null : context.getLaterRunnable());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static WatchingInsertionContext insertItemHonorBlockSelection(CompletionProgressIndicator indicator,
|
||||
public void handleCompletionElementSelected(CompletionParameters parameters,
|
||||
@NotNull LookupElement item,
|
||||
char completionChar) {
|
||||
WatchingInsertionContext context = null;
|
||||
try {
|
||||
StatisticsUpdate update = StatisticsUpdate.collectStatisticChanges(item);
|
||||
context = insertItemHonorBlockSelection((CompletionProcessEx) parameters.getProcess(), item, completionChar, update);
|
||||
update.trackStatistics(context);
|
||||
}
|
||||
finally {
|
||||
if (context != null && context.getLaterRunnable() != null) {
|
||||
context.getLaterRunnable().run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static WatchingInsertionContext insertItemHonorBlockSelection(CompletionProcessEx indicator,
|
||||
LookupElement item,
|
||||
char completionChar,
|
||||
List<LookupElement> items,
|
||||
StatisticsUpdate update) {
|
||||
final Editor editor = indicator.getEditor();
|
||||
|
||||
final int caretOffset = indicator.getCaret().getOffset();
|
||||
final int idEndOffset = indicator.getOffsetMap().containsOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET) ?
|
||||
indicator.getIdentifierEndOffset() :
|
||||
indicator.getOffsetMap().getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET) :
|
||||
CompletionInitializationContext.calcDefaultIdentifierEnd(editor, caretOffset);
|
||||
final int idEndOffsetDelta = idEndOffset - caretOffset;
|
||||
|
||||
@@ -424,7 +439,7 @@ public class CodeCompletionHandlerBase {
|
||||
if (idEnd > targetEditor.getDocument().getTextLength()) {
|
||||
idEnd = targetCaretOffset; // no replacement by Tab when offsets gone wrong for some reason
|
||||
}
|
||||
WatchingInsertionContext currentContext = insertItem(indicator, item, completionChar, items, update,
|
||||
WatchingInsertionContext currentContext = insertItem(indicator.getLookup(), item, completionChar, update,
|
||||
targetEditor, targetFile,
|
||||
targetCaretOffset, idEnd,
|
||||
targetOffsets.getOffsets());
|
||||
@@ -433,18 +448,19 @@ public class CodeCompletionHandlerBase {
|
||||
|
||||
private OffsetsInFile findInjectedOffsetsIfAny(Caret caret) {
|
||||
if (!wasInjected) return topLevelOffsets;
|
||||
|
||||
PsiDocumentManager.getInstance(indicator.getProject()).commitDocument(hostEditor.getDocument());
|
||||
|
||||
PsiDocumentManager.getInstance(topLevelOffsets.getFile().getProject()).commitDocument(hostEditor.getDocument());
|
||||
return topLevelOffsets.toInjectedIfAny(caret.getOffset());
|
||||
}
|
||||
});
|
||||
context = lastContext.get();
|
||||
} else {
|
||||
context = insertItem(indicator, item, completionChar, items, update, editor, PsiUtilBase.getPsiFileInEditor(editor, indicator.getProject()), caretOffset,
|
||||
PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(editor, indicator.getProject());
|
||||
context = insertItem(indicator.getLookup(), item, completionChar, update, editor, psiFile, caretOffset,
|
||||
idEndOffset, indicator.getOffsetMap());
|
||||
}
|
||||
if (context.shouldAddCompletionChar()) {
|
||||
WriteAction.run(() -> addCompletionChar(context, item, editor, indicator, completionChar));
|
||||
WriteAction.run(() -> addCompletionChar(context, item, editor, completionChar));
|
||||
}
|
||||
return context;
|
||||
}
|
||||
@@ -470,15 +486,15 @@ public class CodeCompletionHandlerBase {
|
||||
}
|
||||
}
|
||||
|
||||
private static WatchingInsertionContext insertItem(final CompletionProgressIndicator indicator,
|
||||
final LookupElement item,
|
||||
final char completionChar,
|
||||
List<LookupElement> items,
|
||||
final StatisticsUpdate update,
|
||||
final Editor editor,
|
||||
final PsiFile psiFile,
|
||||
final int caretOffset,
|
||||
final int idEndOffset, final OffsetMap offsetMap) {
|
||||
private static WatchingInsertionContext insertItem(@Nullable final Lookup lookup,
|
||||
final LookupElement item,
|
||||
final char completionChar,
|
||||
final StatisticsUpdate update,
|
||||
final Editor editor,
|
||||
final PsiFile psiFile,
|
||||
final int caretOffset,
|
||||
final int idEndOffset,
|
||||
final OffsetMap offsetMap) {
|
||||
editor.getCaretModel().moveToOffset(caretOffset);
|
||||
int initialStartOffset = Math.max(0, caretOffset - item.getLookupString().length());
|
||||
|
||||
@@ -486,7 +502,9 @@ public class CodeCompletionHandlerBase {
|
||||
offsetMap.addOffset(CompletionInitializationContext.SELECTION_END_OFFSET, caretOffset);
|
||||
offsetMap.addOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET, idEndOffset);
|
||||
|
||||
WatchingInsertionContext context = new WatchingInsertionContext(offsetMap, psiFile, completionChar, items, editor);
|
||||
WatchingInsertionContext context = new WatchingInsertionContext(offsetMap, psiFile, completionChar,
|
||||
lookup != null ? lookup.getItems() : Collections.emptyList(),
|
||||
editor);
|
||||
ApplicationManager.getApplication().runWriteAction(() -> {
|
||||
try {
|
||||
if (caretOffset < idEndOffset && completionChar == Lookup.REPLACE_SELECT_CHAR) {
|
||||
@@ -496,7 +514,7 @@ public class CodeCompletionHandlerBase {
|
||||
assert context.getStartOffset() >= 0 : "stale startOffset: was " + initialStartOffset + "; selEnd=" + caretOffset + "; idEnd=" + idEndOffset + "; file=" + context.getFile();
|
||||
assert context.getTailOffset() >= 0 : "stale tail: was " + initialStartOffset + "; selEnd=" + caretOffset + "; idEnd=" + idEndOffset + "; file=" + context.getFile();
|
||||
|
||||
Project project = indicator.getProject();
|
||||
Project project = psiFile.getProject();
|
||||
if (item.requiresCommittedDocuments()) {
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
}
|
||||
@@ -509,13 +527,15 @@ public class CodeCompletionHandlerBase {
|
||||
|
||||
EditorModificationUtil.scrollToCaret(editor);
|
||||
});
|
||||
update.addSparedChars(indicator, item, context);
|
||||
if (lookup != null) {
|
||||
update.addSparedChars(lookup, item, context);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
private static void addCompletionChar(WatchingInsertionContext context,
|
||||
LookupElement item,
|
||||
Editor editor, CompletionProgressIndicator indicator, char completionChar) {
|
||||
Editor editor, char completionChar) {
|
||||
if (!context.getOffsetMap().containsOffset(InsertionContext.TAIL_OFFSET)) {
|
||||
LOG.info("tailOffset<0 after inserting " + item + " of " + item.getClass() + "; invalidated at: " + context.invalidateTrace + "\n--------");
|
||||
}
|
||||
@@ -526,7 +546,7 @@ public class CodeCompletionHandlerBase {
|
||||
context.getEditor().getCaretModel().moveToOffset(context.getTailOffset());
|
||||
}
|
||||
if (context.getCompletionChar() == Lookup.COMPLETE_STATEMENT_SELECT_CHAR) {
|
||||
Language language = PsiUtilBase.getLanguageInEditor(editor, indicator.getProject());
|
||||
Language language = PsiUtilBase.getLanguageInEditor(editor, context.getFile().getProject());
|
||||
if (language != null) {
|
||||
for (SmartEnterProcessor processor : SmartEnterProcessors.INSTANCE.allForLanguage(language)) {
|
||||
if (processor.processAfterCompletion(editor, context.getFile())) break;
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.lookup.Lookup;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.editor.Caret;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -19,10 +23,40 @@ public class CompletionProcessBase implements CompletionProcessEx, Disposable {
|
||||
protected final Object myLock = new String("CompletionProgressIndicator");
|
||||
protected OffsetsInFile myHostOffsets;
|
||||
private CompletionParameters myParameters;
|
||||
private final Caret myCaret;
|
||||
private final OffsetMap myOffsetMap;
|
||||
|
||||
public CompletionProcessBase(CompletionInitializationContext context) {
|
||||
myInvocationCount = context.getInvocationCount();
|
||||
myHostOffsets = ((CompletionInitializationContextImpl) context).getHostOffsets();
|
||||
myCaret = context.getCaret();
|
||||
myOffsetMap = context.getOffsetMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Project getProject() {
|
||||
return myParameters.getOriginalFile().getProject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor getEditor() {
|
||||
return myParameters.getEditor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Caret getCaret() {
|
||||
return myCaret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OffsetMap getOffsetMap() {
|
||||
return myOffsetMap;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Lookup getLookup() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.lookup.Lookup;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.editor.Caret;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -14,7 +18,15 @@ import java.util.function.Supplier;
|
||||
* @author yole
|
||||
*/
|
||||
interface CompletionProcessEx extends CompletionProcess {
|
||||
Project getProject();
|
||||
Editor getEditor();
|
||||
Caret getCaret();
|
||||
OffsetMap getOffsetMap();
|
||||
OffsetsInFile getHostOffsets();
|
||||
|
||||
@Nullable
|
||||
Lookup getLookup();
|
||||
|
||||
void registerChildDisposable(@NotNull Supplier<Disposable> child);
|
||||
|
||||
void itemSelected(LookupElement item, char aChar);
|
||||
|
||||
+1
-1
@@ -626,7 +626,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Caret getCaret() {
|
||||
public Caret getCaret() {
|
||||
return myCaret;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.codeInsight.completion
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting
|
||||
import com.intellij.codeInsight.lookup.Lookup
|
||||
import com.intellij.codeInsight.lookup.LookupElement
|
||||
import com.intellij.codeInsight.lookup.LookupEvent
|
||||
import com.intellij.featureStatistics.FeatureUsageTracker
|
||||
@@ -24,7 +25,7 @@ class StatisticsUpdate
|
||||
|
||||
override fun dispose() {}
|
||||
|
||||
fun addSparedChars(indicator: CompletionProgressIndicator, item: LookupElement, context: InsertionContext) {
|
||||
fun addSparedChars(lookup: Lookup, item: LookupElement, context: InsertionContext) {
|
||||
val textInserted: String
|
||||
if (context.offsetMap.containsOffset(CompletionInitializationContext.START_OFFSET) &&
|
||||
context.offsetMap.containsOffset(InsertionContext.TAIL_OFFSET) &&
|
||||
@@ -35,7 +36,7 @@ class StatisticsUpdate
|
||||
textInserted = item.lookupString
|
||||
}
|
||||
val withoutSpaces = StringUtil.replace(textInserted, listOf(" ", "\t", "\n"), listOf("", "", ""))
|
||||
var spared = withoutSpaces.length - indicator.lookup.itemPattern(item).length
|
||||
var spared = withoutSpaces.length - lookup.itemPattern(item).length
|
||||
val completionChar = context.completionChar
|
||||
if (!LookupEvent.isSpecialCompletionChar(completionChar) && withoutSpaces.contains(completionChar.toString())) {
|
||||
spared--
|
||||
|
||||
+7
@@ -287,6 +287,13 @@ public final class CompletionServiceImpl extends CompletionService {
|
||||
return new CompletionLookupArrangerImpl(parameters);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void handleCompletionItemSelected(CompletionParameters parameters, LookupElement lookupElement, char completionChar) {
|
||||
CodeCompletionHandlerBase handler =
|
||||
CodeCompletionHandlerBase.createHandler(parameters.getCompletionType(), true, parameters.isAutoPopup(), true);
|
||||
handler.handleCompletionElementSelected(parameters, lookupElement, completionChar);
|
||||
}
|
||||
|
||||
public static boolean isStartMatch(LookupElement element, WeighingContext context) {
|
||||
return getItemMatcher(element, context).isStartMatch(element);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user