diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SelectInAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SelectInAction.java index 30aae28bdffe..6b1abbeea64a 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/SelectInAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/SelectInAction.java @@ -29,6 +29,7 @@ import com.intellij.openapi.ui.popup.util.BaseListPopupStep; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.psi.PsiDocumentManager; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -82,15 +83,12 @@ public class SelectInAction extends AnAction implements DumbAware { } private static class SelectInActionsStep extends BaseListPopupStep { - @NotNull private final SelectInContext mySelectInContext; + private final SelectInContext mySelectInContext; private final List myVisibleTargets; public SelectInActionsStep(@NotNull final Collection targetVector, @NotNull SelectInContext selectInContext) { mySelectInContext = selectInContext; - myVisibleTargets = new ArrayList<>(); - for (SelectInTarget target : targetVector) { - myVisibleTargets.add(target); - } + myVisibleTargets = ContainerUtil.newArrayList(targetVector); init(IdeBundle.message("title.popup.select.target"), myVisibleTargets, null); } diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SelectInContextImpl.java b/platform/lang-impl/src/com/intellij/ide/actions/SelectInContextImpl.java index 922c5bee0ebe..2a971a38d2fa 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/SelectInContextImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/SelectInContextImpl.java @@ -18,6 +18,8 @@ package com.intellij.ide.actions; import com.intellij.codeInsight.TargetElementUtil; import com.intellij.ide.FileEditorProvider; +import com.intellij.ide.FileEditorSelectInContext; +import com.intellij.ide.FileSelectInContext; import com.intellij.ide.SelectInContext; import com.intellij.ide.structureView.StructureView; import com.intellij.ide.structureView.StructureViewBuilder; @@ -44,13 +46,16 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.awt.*; import java.awt.event.InputEvent; -public abstract class SelectInContextImpl implements SelectInContext { - protected final PsiFile myPsiFile; +public class SelectInContextImpl implements SelectInContext { + private final PsiFile myPsiFile; + private final Object mySelector; - protected SelectInContextImpl(PsiFile psiFile) { + private SelectInContextImpl(@NotNull PsiFile psiFile, @Nullable Object selector) { myPsiFile = psiFile; + mySelector = selector; } @Override @@ -68,14 +73,27 @@ public abstract class SelectInContextImpl implements SelectInContext { @Override public Object getSelectorInFile() { - return myPsiFile; + return ObjectUtils.notNull(mySelector, myPsiFile); + } + + @Nullable + @Override + public FileEditorProvider getFileEditorProvider() { + return new FileEditorProvider() { + @Override + public FileEditor openFileEditor() { + return ArrayUtil.getFirstElement(FileEditorManager.getInstance(getProject()).openFile(getVirtualFile(), false)); + } + }; } @Nullable public static SelectInContext createContext(AnActionEvent event) { - DataContext dataContext = event.getDataContext(); + Project project = event.getProject(); + FileEditor editor = event.getData(PlatformDataKeys.FILE_EDITOR); + VirtualFile virtualFile = event.getData(CommonDataKeys.VIRTUAL_FILE); - SelectInContext result = createEditorContext(dataContext); + SelectInContext result = createEditorContext(project, editor, virtualFile); if (result != null) { return result; } @@ -85,68 +103,89 @@ public abstract class SelectInContextImpl implements SelectInContext { return null; } - SelectInContext selectInContext = SelectInContext.DATA_KEY.getData(dataContext); - if (selectInContext == null) { - selectInContext = createPsiContext(event); + result = event.getData(SelectInContext.DATA_KEY); + if (result != null) { + return result; } - if (selectInContext == null) { - Navigatable descriptor = CommonDataKeys.NAVIGATABLE.getData(dataContext); - if (descriptor instanceof OpenFileDescriptor) { - final VirtualFile file = ((OpenFileDescriptor)descriptor).getFile(); - if (file.isValid()) { - Project project = CommonDataKeys.PROJECT.getData(dataContext); - selectInContext = OpenFileDescriptorContext.create(project, file); - } - } + result = createPsiContext(event); + if (result != null) { + return result; } - if (selectInContext == null) { - VirtualFile virtualFile = CommonDataKeys.VIRTUAL_FILE.getData(dataContext); - Project project = CommonDataKeys.PROJECT.getData(dataContext); - if (virtualFile != null && project != null) { - return new VirtualFileSelectInContext(project, virtualFile); - } + Navigatable descriptor = event.getData(CommonDataKeys.NAVIGATABLE); + result = descriptor instanceof OpenFileDescriptor ? createDescriptorContext((OpenFileDescriptor)descriptor) : null; + if (result != null) { + return result; } - return selectInContext; + if (virtualFile != null && project != null) { + return new FileSelectInContext(project, virtualFile); + } + + return null; } @Nullable - private static SelectInContext createEditorContext(DataContext dataContext) { - final Project project = CommonDataKeys.PROJECT.getData(dataContext); - final FileEditor editor = PlatformDataKeys.FILE_EDITOR.getData(dataContext); - return doCreateEditorContext(project, editor, dataContext); + private static SelectInContext createDescriptorContext(OpenFileDescriptor descriptor) { + VirtualFile file = descriptor.getFile(); + Document document = !file.isValid() ? null : FileDocumentManager.getInstance().getDocument(file); + if (document == null) return null; + PsiFile psiFile = PsiDocumentManager.getInstance(descriptor.getProject()).getPsiFile(document); + if (psiFile == null) return null; + return new SelectInContextImpl(psiFile, null) { + @Override + public FileEditorProvider getFileEditorProvider() { + return new FileEditorProvider() { + @Override + public FileEditor openFileEditor() { + descriptor.navigate(false); + FileEditor[] allEditors = FileEditorManager.getInstance(descriptor.getProject()).getAllEditors(descriptor.getFile()); + return ArrayUtil.getFirstElement(allEditors); + } + }; + } + }; } - public static SelectInContext createEditorContext(Project project, FileEditor editor) { - return doCreateEditorContext(project, editor, null); - } - - private static SelectInContext doCreateEditorContext(Project project, FileEditor editor, @Nullable DataContext dataContext) { + private static SelectInContext createEditorContext(@Nullable Project project, + @Nullable FileEditor editor, + @Nullable VirtualFile contextFile) { if (project == null || editor == null) { return null; } + VirtualFile file = FileEditorManagerEx.getInstanceEx(project).getFile(editor); if (file == null) { - file = dataContext == null ? null : CommonDataKeys.VIRTUAL_FILE.getData(dataContext); - if (file == null) { - return null; - } + file = contextFile; } - final PsiFile psiFile = PsiManager.getInstance(project).findFile(file); + + PsiFile psiFile = file == null ? null : PsiManager.getInstance(project).findFile(file); if (psiFile == null) { return null; } + if (editor instanceof TextEditor) { - return new TextEditorContext((TextEditor)editor, psiFile); + return new FileEditorSelectInContext(editor, psiFile) { + @Override + public Object getSelectorInFile() { + PsiFile file = getPsiFile(); + if (file.getViewProvider() instanceof TemplateLanguageFileViewProvider) { + return super.getSelectorInFile(); + } + Editor editor = ((TextEditor)getFileEditor()).getEditor(); + int offset = TargetElementUtil.adjustOffset(file, editor.getDocument(), editor.getCaretModel().getOffset()); + PsiElement element = file.findElementAt(offset); + return element != null ? element : super.getSelectorInFile(); + } + }; } else { StructureViewBuilder builder = editor.getStructureViewBuilder(); StructureView structureView = builder != null ? builder.createStructureView(editor, project) : null; Object selectorInFile = structureView != null ? structureView.getTreeModel().getCurrentEditorElement() : null; if (structureView != null) Disposer.dispose(structureView); - return new SimpleSelectInContext(psiFile, ObjectUtils.chooseNotNull(selectorInFile, psiFile)); + return new SelectInContextImpl(psiFile, ObjectUtils.chooseNotNull(selectorInFile, psiFile)); } } @@ -161,7 +200,7 @@ public abstract class SelectInContextImpl implements SelectInContext { if (psiFile == null) { return null; } - return new SimpleSelectInContext(psiFile, psiElement); + return new SelectInContextImpl(psiFile, psiElement); } @Nullable @@ -172,132 +211,8 @@ public abstract class SelectInContextImpl implements SelectInContext { return (JComponent)source; } else { - return safeCast(PlatformDataKeys.CONTEXT_COMPONENT.getData(event.getDataContext()), JComponent.class); - } - } - - @Nullable - @SuppressWarnings({"unchecked"}) - private static T safeCast(final Object obj, final Class expectedClass) { - if (expectedClass.isInstance(obj)) return (T)obj; - return null; - } - - private static class TextEditorContext extends SelectInContextImpl { - private final TextEditor myEditor; - - public TextEditorContext(TextEditor editor, PsiFile psiFile) { - super(psiFile); - myEditor = editor; - } - - @Override - public FileEditorProvider getFileEditorProvider() { - return new FileEditorProvider() { - @Override - public FileEditor openFileEditor() { - return myEditor; - } - }; - } - - @Override - public Object getSelectorInFile() { - if (myPsiFile.getViewProvider() instanceof TemplateLanguageFileViewProvider) { - return super.getSelectorInFile(); - } - Editor editor = myEditor.getEditor(); - int offset = TargetElementUtil.adjustOffset(myPsiFile, editor.getDocument(), editor.getCaretModel().getOffset()); - PsiElement element = myPsiFile.findElementAt(offset); - return element != null ? element : super.getSelectorInFile(); - } - } - - - private static class OpenFileDescriptorContext extends SelectInContextImpl { - public OpenFileDescriptorContext(PsiFile psiFile) { - super(psiFile); - } - - @Override - public FileEditorProvider getFileEditorProvider() { - return new FileEditorProvider() { - @Override - public FileEditor openFileEditor() { - return FileEditorManager.getInstance(getProject()).openFile(getVirtualFile(), false)[0]; - } - }; - } - - @Nullable - public static SelectInContext create(Project project, VirtualFile file) { - final Document document = FileDocumentManager.getInstance().getDocument(file); - if (document == null) return null; - final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); - if (psiFile == null) return null; - return new OpenFileDescriptorContext(psiFile); - } - } - - private static class SimpleSelectInContext extends SelectInContextImpl { - private final Object mySelector; - - public SimpleSelectInContext(PsiFile psiFile, Object selector) { - super(psiFile); - mySelector = selector; - } - - @Override - public Object getSelectorInFile() { - return mySelector; - } - - @Override - public FileEditorProvider getFileEditorProvider() { - return new FileEditorProvider() { - @Override - public FileEditor openFileEditor() { - final VirtualFile file = myPsiFile.getVirtualFile(); - if (file == null) { - return null; - } - return ArrayUtil.getFirstElement(FileEditorManager.getInstance(getProject()).openFile(file, false)); - } - }; - } - } - - private static class VirtualFileSelectInContext implements SelectInContext { - private final Project myProject; - private final VirtualFile myVirtualFile; - - public VirtualFileSelectInContext(final Project project, final VirtualFile virtualFile) { - myProject = project; - myVirtualFile = virtualFile; - } - - @Override - @NotNull - public Project getProject() { - return myProject; - } - - @Override - @NotNull - public VirtualFile getVirtualFile() { - return myVirtualFile; - } - - @Override - @Nullable - public Object getSelectorInFile() { - return myVirtualFile; - } - - @Override - @Nullable - public FileEditorProvider getFileEditorProvider() { - return null; + Component component = event.getData(PlatformDataKeys.CONTEXT_COMPONENT); + return component instanceof JComponent ? (JComponent)component : null; } } } diff --git a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesAutoscrollFromSourceHandler.java b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesAutoscrollFromSourceHandler.java index 30bbf034a031..affef9d98712 100644 --- a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesAutoscrollFromSourceHandler.java +++ b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesAutoscrollFromSourceHandler.java @@ -15,8 +15,7 @@ */ package com.intellij.ide.favoritesTreeView; -import com.intellij.ide.SelectInContext; -import com.intellij.ide.actions.SelectInContextImpl; +import com.intellij.ide.FileEditorSelectInContext; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; import com.intellij.openapi.project.Project; @@ -24,6 +23,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.ui.AutoScrollFromSourceHandler; +import com.intellij.util.ObjectUtils; import org.jetbrains.annotations.NotNull; /** @@ -33,7 +33,7 @@ public class FavoritesAutoscrollFromSourceHandler extends AutoScrollFromSourceHa private final FavoritesViewSelectInTarget mySelectInTarget = new FavoritesViewSelectInTarget(myProject); public FavoritesAutoscrollFromSourceHandler(@NotNull Project project, @NotNull FavoritesViewTreeBuilder builder) { - super(project, builder.getTree(), builder); + super(project, ObjectUtils.assertNotNull(builder.getTree()), builder); } @Override @@ -48,15 +48,12 @@ public class FavoritesAutoscrollFromSourceHandler extends AutoScrollFromSourceHa @Override protected void selectElementFromEditor(@NotNull FileEditor editor) { - final VirtualFile file = FileEditorManagerEx.getInstanceEx(myProject).getFile(editor); - if (file != null) { - final PsiFile psiFile = PsiManager.getInstance(myProject).findFile(file); - if (psiFile != null) { - final SelectInContext selectInContext = SelectInContextImpl.createEditorContext(myProject, editor); - if (mySelectInTarget.canSelect(selectInContext)) { - mySelectInTarget.selectIn(selectInContext, false); - } - } + VirtualFile file = FileEditorManagerEx.getInstanceEx(myProject).getFile(editor); + PsiFile psiFile = file == null ? null : PsiManager.getInstance(myProject).findFile(file); + if (psiFile == null) return; + FileEditorSelectInContext context = new FileEditorSelectInContext(editor, psiFile); + if (mySelectInTarget.canSelect(context)) { + mySelectInTarget.selectIn(context, false); } } } \ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/ide/FileEditorSelectInContext.java b/platform/platform-api/src/com/intellij/ide/FileEditorSelectInContext.java new file mode 100644 index 000000000000..e03259c88286 --- /dev/null +++ b/platform/platform-api/src/com/intellij/ide/FileEditorSelectInContext.java @@ -0,0 +1,93 @@ +/* + * Copyright 2000-2017 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.ide; + +import com.intellij.lang.injection.InjectedLanguageManager; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.fileEditor.FileEditor; +import com.intellij.openapi.fileEditor.TextEditor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.util.ObjectUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author gregsh + */ +public class FileEditorSelectInContext implements SelectInContext { + private final FileEditor myFileEditor; + private final PsiFile myPsiFile; + + public FileEditorSelectInContext(@NotNull FileEditor fileEditor, @NotNull PsiFile psiFile) { + myFileEditor = fileEditor; + myPsiFile = psiFile; + } + + @NotNull + @Override + public Project getProject() { + return myPsiFile.getProject(); + } + + @NotNull + @Override + public VirtualFile getVirtualFile() { + return myPsiFile.getViewProvider().getVirtualFile(); + } + + @NotNull + public FileEditor getFileEditor() { + return myFileEditor; + } + + @NotNull + public PsiFile getPsiFile() { + return myPsiFile; + } + + @Nullable + @Override + public Object getSelectorInFile() { + return ObjectUtils.notNull(getElementAtCaret(false), myPsiFile); + } + + @Nullable + public PsiElement getElementAtCaret(boolean tryInjected) { + if (!(myFileEditor instanceof TextEditor)) return null; + Editor editor = ((TextEditor)myFileEditor).getEditor(); + int offset = editor.getCaretModel().getOffset(); + if (tryInjected) { + InjectedLanguageManager manager = InjectedLanguageManager.getInstance(getProject()); + PsiElement injectedElementAt = manager.findInjectedElementAt(myPsiFile, offset); + if (injectedElementAt != null) return injectedElementAt; + } + return myPsiFile.findElementAt(offset); + } + + @Nullable + @Override + public FileEditorProvider getFileEditorProvider() { + return new FileEditorProvider() { + @Override + public FileEditor openFileEditor() { + return myFileEditor; + } + }; + } +}