blob: 4a5344171df8a5aed5780404e452585dee2e23a7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2012 Mylyn project committers 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
*******************************************************************************/
package org.eclipse.mylyn.internal.cdt.ui;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.IBinary;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.IFunction;
import org.eclipse.cdt.core.model.IInclude;
import org.eclipse.cdt.core.model.IMethod;
import org.eclipse.cdt.core.model.IParent;
import org.eclipse.cdt.core.model.ISourceReference;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CElementGrouping;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.mylyn.context.core.AbstractContextStructureBridge;
import org.eclipse.mylyn.context.core.ContextCore;
import org.eclipse.mylyn.context.core.IInteractionElement;
import org.eclipse.ui.views.markers.internal.ConcreteMarker;
/**
* @author Mik Kersten
* @author Jeff Johnston
*/
public class CDTStructureBridge extends AbstractContextStructureBridge {
public final static String CONTENT_TYPE = "c/c++"; //$NON-NLS-1$
public final static int C_SOURCEROOT = 1000;
public CDTStructureBridge() {
}
@Override
public String getContentType() {
return CONTENT_TYPE;
}
@Override
public Object getAdaptedParent(Object object) {
if (object instanceof IFile) {
IFile file = (IFile) object;
return CoreModel.getDefault().create(file.getParent());
} else {
return super.getAdaptedParent(object);
}
}
@Override
public String getParentHandle(String handle) {
ICElement cElement = (ICElement) getObjectForHandle(handle);
if (cElement != null && cElement.getParent() != null) {
return getHandleForElement(cElement.getParent());
} else {
return null;
}
}
@Override
public List<String> getChildHandles(String handle) {
Object object = getObjectForHandle(handle);
if (object instanceof ICElement) {
ICElement element = (ICElement) object;
if (element instanceof IParent) {
IParent parent = (IParent) element;
ICElement[] children;
try {
children = parent.getChildren();
List<String> childHandles = new ArrayList<String>();
for (ICElement element2 : children) {
String childHandle = getHandleIdentifier(element2);
if (childHandle != null) {
childHandles.add(childHandle);
}
}
AbstractContextStructureBridge parentBridge = ContextCore.getStructureBridge(parentContentType);
if (parentBridge != null && ContextCore.CONTENT_TYPE_RESOURCE.equals(parentBridge.getContentType())) {
// TODO: Make sure line below is correct
if (element.getElementType() < ICElement.C_NAMESPACE) {
List<String> resourceChildren = parentBridge.getChildHandles(handle);
if (!resourceChildren.isEmpty()) {
childHandles.addAll(resourceChildren);
}
}
}
return childHandles;
} catch (CModelException e) {
// ignore these, usually indicate no-existent element
}
}
}
return Collections.emptyList();
}
public static ICElement getElementForHandle(String handle) {
return CoreModel.create(handle);
}
@Override
public Object getObjectForHandle(String handle) {
return getElementForHandle(handle);
}
// In the CDT, an ICElement does not have a handle interface like a
// JavaElement. So, to find an element again, we save its CProject name,
// plus its path, plus its element name. The CProject name allows us
// to find the CProject. The path allows us to find the ITranslationUnit.
// The element name (optional) allows us to find an element within the
// TranslationUnit.
public static String getHandleForElement(ICElement element) {
String handle = element.getHandleIdentifier();
if (handle != null && !(element instanceof ICProject)) {
ICProject cProject = element.getCProject();
if (cProject != null) {
String projectHandle = getHandleForElement(cProject);
if (handle.equals(projectHandle)) {
// see bug 328300
return null;
}
}
}
return handle;
}
/**
* Uses resource-compatible path for projects
*/
@Override
public String getHandleIdentifier(Object object) {
if (object instanceof ICElement) {
return getHandleForElement((ICElement) object);
} else {
if (object instanceof IAdaptable) {
Object adapter = ((IAdaptable) object).getAdapter(ICElement.class);
if (adapter instanceof ICElement) {
return getHandleForElement((ICElement) adapter);
}
}
}
return null;
}
@Override
public String getLabel(Object object) {
if (object instanceof ICElement) {
return ((ICElement) object).getElementName();
} else {
return ""; //$NON-NLS-1$
}
}
@Override
public boolean canBeLandmark(String handle) {
ICElement element = (ICElement) getObjectForHandle(handle);
if ((element instanceof IMethod || element instanceof IFunction) && element.exists()) {
return true;
} else {
return false;
}
}
/**
* TODO: figure out if the non ICElement stuff is needed
*/
@Override
public boolean acceptsObject(Object object) {
if (object instanceof IResource) {
object = ((IResource) object).getAdapter(ICElement.class);
}
boolean accepts = (object instanceof ICElement && !(object instanceof IBinary))
|| object instanceof CElementGrouping;
return accepts;
}
@Override
public boolean canFilter(Object object) {
if (object instanceof CElementGrouping) {
try {
CElementGrouping grouping = (CElementGrouping) object;
Object[] elements = grouping.getChildren(grouping);
if (elements != null) {
for (Object adaptable : elements) {
IInteractionElement element = ContextCore.getContextManager().getElement(
getHandleIdentifier(adaptable));
if (element != null && element.getInterest().isInteresting()) {
return false;
}
}
}
} catch (Exception e) {
return false;
}
}
return true;
}
@Override
public boolean isDocument(String handle) {
ICElement element = (ICElement) getObjectForHandle(handle);
return element instanceof ITranslationUnit;
}
@Override
public String getHandleForOffsetInObject(Object object, int offset) {
IMarker marker;
int charStart = 0;
if (object instanceof ConcreteMarker) {
marker = ((ConcreteMarker) object).getMarker();
}
if (object instanceof IMarker) {
marker = (IMarker) object;
} else {
return null;
}
Object attribute = marker.getAttribute(IMarker.CHAR_START, 0);
if (attribute instanceof Integer) {
charStart = ((Integer) attribute).intValue();
}
try {
ITranslationUnit translationUnit = null;
IResource resource = marker.getResource();
if (resource instanceof IFile) {
IFile file = (IFile) resource;
if (CoreModel.isValidTranslationUnitName(null, file.getName())) {
ICElement element = CoreModel.getDefault().create(file);
translationUnit = CoreModel.getDefault().createTranslationUnitFrom(element.getCProject(),
element.getPath());
} else {
return null;
}
}
if (translationUnit != null) {
ICElement cElement = translationUnit.getElementAtOffset(charStart);
if (cElement != null) {
if (cElement instanceof IInclude) {
cElement = cElement.getParent().getParent();
}
return cElement.getElementName();
} else {
return null;
}
} else {
return null;
}
} catch (CModelException e) {
return null;
}
}
@Override
public String getContentType(String elementHandle) {
return getContentType();
}
/**
* Some copying from:
*
* @see org.eclipse.jdt.ui.ProblemsLabelDecorator
*/
public boolean containsProblem(IInteractionElement node) {
try {
ICElement element = (ICElement) getObjectForHandle(node.getHandleIdentifier());
switch (element.getElementType()) {
case ICElement.C_PROJECT:
case ICElement.C_CCONTAINER:
case ICElement.C_VCONTAINER:
return getErrorTicksFromMarkers(element.getResource(), IResource.DEPTH_INFINITE, null);
case ICElement.C_UNIT:
return getErrorTicksFromMarkers(element.getResource(), IResource.DEPTH_ONE, null);
case ICElement.C_USING:
case ICElement.C_NAMESPACE:
case ICElement.C_INCLUDE:
case ICElement.C_TYPEDEF:
case ICElement.C_MACRO:
case ICElement.C_FUNCTION:
case ICElement.C_METHOD:
case ICElement.C_FIELD:
case ICElement.C_VARIABLE_LOCAL:
case ICElement.C_CLASS:
ITranslationUnit cu = (ITranslationUnit) element.getAncestor(ICElement.C_UNIT);
if (cu != null) {
return getErrorTicksFromMarkers(element.getResource(), IResource.DEPTH_ONE, null);
}
}
} catch (CoreException e) {
// ignore
}
return false;
}
private boolean getErrorTicksFromMarkers(IResource res, int depth, ISourceReference sourceElement)
throws CoreException {
if (res == null || !res.isAccessible()) {
return false;
}
IMarker[] markers = res.findMarkers(IMarker.PROBLEM, true, depth);
if (markers != null) {
for (IMarker curr : markers) {
if (sourceElement == null) {
int priority = curr.getAttribute(IMarker.SEVERITY, -1);
if (priority == IMarker.SEVERITY_ERROR) {
return true;
}
}
}
}
return false;
}
}