blob: 8c6661c0b8a68c5984bce3d492a3156bfc725c91 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 IBM Corporation and others. All rights reserved. This
* program and the accompanying materials are made available under the terms of
* the Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors: Sian January - initial version
******************************************************************************/
package org.eclipse.ajdt.internal.ui.visualiser;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import org.aspectj.asm.IProgramElement;
import org.aspectj.asm.IRelationship;
import org.eclipse.ajdt.core.javaelements.IAJCodeElement;
import org.eclipse.ajdt.core.model.AJProjectModelFacade;
import org.eclipse.ajdt.core.model.AJProjectModelFactory;
import org.eclipse.ajdt.core.model.AJRelationshipManager;
import org.eclipse.ajdt.core.model.AJRelationshipType;
import org.eclipse.ajdt.internal.ui.resources.AspectJImages;
import org.eclipse.ajdt.internal.ui.text.UIMessages;
import org.eclipse.ajdt.ui.AspectJUIPlugin;
import org.eclipse.contribution.visualiser.VisualiserPlugin;
import org.eclipse.contribution.visualiser.core.ProviderManager;
import org.eclipse.contribution.visualiser.core.Stripe;
import org.eclipse.contribution.visualiser.interfaces.IMarkupKind;
import org.eclipse.contribution.visualiser.interfaces.IMember;
import org.eclipse.contribution.visualiser.jdtImpl.JDTMember;
import org.eclipse.contribution.visualiser.markerImpl.ResourceMember;
import org.eclipse.contribution.visualiser.simpleImpl.SimpleMarkupKind;
import org.eclipse.contribution.visualiser.simpleImpl.SimpleMarkupProvider;
import org.eclipse.contribution.visualiser.simpleImpl.StealthMarkupKind;
import org.eclipse.contribution.visualiser.utils.JDTUtils;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.ui.IActionBars;
/**
* Markup provider for AJDT
*/
public class AJDTMarkupProvider extends SimpleMarkupProvider {
private IAction hideErrorsAction;
private Action hideWarningsAction;
private boolean hideErrors;
private boolean hideWarnings;
private Map<String, IMarkupKind> kindMap;
protected static final String aspectJErrorKind = "declare error"; //$NON-NLS-1$
protected static final String aspectJWarningKind = "declare warning"; //$NON-NLS-1$
protected Map<String, String> savedColours;
private static Color aspectJErrorColor = new Color(null, new RGB(228,5,64));
private static Color aspectJWarningColor = new Color(null, new RGB(255,206,90));
private Action resetColorMemoryAction;
private static String resetColorMemoryID = "ResetColorMemoryUniqueID32dfnio239"; //$NON-NLS-1$
private IPreferenceStore prefs = AspectJUIPlugin.getDefault().getPreferenceStore();
private static final String allPrefereceKeys = "AJDTVisualiserMarkupProvider.allPrefereceKeys"; //$NON-NLS-1$
/**
* Get a List of Stripes for the given member, which are its markups.
*/
public List<Stripe> getMemberMarkups(IMember member) {
if(kindMap == null) {
updateModel();
}
List markupList = super.getMemberMarkups(member);
if(markupList != null) {
return checkErrorsAndWarnings(markupList);
}
return null;
}
private void updateModel() {
if(ProviderManager.getContentProvider() instanceof AJDTContentProvider) {
IJavaProject jp = ((AJDTContentProvider)ProviderManager.getContentProvider()).getCurrentProject();
if( jp != null) {
AJProjectModelFacade model = AJProjectModelFactory.getInstance().getModelForProject(jp.getProject());
Collection<IRelationship> allRelationships = model.getRelationshipsForProject(
new AJRelationshipType[] {AJRelationshipManager.ADVISED_BY, AJRelationshipManager.ANNOTATED_BY,
AJRelationshipManager.ASPECT_DECLARATIONS, AJRelationshipManager.MATCHES_DECLARE});
if(allRelationships != null) {
for (IRelationship relationship : allRelationships) {
List<IMarkupKind> kinds = new ArrayList<IMarkupKind>();
IProgramElement sourceIpe = model.getProgramElement(relationship.getSourceHandle());
if(sourceIpe != null) {
List<String> targets = relationship.getTargets();
for (String targetStr : targets) {
IJavaElement target = model.programElementToJavaElement(targetStr);
String simpleName;
String qualifiedName;
if(!(target instanceof IAJCodeElement)) {
IJavaElement enclosingType = target.getAncestor(IJavaElement.TYPE);
if (enclosingType == null) {
// Bug 324706 I don't know why the sloc is null. Log the bug and
// continue on.
String handleIdentifier;
try {
if (target.getElementName().equals(AJProjectModelFacade.ERROR_JAVA_ELEMENT.getElementName())) {
handleIdentifier = AJProjectModelFacade.ERROR_JAVA_ELEMENT.getElementName();
} else {
handleIdentifier = target.getHandleIdentifier();
}
} catch (NullPointerException e) {
VisualiserPlugin.log(IStatus.WARNING,
"Error computeing handle identifier");
handleIdentifier = "<CAN'T COMPUTE>";
}
VisualiserPlugin.log(IStatus.WARNING,
"Bug 324706: null containing type found for " + target.getElementName() +
"\nHandle identifier is: " + handleIdentifier);
// avoid an npe
continue;
}
simpleName = enclosingType.getElementName();
qualifiedName = ((IType) enclosingType).getFullyQualifiedName('.');
} else { // It's an injar aspect so we wno't be able to find the parents
qualifiedName = target.getElementName();
String[] parts = qualifiedName.split(" "); //$NON-NLS-1$
String aNameWithExtension = parts[parts.length - 1];
if(aNameWithExtension.indexOf('.') != -1) { // $NON-NLS-1$
simpleName = aNameWithExtension.substring(0, aNameWithExtension.lastIndexOf('.')); // $NON-NLS-1$
} else {
simpleName = aNameWithExtension;
}
}
if (sourceIpe.getSourceLocation() == null) {
// Bug 324706 I don't know why the sloc is null. Log the bug and
// continue on.
VisualiserPlugin.log(IStatus.WARNING,
"Bug 324706: Warning, null source location found in " + sourceIpe.getName() +
"\nHandle identifier is: " + sourceIpe.getHandleIdentifier());
// avoid an npe
continue;
}
int lineNum = sourceIpe.getSourceLocation().getLine();
IJavaElement sourceJe = model.programElementToJavaElement(relationship.getSourceHandle());
if (sourceJe != null) {
IJavaElement compilationUnitAncestor = sourceJe.getAncestor(IJavaElement.COMPILATION_UNIT);
if(compilationUnitAncestor != null) {
String memberName = compilationUnitAncestor.getElementName();
memberName = memberName.substring(0, memberName.lastIndexOf(".")); //$NON-NLS-1$
String packageName = sourceJe.getAncestor(IJavaElement.PACKAGE_FRAGMENT).getElementName();
if(!(packageName.equals(""))) { //$NON-NLS-1$
memberName = packageName + "." + memberName; //$NON-NLS-1$
}
IMarkupKind markupKind = null;
if(kindMap == null) {
kindMap = new HashMap<String, IMarkupKind>();
}
if(relationship.getName().equals(AJRelationshipManager.MATCHES_DECLARE.getDisplayName())) {
String sourceName = target.getElementName();
boolean errorKind = sourceName.startsWith(aspectJErrorKind);
if(kindMap.get(sourceName + ":::" + qualifiedName) instanceof IMarkupKind) { //$NON-NLS-1$
markupKind = kindMap.get(sourceName + ":::" + qualifiedName); //$NON-NLS-1$
} else {
markupKind = new ErrorOrWarningMarkupKind(sourceName + ":::" + simpleName, errorKind); //$NON-NLS-1$
kindMap.put(sourceName + ":::" + qualifiedName, markupKind); //$NON-NLS-1$
}
} else {
if(kindMap.get(qualifiedName) instanceof IMarkupKind) {
markupKind = kindMap.get(qualifiedName);
} else {
markupKind = new SimpleMarkupKind(simpleName, qualifiedName);
kindMap.put(qualifiedName, markupKind);
}
}
kinds.add(markupKind);
Stripe stripe = new Stripe(kinds, lineNum, 1);
addMarkup(memberName, stripe);
}
}
}
}
}
}
}
}
processMarkups();
}
/**
* @param kinds
* @return
*/
private List<Stripe> checkErrorsAndWarnings(List stripes) {
List<Stripe> returningStripes = new ArrayList<Stripe>();
for (Iterator iter = stripes.iterator(); iter.hasNext();) {
Stripe stripe = (Stripe) iter.next();
List<IMarkupKind> kinds = new ArrayList<IMarkupKind>(stripe.getKinds());
for (Iterator<IMarkupKind> iterator = kinds.iterator(); iterator.hasNext();) {
IMarkupKind kind = iterator.next();
if(kind instanceof StealthMarkupKind) {
String name = kind.getName();
String[] parts = name.split(":::"); //$NON-NLS-1$
if(parts.length > 1) {
String eOrWKind = parts[0];
if(eOrWKind.startsWith(aspectJErrorKind) && hideErrors) {
iterator.remove();
continue;
}
if(eOrWKind.startsWith(aspectJWarningKind) && hideWarnings) {
iterator.remove();
continue;
}
String aspectName = parts[1];
if(VisualiserPlugin.menu != null) {
if(!VisualiserPlugin.menu.getActive(aspectName)) {
iterator.remove();
}
}
}
}
}
if(kinds.size() > 0) {
Stripe newStripe = new Stripe(kinds, stripe.getOffset(), stripe.getDepth());
returningStripes.add(newStripe);
}
}
return returningStripes;
}
/**
* Get the colour for a given kind
* @param kind - the kind
* @return the Color for that kind
*/
public Color getColorFor(IMarkupKind kind){
if(kind.getName().startsWith(aspectJErrorKind)) {
return aspectJErrorColor;
} else if (kind.getName().startsWith(aspectJWarningKind)) {
return aspectJWarningColor;
} else {
Color savedColor = getSavedColour(kind.getFullName());
if(savedColor == null) {
return super.getColorFor(kind);
} else {
return savedColor;
}
}
}
/**
* Set the color for a kind.
* @param string - the kind
* @param color - the Color
*/
public void setColorFor(IMarkupKind kind, Color color) {
super.setColorFor(kind, color);
saveColourForAspect(kind.getFullName(), color.getRed(), color.getGreen(), color.getBlue());
}
/**
* Get all the markup kinds.
* @return a Set of IMarkupKinds
*/
public SortedSet<IMarkupKind> getAllMarkupKinds() {
if(kindMap == null) {
updateModel();
}
TreeSet<IMarkupKind> kinds = new TreeSet<IMarkupKind>();
if(kindMap != null) {
kinds.addAll(kindMap.values());
}
return kinds;
}
/**
* Process a mouse click on a stripe. This method opens the editor at the line of the stripe clicked.
* @see org.eclipse.contribution.visualiser.interfaces.IMarkupProvider#processMouseclick(java.lang.String, org.eclipse.contribution.visualiser.core.Stripe, int)
*/
public boolean processMouseclick(IMember member, Stripe stripe, int buttonClicked) {
if (buttonClicked == 1) {
if (member instanceof JDTMember) {
IJavaElement jEl = ((JDTMember)member).getResource();
if (jEl != null) {
JDTUtils.openInEditor(jEl.getResource(), stripe.getOffset());
}
} else if (member instanceof ResourceMember) {
IResource res = ((ResourceMember)member).getResource();
if (res != null) {
JDTUtils.openInEditor(res, stripe.getOffset());
}
}
return false;
} else {
return true;
}
}
protected void saveColourForAspect(String aspectName, int r, int g, int b) {
if(ProviderManager.getContentProvider() instanceof AJDTContentProvider) {
IProject currentProject = ((AJDTContentProvider)ProviderManager.getContentProvider()).getCurrentProject().getProject();
String key = currentProject + ":::" + aspectName; //$NON-NLS-1$
if(prefs.getString(key) == null) {
prefs.setDefault(key, ""); //$NON-NLS-1$
}
// Save all keys we add in order that they can be reset.
String allColourKeys = prefs.getString(allPrefereceKeys);
if(allColourKeys == null) {
prefs.putValue(allPrefereceKeys, key);
prefs.setDefault(allPrefereceKeys, ""); //$NON-NLS-1$
} else {
allColourKeys += "," + key; //$NON-NLS-1$
prefs.putValue(allPrefereceKeys, allColourKeys);
}
String value = r + "," + g + "," + b; //$NON-NLS-1$ //$NON-NLS-2$
prefs.setValue(key, value);
if(savedColours == null) {
savedColours = new HashMap<String, String>();
}
savedColours.remove(key);
savedColours.put(key, value);
}
}
/**
* Empty the data structures that contain the stripe and kind information
*/
public void resetMarkupsAndKinds() {
super.resetMarkupsAndKinds();
kindMap = null;
}
protected Color getSavedColour(String aspectName) {
if(ProviderManager.getContentProvider() instanceof AJDTContentProvider) {
IProject currentProject = ((AJDTContentProvider)ProviderManager.getContentProvider()).getCurrentProject().getProject();
String key = currentProject + ":::" + aspectName; //$NON-NLS-1$
if(savedColours == null) {
savedColours = new HashMap<String, String>();
}
String value = savedColours.get(key);
if(value == null) {
IPreferenceStore prefs = AspectJUIPlugin.getDefault().getPreferenceStore();
value = prefs.getString(key);
savedColours.put(key, value);
}
if(value != null && value != "") { //$NON-NLS-1$
String[] rgb = value.split(","); //$NON-NLS-1$
if(rgb.length != 3) {
return null;
} else {
int r = Integer.parseInt(rgb[0]);
int g = Integer.parseInt(rgb[1]);
int b = Integer.parseInt(rgb[2]);
return new Color(null, new RGB(r,g,b));
}
}
}
return null;
}
/**
* Activate the markup provider.
*/
public void activate() {
if(VisualiserPlugin.menu != null) {
resetColorMemoryAction = new Action() {
public void run() {
resetSavedColours();
VisualiserPlugin.refresh();
}
};
resetColorMemoryAction.setImageDescriptor(AspectJImages.RESET_COLOURS.getImageDescriptor());
resetColorMemoryAction.setText(UIMessages.ResetColorMemory);
resetColorMemoryAction.setId(resetColorMemoryID);
hideErrorsAction = new Action() {
public int getStyle() {
return IAction.AS_CHECK_BOX;
}
public void run() {
hideErrors = hideErrorsAction.isChecked();
VisualiserPlugin.refresh();
}
};
hideErrorsAction.setImageDescriptor(AspectJImages.HIDE_ERRORS.getImageDescriptor());
hideErrorsAction.setToolTipText(UIMessages.HideErrors);
hideWarningsAction = new Action() {
public int getStyle() {
return IAction.AS_CHECK_BOX;
}
public void run() {
hideWarnings = hideWarningsAction.isChecked();
VisualiserPlugin.refresh();
}
};
hideWarningsAction.setImageDescriptor(AspectJImages.HIDE_WARNINGS.getImageDescriptor());
hideWarningsAction.setToolTipText(UIMessages.HideWarnings);
IActionBars menuActionBars = VisualiserPlugin.menu.getViewSite().getActionBars();
IToolBarManager toolBarManager = menuActionBars.getToolBarManager();
toolBarManager.add(hideErrorsAction);
toolBarManager.add(hideWarningsAction);
toolBarManager.update(true);
IMenuManager menuManager = menuActionBars.getMenuManager();
menuManager.add(new Separator());
menuManager.add(resetColorMemoryAction);
}
}
/**
* Reset all the saved colours
*/
protected void resetSavedColours() {
String colourKeys = prefs.getString(allPrefereceKeys);
if(colourKeys != null && colourKeys != "") { //$NON-NLS-1$
String[] keys = colourKeys.split(","); //$NON-NLS-1$
for (int i = 0; i < keys.length; i++) {
prefs.setToDefault(keys[i]);
}
prefs.setToDefault(allPrefereceKeys);
}
savedColours = new HashMap<String, String>();
super.resetColours();
}
/**
* Deactivate
*/
public void deactivate() {
super.deactivate();
if(VisualiserPlugin.menu != null) {
IActionBars menuActionBars = VisualiserPlugin.menu.getViewSite().getActionBars();
IToolBarManager toolBarManager = menuActionBars.getToolBarManager();
toolBarManager.removeAll();
toolBarManager.update(true);
IMenuManager menuManager = menuActionBars.getMenuManager();
menuManager.remove(resetColorMemoryID);
menuManager.update(true);
}
}
private class ErrorOrWarningMarkupKind extends StealthMarkupKind {
private boolean errorKind;
private String declaringAspect;
/**
* @param name
*/
public ErrorOrWarningMarkupKind(String name, boolean errorKind) {
super(name);
this.errorKind = errorKind;
String[] nameParts = name.split(":::"); //$NON-NLS-1$
if(nameParts.length > 1) {
declaringAspect = nameParts[1];
}
}
public String toString() {
if (errorKind) {
return UIMessages.AspectJError + ": " + declaringAspect; //$NON-NLS-1$
} else {
return UIMessages.AspectJWarning + ": " + declaringAspect; //$NON-NLS-1$
}
}
}
}