added read/write access filters to UsageView

This commit is contained in:
Eugene Zhuravlev
2005-01-17 19:33:10 +03:00
parent 2d39ead5af
commit fd4a6533ef
13 changed files with 276 additions and 90 deletions
@@ -0,0 +1,14 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.usages;
/**
* @author Eugene Zhuravlev
* Date: Jan 17, 2005
*/
public interface ReadWriteAccessUsage extends Usage{
boolean isAccessedForWriting();
boolean isAccessedForReading();
}
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.usages;
import com.intellij.usageView.UsageInfo;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReferenceExpression;
import com.intellij.psi.util.PsiUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.Icons;
/**
* @author Eugene Zhuravlev
* Date: Jan 17, 2005
*/
public class ReadWriteAccessUsageInfo2UsageAdapter extends UsageInfo2UsageAdapter implements ReadWriteAccessUsage{
private static final Logger LOG = Logger.getInstance("#com.intellij.usages.ReadWriteAccessUsageInfo2UsageAdapter");
private final boolean myAccessedForReading;
private final boolean myAccessedForWriting;
public ReadWriteAccessUsageInfo2UsageAdapter(final UsageInfo usageInfo) {
super(usageInfo);
final PsiElement element = getUsageInfo().getElement();
LOG.assertTrue(element instanceof PsiReferenceExpression);
final PsiReferenceExpression referent = (PsiReferenceExpression)element;
myAccessedForReading = PsiUtil.isAccessedForReading(referent);
myAccessedForWriting = isAccessedForWriting(referent);
if (myIcon == null) {
if (myAccessedForReading && myAccessedForWriting) {
myIcon = Icons.VARIABLE_RW_ACCESS;
}
else if (myAccessedForWriting) {
myIcon = Icons.VARIABLE_WRITE_ACCESS; // If icon is changed, don't forget to change UTCompositeUsageNode.getIcon();
}
else if (myAccessedForReading){
myIcon = Icons.VARIABLE_READ_ACCESS; // If icon is changed, don't forget to change UTCompositeUsageNode.getIcon();
}
}
}
public boolean isAccessedForWriting() {
return myAccessedForWriting;
}
public boolean isAccessedForReading() {
return myAccessedForReading;
}
private static boolean isAccessedForWriting(PsiReferenceExpression referent) {
if (PsiUtil.isAccessedForWriting(referent)) {
return true;
}
/*
todo: when searching usages of fields, should show all found setters as a "write usage"
if (myProcessedElementsPointers.length > 0) {
PsiElement referee = myProcessedElementsPointers[0].getElement();
if (referee instanceof PsiField && !referent.isReferenceTo(referee)) {
PsiElement actualReferee = referent.resolve();
return actualReferee instanceof PsiMethod && PropertyUtil.isSimplePropertySetter((PsiMethod)actualReferee);
}
}
*/
return false;
}
}
@@ -17,11 +17,9 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiCompiledElement;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiUtil;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageTreeColors;
import com.intellij.usageView.UsageTreeColorsScheme;
@@ -48,15 +46,13 @@ public class UsageInfo2UsageAdapter implements Usage, UsageInModule, UsageInLibr
private int myLineNumber;
private int myColumnNumber;
private PsiFile myPsiFile;
private Icon myIcon;
protected Icon myIcon;
private List<RangeMarker> myRangeMarkers = new ArrayList<RangeMarker>();
private boolean myShowReadAccessIcon;
private boolean myShowWriteAccessIcon;
private TextChunk[] myTextChunks;
private Document myDocument;
private EditorColorsScheme myColorsScheme;
public UsageInfo2UsageAdapter(UsageInfo usageInfo) {
public UsageInfo2UsageAdapter(final UsageInfo usageInfo) {
myColorsScheme = UsageTreeColorsScheme.getInstance().getScheme();
myUsageInfo = usageInfo;
PsiElement element = myUsageInfo.getElement();
@@ -64,8 +60,7 @@ public class UsageInfo2UsageAdapter implements Usage, UsageInModule, UsageInLibr
Project project = element.getProject();
myDocument = PsiDocumentManager.getInstance(project).getDocument(myPsiFile);
myShowReadAccessIcon = false; // TODO:
myShowWriteAccessIcon = false;
final PsiElement psiElement = usageInfo.getElement();
TextRange range = element.getTextRange();
int startOffset = range.getStartOffset() + usageInfo.startOffset;
@@ -76,8 +71,11 @@ public class UsageInfo2UsageAdapter implements Usage, UsageInModule, UsageInLibr
int lineStartOffset = myDocument.getLineStartOffset(myLineNumber);
myColumnNumber = startOffset - lineStartOffset;
LOG.assertTrue(endOffset <= myDocument.getTextLength(), "Invalid usage info, psiElement:" + usageInfo.getElement()
+ " end offset: " + endOffset + " psiFile: " + myPsiFile.getName());
if (endOffset > myDocument.getTextLength()) {
LOG.assertTrue(false,
"Invalid usage info, psiElement:" + psiElement + " end offset: " + endOffset + " psiFile: " + myPsiFile.getName()
);
}
myRangeMarkers.add(myDocument.createRangeMarker(startOffset, endOffset));
@@ -86,16 +84,6 @@ public class UsageInfo2UsageAdapter implements Usage, UsageInModule, UsageInLibr
}
else {
myIcon = element.getIcon(0);
if (myIcon == null) {
if (myShowReadAccessIcon || myShowWriteAccessIcon) {
if (myShowWriteAccessIcon) {
myIcon = Icons.VARIABLE_WRITE_ACCESS; // If icon is changed, don't forget to change UTCompositeUsageNode.getIcon();
}
else {
myIcon = Icons.VARIABLE_READ_ACCESS; // If icon is changed, don't forget to change UTCompositeUsageNode.getIcon();
}
}
}
}
initChunks();
@@ -376,15 +364,6 @@ public class UsageInfo2UsageAdapter implements Usage, UsageInModule, UsageInLibr
return myUsageInfo.isNonCodeUsage;
}
public static Usage[] convert(UsageInfo[] usageInfos) {
Usage[] usages = new Usage[usageInfos.length];
for (int i = 0; i < usages.length; i++) {
usages[i] = new UsageInfo2UsageAdapter(usageInfos[i]);
}
return usages;
}
public UsageInfo getUsageInfo() {
return myUsageInfo;
}
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.usages;
import com.intellij.usageView.UsageInfo;
import com.intellij.psi.PsiReferenceExpression;
/**
* @author Eugene Zhuravlev
* Date: Jan 17, 2005
*/
public class UsageInfoToUsageConverter {
public static Usage convert(UsageInfo usageInfo) {
if (usageInfo.getElement() instanceof PsiReferenceExpression) {
return new ReadWriteAccessUsageInfo2UsageAdapter(usageInfo);
}
return new UsageInfo2UsageAdapter(usageInfo);
}
public static Usage[] convert(UsageInfo[] usageInfos) {
Usage[] usages = new Usage[usageInfos.length];
for (int i = 0; i < usages.length; i++) {
usages[i] = convert(usageInfos[i]);
}
return usages;
}
}
@@ -2,20 +2,23 @@ package com.intellij.usages.impl;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.ToggleAction;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.actionSystem.ToggleAction;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.usages.impl.rules.ImportFilteringRule;
import com.intellij.usages.impl.rules.ReadAccessFilteringRule;
import com.intellij.usages.impl.rules.WriteAccessFilteringRule;
import com.intellij.usages.rules.UsageFilteringRule;
import com.intellij.usages.rules.UsageFilteringRuleProvider;
import com.intellij.util.Icons;
import org.jdom.Element;
import javax.swing.*;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import java.awt.event.KeyEvent;
/**
* Created by IntelliJ IDEA.
@@ -25,22 +28,35 @@ import java.awt.event.KeyEvent;
* To change this template use File | Settings | File Templates.
*/
public class UsageFilteringRuleProviderImpl extends UsageFilteringRuleProvider implements ApplicationComponent, JDOMExternalizable {
public boolean FILTER_IMPORTS = false;
public boolean SHOW_IMPORTS = true;
public boolean SHOW_READ_ACCESS = true;
public boolean SHOW_WRITE_ACCESS = true;
public UsageFilteringRule[] getActiveRules(Project project) {
final List<UsageFilteringRule> rules = new ArrayList<UsageFilteringRule>();
if (FILTER_IMPORTS) {
if (!SHOW_IMPORTS) {
rules.add(new ImportFilteringRule());
}
if (!SHOW_READ_ACCESS) {
rules.add(new ReadAccessFilteringRule());
}
if (!SHOW_WRITE_ACCESS) {
rules.add(new WriteAccessFilteringRule());
}
return rules.toArray(new UsageFilteringRule[rules.size()]);
}
public AnAction[] createFilteringActions(UsageViewImpl view) {
final ShowImportsAction showImportsAction = new ShowImportsAction(view);
showImportsAction.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_I, KeyEvent.CTRL_DOWN_MASK)), view.getComponent());
return new AnAction[] {
showImportsAction,
};
final ShowReadAccessUsagesAction showReadAccessUsagesAction = new ShowReadAccessUsagesAction(view);
showReadAccessUsagesAction.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK)), view.getComponent());
final ShowWriteAccessUsagesAction showWriteAccessUsagesAction = new ShowWriteAccessUsagesAction(view);
showWriteAccessUsagesAction.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_W, KeyEvent.CTRL_DOWN_MASK)), view.getComponent());
return new AnAction[] {showImportsAction, showReadAccessUsagesAction, showWriteAccessUsagesAction};
}
private class ShowImportsAction extends ToggleAction {
@@ -52,11 +68,47 @@ public class UsageFilteringRuleProviderImpl extends UsageFilteringRuleProvider i
}
public boolean isSelected(AnActionEvent e) {
return !FILTER_IMPORTS;
return SHOW_IMPORTS;
}
public void setSelected(AnActionEvent e, boolean state) {
FILTER_IMPORTS = !state;
SHOW_IMPORTS = state;
myView.rulesChanged();
}
}
private class ShowReadAccessUsagesAction extends ToggleAction {
private UsageViewImpl myView;
public ShowReadAccessUsagesAction(UsageViewImpl view) {
super("Show read access", null, IconLoader.getIcon("/actions/showReadAccess.png"));
myView = view;
}
public boolean isSelected(AnActionEvent e) {
return SHOW_READ_ACCESS;
}
public void setSelected(AnActionEvent e, boolean state) {
SHOW_READ_ACCESS = state;
myView.rulesChanged();
}
}
private class ShowWriteAccessUsagesAction extends ToggleAction {
private UsageViewImpl myView;
public ShowWriteAccessUsagesAction(UsageViewImpl view) {
super("Show write access", null, IconLoader.getIcon("/actions/showWriteAccess.png"));
myView = view;
}
public boolean isSelected(AnActionEvent e) {
return SHOW_WRITE_ACCESS;
}
public void setSelected(AnActionEvent e, boolean state) {
SHOW_WRITE_ACCESS = state;
myView.rulesChanged();
}
}
@@ -375,25 +375,33 @@ public class UsageViewImpl implements UsageView {
}
public void appendUsage(Usage usage) {
UsageNode node = myBuilder.appendUsage(usage);
if (myUsageNodes.size() == 0) { //first usage
TreePath usagePath = new TreePath(node.getPath());
myTree.expandPath(usagePath.getParentPath());
myTree.setSelectionPath(usagePath);
final UsageNode node = myBuilder.appendUsage(usage);
if (node != null) {
if (myUsageNodes.size() == 0) { //first usage
TreePath usagePath = new TreePath(node.getPath());
myTree.expandPath(usagePath.getParentPath());
myTree.setSelectionPath(usagePath);
}
}
myUsageNodes.put(usage, node);
}
public void includeUsages(Usage[] usages) {
for (int i = 0; i < usages.length; i++) {
myUsageNodes.get(usages[i]).setUsageExcluded(false);
final UsageNode node = myUsageNodes.get(usages[i]);
if (node != null) {
node.setUsageExcluded(false);
}
}
updateImmediately();
}
public void excludeUsages(Usage[] usages) {
for (int i = 0; i < usages.length; i++) {
myUsageNodes.get(usages[i]).setUsageExcluded(true);
final UsageNode node = myUsageNodes.get(usages[i]);
if (node != null) {
node.setUsageExcluded(true);
}
}
updateImmediately();
}
@@ -560,15 +568,14 @@ public class UsageViewImpl implements UsageView {
}
private Set<Usage> getReadOnlyUsages() {
Set<Usage> result = new HashSet<Usage>();
Collection<UsageNode> usageNodes = myUsageNodes.values();
for (Iterator<UsageNode> i = usageNodes.iterator(); i.hasNext();) {
UsageNode node = i.next();
if (node.getUsage().isReadOnly()) {
result.add(node.getUsage());
final Set<Usage> result = new HashSet<Usage>();
final Collection<Usage> usages = myUsageNodes.keySet();
for (Iterator<Usage> i = usages.iterator(); i.hasNext();) {
Usage usage = i.next();
if (usage.isReadOnly()) {
result.add(usage);
}
}
return result;
}
@@ -594,8 +601,13 @@ public class UsageViewImpl implements UsageView {
Set<Usage> result = new HashSet<Usage>();
Collection<UsageNode> usageNodes = myUsageNodes.values();
for (Iterator<UsageNode> i = usageNodes.iterator(); i.hasNext();) {
UsageNode node = i.next();
if (node.isExcluded()) result.add(node.getUsage());
final UsageNode node = i.next();
if (node == null) {
continue;
}
if (node.isExcluded()) {
result.add(node.getUsage());
}
}
return result;
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.usages.impl.rules;
import com.intellij.usages.rules.UsageFilteringRule;
import com.intellij.usages.rules.PsiElementUsage;
import com.intellij.usages.Usage;
import com.intellij.usages.ReadWriteAccessUsage;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
/**
* @author Eugene Zhuravlev
* Date: Jan 17, 2005
*/
public class ReadAccessFilteringRule implements UsageFilteringRule{
public boolean isVisible(Usage usage) {
if (usage instanceof ReadWriteAccessUsage) {
final ReadWriteAccessUsage readWriteAccessUsage = (ReadWriteAccessUsage)usage;
final boolean isForReadingOnly = readWriteAccessUsage.isAccessedForReading() && !readWriteAccessUsage.isAccessedForWriting();
return !isForReadingOnly;
}
return true;
}
}
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.usages.impl.rules;
import com.intellij.usages.rules.UsageFilteringRule;
import com.intellij.usages.rules.PsiElementUsage;
import com.intellij.usages.Usage;
import com.intellij.usages.ReadWriteAccessUsage;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
/**
* @author Eugene Zhuravlev
* Date: Jan 17, 2005
*/
public class WriteAccessFilteringRule implements UsageFilteringRule{
public boolean isVisible(Usage usage) {
if (usage instanceof ReadWriteAccessUsage) {
final ReadWriteAccessUsage readWriteAccessUsage = (ReadWriteAccessUsage)usage;
final boolean isForWrightingOnly = readWriteAccessUsage.isAccessedForWriting() && !readWriteAccessUsage.isAccessedForReading();
return !isForWrightingOnly;
}
return true;
}
}
@@ -537,9 +537,7 @@ public class FindUsagesManager {
}
}
private UsageSearcher getUsageSearcher(final PsiElement[] elementsToSearch,
final FindUsagesOptions options,
final PsiFile scopeFile) {
private UsageSearcher getUsageSearcher(final PsiElement[] elementsToSearch, final FindUsagesOptions options, final PsiFile scopeFile) {
return new UsageSearcher() {
public void generate(final Processor<Usage> processor) {
if (scopeFile != null) {
@@ -549,10 +547,10 @@ public class FindUsagesManager {
final PsiElement elementToSearch = elementsToSearch[i];
if (elementToSearch != null && elementToSearch.isValid()) {
FindUsagesUtil.processUsages(elementToSearch, new Processor<UsageInfo>() {
public boolean process(UsageInfo usageInfo) {
return processor.process(new UsageInfo2UsageAdapter(usageInfo));
}
}, options);
public boolean process(UsageInfo usageInfo) {
return processor.process(UsageInfoToUsageConverter.convert(usageInfo));
}
}, options);
}
}
}
@@ -37,7 +37,8 @@ public class FindUsagesUtil {
else{
addElementUsages(element, new Processor<UsageInfo>() {
public boolean process(UsageInfo info) {
boolean isWrite = isAccessedForWriting(info.getElement());
final PsiElement element = info.getElement();
boolean isWrite = (element instanceof PsiExpression)? PsiUtil.isAccessedForWriting(((PsiExpression)element)) : false;
if (isWrite == options.isWriteAccess) {
if (!processor.process(info)) return false;
}
@@ -577,23 +578,4 @@ public class FindUsagesUtil {
}
return true;
}
public static boolean isAccessedForWriting (PsiElement element) {
if (element instanceof PsiReferenceExpression) {
PsiReferenceExpression referent = (PsiReferenceExpression)element;
//[ven] TODO: make a separate highlighting feature
/*if (referent.getParent() instanceof PsiArrayAccessExpression) {
PsiArrayAccessExpression arrayAccess = (PsiArrayAccessExpression)referent.getParent();
while (arrayAccess.getParent() instanceof PsiArrayAccessExpression) arrayAccess =
(PsiArrayAccessExpression)arrayAccess.getParent();
return PsiUtil.isAccessedForWriting(arrayAccess);
}*/
return PsiUtil.isAccessedForWriting(referent);
}
return false;
}
}
@@ -91,7 +91,7 @@ public class UsagesPanel extends JPanel {
private void showUsages(final UsageInfo[] usageInfos) {
try {
Usage[] usages = UsageInfo2UsageAdapter.convert(usageInfos);
Usage[] usages = UsageInfoToUsageConverter.convert(usageInfos);
UsageViewPresentation presentation = new UsageViewPresentation();
presentation.setCodeUsagesString("Usages of the right tree scope selection in the left tree scope selection");
UsageView usageView = myProject.getComponent(UsageViewManager.class).createUsageView(new UsageTarget[0],
@@ -204,7 +204,7 @@ public abstract class BaseRefactoringProcessor {
}
UsageInfo[] usageInfos = viewDescriptor.getUsages();
final Usage[] usages = UsageInfo2UsageAdapter.convert(usageInfos);
final Usage[] usages = UsageInfoToUsageConverter.convert(usageInfos);
for (int i = 0; i < usages.length; i++) {
Usage usage = usages[i];
@@ -28,10 +28,7 @@ import com.intellij.usageView.FindUsagesCommand;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewDescriptor;
import com.intellij.usageView.UsageViewUtil;
import com.intellij.usages.UsageInfo2UsageAdapter;
import com.intellij.usages.UsageTarget;
import com.intellij.usages.UsageViewManager;
import com.intellij.usages.UsageViewPresentation;
import com.intellij.usages.*;
import com.intellij.util.IncorrectOperationException;
import java.util.*;
@@ -825,7 +822,7 @@ public class InheritanceToDelegationProcessor extends BaseRefactoringProcessor {
UsageViewManager manager = myProject.getComponent(UsageViewManager.class);
manager.showUsages(new UsageTarget[]{new PsiElement2UsageTargetAdapter(myClass)},
UsageInfo2UsageAdapter.convert(usages),
UsageInfoToUsageConverter.convert(usages),
presentation);
WindowManager.getInstance().getStatusBar(myProject).setInfo("Instances upcasted to java.lang.Object found");