blob: 85e660401feab1da34d11da60ac27d0a6f36c62d [file] [log] [blame]
/*
* 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.codeInspection.ui;
import com.intellij.CommonBundle;
import com.intellij.analysis.AnalysisScope;
import com.intellij.analysis.AnalysisUIOptions;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.*;
import com.intellij.codeInspection.reference.RefElement;
import com.intellij.codeInspection.reference.RefEntity;
import com.intellij.codeInspection.ui.actions.ExportHTMLAction;
import com.intellij.codeInspection.ui.actions.InspectionsOptionsToolbarAction;
import com.intellij.codeInspection.ui.actions.InvokeQuickFixAction;
import com.intellij.icons.AllIcons;
import com.intellij.ide.*;
import com.intellij.ide.actions.ContextHelpAction;
import com.intellij.injected.editor.VirtualFileWindow;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.pom.Navigatable;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.ui.*;
import com.intellij.util.OpenSourceUtil;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.*;
import java.util.List;
/**
* @author max
*/
public class InspectionResultsView extends JPanel implements Disposable, OccurenceNavigator, DataProvider {
public static final DataKey<InspectionResultsView> DATA_KEY = DataKey.create("inspectionView");
private final Project myProject;
private InspectionTree myTree;
private final Browser myBrowser;
private Map<HighlightDisplayLevel, Map<String, InspectionGroupNode>> myGroups = null;
private OccurenceNavigator myOccurenceNavigator;
private InspectionProfile myInspectionProfile;
private final AnalysisScope myScope;
@NonNls
private static final String HELP_ID = "reference.toolWindows.inspections";
private final Map<HighlightDisplayLevel, InspectionSeverityGroupNode> mySeverityGroupNodes = new TreeMap<HighlightDisplayLevel, InspectionSeverityGroupNode>(new Comparator<HighlightDisplayLevel>() {
@Override
public int compare(HighlightDisplayLevel o1, HighlightDisplayLevel o2) {
final int severityDiff = o1.getSeverity().compareTo(o2.getSeverity());
if (severityDiff == 0) {
return o1.getName().compareTo(o2.getName());
}
return severityDiff;
}
});
private final Splitter mySplitter;
@NotNull
private final GlobalInspectionContextImpl myGlobalInspectionContext;
private boolean myRerun = false;
@NotNull
private final InspectionRVContentProvider myProvider;
private AnAction myIncludeAction;
private AnAction myExcludeAction;
public InspectionResultsView(@NotNull final Project project,
final InspectionProfile inspectionProfile,
@NotNull AnalysisScope scope,
@NotNull GlobalInspectionContextImpl globalInspectionContext,
@NotNull InspectionRVContentProvider provider) {
setLayout(new BorderLayout());
myProject = project;
myInspectionProfile = inspectionProfile;
myScope = scope;
myGlobalInspectionContext = globalInspectionContext;
myProvider = provider;
myTree = new InspectionTree(project, globalInspectionContext);
initTreeListeners();
myOccurenceNavigator = initOccurenceNavigator();
myBrowser = new Browser(this);
mySplitter = new Splitter(false, AnalysisUIOptions.getInstance(myProject).SPLITTER_PROPORTION);
mySplitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myTree, SideBorder.LEFT | SideBorder.RIGHT));
mySplitter.setSecondComponent(myBrowser);
mySplitter.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (Splitter.PROP_PROPORTION.equals(evt.getPropertyName())) {
myGlobalInspectionContext.setSplitterProportion(((Float)evt.getNewValue()).floatValue());
}
}
});
add(mySplitter, BorderLayout.CENTER);
myBrowser.addClickListener(new Browser.ClickListener() {
@Override
public void referenceClicked(final Browser.ClickEvent e) {
if (e.getEventType() == Browser.ClickEvent.REF_ELEMENT) {
final RefElement refElement = e.getClickedElement();
final OpenFileDescriptor descriptor = getOpenFileDescriptor(refElement);
if (descriptor != null) {
FileEditorManager.getInstance(project).openTextEditor(descriptor, false);
}
}
else if (e.getEventType() == Browser.ClickEvent.FILE_OFFSET) {
final VirtualFile file = e.getFile();
final OpenFileDescriptor descriptor = new OpenFileDescriptor(project, file, e.getStartOffset());
final Editor editor = FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
if (editor != null) {
final TextAttributes selectionAttributes =
EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
HighlightManager.getInstance(project)
.addRangeHighlight(editor, e.getStartOffset(), e.getEndOffset(), selectionAttributes, true, null);
}
}
}
});
createActionsToolbar();
TreeUtil.selectFirstNode(myTree);
}
private void initTreeListeners() {
myTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
syncBrowser();
if (isAutoScrollMode()) {
OpenSourceUtil.openSourcesFrom(DataManager.getInstance().getDataContext(InspectionResultsView.this), false);
}
}
});
new DoubleClickListener() {
@Override
protected boolean onDoubleClick(MouseEvent e) {
OpenSourceUtil.openSourcesFrom(DataManager.getInstance().getDataContext(InspectionResultsView.this), true);
return true;
}
}.installOn(myTree);
myTree.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
OpenSourceUtil.openSourcesFrom(DataManager.getInstance().getDataContext(InspectionResultsView.this), false);
}
}
});
myTree.addMouseListener(new PopupHandler() {
@Override
public void invokePopup(Component comp, int x, int y) {
popupInvoked(comp, x, y);
}
});
SmartExpander.installOn(myTree);
}
private OccurenceNavigatorSupport initOccurenceNavigator(){
return new OccurenceNavigatorSupport(myTree) {
@Override
@Nullable
protected Navigatable createDescriptorForNode(DefaultMutableTreeNode node) {
if (node instanceof InspectionTreeNode && ((InspectionTreeNode)node).isResolved()) {
return null;
}
if (node instanceof RefElementNode) {
final RefElementNode refNode = (RefElementNode)node;
if (refNode.hasDescriptorsUnder()) return null;
final RefEntity element = refNode.getElement();
if (element == null || !element.isValid()) return null;
final CommonProblemDescriptor problem = refNode.getProblem();
if (problem != null) {
return navigate(problem);
}
if (element instanceof RefElement) {
return getOpenFileDescriptor((RefElement)element);
}
}
else if (node instanceof ProblemDescriptionNode) {
if (!((ProblemDescriptionNode)node).isValid()) return null;
return navigate(((ProblemDescriptionNode)node).getDescriptor());
}
return null;
}
@Nullable
private Navigatable navigate(final CommonProblemDescriptor descriptor) {
return getSelectedNavigatable(descriptor);
}
@Override
public String getNextOccurenceActionName() {
return InspectionsBundle.message("inspection.action.go.next");
}
@Override
public String getPreviousOccurenceActionName() {
return InspectionsBundle.message("inspection.actiongo.prev");
}
};
}
private void createActionsToolbar() {
final JComponent leftActionsToolbar = createLeftActionsToolbar();
final JComponent rightActionsToolbar = createRightActionsToolbar();
JPanel westPanel = new JPanel(new BorderLayout());
westPanel.add(leftActionsToolbar, BorderLayout.WEST);
westPanel.add(rightActionsToolbar, BorderLayout.EAST);
add(westPanel, BorderLayout.WEST);
}
@SuppressWarnings({"NonStaticInitializer"})
private JComponent createRightActionsToolbar() {
myIncludeAction = new AnAction(InspectionsBundle.message("inspections.result.view.include.action.text")){
{
registerCustomShortcutSet(CommonShortcuts.INSERT, myTree);
}
@Override
public void actionPerformed(AnActionEvent e) {
((InspectionTreeNode)myTree.getSelectionPath().getLastPathComponent()).amnesty();
updateView(false);
}
@Override
public void update(final AnActionEvent e) {
final TreePath path = myTree.getSelectionPath();
e.getPresentation().setEnabled(path != null && !myGlobalInspectionContext.getUIOptions().FILTER_RESOLVED_ITEMS);
}
};
myExcludeAction = new AnAction(InspectionsBundle.message("inspections.result.view.exclude.action.text")) {
{
registerCustomShortcutSet(CommonShortcuts.getDelete(), myTree);
}
@Override
public void actionPerformed(final AnActionEvent e) {
((InspectionTreeNode)myTree.getSelectionPath().getLastPathComponent()).ignoreElement();
updateView(false);
}
@Override
public void update(final AnActionEvent e) {
final TreePath path = myTree.getSelectionPath();
e.getPresentation().setEnabled(path != null);
}
};
DefaultActionGroup specialGroup = new DefaultActionGroup();
specialGroup.add(myGlobalInspectionContext.getUIOptions().createGroupBySeverityAction(this));
specialGroup.add(myGlobalInspectionContext.getUIOptions().createGroupByDirectoryAction(this));
specialGroup.add(myGlobalInspectionContext.getUIOptions().createFilterResolvedItemsAction(this));
specialGroup.add(myGlobalInspectionContext.getUIOptions().createShowOutdatedProblemsAction(this));
specialGroup.add(myGlobalInspectionContext.getUIOptions().createShowDiffOnlyAction(this));
specialGroup.add(new EditSettingsAction());
specialGroup.add(new InvokeQuickFixAction(this));
specialGroup.add(new InspectionsOptionsToolbarAction(this));
return createToolbar(specialGroup);
}
private JComponent createLeftActionsToolbar() {
final CommonActionsManager actionsManager = CommonActionsManager.getInstance();
DefaultActionGroup group = new DefaultActionGroup();
group.add(new RerunAction(this));
group.add(new CloseAction());
final TreeExpander treeExpander = new TreeExpander() {
@Override
public void expandAll() {
TreeUtil.expandAll(myTree);
}
@Override
public boolean canExpand() {
return true;
}
@Override
public void collapseAll() {
TreeUtil.collapseAll(myTree, 0);
}
@Override
public boolean canCollapse() {
return true;
}
};
group.add(actionsManager.createExpandAllAction(treeExpander, myTree));
group.add(actionsManager.createCollapseAllAction(treeExpander, myTree));
group.add(actionsManager.createPrevOccurenceAction(getOccurenceNavigator()));
group.add(actionsManager.createNextOccurenceAction(getOccurenceNavigator()));
group.add(myGlobalInspectionContext.createToggleAutoscrollAction());
group.add(new ExportHTMLAction(this));
group.add(new ContextHelpAction(HELP_ID));
return createToolbar(group);
}
private static JComponent createToolbar(final DefaultActionGroup specialGroup) {
return ActionManager.getInstance()
.createActionToolbar(ActionPlaces.CODE_INSPECTION, specialGroup, false).getComponent();
}
@Override
public void dispose(){
mySplitter.dispose();
myBrowser.dispose();
myTree = null;
myOccurenceNavigator = null;
myInspectionProfile = null;
}
private boolean isAutoScrollMode() {
String activeToolWindowId = ToolWindowManager.getInstance(myProject).getActiveToolWindowId();
return myGlobalInspectionContext.getUIOptions().AUTOSCROLL_TO_SOURCE &&
(activeToolWindowId == null || activeToolWindowId.equals(ToolWindowId.INSPECTION));
}
@Nullable
private static OpenFileDescriptor getOpenFileDescriptor(final RefElement refElement) {
final VirtualFile[] file = new VirtualFile[1];
final int[] offset = new int[1];
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
PsiElement psiElement = refElement.getElement();
if (psiElement != null) {
final PsiFile containingFile = psiElement.getContainingFile();
if (containingFile != null) {
file[0] = containingFile.getVirtualFile();
offset[0] = psiElement.getTextOffset();
}
}
else {
file[0] = null;
}
}
});
if (file[0] != null && file[0].isValid()) {
return new OpenFileDescriptor(refElement.getRefManager().getProject(), file[0], offset[0]);
}
return null;
}
private void syncBrowser() {
if (myTree.getSelectionModel().getSelectionCount() != 1) {
myBrowser.showEmpty();
}
else {
TreePath pathSelected = myTree.getSelectionModel().getLeadSelectionPath();
if (pathSelected != null) {
final InspectionTreeNode node = (InspectionTreeNode)pathSelected.getLastPathComponent();
if (node instanceof RefElementNode) {
final RefElementNode refElementNode = (RefElementNode)node;
final CommonProblemDescriptor problem = refElementNode.getProblem();
final RefEntity refSelected = refElementNode.getElement();
if (problem != null) {
showInBrowser(refSelected, problem);
}
else {
showInBrowser(refSelected);
}
}
else if (node instanceof ProblemDescriptionNode) {
final ProblemDescriptionNode problemNode = (ProblemDescriptionNode)node;
showInBrowser(problemNode.getElement(), problemNode.getDescriptor());
}
else if (node instanceof InspectionNode) {
showInBrowser(((InspectionNode)node).getToolWrapper());
}
else {
myBrowser.showEmpty();
}
}
}
}
private void showInBrowser(final RefEntity refEntity) {
Cursor currentCursor = getCursor();
setCursor(new Cursor(Cursor.WAIT_CURSOR));
myBrowser.showPageFor(refEntity);
setCursor(currentCursor);
}
private void showInBrowser(@NotNull InspectionToolWrapper toolWrapper) {
Cursor currentCursor = getCursor();
setCursor(new Cursor(Cursor.WAIT_CURSOR));
myBrowser.showDescription(toolWrapper);
setCursor(currentCursor);
}
private void showInBrowser(final RefEntity refEntity, CommonProblemDescriptor descriptor) {
Cursor currentCursor = getCursor();
setCursor(new Cursor(Cursor.WAIT_CURSOR));
myBrowser.showPageFor(refEntity, descriptor);
setCursor(currentCursor);
}
@NotNull
public InspectionNode addTool(@NotNull final InspectionToolWrapper toolWrapper, HighlightDisplayLevel errorLevel, boolean groupedBySeverity) {
String groupName =
toolWrapper.getGroupDisplayName().isEmpty() ? InspectionProfileEntry.GENERAL_GROUP_NAME : toolWrapper.getGroupDisplayName();
InspectionTreeNode parentNode = getToolParentNode(groupName, errorLevel, groupedBySeverity);
InspectionNode toolNode = new InspectionNode(toolWrapper);
boolean showStructure = myGlobalInspectionContext.getUIOptions().SHOW_STRUCTURE;
myProvider.appendToolNodeContent(myGlobalInspectionContext, toolNode, parentNode, showStructure);
InspectionToolPresentation presentation = myGlobalInspectionContext.getPresentation(toolWrapper);
toolNode = presentation.createToolNode(myGlobalInspectionContext, toolNode, myProvider, parentNode, showStructure);
((DefaultInspectionToolPresentation)presentation).myToolNode = toolNode;
registerActionShortcuts(presentation);
return toolNode;
}
private void registerActionShortcuts(@NotNull InspectionToolPresentation presentation) {
final QuickFixAction[] fixes = presentation.getQuickFixes(RefEntity.EMPTY_ELEMENTS_ARRAY);
if (fixes != null) {
for (QuickFixAction fix : fixes) {
fix.registerCustomShortcutSet(fix.getShortcutSet(), this);
}
}
}
private void clearTree() {
myTree.removeAllNodes();
mySeverityGroupNodes.clear();
}
@Nullable
public String getCurrentProfileName() {
return myInspectionProfile == null ? null : myInspectionProfile.getDisplayName();
}
public InspectionProfile getCurrentProfile() {
return myInspectionProfile;
}
public boolean update(){
return updateView(true);
}
public boolean updateView(boolean strict) {
if (!strict && !myGlobalInspectionContext.getUIOptions().FILTER_RESOLVED_ITEMS){
myTree.repaint();
return false;
}
clearTree();
boolean resultsFound = buildTree();
myTree.restoreExpansionAndSelection();
return resultsFound;
}
private boolean buildTree() {
InspectionProfile profile = myInspectionProfile;
boolean isGroupedBySeverity = myGlobalInspectionContext.getUIOptions().GROUP_BY_SEVERITY;
myGroups = new HashMap<HighlightDisplayLevel, Map<String, InspectionGroupNode>>();
final Map<String, Tools> tools = myGlobalInspectionContext.getTools();
boolean resultsFound = false;
for (Tools currentTools : tools.values()) {
InspectionToolWrapper defaultToolWrapper = currentTools.getDefaultState().getTool();
final HighlightDisplayKey key = HighlightDisplayKey.find(defaultToolWrapper.getShortName());
for (ScopeToolState state : currentTools.getTools()) {
InspectionToolWrapper toolWrapper = state.getTool();
if (myProvider.checkReportedProblems(myGlobalInspectionContext, toolWrapper)) {
addTool(toolWrapper, ((InspectionProfileImpl)profile).getErrorLevel(key, state.getScope(myProject), myProject), isGroupedBySeverity);
resultsFound = true;
}
}
}
return resultsFound;
}
@NotNull
public InspectionTreeNode getToolParentNode(@NotNull String groupName, HighlightDisplayLevel errorLevel, boolean groupedBySeverity) {
if (groupName.isEmpty()) {
return getRelativeRootNode(groupedBySeverity, errorLevel);
}
if (myGroups == null) {
myGroups = new HashMap<HighlightDisplayLevel, Map<String, InspectionGroupNode>>();
}
Map<String, InspectionGroupNode> map = myGroups.get(errorLevel);
if (map == null) {
map = new HashMap<String, InspectionGroupNode>();
myGroups.put(errorLevel, map);
}
Map<String, InspectionGroupNode> searchMap = new HashMap<String, InspectionGroupNode>(map);
if (!groupedBySeverity) {
for (Map<String, InspectionGroupNode> groupMap : myGroups.values()) {
searchMap.putAll(groupMap);
}
}
InspectionGroupNode group = searchMap.get(groupName);
if (group == null) {
group = new InspectionGroupNode(groupName);
map.put(groupName, group);
getRelativeRootNode(groupedBySeverity, errorLevel).add(group);
}
return group;
}
@NotNull
private InspectionTreeNode getRelativeRootNode(boolean isGroupedBySeverity, HighlightDisplayLevel level) {
if (isGroupedBySeverity) {
if (mySeverityGroupNodes.containsKey(level)) {
return mySeverityGroupNodes.get(level);
}
final InspectionSeverityGroupNode severityGroupNode = new InspectionSeverityGroupNode(myProject, level);
mySeverityGroupNodes.put(level, severityGroupNode);
myTree.getRoot().add(severityGroupNode);
return severityGroupNode;
}
return myTree.getRoot();
}
private OccurenceNavigator getOccurenceNavigator() {
return myOccurenceNavigator;
}
@Override
public boolean hasNextOccurence() {
return myOccurenceNavigator != null && myOccurenceNavigator.hasNextOccurence();
}
@Override
public boolean hasPreviousOccurence() {
return myOccurenceNavigator != null && myOccurenceNavigator.hasPreviousOccurence();
}
@Override
public OccurenceInfo goNextOccurence() {
return myOccurenceNavigator != null ? myOccurenceNavigator.goNextOccurence() : null;
}
@Override
public OccurenceInfo goPreviousOccurence() {
return myOccurenceNavigator != null ? myOccurenceNavigator.goPreviousOccurence() : null;
}
@Override
public String getNextOccurenceActionName() {
return myOccurenceNavigator != null ? myOccurenceNavigator.getNextOccurenceActionName() : "";
}
@Override
public String getPreviousOccurenceActionName() {
return myOccurenceNavigator != null ? myOccurenceNavigator.getPreviousOccurenceActionName() : "";
}
@NotNull
public Project getProject() {
return myProject;
}
@Override
public Object getData(String dataId) {
if (PlatformDataKeys.HELP_ID.is(dataId)) return HELP_ID;
if (DATA_KEY.is(dataId)) return this;
if (myTree == null) return null;
TreePath[] paths = myTree.getSelectionPaths();
if (paths == null || paths.length == 0) return null;
if (paths.length > 1) {
if (LangDataKeys.PSI_ELEMENT_ARRAY.is(dataId)) {
return collectPsiElements();
}
return null;
}
TreePath path = paths[0];
InspectionTreeNode selectedNode = (InspectionTreeNode)path.getLastPathComponent();
if (selectedNode instanceof RefElementNode) {
final RefElementNode refElementNode = (RefElementNode)selectedNode;
RefEntity refElement = refElementNode.getElement();
if (refElement == null) return null;
final RefEntity item = refElement.getRefManager().getRefinedElement(refElement);
if (!item.isValid()) return null;
PsiElement psiElement = item instanceof RefElement ? ((RefElement)item).getElement() : null;
if (psiElement == null) return null;
final CommonProblemDescriptor problem = refElementNode.getProblem();
if (problem != null) {
if (problem instanceof ProblemDescriptor) {
psiElement = ((ProblemDescriptor)problem).getPsiElement();
if (psiElement == null) return null;
}
else {
return null;
}
}
if (CommonDataKeys.NAVIGATABLE.is(dataId)) {
return getSelectedNavigatable(problem, psiElement);
}
else if (CommonDataKeys.PSI_ELEMENT.is(dataId)) {
return psiElement.isValid() ? psiElement : null;
}
}
else if (selectedNode instanceof ProblemDescriptionNode && CommonDataKeys.NAVIGATABLE.is(dataId)) {
return getSelectedNavigatable(((ProblemDescriptionNode)selectedNode).getDescriptor());
}
return null;
}
@Nullable
private Navigatable getSelectedNavigatable(final CommonProblemDescriptor descriptor) {
return getSelectedNavigatable(descriptor,
descriptor instanceof ProblemDescriptor ? ((ProblemDescriptor)descriptor).getPsiElement() : null);
}
@Nullable
private Navigatable getSelectedNavigatable(final CommonProblemDescriptor descriptor, final PsiElement psiElement) {
if (descriptor instanceof ProblemDescriptorBase) {
Navigatable navigatable = ((ProblemDescriptorBase) descriptor).getNavigatable();
if (navigatable != null) {
return navigatable;
}
}
if (psiElement == null || !psiElement.isValid()) return null;
PsiFile containingFile = psiElement.getContainingFile();
VirtualFile virtualFile = containingFile == null ? null : containingFile.getVirtualFile();
if (virtualFile != null) {
int startOffset = psiElement.getTextOffset();
if (descriptor instanceof ProblemDescriptorBase) {
final TextRange textRange = ((ProblemDescriptorBase)descriptor).getTextRangeForNavigation();
if (textRange != null) {
if (virtualFile instanceof VirtualFileWindow) {
virtualFile = ((VirtualFileWindow)virtualFile).getDelegate();
}
startOffset = textRange.getStartOffset();
}
}
return new OpenFileDescriptor(myProject, virtualFile, startOffset);
}
return null;
}
private PsiElement[] collectPsiElements() {
RefEntity[] refElements = myTree.getSelectedElements();
List<PsiElement> psiElements = new ArrayList<PsiElement>();
for (RefEntity refElement : refElements) {
PsiElement psiElement = refElement instanceof RefElement ? ((RefElement)refElement).getElement() : null;
if (psiElement != null && psiElement.isValid()) {
psiElements.add(psiElement);
}
}
return PsiUtilCore.toPsiElementArray(psiElements);
}
private void popupInvoked(Component component, int x, int y) {
final TreePath path = myTree.getLeadSelectionPath();
if (path == null) return;
final DefaultActionGroup actions = new DefaultActionGroup();
final ActionManager actionManager = ActionManager.getInstance();
actions.add(actionManager.getAction(IdeActions.ACTION_EDIT_SOURCE));
actions.add(actionManager.getAction(IdeActions.ACTION_FIND_USAGES));
actions.add(myIncludeAction);
actions.add(myExcludeAction);
actions.addSeparator();
final InspectionToolWrapper toolWrapper = myTree.getSelectedToolWrapper();
if (toolWrapper != null) {
final QuickFixAction[] quickFixes = myProvider.getQuickFixes(toolWrapper, myTree);
if (quickFixes != null) {
for (QuickFixAction quickFixe : quickFixes) {
actions.add(quickFixe);
}
}
final HighlightDisplayKey key = HighlightDisplayKey.find(toolWrapper.getShortName());
if (key == null) return; //e.g. DummyEntryPointsTool
//options
actions.addSeparator();
actions.add(new EditSettingsAction());
final List<AnAction> options = new InspectionsOptionsToolbarAction(this).createActions();
for (AnAction action : options) {
actions.add(action);
}
}
actions.addSeparator();
actions.add(actionManager.getAction(IdeActions.GROUP_VERSION_CONTROLS));
final ActionPopupMenu menu = actionManager.createActionPopupMenu(ActionPlaces.CODE_INSPECTION, actions);
menu.getComponent().show(component, x, y);
}
@NotNull
public InspectionTree getTree(){
return myTree;
}
@NotNull
public GlobalInspectionContextImpl getGlobalInspectionContext() {
return myGlobalInspectionContext;
}
@NotNull
public InspectionRVContentProvider getProvider() {
return myProvider;
}
public boolean isSingleToolInSelection() {
return myTree != null && myTree.getSelectedToolWrapper() != null;
}
public boolean isRerun() {
boolean rerun = myRerun;
myRerun = false;
return rerun;
}
private InspectionProfile guessProfileToSelect(final InspectionProjectProfileManager profileManager) {
final Set<InspectionProfile> profiles = new HashSet<InspectionProfile>();
final RefEntity[] selectedElements = myTree.getSelectedElements();
for (RefEntity selectedElement : selectedElements) {
if (selectedElement instanceof RefElement) {
final RefElement refElement = (RefElement)selectedElement;
final PsiElement element = refElement.getElement();
if (element != null) {
profiles.add(profileManager.getInspectionProfile());
}
}
}
if (profiles.isEmpty()) {
return (InspectionProfile)profileManager.getProjectProfileImpl();
}
return profiles.iterator().next();
}
public boolean isProfileDefined() {
return myInspectionProfile != null && myInspectionProfile.isEditable();
}
public static void showPopup(AnActionEvent e, JBPopup popup) {
final InputEvent event = e.getInputEvent();
if (event instanceof MouseEvent) {
popup.showUnderneathOf(event.getComponent());
} else {
popup.showInBestPositionFor(e.getDataContext());
}
}
public AnalysisScope getScope() {
return myScope;
}
private class CloseAction extends AnAction implements DumbAware {
private CloseAction() {
super(CommonBundle.message("action.close"), null, AllIcons.Actions.Cancel);
}
@Override
public void actionPerformed(AnActionEvent e) {
myGlobalInspectionContext.close(true);
}
}
private class EditSettingsAction extends AnAction {
private EditSettingsAction() {
super(InspectionsBundle.message("inspection.action.edit.settings"), InspectionsBundle.message("inspection.action.edit.settings"),
AllIcons.General.Settings);
}
@Override
public void actionPerformed(AnActionEvent e) {
final InspectionProjectProfileManager profileManager = InspectionProjectProfileManager.getInstance(myProject);
final InspectionToolWrapper toolWrapper = myTree.getSelectedToolWrapper();
InspectionProfile inspectionProfile = myInspectionProfile;
final boolean profileIsDefined = isProfileDefined();
if (!profileIsDefined) {
inspectionProfile = guessProfileToSelect(profileManager);
}
if (toolWrapper != null) {
final HighlightDisplayKey key = HighlightDisplayKey.find(toolWrapper.getShortName()); //do not search for dead code entry point tool
if (key != null){
if (new EditInspectionToolsSettingsAction(key).editToolSettings(myProject, (InspectionProfileImpl)inspectionProfile, profileIsDefined)
&& profileIsDefined){
updateCurrentProfile();
}
return;
}
}
if (EditInspectionToolsSettingsAction.editToolSettings(myProject, inspectionProfile, profileIsDefined, null) && profileIsDefined) {
updateCurrentProfile();
}
}
}
public void updateCurrentProfile() {
final String name = myInspectionProfile.getName();
myInspectionProfile = (InspectionProfile)myInspectionProfile.getProfileManager().getProfile(name);
}
private class RerunAction extends AnAction {
public RerunAction(JComponent comp) {
super(InspectionsBundle.message("inspection.action.rerun"), InspectionsBundle.message("inspection.action.rerun"),
AllIcons.Actions.Rerun);
registerCustomShortcutSet(CommonShortcuts.getRerun(), comp);
}
@Override
public void update(AnActionEvent e) {
e.getPresentation().setEnabled(myScope.isValid());
}
@Override
public void actionPerformed(AnActionEvent e) {
rerun();
}
private void rerun() {
myRerun = true;
if (myScope.isValid()) {
AnalysisUIOptions.getInstance(myProject).save(myGlobalInspectionContext.getUIOptions());
myGlobalInspectionContext.doInspections(myScope);
}
}
}
}