IDEA-128025 Expand selection in multiple carets through injections still failing

This commit is contained in:
Dmitry Batrak
2014-08-04 15:55:57 +04:00
parent abfb033251
commit 7a0414307f
39 changed files with 415 additions and 206 deletions

View File

@@ -11,7 +11,7 @@ public class Test {
@Override
void bar() {
}
}
}

View File

@@ -537,11 +537,6 @@ public abstract class CodeInsightTestCase extends PsiTestCase {
}
}
@Override
public Object getData(String dataId) {
return CommonDataKeys.EDITOR.is(dataId) ? myEditor : super.getData(dataId);
}
protected VirtualFile getVirtualFile(@NonNls @NotNull String filePath) {
String fullPath = getTestDataPath() + filePath;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -297,6 +297,10 @@ public abstract class AnAction implements PossiblyDumbAware {
return myIsDefaultIcon;
}
/**
* Enables automatic detection of injected fragments in editor. Values in DataContext, passed to the action, like EDITOR, PSI_FILE
* will refer to an injected fragment, if caret is currently positioned on it.
*/
public void setInjectedContext(boolean worksInInjected) {
myWorksInInjected = worksInInjected;
}

View File

@@ -117,6 +117,18 @@ public class AnActionEvent implements PlaceProvider<String> {
return StringUtil.trimStart(dataId, ourInjectedPrefix);
}
public static DataContext getInjectedDataContext(final DataContext context) {
return new DataContext() {
@Override
@Nullable
public Object getData(@NonNls String dataId) {
Object injected = context.getData(injectedId(dataId));
if (injected != null) return injected;
return context.getData(dataId);
}
};
}
/**
* Returns the context which allows to retrieve information about the state of IDEA related to
* the action invocation (active editor, selection and so on).
@@ -125,18 +137,7 @@ public class AnActionEvent implements PlaceProvider<String> {
*/
@NotNull
public DataContext getDataContext() {
if (!myWorksInInjected) {
return myDataContext;
}
return new DataContext() {
@Override
@Nullable
public Object getData(@NonNls String dataId) {
Object injected = myDataContext.getData(injectedId(dataId));
if (injected != null) return injected;
return myDataContext.getData(dataId);
}
};
return myWorksInInjected ? getInjectedDataContext(myDataContext) : myDataContext;
}
@Nullable

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.actionSystem;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
@@ -25,7 +26,14 @@ import com.intellij.psi.PsiFile;
public class CommonDataKeys {
public static final DataKey<Project> PROJECT = DataKey.create("project");
public static final DataKey<Editor> EDITOR = DataKey.create("editor");
/**
* This key can be used to obtain reference to host editor instance, in case {@link #EDITOR} key is referring to an injected editor.
*/
public static final DataKey<Editor> HOST_EDITOR = DataKey.create("host.editor");
/**
* A key to retrieve caret instance (in host or injected editor, depending on context).
*/
public static final DataKey<Caret> CARET = DataKey.create("caret");
/**
* Returns com.intellij.openapi.editor.Editor even if focus currently is in find bar
*/

View File

@@ -26,10 +26,12 @@ package com.intellij.codeInsight.editorActions;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.Nullable;
public class CodeBlockEndAction extends EditorAction {
public CodeBlockEndAction() {
@@ -43,7 +45,7 @@ public class CodeBlockEndAction extends EditorAction {
}
@Override
public void execute(Editor editor, DataContext dataContext) {
public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project != null) {
CodeBlockUtil.moveCaretToCodeBlockEnd(project, editor, false);

View File

@@ -26,10 +26,12 @@ package com.intellij.codeInsight.editorActions;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.Nullable;
public class CodeBlockEndWithSelectionAction extends EditorAction {
public CodeBlockEndWithSelectionAction() {
@@ -43,7 +45,7 @@ public class CodeBlockEndWithSelectionAction extends EditorAction {
}
@Override
public void execute(Editor editor, DataContext dataContext) {
public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project != null) {
CodeBlockUtil.moveCaretToCodeBlockEnd(project, editor, true);

View File

@@ -26,10 +26,12 @@ package com.intellij.codeInsight.editorActions;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.Nullable;
public class CodeBlockStartAction extends EditorAction {
public CodeBlockStartAction() {
@@ -43,7 +45,7 @@ public class CodeBlockStartAction extends EditorAction {
}
@Override
public void execute(Editor editor, DataContext dataContext) {
public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project != null) {
CodeBlockUtil.moveCaretToCodeBlockStart(project, editor, false);

View File

@@ -26,10 +26,12 @@ package com.intellij.codeInsight.editorActions;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.Nullable;
public class CodeBlockStartWithSelectionAction extends EditorAction {
public CodeBlockStartWithSelectionAction() {
@@ -43,7 +45,7 @@ public class CodeBlockStartWithSelectionAction extends EditorAction {
}
@Override
public void execute(Editor editor, DataContext dataContext) {
public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project != null) {
CodeBlockUtil.moveCaretToCodeBlockStart(project, editor, true);

View File

@@ -61,8 +61,8 @@ public class EnterHandler extends BaseEnterHandler {
}
@Override
public boolean isEnabled(Editor editor, DataContext dataContext) {
return myOriginalHandler.isEnabled(editor, dataContext);
public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
return myOriginalHandler.isEnabled(editor, caret, dataContext);
}
@Override

View File

@@ -25,6 +25,7 @@ import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
@@ -51,14 +52,14 @@ public class SelectWordHandler extends EditorActionHandler {
}
@Override
public void execute(@NotNull Editor editor, DataContext dataContext) {
public void doExecute(@NotNull Editor editor, @Nullable Caret caret, DataContext dataContext) {
if (LOG.isDebugEnabled()) {
LOG.debug("enter: execute(editor='" + editor + "')");
}
Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(editor.getComponent()));
if (project == null) {
if (myOriginalHandler != null) {
myOriginalHandler.execute(editor, dataContext);
myOriginalHandler.execute(editor, caret, dataContext);
}
return;
}
@@ -74,7 +75,7 @@ public class SelectWordHandler extends EditorActionHandler {
}
if (range == null) {
if (myOriginalHandler != null) {
myOriginalHandler.execute(editor, dataContext);
myOriginalHandler.execute(editor, caret, dataContext);
}
}
else {

View File

@@ -19,6 +19,7 @@ package com.intellij.codeInsight.editorActions;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.FoldRegion;
@@ -28,6 +29,7 @@ import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.util.Processor;
import org.jetbrains.annotations.Nullable;
public class UnSelectWordHandler extends EditorActionHandler {
private final EditorActionHandler myOriginalHandler;
@@ -38,14 +40,17 @@ public class UnSelectWordHandler extends EditorActionHandler {
}
@Override
public void execute(Editor editor, DataContext dataContext) {
public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(editor.getComponent()));
if (project == null) {
return;
}
Document document = editor.getDocument();
final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
if (file == null) {
if (myOriginalHandler != null) {
myOriginalHandler.execute(editor, dataContext);
myOriginalHandler.execute(editor, caret, dataContext);
}
return;
}

View File

@@ -16,13 +16,13 @@
package com.intellij.codeInsight.editorActions.smartEnter;
import com.intellij.codeInsight.actions.BaseCodeInsightAction;
import com.intellij.codeInsight.editorActions.enter.EnterAfterUnmatchedBraceHandler;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.lang.Language;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
@@ -41,15 +41,7 @@ import java.util.List;
public class SmartEnterAction extends EditorAction {
public SmartEnterAction() {
super(new Handler());
}
@Override
protected Editor getEditor(@NotNull final DataContext dataContext) {
final Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
if (editor == null) return null;
Project project = editor.getProject();
if (project == null) project = CommonDataKeys.PROJECT.getData(dataContext);
return project == null ? null : BaseCodeInsightAction.getInjectedEditor(project, editor);
setInjectedContext(true);
}
private static class Handler extends EditorWriteActionHandler {
@@ -58,15 +50,15 @@ public class SmartEnterAction extends EditorAction {
}
@Override
public boolean isEnabled(Editor editor, DataContext dataContext) {
return getEnterHandler().isEnabled(editor, dataContext);
public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
return getEnterHandler().isEnabled(editor, caret, dataContext);
}
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
public void executeWriteAction(Editor editor, Caret caret, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project == null || editor.isOneLineMode()) {
plainEnter(editor, dataContext);
plainEnter(editor, caret, dataContext);
return;
}
@@ -76,13 +68,13 @@ public class SmartEnterAction extends EditorAction {
PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(editor, project);
if (psiFile == null) {
plainEnter(editor, dataContext);
plainEnter(editor, caret, dataContext);
return;
}
if (EnterAfterUnmatchedBraceHandler.isAfterUnmatchedLBrace(editor, caretOffset, psiFile.getFileType())) {
EditorActionHandler enterHandler = EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_ENTER);
enterHandler.execute(editor, dataContext);
enterHandler.execute(editor, caret, dataContext);
return;
}
@@ -100,13 +92,13 @@ public class SmartEnterAction extends EditorAction {
}
}
if (!processed) {
plainEnter(editor, dataContext);
plainEnter(editor, caret, dataContext);
}
}
}
public static void plainEnter(Editor editor, DataContext dataContext) {
getEnterHandler().execute(editor, dataContext);
public static void plainEnter(Editor editor, Caret caret, DataContext dataContext) {
getEnterHandler().execute(editor, caret, dataContext);
}
private static EditorActionHandler getEnterHandler() {

View File

@@ -26,6 +26,7 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
import org.jetbrains.annotations.NotNull;
public class EnterHandler extends BaseEnterHandler {
private final EditorActionHandler myOriginalHandler;
@@ -36,8 +37,8 @@ public class EnterHandler extends BaseEnterHandler {
}
@Override
public boolean isEnabled(Editor editor, DataContext dataContext) {
return myOriginalHandler.isEnabled(editor, dataContext);
public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
return myOriginalHandler.isEnabled(editor, caret, dataContext);
}
@Override

View File

@@ -19,11 +19,13 @@ import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateSettings;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
@@ -32,7 +34,7 @@ public class ExpandLiveTemplateByTabAction extends EditorAction {
public ExpandLiveTemplateByTabAction() {
super(new EditorWriteActionHandler(true) {
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
public void executeWriteAction(Editor editor, @Nullable Caret caret, DataContext dataContext) {
Project project = editor.getProject();
assert project != null;
PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());

View File

@@ -616,7 +616,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
sink.put(OpenFileDescriptor.NAVIGATE_IN_EDITOR, myConsoleEditor);
}
else if (getProject().isInitialized()) {
sink.put(key, FileEditorManagerEx.getInstanceEx(getProject()).getData(key.getName(), myConsoleEditor, myVirtualFile));
sink.put(key, FileEditorManagerEx.getInstanceEx(getProject()).getData(key.getName(), myConsoleEditor, myConsoleEditor.getCaretModel().getCurrentCaret()));
}
}

View File

@@ -35,6 +35,7 @@ import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
@@ -45,18 +46,13 @@ public class SelectWordAtCaretAction extends TextComponentEditorAction implement
setInjectedContext(true);
}
@Override
public EditorActionHandler getHandler() {
return new Handler(super.getHandler());
}
private static class DefaultHandler extends EditorActionHandler {
private DefaultHandler() {
super(true);
}
@Override
public void execute(Editor editor, DataContext dataContext) {
public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
int lineNumber = editor.getCaretModel().getLogicalPosition().line;
int caretOffset = editor.getCaretModel().getOffset();
Document document = editor.getDocument();
@@ -94,23 +90,24 @@ public class SelectWordAtCaretAction extends TextComponentEditorAction implement
}
}
private static class Handler extends EditorActionHandler {
public static class Handler extends EditorActionHandler {
private final EditorActionHandler myDefaultHandler;
private Handler(EditorActionHandler defaultHandler) {
public Handler(EditorActionHandler defaultHandler) {
super(true);
myDefaultHandler = defaultHandler;
}
@Override
public void execute(Editor editor, DataContext dataContext) {
public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
final IndentGuideDescriptor guide = editor.getIndentsModel().getCaretIndentGuide();
final SelectionModel selectionModel = editor.getSelectionModel();
if (guide != null && !selectionModel.hasSelection() && !selectionModel.hasBlockSelection() && isWhitespaceAtCaret(editor)) {
selectWithGuide(editor, guide);
}
else {
myDefaultHandler.execute(editor, dataContext);
myDefaultHandler.execute(editor, caret, dataContext);
}
}

View File

@@ -19,9 +19,12 @@ package com.intellij.openapi.fileEditor.impl.text;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.ide.IdeView;
import com.intellij.ide.util.EditorHelper;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.injected.editor.InjectedCaret;
import com.intellij.lang.Language;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.fileEditor.EditorDataProvider;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
@@ -42,45 +45,64 @@ import static com.intellij.util.containers.ContainerUtil.addIfNotNull;
public class TextEditorPsiDataProvider implements EditorDataProvider {
@Override
@Nullable
public Object getData(@NotNull final String dataId, @NotNull final Editor e, @NotNull final VirtualFile file) {
if (!file.isValid()) return null;
public Object getData(@NotNull final String dataId, @NotNull final Editor e, @NotNull final Caret caret) {
if (!(e instanceof EditorEx)) {
return null;
}
VirtualFile file = ((EditorEx)e).getVirtualFile();
if (file == null || !file.isValid()) return null;
Project project = e.getProject();
if (dataId.equals(injectedId(EDITOR.getName()))) {
if (PsiDocumentManager.getInstance(e.getProject()).isUncommited(e.getDocument())) {
if (project == null || PsiDocumentManager.getInstance(project).isUncommited(e.getDocument())) {
return e;
}
else {
return InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(e, getPsiFile(e, file));
return InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(e, caret, getPsiFile(e, file));
}
}
if (HOST_EDITOR.is(dataId)) {
return e instanceof EditorWindow ? ((EditorWindow)e).getDelegate() : e;
}
if (CARET.is(dataId)) {
return caret;
}
if (dataId.equals(injectedId(CARET.getName()))) {
Editor editor = (Editor)getData(injectedId(EDITOR.getName()), e, caret);
assert editor != null;
return getInjectedCaret(editor, caret);
}
if (dataId.equals(injectedId(PSI_ELEMENT.getName()))) {
return getPsiElementIn((Editor)getData(injectedId(EDITOR.getName()), e, file), file);
Editor editor = (Editor)getData(injectedId(EDITOR.getName()), e, caret);
assert editor != null;
Caret injectedCaret = getInjectedCaret(editor, caret);
return getPsiElementIn(editor, injectedCaret, file);
}
if (PSI_ELEMENT.is(dataId)){
return getPsiElementIn(e, file);
return getPsiElementIn(e, caret, file);
}
if (dataId.equals(injectedId(LANGUAGE.getName()))) {
PsiFile psiFile = (PsiFile)getData(injectedId(PSI_FILE.getName()), e, file);
Editor editor = (Editor)getData(injectedId(EDITOR.getName()), e, file);
PsiFile psiFile = (PsiFile)getData(injectedId(PSI_FILE.getName()), e, caret);
Editor editor = (Editor)getData(injectedId(EDITOR.getName()), e, caret);
if (psiFile == null || editor == null) return null;
return getLanguageAtCurrentPositionInEditor(editor, psiFile);
Caret injectedCaret = getInjectedCaret(editor, caret);
return getLanguageAtCurrentPositionInEditor(injectedCaret, psiFile);
}
if (LANGUAGE.is(dataId)) {
final PsiFile psiFile = getPsiFile(e, file);
if (psiFile == null) return null;
return getLanguageAtCurrentPositionInEditor(e, psiFile);
return getLanguageAtCurrentPositionInEditor(caret, psiFile);
}
if (dataId.equals(injectedId(VIRTUAL_FILE.getName()))) {
PsiFile psiFile = (PsiFile)getData(injectedId(PSI_FILE.getName()), e, file);
PsiFile psiFile = (PsiFile)getData(injectedId(PSI_FILE.getName()), e, caret);
if (psiFile == null) return null;
return psiFile.getVirtualFile();
}
if (dataId.equals(injectedId(PSI_FILE.getName()))) {
Editor editor = (Editor)getData(injectedId(EDITOR.getName()), e, file);
Editor editor = (Editor)getData(injectedId(EDITOR.getName()), e, caret);
if (editor == null) {
return null;
}
final Project project = editor.getProject();
if (project == null) {
return null;
}
@@ -90,7 +112,7 @@ public class TextEditorPsiDataProvider implements EditorDataProvider {
return getPsiFile(e, file);
}
if (IDE_VIEW.is(dataId)) {
final PsiFile psiFile = PsiManager.getInstance(e.getProject()).findFile(file);
final PsiFile psiFile = project == null ? null : PsiManager.getInstance(project).findFile(file);
final PsiDirectory psiDirectory = psiFile != null ? psiFile.getParent() : null;
if (psiDirectory != null && psiDirectory.isPhysical()) {
return new IdeView() {
@@ -117,20 +139,32 @@ public class TextEditorPsiDataProvider implements EditorDataProvider {
}
}
if (CONTEXT_LANGUAGES.is(dataId)) {
return computeLanguages(e, file);
return computeLanguages(e, caret);
}
return null;
}
private static Language getLanguageAtCurrentPositionInEditor(final Editor editor, final PsiFile psiFile) {
final SelectionModel selectionModel = editor.getSelectionModel();
int caretOffset = editor.getCaretModel().getOffset();
int mostProbablyCorrectLanguageOffset = caretOffset == selectionModel.getSelectionStart() ||
caretOffset == selectionModel.getSelectionEnd()
? selectionModel.getSelectionStart()
@NotNull
private static Caret getInjectedCaret(@NotNull Editor editor, @NotNull Caret hostCaret) {
if (!(editor instanceof EditorWindow) || hostCaret instanceof InjectedCaret) {
return hostCaret;
}
for (Caret caret : editor.getCaretModel().getAllCarets()) {
if (((InjectedCaret)caret).getDelegate() == hostCaret) {
return caret;
}
}
throw new IllegalArgumentException("Cannot find injected caret corresponding to " + hostCaret);
}
private static Language getLanguageAtCurrentPositionInEditor(Caret caret, final PsiFile psiFile) {
int caretOffset = caret.getOffset();
int mostProbablyCorrectLanguageOffset = caretOffset == caret.getSelectionStart() ||
caretOffset == caret.getSelectionEnd()
? caret.getSelectionStart()
: caretOffset;
if (selectionModel.hasSelection()) {
return getLanguageAtOffset(psiFile, mostProbablyCorrectLanguageOffset, selectionModel.getSelectionEnd());
if (caret.hasSelection()) {
return getLanguageAtOffset(psiFile, mostProbablyCorrectLanguageOffset, caret.getSelectionEnd());
}
return PsiUtilCore.getLanguageAtOffset(psiFile, mostProbablyCorrectLanguageOffset);
@@ -149,12 +183,13 @@ public class TextEditorPsiDataProvider implements EditorDataProvider {
}
@Nullable
private static PsiElement getPsiElementIn(@NotNull Editor editor, @NotNull VirtualFile file) {
private static PsiElement getPsiElementIn(@NotNull Editor editor, @NotNull Caret caret, @NotNull VirtualFile file) {
final PsiFile psiFile = getPsiFile(editor, file);
if (psiFile == null) return null;
try {
return TargetElementUtilBase.findTargetElement(editor, TargetElementUtilBase.getInstance().getReferenceSearchFlags());
TargetElementUtilBase util = TargetElementUtilBase.getInstance();
return util.findTargetElement(editor, util.getReferenceSearchFlags(), caret.getOffset());
}
catch (IndexNotReadyException e) {
return null;
@@ -174,13 +209,13 @@ public class TextEditorPsiDataProvider implements EditorDataProvider {
return psiFile != null && psiFile.isValid() ? psiFile : null;
}
private Language[] computeLanguages(@NotNull Editor editor, @NotNull VirtualFile file) {
private Language[] computeLanguages(@NotNull Editor editor, @NotNull Caret caret) {
LinkedHashSet<Language> set = new LinkedHashSet<Language>(4);
Language injectedLanguage = (Language)getData(injectedId(LANGUAGE.getName()), editor, file);
Language injectedLanguage = (Language)getData(injectedId(LANGUAGE.getName()), editor, caret);
addIfNotNull(injectedLanguage, set);
Language language = (Language)getData(LANGUAGE.getName(), editor, file);
Language language = (Language)getData(LANGUAGE.getName(), editor, caret);
addIfNotNull(language, set);
PsiFile psiFile = (PsiFile)getData(PSI_FILE.getName(), editor, file);
PsiFile psiFile = (PsiFile)getData(PSI_FILE.getName(), editor, caret);
if (psiFile != null) {
addIfNotNull(psiFile.getViewProvider().getBaseLanguage(), set);
}

View File

@@ -24,7 +24,6 @@ import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
@@ -168,6 +167,13 @@ public class InjectedLanguageUtil {
return getEditorForInjectedLanguageNoCommit(editor, file, offset);
}
public static Editor getEditorForInjectedLanguageNoCommit(@Nullable Editor editor, @Nullable Caret caret, @Nullable PsiFile file) {
if (editor == null || file == null || editor instanceof EditorWindow || caret == null) return editor;
PsiFile injectedFile = findInjectedPsiNoCommit(file, caret.getOffset());
return getInjectedEditorForInjectedFile(editor, caret, injectedFile);
}
public static Caret getCaretForInjectedLanguageNoCommit(@Nullable Caret caret, @Nullable PsiFile file) {
if (caret == null || file == null || caret instanceof InjectedCaret) return caret;
@@ -218,17 +224,21 @@ public class InjectedLanguageUtil {
@NotNull
public static Editor getInjectedEditorForInjectedFile(@NotNull Editor hostEditor, @Nullable final PsiFile injectedFile) {
return getInjectedEditorForInjectedFile(hostEditor, hostEditor.getCaretModel().getCurrentCaret(), injectedFile);
}
@NotNull
public static Editor getInjectedEditorForInjectedFile(@NotNull Editor hostEditor, @NotNull Caret hostCaret, @Nullable final PsiFile injectedFile) {
if (injectedFile == null || hostEditor instanceof EditorWindow || hostEditor.isDisposed()) return hostEditor;
Project project = hostEditor.getProject();
if (project == null) project = injectedFile.getProject();
Document document = PsiDocumentManager.getInstance(project).getDocument(injectedFile);
if (!(document instanceof DocumentWindowImpl)) return hostEditor;
DocumentWindowImpl documentWindow = (DocumentWindowImpl)document;
SelectionModel selectionModel = hostEditor.getSelectionModel();
if (selectionModel.hasSelection()) {
int selstart = selectionModel.getSelectionStart();
if (hostCaret.hasSelection()) {
int selstart = hostCaret.getSelectionStart();
if (selstart != -1) {
int selend = Math.max(selstart, selectionModel.getSelectionEnd());
int selend = Math.max(selstart, hostCaret.getSelectionEnd());
if (!documentWindow.containsRange(selstart, selend)) {
// selection spreads out the injected editor range
return hostEditor;

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.editor.actionSystem;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class CaretSpecificDataContext implements DataContext {
private final DataContext myDelegate;
private final Caret myCaret;
public CaretSpecificDataContext(@NotNull DataContext delegate, @NotNull Caret caret) {
myDelegate = delegate;
myCaret = caret;
}
@Nullable
@Override
public Object getData(@NonNls String dataId) {
Project project = CommonDataKeys.PROJECT.getData(myDelegate);
if (project == null) {
return null;
}
Object data = FileEditorManager.getInstance(project).getData(dataId, myCaret.getEditor(), myCaret);
return data == null ? myDelegate.getData(dataId) : data;
}
}

View File

@@ -26,13 +26,14 @@ import org.jetbrains.annotations.Nullable;
import java.awt.event.KeyEvent;
import static com.intellij.openapi.actionSystem.CommonDataKeys.EDITOR;
import static com.intellij.openapi.actionSystem.CommonDataKeys.PROJECT;
public abstract class EditorAction extends AnAction implements DumbAware {
private EditorActionHandler myHandler;
private boolean myHandlersLoaded;
public EditorActionHandler getHandler() {
public final EditorActionHandler getHandler() {
ensureHandlersLoaded();
return myHandler;
}
@@ -46,6 +47,7 @@ public abstract class EditorAction extends AnAction implements DumbAware {
ensureHandlersLoaded();
EditorActionHandler tmp = myHandler;
myHandler = newHandler;
myHandler.setWorksInInjected(isInInjectedContext());
return tmp;
}
@@ -58,11 +60,21 @@ public abstract class EditorAction extends AnAction implements DumbAware {
final EditorActionHandlerBean handlerBean = extensions[i];
if (handlerBean.action.equals(id)) {
myHandler = handlerBean.getHandler(myHandler);
myHandler.setWorksInInjected(isInInjectedContext());
}
}
}
}
@Override
public void setInjectedContext(boolean worksInInjected) {
super.setInjectedContext(worksInInjected);
// we assume that this method is called in constructor at the point
// where the chain of handlers is not initialized yet
// and it's enough to pass the flag to the default handler only
myHandler.setWorksInInjected(isInInjectedContext());
}
@Override
public final void actionPerformed(AnActionEvent e) {
DataContext dataContext = e.getDataContext();
@@ -72,7 +84,7 @@ public abstract class EditorAction extends AnAction implements DumbAware {
@Nullable
protected Editor getEditor(@NotNull DataContext dataContext) {
return CommonDataKeys.EDITOR.getData(dataContext);
return EDITOR.getData(dataContext);
}
public final void actionPerformed(final Editor editor, @NotNull final DataContext dataContext) {
@@ -102,7 +114,7 @@ public abstract class EditorAction extends AnAction implements DumbAware {
}
public void update(Editor editor, Presentation presentation, DataContext dataContext) {
presentation.setEnabled(getHandler().isEnabled(editor, dataContext));
presentation.setEnabled(getHandler().isEnabled(editor, null, dataContext));
}
public void updateForKeyboardAccess(Editor editor, Presentation presentation, DataContext dataContext) {

View File

@@ -15,7 +15,7 @@
*/
package com.intellij.openapi.editor.actionSystem;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.CaretAction;
import com.intellij.openapi.editor.Editor;
@@ -35,7 +35,9 @@ import org.jetbrains.annotations.Nullable;
*/
public abstract class EditorActionHandler {
private final boolean myRunForEachCaret;
private boolean myWorksInInjected;
private boolean inExecution;
private boolean inCheck;
protected EditorActionHandler() {
this(false);
@@ -46,16 +48,91 @@ public abstract class EditorActionHandler {
}
/**
* Checks if the action handler is currently enabled.
*
* @param editor the editor in which the action is invoked.
* @param dataContext the data context for the action.
* @return true if the action is enabled, false otherwise
* @deprecated Implementations should override
* {@link #isEnabledForCaret(com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.openapi.actionSystem.DataContext)}
* instead,
* client code should invoke
* {@link #isEnabled(com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.openapi.actionSystem.DataContext)}
* instead.
*/
public boolean isEnabled(Editor editor, DataContext dataContext) {
return true;
public boolean isEnabled(Editor editor, final DataContext dataContext) {
if (inCheck) {
return true;
}
inCheck = true;
try {
if (editor == null) {
return false;
}
Editor hostEditor = dataContext == null ? null : CommonDataKeys.HOST_EDITOR.getData(dataContext);
if (hostEditor == null) {
hostEditor = editor;
}
final boolean[] result = new boolean[1];
final CaretTask check = new CaretTask() {
@Override
public void perform(@NotNull Caret caret, @Nullable DataContext dataContext) {
result[0] = true;
}
};
if (myRunForEachCaret) {
hostEditor.getCaretModel().runForEachCaret(new CaretAction() {
@Override
public void perform(Caret caret) {
doIfEnabled(caret, dataContext, check);
}
});
}
else {
doIfEnabled(hostEditor.getCaretModel().getCurrentCaret(), dataContext, check);
}
return result[0];
}
finally {
inCheck = false;
}
}
private void doIfEnabled(@NotNull Caret hostCaret, @Nullable DataContext context, @NotNull CaretTask task) {
DataContext caretContext = context == null ? null : new CaretSpecificDataContext(context, hostCaret);
if (myWorksInInjected && caretContext != null) {
DataContext injectedCaretContext = AnActionEvent.getInjectedDataContext(caretContext);
Caret injectedCaret = CommonDataKeys.CARET.getData(injectedCaretContext);
if (injectedCaret != null && injectedCaret != hostCaret && isEnabledForCaret(injectedCaret.getEditor(), injectedCaret, injectedCaretContext)) {
task.perform(injectedCaret, injectedCaretContext);
return;
}
}
if (isEnabledForCaret(hostCaret.getEditor(), hostCaret, caretContext)) {
task.perform(hostCaret, caretContext);
}
}
/**
* Implementations can override this method to define whether handler is enabled for a specific caret in a given editor.
*/
protected boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
if (inCheck) {
return true;
}
inCheck = true;
try {
//noinspection deprecation
return isEnabled(editor, dataContext);
}
finally {
inCheck = false;
}
}
/**
* If <code>caret</code> is <code>null</code>, checks whether handler is enabled in general (i.e. enabled for at least one caret in editor),
* if <code>caret</code> is not <code>null</code>, checks whether it's enabled for specified caret.
*/
public final boolean isEnabled(@NotNull Editor editor, @Nullable Caret caret, DataContext dataContext) {
//noinspection deprecation
return caret == null ? isEnabled(editor, dataContext) : isEnabledForCaret(editor, caret, dataContext);
}
/**
* @deprecated To implement action logic, override
* {@link #doExecute(com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.openapi.actionSystem.DataContext)},
@@ -112,22 +189,49 @@ public abstract class EditorActionHandler {
* @param editor the editor in which the action is invoked.
* @param dataContext the data context for the action.
*/
public final void execute(@NotNull final Editor editor, @Nullable Caret contextCaret, final DataContext dataContext) {
public final void execute(@NotNull Editor editor, @Nullable final Caret contextCaret, final DataContext dataContext) {
Editor hostEditor = dataContext == null ? null : CommonDataKeys.HOST_EDITOR.getData(dataContext);
if (hostEditor == null) {
hostEditor = editor;
}
if (contextCaret == null && runForAllCarets()) {
editor.getCaretModel().runForEachCaret(new CaretAction() {
hostEditor.getCaretModel().runForEachCaret(new CaretAction() {
@Override
public void perform(Caret caret) {
doExecute(editor, caret, dataContext);
doIfEnabled(caret, dataContext, new CaretTask() {
@Override
public void perform(@NotNull Caret caret, @Nullable DataContext dataContext) {
doExecute(caret.getEditor(), caret, dataContext);
}
});
}
}, true);
}
else {
doExecute(editor, contextCaret, dataContext);
if (contextCaret == null) {
doIfEnabled(hostEditor.getCaretModel().getCurrentCaret(), dataContext, new CaretTask() {
@Override
public void perform(@NotNull Caret caret, @Nullable DataContext dataContext) {
doExecute(caret.getEditor(), null, dataContext);
}
});
}
else {
doExecute(editor, contextCaret, dataContext);
}
}
}
void setWorksInInjected(boolean worksInInjected) {
myWorksInInjected = worksInInjected;
}
public DocCommandGroupId getCommandGroupId(Editor editor) {
// by default avoid merging two consequential commands, and, in the same time, pass along the Document
return DocCommandGroupId.noneGroupId(editor.getDocument());
}
private interface CaretTask {
void perform(@NotNull Caret caret, @Nullable DataContext dataContext);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,14 +15,14 @@
*/
package com.intellij.openapi.fileEditor;
import com.intellij.openapi.editor.Caret;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.vfs.VirtualFile;
/**
* @author peter
*/
public interface EditorDataProvider {
@Nullable Object getData(@NotNull String dataId, @NotNull Editor e, @NotNull VirtualFile file);
@Nullable Object getData(@NotNull String dataId, @NotNull Editor e, @NotNull Caret caret);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package com.intellij.openapi.fileEditor;
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.Key;
@@ -183,6 +184,13 @@ public abstract class FileEditorManager {
public abstract void registerExtraEditorDataProvider(@NotNull EditorDataProvider provider, Disposable parentDisposable);
/**
* Returns data associated with given editor/caret context. Data providers are registered via
* {@link #registerExtraEditorDataProvider(EditorDataProvider, com.intellij.openapi.Disposable)} method.
*/
@Nullable
public abstract Object getData(@NotNull String dataId, @NotNull Editor editor, @NotNull Caret caret);
/**
* Selects a specified file editor tab for the specified editor.
* @param file a file to switch the file editor tab for. The function does nothing if the file is not currently open in the editor.

View File

@@ -30,6 +30,8 @@ import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.util.ui.MacUIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class EnterAction extends EditorAction {
public EnterAction() {
@@ -43,13 +45,13 @@ public class EnterAction extends EditorAction {
}
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
public void executeWriteAction(Editor editor, @Nullable Caret caret, DataContext dataContext) {
CommandProcessor.getInstance().setCurrentCommandName(EditorBundle.message("typing.command.name"));
insertNewLineAtCaret(editor);
}
@Override
public boolean isEnabled(Editor editor, DataContext dataContext) {
public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
return !editor.isOneLineMode();
}
}

View File

@@ -57,7 +57,7 @@ public class IndentSelectionAction extends EditorAction {
@Override
public void executeWriteAction(Editor editor, @Nullable Caret caret, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (isEnabled(editor, dataContext)) {
if (isEnabled(editor, caret, dataContext)) {
indentSelection(editor, project);
}
}

View File

@@ -18,10 +18,7 @@ package com.intellij.openapi.editor.actions;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
@@ -30,6 +27,7 @@ import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.util.Key;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;
/**
* @author max
@@ -48,13 +46,13 @@ public class SplitLineAction extends EditorAction {
}
@Override
public boolean isEnabled(Editor editor, DataContext dataContext) {
return getEnterHandler().isEnabled(editor, dataContext) &&
public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
return getEnterHandler().isEnabled(editor, caret, dataContext) &&
!((EditorEx)editor).isEmbeddedIntoDialogWrapper();
}
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
public void executeWriteAction(Editor editor, Caret caret, DataContext dataContext) {
CopyPasteManager.getInstance().stopKillRings();
final Document document = editor.getDocument();
final RangeMarker rangeMarker =
@@ -77,7 +75,7 @@ public class SplitLineAction extends EditorAction {
} else {
DataManager.getInstance().saveInDataContext(dataContext, SPLIT_LINE_KEY, true);
try {
getEnterHandler().execute(editor, dataContext);
getEnterHandler().execute(editor, caret, dataContext);
}
finally {
DataManager.getInstance().saveInDataContext(dataContext, SPLIT_LINE_KEY, null);

View File

@@ -17,6 +17,7 @@ package com.intellij.openapi.editor.actions;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.actionSystem.EditorAction;
@@ -24,6 +25,7 @@ import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.openapi.ide.CopyPasteManager;
import org.jetbrains.annotations.NotNull;
/**
* @author max
@@ -39,12 +41,12 @@ public class StartNewLineAction extends EditorAction {
}
@Override
public boolean isEnabled(Editor editor, DataContext dataContext) {
return getEnterHandler().isEnabled(editor, dataContext);
public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
return getEnterHandler().isEnabled(editor, caret, dataContext);
}
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
public void executeWriteAction(Editor editor, Caret caret, DataContext dataContext) {
CopyPasteManager.getInstance().stopKillRings();
if (editor.getDocument().getLineCount() != 0) {
editor.getSelectionModel().removeSelection();
@@ -53,7 +55,7 @@ public class StartNewLineAction extends EditorAction {
editor.getCaretModel().moveToOffset(lineEndOffset);
}
getEnterHandler().execute(editor, dataContext);
getEnterHandler().execute(editor, caret, dataContext);
}
private static EditorActionHandler getEnterHandler() {

View File

@@ -42,8 +42,8 @@ public class StartNewLineBeforeAction extends EditorAction {
}
@Override
public boolean isEnabled(Editor editor, DataContext dataContext) {
return getHandler(IdeActions.ACTION_EDITOR_ENTER).isEnabled(editor, dataContext);
public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
return getHandler(IdeActions.ACTION_EDITOR_ENTER).isEnabled(editor, caret, dataContext);
}
@Override

View File

@@ -24,11 +24,13 @@
*/
package com.intellij.openapi.editor.actions;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.project.DumbAware;
import org.jetbrains.annotations.Nullable;
public class UnselectWordAtCaretAction extends EditorAction implements DumbAware {
public UnselectWordAtCaretAction() {
@@ -42,7 +44,7 @@ public class UnselectWordAtCaretAction extends EditorAction implements DumbAware
}
@Override
public void execute(Editor editor, DataContext dataContext) {
public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package com.intellij.openapi.fileEditor.ex;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.EditorDataProvider;
import com.intellij.openapi.fileEditor.FileEditor;
@@ -164,9 +165,9 @@ public abstract class FileEditorManagerEx extends FileEditorManager implements B
public abstract boolean isInsideChange();
@Nullable
public final Object getData(@NotNull String dataId, @NotNull Editor editor, @NotNull VirtualFile file) {
public final Object getData(@NotNull String dataId, @NotNull Editor editor, @NotNull Caret caret) {
for (final EditorDataProvider dataProvider : myDataProviders) {
final Object o = dataProvider.getData(dataId, editor, file);
final Object o = dataProvider.getData(dataId, editor, caret);
if (o != null) return o;
}
return null;

View File

@@ -36,7 +36,6 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.impl.EditorHistoryManager;
import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
import com.intellij.openapi.fileTypes.FileTypeEvent;
import com.intellij.openapi.fileTypes.FileTypeListener;
import com.intellij.openapi.fileTypes.FileTypeManager;
@@ -278,7 +277,7 @@ class TextEditorComponent extends JBLoadingPanel implements DataProvider {
if (e == null) return null;
if (!myProject.isDisposed()) {
final Object o = ((FileEditorManagerImpl)FileEditorManager.getInstance(myProject)).getData(dataId, e, myFile);
final Object o = FileEditorManager.getInstance(myProject).getData(dataId, e, e.getCaretModel().getCurrentCaret());
if (o != null) return o;
}

View File

@@ -652,6 +652,7 @@
<editorActionHandler action="EditorEnter" implementationClass="com.intellij.codeInsight.editorActions.EnterHandler" id="editorEnter"/>
<editorActionHandler action="EditorLineEnd" implementationClass="com.intellij.codeInsight.editorActions.EndHandler"/>
<editorActionHandler action="EditorSelectWord" implementationClass="com.intellij.codeInsight.editorActions.SelectWordHandler"/>
<editorActionHandler action="EditorSelectWord" implementationClass="com.intellij.openapi.editor.actions.SelectWordAtCaretAction$Handler" order="first"/>
<editorActionHandler action="EditorUnSelectWord" implementationClass="com.intellij.codeInsight.editorActions.UnSelectWordHandler"/>
<editorActionHandler action="EditorPaste" implementationClass="com.intellij.codeInsight.editorActions.PasteHandler"/>
<editorActionHandler action="EditorCopy" implementationClass="com.intellij.codeInsight.editorActions.CopyHandler"/>

View File

@@ -23,7 +23,6 @@ import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.actionSystem.TypedAction;
import com.intellij.openapi.editor.ex.EditorEx;
@@ -46,7 +45,6 @@ import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.junit.Assert;
import java.awt.*;
import java.util.ArrayList;
@@ -73,40 +71,45 @@ public class EditorTestUtil {
public static void performTypingAction(Editor editor, char c) {
EditorActionManager actionManager = EditorActionManager.getInstance();
if (c == BACKSPACE_FAKE_CHAR) {
EditorActionHandler actionHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_BACKSPACE);
actionHandler.execute(editor, DataManager.getInstance().getDataContext());
executeAction(editor, IdeActions.ACTION_EDITOR_BACKSPACE);
} else if (c == SMART_ENTER_FAKE_CHAR) {
EditorActionHandler actionHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_COMPLETE_STATEMENT);
actionHandler.execute(editor, DataManager.getInstance().getDataContext());
executeAction(editor, IdeActions.ACTION_EDITOR_COMPLETE_STATEMENT);
} else if (c == SMART_LINE_SPLIT_CHAR) {
EditorActionHandler actionHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_SPLIT);
actionHandler.execute(editor, DataManager.getInstance().getDataContext());
executeAction(editor, IdeActions.ACTION_EDITOR_SPLIT);
}
else if (c == '\n') {
EditorActionHandler actionHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_ENTER);
actionHandler.execute(editor, DataManager.getInstance().getDataContext());
executeAction(editor, IdeActions.ACTION_EDITOR_ENTER);
}
else {
TypedAction action = actionManager.getTypedAction();
action.actionPerformed(editor, c, DataManager.getInstance().getDataContext());
action.actionPerformed(editor, c, DataManager.getInstance().getDataContext(editor.getContentComponent()));
}
}
public static void performReferenceCopy(DataContext dataContext) {
public static void executeAction(Editor editor, String actionId) {
executeAction(editor, actionId, false);
}
public static void executeAction(Editor editor, String actionId, boolean assertActionIsEnabled) {
ActionManager actionManager = ActionManager.getInstance();
AnAction action = actionManager.getAction(IdeActions.ACTION_COPY_REFERENCE);
AnActionEvent
event = new AnActionEvent(null, dataContext, "", action.getTemplatePresentation(),
ActionManager.getInstance(), 0);
action.update(event);
Assert.assertTrue(event.getPresentation().isEnabled());
AnAction action = actionManager.getAction(actionId);
assertNotNull(action);
DataContext dataContext = DataManager.getInstance().getDataContext(editor.getContentComponent());
AnActionEvent event = new AnActionEvent(null, dataContext, "", action.getTemplatePresentation(), actionManager, 0);
action.beforeActionPerformedUpdate(event);
if (!event.getPresentation().isEnabled()) {
assertFalse("Action " + actionId + " is disabled", assertActionIsEnabled);
return;
}
action.actionPerformed(event);
}
public static void performReferenceCopy(Editor editor) {
executeAction(editor, IdeActions.ACTION_COPY_REFERENCE, true);
}
public static void performPaste(Editor editor) {
EditorActionManager actionManager = EditorActionManager.getInstance();
EditorActionHandler actionHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_PASTE);
actionHandler.execute(editor, null, DataManager.getInstance().getDataContext());
executeAction(editor, IdeActions.ACTION_EDITOR_PASTE, true);
}
public static List<IElementType> getAllTokens(EditorHighlighter highlighter) {

View File

@@ -19,10 +19,7 @@ import com.intellij.codeInsight.generation.actions.CommentByLineCommentAction;
import com.intellij.ide.DataManager;
import com.intellij.injected.editor.DocumentWindow;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.ex.PathManagerEx;
@@ -353,24 +350,6 @@ public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTest
return userMessage + " [" + engineMessage + "]";
}
@Override
public Object getData(String dataId) {
if (CommonDataKeys.EDITOR.is(dataId)) {
return myEditor;
}
if (dataId.equals(AnActionEvent.injectedId(CommonDataKeys.EDITOR.getName()))) {
return InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(getEditor(), getFile());
}
if (CommonDataKeys.PSI_FILE.is(dataId)) {
return myFile;
}
if (dataId.equals(AnActionEvent.injectedId(CommonDataKeys.PSI_FILE.getName()))) {
Editor editor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(getEditor(), getFile());
return editor instanceof EditorWindow ? ((EditorWindow)editor).getInjectedFile() : getFile();
}
return super.getData(dataId);
}
/**
* @return Editor used in test.
*/
@@ -508,9 +487,7 @@ public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTest
CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
@Override
public void run() {
EditorActionManager actionManager = EditorActionManager.getInstance();
EditorActionHandler actionHandler = actionManager.getActionHandler(actionId);
actionHandler.execute(getEditor(), null, DataManager.getInstance().getDataContext());
EditorTestUtil.executeAction(getEditor(), actionId);
}
}, "", null);
}

View File

@@ -722,10 +722,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
@Override
public Object getData(String dataId) {
if (CommonDataKeys.PROJECT.is(dataId)) {
return ourProject;
}
return null;
return ourProject == null || ourProject.isDisposed() ? null : new TestDataProvider(ourProject).getData(dataId);
}
protected Sdk getProjectJDK() {

View File

@@ -20,7 +20,6 @@ import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.impl.EditorComponentImpl;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
@@ -50,18 +49,21 @@ public class TestDataProvider implements DataProvider {
if (CommonDataKeys.PROJECT.is(dataId)) {
return myProject;
}
else if (CommonDataKeys.EDITOR.is(dataId) || OpenFileDescriptor.NAVIGATE_IN_EDITOR.is(dataId)) {
return FileEditorManager.getInstance(myProject).getSelectedTextEditor();
FileEditorManagerEx manager = FileEditorManagerEx.getInstanceEx(myProject);
if (manager == null) {
return null;
}
if (CommonDataKeys.EDITOR.is(dataId) || OpenFileDescriptor.NAVIGATE_IN_EDITOR.is(dataId)) {
return manager.getSelectedTextEditor();
}
else if (PlatformDataKeys.FILE_EDITOR.is(dataId)) {
Editor editor = FileEditorManager.getInstance(myProject).getSelectedTextEditor();
Editor editor = manager.getSelectedTextEditor();
return editor == null ? null : TextEditorProvider.getInstance().getTextEditor(editor);
}
else {
Editor editor = (Editor)getData(CommonDataKeys.EDITOR.getName());
if (editor != null) {
FileEditorManagerEx manager = FileEditorManagerEx.getInstanceEx(myProject);
Object managerData = manager.getData(dataId, editor, manager.getSelectedFiles()[0]);
Object managerData = manager.getData(dataId, editor, editor.getCaretModel().getCurrentCaret());
if (managerData != null) {
return managerData;
}

View File

@@ -205,7 +205,7 @@ class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTestFixtu
Editor editor = (Editor)getData(CommonDataKeys.EDITOR.getName());
if (editor != null) {
FileEditorManagerEx manager = FileEditorManagerEx.getInstanceEx(myProject);
return manager.getData(dataId, editor, manager.getSelectedFiles()[0]);
return manager.getData(dataId, editor, editor.getCaretModel().getCurrentCaret());
}
else if (LangDataKeys.IDE_VIEW.is(dataId)) {
VirtualFile[] contentRoots = ProjectRootManager.getInstance(myProject).getContentRoots();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -102,11 +102,7 @@ public class RenameTo extends ShowSuggestions implements SpellCheckerQuickFix {
} else if (ApplicationManager.getApplication().isUnitTestMode()) { // TextEditorComponent / FiledEditorManagerImpl give away the data in real life
map.put(
CommonDataKeys.PSI_ELEMENT.getName(),
new TextEditorPsiDataProvider().getData(
CommonDataKeys.PSI_ELEMENT.getName(),
editor,
containingFile.getVirtualFile()
)
new TextEditorPsiDataProvider().getData(CommonDataKeys.PSI_ELEMENT.getName(), editor, editor.getCaretModel().getCurrentCaret())
);
}