diff --git a/platform/lang-api/src/com/intellij/openapi/actionSystem/LangDataKeys.java b/platform/lang-api/src/com/intellij/openapi/actionSystem/LangDataKeys.java index 80bb6c7ad69c..f590c003e872 100644 --- a/platform/lang-api/src/com/intellij/openapi/actionSystem/LangDataKeys.java +++ b/platform/lang-api/src/com/intellij/openapi/actionSystem/LangDataKeys.java @@ -39,6 +39,7 @@ public class LangDataKeys extends PlatformDataKeys { public static final DataKey PSI_ELEMENT = DataKey.create("psi.Element"); public static final DataKey PSI_FILE = DataKey.create("psi.File"); public static final DataKey LANGUAGE = DataKey.create("Language"); + public static final DataKey CONTEXT_LANGUAGES = DataKey.create("context.Languages"); public static final DataKey PSI_ELEMENT_ARRAY = DataKey.create("psi.Element.array"); /** diff --git a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorPsiDataProvider.java b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorPsiDataProvider.java index ef263c58b789..a4d2f5012b6f 100644 --- a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorPsiDataProvider.java +++ b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorPsiDataProvider.java @@ -20,9 +20,6 @@ import com.intellij.codeInsight.TargetElementUtilBase; import com.intellij.ide.IdeView; import com.intellij.ide.util.EditorHelper; import com.intellij.lang.Language; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.LangDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.fileEditor.EditorDataProvider; @@ -35,12 +32,18 @@ import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.PsiUtilBase; import org.jetbrains.annotations.Nullable; +import java.util.LinkedHashSet; + +import static com.intellij.openapi.actionSystem.AnActionEvent.injectedId; +import static com.intellij.openapi.actionSystem.LangDataKeys.*; +import static com.intellij.util.containers.ContainerUtil.addIfNotNull; + public class TextEditorPsiDataProvider implements EditorDataProvider { @Nullable public Object getData(final String dataId, final Editor e, final VirtualFile file) { if (!file.isValid()) return null; - if (dataId.equals(AnActionEvent.injectedId(PlatformDataKeys.EDITOR.getName()))) { + if (dataId.equals(injectedId(EDITOR.getName()))) { if (PsiDocumentManager.getInstance(e.getProject()).isUncommited(e.getDocument())) { return e; } @@ -48,30 +51,30 @@ public class TextEditorPsiDataProvider implements EditorDataProvider { return InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(e, getPsiFile(e, file)); } } - if (dataId.equals(AnActionEvent.injectedId(LangDataKeys.PSI_ELEMENT.getName()))) { - return getPsiElementIn((Editor)getData(AnActionEvent.injectedId(PlatformDataKeys.EDITOR.getName()), e, file), file); + if (dataId.equals(injectedId(PSI_ELEMENT.getName()))) { + return getPsiElementIn((Editor)getData(injectedId(EDITOR.getName()), e, file), file); } - if (LangDataKeys.PSI_ELEMENT.is(dataId)){ + if (PSI_ELEMENT.is(dataId)){ return getPsiElementIn(e, file); } - if (dataId.equals(AnActionEvent.injectedId(LangDataKeys.LANGUAGE.getName()))) { - PsiFile psiFile = (PsiFile)getData(AnActionEvent.injectedId(LangDataKeys.PSI_FILE.getName()), e, file); - Editor editor = (Editor)getData(AnActionEvent.injectedId(PlatformDataKeys.EDITOR.getName()), e, 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); if (psiFile == null || editor == null) return null; return getLanguageAtCurrentPositionInEditor(editor, psiFile); } - if (LangDataKeys.LANGUAGE.is(dataId)) { + if (LANGUAGE.is(dataId)) { final PsiFile psiFile = getPsiFile(e, file); if (psiFile == null) return null; return getLanguageAtCurrentPositionInEditor(e, psiFile); } - if (dataId.equals(AnActionEvent.injectedId(PlatformDataKeys.VIRTUAL_FILE.getName()))) { - PsiFile psiFile = (PsiFile)getData(AnActionEvent.injectedId(LangDataKeys.PSI_FILE.getName()), e, file); + if (dataId.equals(injectedId(VIRTUAL_FILE.getName()))) { + PsiFile psiFile = (PsiFile)getData(injectedId(PSI_FILE.getName()), e, file); if (psiFile == null) return null; return psiFile.getVirtualFile(); } - if (dataId.equals(AnActionEvent.injectedId(LangDataKeys.PSI_FILE.getName()))) { - Editor editor = (Editor)getData(AnActionEvent.injectedId(PlatformDataKeys.EDITOR.getName()), e, file); + if (dataId.equals(injectedId(PSI_FILE.getName()))) { + Editor editor = (Editor)getData(injectedId(EDITOR.getName()), e, file); if (editor == null) { return null; } @@ -81,10 +84,10 @@ public class TextEditorPsiDataProvider implements EditorDataProvider { } return PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); } - if (LangDataKeys.PSI_FILE.is(dataId)) { + if (PSI_FILE.is(dataId)) { return getPsiFile(e, file); } - if (LangDataKeys.IDE_VIEW.is(dataId)) { + if (IDE_VIEW.is(dataId)) { final PsiFile psiFile = PsiManager.getInstance(e.getProject()).findFile(file); final PsiDirectory psiDirectory = psiFile != null ? psiFile.getParent() : null; if (psiDirectory != null && psiDirectory.isPhysical()) { @@ -107,18 +110,25 @@ public class TextEditorPsiDataProvider implements EditorDataProvider { }; } } + if (CONTEXT_LANGUAGES.is(dataId)) { + return computeLanguages(e, file); + } return null; } private static Language getLanguageAtCurrentPositionInEditor(final Editor editor, final PsiFile psiFile) { + int mostProbablyCorrectLanguageOffset = getOffset(editor); + + return PsiUtilBase.getLanguageAtOffset(psiFile, mostProbablyCorrectLanguageOffset); + } + + private static int getOffset(Editor editor) { final SelectionModel selectionModel = editor.getSelectionModel(); int caretOffset = editor.getCaretModel().getOffset(); - int mostProbablyCorrectLanguageOffset = caretOffset == selectionModel.getSelectionStart() || + return caretOffset == selectionModel.getSelectionStart() || caretOffset == selectionModel.getSelectionEnd() ? selectionModel.getSelectionStart() : caretOffset; - - return PsiUtilBase.getLanguageAtOffset(psiFile, mostProbablyCorrectLanguageOffset); } @Nullable @@ -134,6 +144,7 @@ public class TextEditorPsiDataProvider implements EditorDataProvider { } } + @Nullable private static PsiFile getPsiFile(Editor e, VirtualFile file) { if (!file.isValid()) { return null; // fix for SCR 40329 @@ -145,4 +156,17 @@ public class TextEditorPsiDataProvider implements EditorDataProvider { PsiFile psiFile = PsiManager.getInstance(project).findFile(file); return psiFile != null && psiFile.isValid() ? psiFile : null; } + + private Language[] computeLanguages(Editor editor, VirtualFile file) { + LinkedHashSet set = new LinkedHashSet(4); + Language injectedLanguage = (Language)getData(injectedId(LANGUAGE.getName()), editor, file); + addIfNotNull(injectedLanguage, set); + Language language = (Language)getData(LANGUAGE.getName(), editor, file); + addIfNotNull(language, set); + PsiFile psiFile = (PsiFile)getData(PSI_FILE.getName(), editor, file); + if (psiFile != null) { + addIfNotNull(psiFile.getViewProvider().getBaseLanguage(), set); + } + return set.toArray(new Language[set.size()]); + } } diff --git a/platform/lang-impl/src/com/intellij/refactoring/actions/BasePlatformRefactoringAction.java b/platform/lang-impl/src/com/intellij/refactoring/actions/BasePlatformRefactoringAction.java index f97d7f6c8b61..b44edd6d7e0e 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/actions/BasePlatformRefactoringAction.java +++ b/platform/lang-impl/src/com/intellij/refactoring/actions/BasePlatformRefactoringAction.java @@ -49,16 +49,18 @@ public abstract class BasePlatformRefactoringAction extends BaseRefactoringActio @Override protected final RefactoringActionHandler getHandler(DataContext dataContext) { - final Language language = LangDataKeys.LANGUAGE.getData(dataContext); - if (language != null) { - List providers = LanguageRefactoringSupport.INSTANCE.allForLanguage(language); - if (providers.isEmpty()) return null; - if (providers.size() == 1) return getRefactoringHandler(providers.get(0)); - PsiElement element = LangDataKeys.PSI_ELEMENT.getData(dataContext); - if (element != null) { - for (RefactoringSupportProvider provider : providers) { - if (provider.isAvailable(element)) { - return getRefactoringHandler(provider); + final Language[] languages = LangDataKeys.CONTEXT_LANGUAGES.getData(dataContext); + if (languages != null) { + for (Language language : languages) { + List providers = LanguageRefactoringSupport.INSTANCE.allForLanguage(language); + if (providers.isEmpty()) continue; + if (providers.size() == 1) return getRefactoringHandler(providers.get(0)); + PsiElement element = LangDataKeys.PSI_ELEMENT.getData(dataContext); + if (element != null) { + for (RefactoringSupportProvider provider : providers) { + if (provider.isAvailable(element)) { + return getRefactoringHandler(provider); + } } } } diff --git a/platform/lang-impl/src/com/intellij/refactoring/actions/BaseRefactoringAction.java b/platform/lang-impl/src/com/intellij/refactoring/actions/BaseRefactoringAction.java index fcf17565f948..8c4f104a413e 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/actions/BaseRefactoringAction.java +++ b/platform/lang-impl/src/com/intellij/refactoring/actions/BaseRefactoringAction.java @@ -23,11 +23,12 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; import com.intellij.psi.*; -import com.intellij.psi.util.PsiUtilBase; import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.util.CommonRefactoringUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -36,6 +37,13 @@ import java.util.Arrays; import java.util.List; public abstract class BaseRefactoringAction extends AnAction { + private final Condition myLanguageCondition = new Condition() { + @Override + public boolean value(Language language) { + return isAvailableForLanguage(language); + } + }; + protected abstract boolean isAvailableInEditorOnly(); protected abstract boolean isEnabledOnElements(PsiElement[] elements); @@ -117,9 +125,13 @@ public abstract class BaseRefactoringAction extends AnAction { } element = getElementAtCaret(editor, file); } - boolean isVisible = element != null && - !(element instanceof SyntheticElement) && - isAvailableForLanguage(PsiUtilBase.getLanguageInEditor(editor, project)); + Language[] languages = e.getData(LangDataKeys.CONTEXT_LANGUAGES); + if (element == null || element instanceof SyntheticElement || languages == null) { + hideAction(e); + return; + } + + boolean isVisible = ContainerUtil.find(languages, myLanguageCondition) != null; if (isVisible) { boolean isEnabled = isAvailableOnElementInEditorAndFile(element, editor, file); if (!isEnabled) {