下面列出了com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil#getTopLevelEditor ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void scheduleContributorsAfterAsyncCommit(CompletionInitializationContextImpl initContext, CompletionProgressIndicator indicator, OffsetsInFile hostCopyOffsets, boolean hasModifiers) {
CompletionPhase phase;
if (synchronous) {
phase = new CompletionPhase.BgCalculation(indicator);
indicator.makeSureLookupIsShown(0);
}
else {
phase = new CompletionPhase.CommittingDocuments(indicator, InjectedLanguageUtil.getTopLevelEditor(indicator.getEditor()));
}
CompletionServiceImpl.setCompletionPhase(phase);
AppUIExecutor.onUiThread().withDocumentsCommitted(initContext.getProject()).expireWith(phase).execute(() -> {
if (phase instanceof CompletionPhase.CommittingDocuments) {
((CompletionPhase.CommittingDocuments)phase).replaced = true;
}
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.BgCalculation(indicator));
startContributorThread(initContext, indicator, hostCopyOffsets, hasModifiers);
});
}
private static Runnable rememberDocumentState(final Editor _editor) {
final Editor editor = InjectedLanguageUtil.getTopLevelEditor(_editor);
final String documentText = editor.getDocument().getText();
final int caret = editor.getCaretModel().getOffset();
final int selStart = editor.getSelectionModel().getSelectionStart();
final int selEnd = editor.getSelectionModel().getSelectionEnd();
final int vOffset = editor.getScrollingModel().getVerticalScrollOffset();
final int hOffset = editor.getScrollingModel().getHorizontalScrollOffset();
return () -> {
DocumentEx document = (DocumentEx)editor.getDocument();
document.replaceString(0, document.getTextLength(), documentText);
editor.getCaretModel().moveToOffset(caret);
editor.getSelectionModel().setSelection(selStart, selEnd);
editor.getScrollingModel().scrollHorizontally(hOffset);
editor.getScrollingModel().scrollVertically(vOffset);
};
}
@Override
public boolean maySaveDocument(@Nonnull Document document, boolean isSaveExplicit) {
if (ApplicationManager.getApplication().isDisposed() || isSaveExplicit) {
return true;
}
for (Project project : ProjectManager.getInstance().getOpenProjects()) {
if (!project.isInitialized() || project.isDisposed()) {
continue;
}
LookupEx lookup = LookupManager.getInstance(project).getActiveLookup();
if (lookup != null) {
Editor editor = InjectedLanguageUtil.getTopLevelEditor(lookup.getEditor());
if (editor.getDocument() == document) {
return false;
}
}
}
return true;
}
@Override
public Result preprocessEnter(
PsiFile file,
Editor editor,
Ref<Integer> caretOffset,
Ref<Integer> caretAdvance,
DataContext dataContext,
EditorActionHandler originalHandler) {
int offset = caretOffset.get();
if (editor instanceof EditorWindow) {
file = InjectedLanguageManager.getInstance(file.getProject()).getTopLevelFile(file);
editor = InjectedLanguageUtil.getTopLevelEditor(editor);
offset = editor.getCaretModel().getOffset();
}
if (!isApplicable(file, dataContext) || !insertIndent(file, offset)) {
return Result.Continue;
}
int indent = SectionParser.INDENT;
editor.getCaretModel().moveToOffset(offset);
Document doc = editor.getDocument();
PsiDocumentManager.getInstance(file.getProject()).commitDocument(doc);
originalHandler.execute(editor, editor.getCaretModel().getCurrentCaret(), dataContext);
LogicalPosition position = editor.getCaretModel().getLogicalPosition();
if (position.column < indent) {
String spaces = StringUtil.repeatSymbol(' ', indent - position.column);
doc.insertString(editor.getCaretModel().getOffset(), spaces);
}
editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(position.line, indent));
return Result.Stop;
}
static OffsetsInFile insertDummyIdentifier(CompletionInitializationContext initContext, CompletionProgressIndicator indicator) {
OffsetsInFile topLevelOffsets = indicator.getHostOffsets();
CompletionAssertions.checkEditorValid(initContext.getEditor());
if (initContext.getDummyIdentifier().isEmpty()) {
return topLevelOffsets;
}
Editor hostEditor = InjectedLanguageUtil.getTopLevelEditor(initContext.getEditor());
OffsetMap hostMap = topLevelOffsets.getOffsets();
PsiFile hostCopy = obtainFileCopy(topLevelOffsets.getFile());
Document copyDocument = Objects.requireNonNull(hostCopy.getViewProvider().getDocument());
String dummyIdentifier = initContext.getDummyIdentifier();
int startOffset = hostMap.getOffset(CompletionInitializationContext.START_OFFSET);
int endOffset = hostMap.getOffset(CompletionInitializationContext.SELECTION_END_OFFSET);
indicator.registerChildDisposable(() -> new OffsetTranslator(hostEditor.getDocument(), initContext.getFile(), copyDocument, startOffset, endOffset, dummyIdentifier));
copyDocument.setText(hostEditor.getDocument().getText());
OffsetMap copyOffsets = topLevelOffsets.getOffsets().copyOffsets(copyDocument);
indicator.registerChildDisposable(() -> copyOffsets);
copyDocument.replaceString(startOffset, endOffset, dummyIdentifier);
return new OffsetsInFile(hostCopy, copyOffsets);
}
private static WatchingInsertionContext insertItemHonorBlockSelection(CompletionProcessEx indicator, LookupElement item, char completionChar, StatisticsUpdate update) {
final Editor editor = indicator.getEditor();
final int caretOffset = indicator.getCaret().getOffset();
final int idEndOffset = calcIdEndOffset(indicator);
final int idEndOffsetDelta = idEndOffset - caretOffset;
WatchingInsertionContext context;
if (editor.getCaretModel().supportsMultipleCarets()) {
Ref<WatchingInsertionContext> lastContext = Ref.create();
Editor hostEditor = InjectedLanguageUtil.getTopLevelEditor(editor);
boolean wasInjected = hostEditor != editor;
OffsetsInFile topLevelOffsets = indicator.getHostOffsets();
hostEditor.getCaretModel().runForEachCaret(caret -> {
OffsetsInFile targetOffsets = findInjectedOffsetsIfAny(caret, wasInjected, topLevelOffsets, hostEditor);
PsiFile targetFile = targetOffsets.getFile();
Editor targetEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(hostEditor, targetFile);
int targetCaretOffset = targetEditor.getCaretModel().getOffset();
int idEnd = targetCaretOffset + idEndOffsetDelta;
if (idEnd > targetEditor.getDocument().getTextLength()) {
idEnd = targetCaretOffset; // no replacement by Tab when offsets gone wrong for some reason
}
WatchingInsertionContext currentContext = insertItem(indicator.getLookup(), item, completionChar, update, targetEditor, targetFile, targetCaretOffset, idEnd, targetOffsets.getOffsets());
lastContext.set(currentContext);
});
context = lastContext.get();
}
else {
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));
}
checkPsiTextConsistency(indicator);
return context;
}
@Nullable
public static LookupEx getActiveLookup(@Nullable Editor editor) {
if (editor == null) return null;
final Project project = editor.getProject();
if (project == null || project.isDisposed()) return null;
final LookupEx lookup = getInstance(project).getActiveLookup();
if (lookup == null) return null;
return lookup.getTopLevelEditor() == InjectedLanguageUtil.getTopLevelEditor(editor) ? lookup : null;
}
public LookupImpl(Project project, Editor editor, @Nonnull LookupArranger arranger) {
super(new JPanel(new BorderLayout()));
setForceShowAsPopup(true);
setCancelOnClickOutside(false);
setResizable(true);
myProject = project;
myEditor = InjectedLanguageUtil.getTopLevelEditor(editor);
myArranger = arranger;
myPresentableArranger = arranger;
myEditor.getColorsScheme().getFontPreferences().copyTo(myFontPreferences);
DaemonCodeAnalyzer.getInstance(myProject).disableUpdateByTimer(this);
myCellRenderer = new LookupCellRenderer(this);
myList.setCellRenderer(myCellRenderer);
myList.setFocusable(false);
myList.setFixedCellWidth(50);
myList.setBorder(null);
// a new top level frame just got the focus. This is important to prevent screen readers
// from announcing the title of the top level frame when the list is shown (or hidden),
// as they usually do when a new top-level frame receives the focus.
AccessibleContextUtil.setParent((Component)myList, myEditor.getContentComponent());
myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
myList.setBackground(LookupCellRenderer.BACKGROUND_COLOR);
myAdComponent = new Advertiser();
myAdComponent.setBackground(LookupCellRenderer.BACKGROUND_COLOR);
myOffsets = new LookupOffsets(myEditor);
final CollectionListModel<LookupElement> model = getListModel();
addEmptyItem(model);
updateListHeight(model);
addListeners();
}
@Override
protected void revertStateOnFinish() {
final Editor editor = InjectedLanguageUtil.getTopLevelEditor(myEditor);
if (editor == FileEditorManager.getInstance(myProject).getSelectedTextEditor()) {
((DesktopEditorImpl)editor).startDumb();
}
revertState();
}
@Override
public Result preprocessEnter(
PsiFile file,
Editor editor,
Ref<Integer> caretOffset,
Ref<Integer> caretAdvance,
DataContext dataContext,
EditorActionHandler originalHandler) {
int offset = caretOffset.get();
if (editor instanceof EditorWindow) {
file = InjectedLanguageManager.getInstance(file.getProject()).getTopLevelFile(file);
editor = InjectedLanguageUtil.getTopLevelEditor(editor);
offset = editor.getCaretModel().getOffset();
}
if (!isApplicable(file, dataContext)) {
return Result.Continue;
}
// Previous enter handler's (e.g. EnterBetweenBracesHandler) can introduce a mismatch
// between the editor's caret model and the offset we've been provided with.
editor.getCaretModel().moveToOffset(offset);
Document doc = editor.getDocument();
PsiDocumentManager.getInstance(file.getProject()).commitDocument(doc);
// #api173: get file, language specific settings instead
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(file.getProject());
Integer indent = determineIndent(file, editor, offset, settings);
if (indent == null) {
return Result.Continue;
}
removeTrailingWhitespace(doc, file, offset);
originalHandler.execute(editor, editor.getCaretModel().getCurrentCaret(), dataContext);
LogicalPosition position = editor.getCaretModel().getLogicalPosition();
if (position.column == indent) {
return Result.Stop;
}
if (position.column > indent) {
// default enter handler has added too many spaces -- remove them
int excess = position.column - indent;
doc.deleteString(
editor.getCaretModel().getOffset() - excess, editor.getCaretModel().getOffset());
} else if (position.column < indent) {
String spaces = StringUtil.repeatSymbol(' ', indent - position.column);
doc.insertString(editor.getCaretModel().getOffset(), spaces);
}
editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(position.line, indent));
return Result.Stop;
}
public static void scheduleAsyncCompletion(@Nonnull Editor _editor,
@Nonnull CompletionType completionType,
@Nullable Condition<? super PsiFile> condition,
@Nonnull Project project,
@Nullable CompletionProgressIndicator prevIndicator) {
Editor topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(_editor);
int offset = topLevelEditor.getCaretModel().getOffset();
CommittingDocuments phase = new CommittingDocuments(prevIndicator, topLevelEditor);
CompletionServiceImpl.setCompletionPhase(phase);
phase.ignoreCurrentDocumentChange();
boolean autopopup = prevIndicator == null || prevIndicator.isAutopopupCompletion();
ReadAction.nonBlocking(() -> {
// retrieve the injected file from scratch since our typing might have destroyed the old one completely
PsiFile topLevelFile = PsiDocumentManager.getInstance(project).getPsiFile(topLevelEditor.getDocument());
Editor completionEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(topLevelEditor, topLevelFile, offset);
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(completionEditor.getDocument());
if (file == null || autopopup && shouldSkipAutoPopup(completionEditor, file) || condition != null && !condition.value(file)) {
return null;
}
loadContributorsOutsideEdt(completionEditor, file);
return completionEditor;
}).withDocumentsCommitted(project).expireWith(phase).expireWhen(() -> phase.isExpired()).finishOnUiThread(ModalityState.current(), completionEditor -> {
if (completionEditor != null) {
int time = prevIndicator == null ? 0 : prevIndicator.getInvocationCount();
CodeCompletionHandlerBase handler = CodeCompletionHandlerBase.createHandler(completionType, false, autopopup, false);
handler.invokeCompletion(project, completionEditor, time, false);
}
else if (phase == CompletionServiceImpl.getCompletionPhase()) {
CompletionServiceImpl.setCompletionPhase(NoCompletion);
}
}).submit(ourExecutor).onError(__ -> AppUIUtil.invokeOnEdt(() -> {
if (phase == CompletionServiceImpl.getCompletionPhase()) {
CompletionServiceImpl.setCompletionPhase(NoCompletion);
}
}));
}