context languages

This commit is contained in:
Dmitry Avdeev
2010-08-18 15:22:55 +04:00
parent c4d28fafbc
commit ddea097460
4 changed files with 73 additions and 34 deletions
@@ -39,6 +39,7 @@ public class LangDataKeys extends PlatformDataKeys {
public static final DataKey<PsiElement> PSI_ELEMENT = DataKey.create("psi.Element");
public static final DataKey<PsiFile> PSI_FILE = DataKey.create("psi.File");
public static final DataKey<Language> LANGUAGE = DataKey.create("Language");
public static final DataKey<Language[]> CONTEXT_LANGUAGES = DataKey.create("context.Languages");
public static final DataKey<PsiElement[]> PSI_ELEMENT_ARRAY = DataKey.create("psi.Element.array");
/**
@@ -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<Language> set = new LinkedHashSet<Language>(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()]);
}
}
@@ -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<RefactoringSupportProvider> 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<RefactoringSupportProvider> 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);
}
}
}
}
@@ -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<Language> myLanguageCondition = new Condition<Language>() {
@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) {