blob: 67900c4e72b6fc0cc1740504ffd34ca2d9f773f5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2009 Wind River Systems, Inc. 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:
* Markus Schorn - initial API and implementation
* Ed Swartz (Nokia)
* IBM Corporation
*******************************************************************************/
/* -- ST-Origin --
* Source folder: org.eclipse.cdt.ui/src
* Class: org.eclipse.cdt.internal.ui.viewsupport.IndexUI
* Version: 1.23
*/
package org.eclipse.ptp.internal.rdt.core.index;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.ICompositeType;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IEnumerator;
import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IIndexLocationConverter;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.index.IndexLocationFactory;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.IInclude;
import org.eclipse.cdt.core.model.ISourceRange;
import org.eclipse.cdt.core.model.ISourceReference;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.internal.core.index.IndexFileLocation;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.ptp.internal.rdt.core.model.BindingAdapter;
import org.eclipse.ptp.internal.rdt.core.model.CElement;
import org.eclipse.ptp.internal.rdt.core.model.ICProjectFactory;
import org.eclipse.ptp.internal.rdt.core.model.TranslationUnit;
import org.eclipse.ptp.rdt.core.RDTLog;
import org.eclipse.ptp.rdt.core.activator.Activator;
public class IndexQueries {
private static final ICElement[] EMPTY_ELEMENTS = new ICElement[0];
public static IIndexBinding elementToBinding(IIndex index, ICElement element) throws CoreException {
if (element instanceof ISourceReference) {
ISourceReference sf = ((ISourceReference)element);
ISourceRange range= sf.getSourceRange();
if (range.getIdLength() != 0) {
IIndexName name= remoteElementToName(index, element);
if (name != null) {
return index.findBinding(name);
}
}
else {
String name= element.getElementName();
name= name.substring(name.lastIndexOf(':')+1);
IIndexBinding[] bindings= index.findBindings(name.toCharArray(), IndexFilter.ALL, new NullProgressMonitor());
for (int i = 0; i < bindings.length; i++) {
IIndexBinding binding = bindings[i];
if (checkBinding(binding, element)) {
return binding;
}
}
}
}
return null;
}
private static boolean checkBinding(IIndexBinding binding, ICElement element) {
try {
switch(element.getElementType()) {
case ICElement.C_ENUMERATION:
return binding instanceof IEnumeration;
case ICElement.C_NAMESPACE:
return binding instanceof ICPPNamespace;
case ICElement.C_STRUCT_DECLARATION:
case ICElement.C_STRUCT:
return binding instanceof ICompositeType &&
((ICompositeType) binding).getKey() == ICompositeType.k_struct;
case ICElement.C_CLASS:
case ICElement.C_CLASS_DECLARATION:
return binding instanceof ICPPClassType &&
((ICompositeType) binding).getKey() == ICPPClassType.k_class;
case ICElement.C_UNION:
case ICElement.C_UNION_DECLARATION:
return binding instanceof ICompositeType &&
((ICompositeType) binding).getKey() == ICompositeType.k_union;
case ICElement.C_TYPEDEF:
return binding instanceof ITypedef;
case ICElement.C_METHOD:
case ICElement.C_METHOD_DECLARATION:
return binding instanceof ICPPMethod;
case ICElement.C_FIELD:
return binding instanceof IField;
case ICElement.C_FUNCTION:
case ICElement.C_FUNCTION_DECLARATION:
return binding instanceof ICPPFunction && !(binding instanceof ICPPMethod);
case ICElement.C_VARIABLE:
case ICElement.C_VARIABLE_DECLARATION:
return binding instanceof IVariable;
case ICElement.C_ENUMERATOR:
return binding instanceof IEnumerator;
case ICElement.C_TEMPLATE_CLASS:
case ICElement.C_TEMPLATE_CLASS_DECLARATION:
case ICElement.C_TEMPLATE_STRUCT:
case ICElement.C_TEMPLATE_STRUCT_DECLARATION:
case ICElement.C_TEMPLATE_UNION:
case ICElement.C_TEMPLATE_UNION_DECLARATION:
return binding instanceof ICPPClassTemplate;
case ICElement.C_TEMPLATE_FUNCTION:
case ICElement.C_TEMPLATE_FUNCTION_DECLARATION:
return binding instanceof ICPPFunctionTemplate && !(binding instanceof ICPPMethod);
case ICElement.C_TEMPLATE_METHOD_DECLARATION:
case ICElement.C_TEMPLATE_METHOD:
return binding instanceof ICPPFunctionTemplate && binding instanceof ICPPMethod;
case ICElement.C_TEMPLATE_VARIABLE:
return binding instanceof ICPPTemplateParameter;
}
} catch (DOMException e) {
// index bindings don't throw the DOMException.
}
return false;
}
public static IIndexName elementToName(IIndex index, ICElement element) throws CoreException {
if (element instanceof ISourceReference) {
ISourceReference sf = ((ISourceReference)element);
ITranslationUnit tu= sf.getTranslationUnit();
if (tu != null) {
IIndexFileLocation location= IndexLocationFactory.getIFL(tu);
if (location != null) {
IIndexFile[] files= index.getFiles(location);
for (int i = 0; i < files.length; i++) {
IIndexFile file = files[i];
String elementName= element.getElementName();
int idx= elementName.lastIndexOf(":")+1; //$NON-NLS-1$
ISourceRange pos= sf.getSourceRange();
// IRegion region = getConvertedRegion(tu, file, pos.getIdStartPos()+idx, pos.getIdLength()-idx);
int offset = pos.getIdStartPos()+idx;
int length = pos.getIdLength()-idx;
IIndexName[] names= file.findNames(offset, length);
for (int j = 0; j < names.length; j++) {
IIndexName name = names[j];
if (!name.isReference() && elementName.endsWith(new String(name.toCharArray()))) {
return name;
}
}
}
}
}
}
return null;
}
public static IIndexName remoteElementToName(IIndex index, ICElement element) throws CoreException {
if (element instanceof ISourceReference) {
ISourceReference sf = ((ISourceReference)element);
ITranslationUnit tu= sf.getTranslationUnit();
if (tu != null) {
URI uri = null;
try {
uri = convertRemoteURIToLocal(tu.getLocationURI());
} catch (URISyntaxException e) {
RDTLog.logError(e);
}
IIndexFileLocation location = null;
if(uri != null)
location = new IndexFileLocation(uri, null);
if (location != null) {
IIndexFile[] files= index.getFiles(location);
for (int i = 0; i < files.length; i++) {
IIndexFile file = files[i];
String elementName= element.getElementName();
int idx= elementName.lastIndexOf(":")+1; //$NON-NLS-1$
ISourceRange pos= sf.getSourceRange();
// IRegion region = getConvertedRegion(tu, file, pos.getIdStartPos()+idx, pos.getIdLength()-idx);
int offset = pos.getIdStartPos()+idx;
int length = pos.getIdLength()-idx;
IIndexName[] names= file.findNames(offset, length);
for (int j = 0; j < names.length; j++) {
IIndexName name = names[j];
if (!name.isReference() && elementName.endsWith(new String(name.toCharArray()))) {
return name;
}
}
}
}
}
}
return null;
}
private static URI convertRemoteURIToLocal(URI locationURI) throws URISyntaxException {
URI uri = new URI("file", null, locationURI.getPath(), null); //$NON-NLS-1$
return uri;
}
public static boolean isIndexed(IIndex index, ICElement element) throws CoreException {
if (element instanceof ISourceReference) {
ISourceReference sf = ((ISourceReference)element);
ITranslationUnit tu= sf.getTranslationUnit();
if (tu != null) {
IIndexFileLocation location= IndexLocationFactory.getIFL(tu);
if (location != null) {
IIndexFile[] files= index.getFiles(location);
return files.length > 0;
}
}
}
return false;
}
public static IIndexInclude elementToInclude(IIndex index, IInclude include) throws CoreException {
if (include != null) {
ITranslationUnit tu= include.getTranslationUnit();
if (tu != null) {
IIndexFileLocation location= IndexLocationFactory.getIFL(tu);
if (location != null) {
IIndexFile[] files= index.getFiles(location);
for (int j=0; j<files.length; j++) {
IIndexFile file= files[j];
String elementName= include.getElementName();
elementName= elementName.substring(elementName.lastIndexOf('/')+1);
ISourceRange pos= include.getSourceRange();
//IRegion region= getConvertedRegion(tu, file, pos.getIdStartPos(), pos.getIdLength());
int offset = pos.getIdStartPos();
IIndexInclude[] includes= index.findIncludes(file);
int bestDiff= Integer.MAX_VALUE;
IIndexInclude best= null;
for (int i = 0; i < includes.length; i++) {
IIndexInclude candidate = includes[i];
int diff= Math.abs(candidate.getNameOffset()- offset);
if (diff > bestDiff) {
break;
}
if (candidate.getName().endsWith(elementName)) {
bestDiff= diff;
best= candidate;
}
}
return best;
}
}
}
}
return null;
}
public static ICElement[] findRepresentative(IIndex index, IBinding binding, IIndexLocationConverter converter, ICProject preferProject, ICProjectFactory projectFactory) throws CoreException {
ICElement[] defs = findAllDefinitions(index, binding, converter, preferProject, projectFactory);
if (defs.length == 0) {
ICElement elem = findAnyDeclaration(index, preferProject, binding, converter, projectFactory);
if (elem != null) {
defs = new ICElement[] { elem };
}
}
return defs;
}
public static ICElement[] findAllDefinitions(IIndex index, IBinding binding, IIndexLocationConverter converter, ICProject preferProject, ICProjectFactory projectFactory) throws CoreException {
if (binding != null) {
IIndexName[] defs= index.findNames(binding, IIndex.FIND_DEFINITIONS | IIndex.SEARCH_ACROSS_LANGUAGE_BOUNDARIES);
ArrayList<ICElement> result= new ArrayList<ICElement>();
for (int i = 0; i < defs.length; i++) {
IIndexName in = defs[i];
ICElement definition= getCElementForName(preferProject, index, in, converter, projectFactory);
if (definition != null) {
result.add(definition);
}
}
return result.toArray(new ICElement[result.size()]);
}
return EMPTY_ELEMENTS;
}
/**
* Creates CElementHandles for definitions or declarations when you expect to find those
* in the index.
* @param preferProject
* @param index
* @param declName
* @return the ICElementHandle or <code>null</code>.
*/
public static ICElement getCElementForName(ICProject preferProject, IIndex index, IASTName declName, IIndexLocationConverter converter, ICProjectFactory projectFactory)
throws CoreException {
assert !declName.isReference();
IBinding binding= declName.resolveBinding();
if (binding != null) {
ICProject cProject = preferProject;
if(preferProject == null) {
cProject = projectFactory.getProjectForFile(declName.getFileLocation().getFileName());
}
ITranslationUnit tu= getTranslationUnit(cProject, declName, converter);
if (tu != null) {
// IFile file= (IFile) tu.getResource();
// long timestamp= file != null ? file.getLocalTimeStamp() : 0;
IASTFileLocation loc= declName.getFileLocation();
// IRegion region= new Region(loc.getNodeOffset(), loc.getNodeLength());
// IPositionConverter converter= CCorePlugin.getPositionTrackerManager().findPositionConverter(tu, timestamp);
// if (converter != null) {
// region= converter.actualToHistoric(region);
// }
try {
return BindingAdapter.adaptBinding(tu, binding, loc.getNodeOffset(), loc.getNodeLength(), declName.isDefinition());
} catch (DOMException e) {
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "", e)); //$NON-NLS-1$
}
}
}
return null;
}
public static ITranslationUnit getTranslationUnit(ICProject cproject, IName name, IIndexLocationConverter converter) {
return getTranslationUnit(cproject, name.getFileLocation(), converter);
}
private static ITranslationUnit getTranslationUnit(ICProject cproject, final IASTFileLocation fileLocation,
IIndexLocationConverter converter) {
if (converter == null)
throw new IllegalArgumentException();
if (fileLocation != null) {
IPath path = Path.fromOSString(fileLocation.getFileName());
if (converter != null) {
IIndexFileLocation location = converter.fromInternalFormat(fileLocation.getFileName());
TranslationUnit unit = new TranslationUnit(cproject, path.lastSegment(), cproject == null ? null : cproject
.getElementName(), location.getURI());
return unit;
}
}
return null;
}
public static ICElement getCElementForName(ICProject preferProject, IIndex index, IIndexName declName, IIndexLocationConverter converter, ICProjectFactory projectFactory)
throws CoreException {
assert !declName.isReference();
ICProject cProject = preferProject;
if(preferProject == null) {
cProject = projectFactory.getProjectForFile(declName.getFileLocation().getFileName());
}
ITranslationUnit tu= getTranslationUnit(cProject, declName, converter);
if (tu != null) {
return getCElementForName(tu, index, declName, projectFactory);
}
return null;
}
public static ICElement getCElementForName(ITranslationUnit tu, IIndex index, IIndexName declName, ICProjectFactory projectFactory)
throws CoreException {
// IRegion region= new Region(declName.getNodeOffset(), declName.getNodeLength());
// long timestamp= declName.getFile().getTimestamp();
try {
return BindingAdapter.adaptBinding(tu, index.findBinding(declName), declName.getNodeOffset(), declName.getNodeLength(), declName.isDefinition());
} catch (DOMException e) {
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "", e)); //$NON-NLS-1$
}
}
public static ICElement findAnyDeclaration(IIndex index, ICProject preferProject, IBinding binding, IIndexLocationConverter converter, ICProjectFactory projectFactory)
throws CoreException {
if (binding != null) {
IIndexName[] names= index.findNames(binding, IIndex.FIND_DECLARATIONS);
for (int i = 0; i < names.length; i++) {
ICElement elem= getCElementForName(preferProject, index, names[i], converter, projectFactory);
if (elem != null) {
return elem;
}
}
}
return null;
}
public static ICElement attemptConvertionToHandle(IIndex index, ICElement input, IIndexLocationConverter converter, ICProjectFactory projectFactory) throws CoreException {
if (input instanceof CElement) {
return input;
}
IIndexName name= elementToName(index, input);
if (name != null) {
ICElement handle= getCElementForName(input.getCProject(), index, name, converter, projectFactory);
if (handle != null) {
return handle;
}
}
return input;
}
public static IASTName getSelectedName(IIndex index, ITranslationUnit workingCopy, int selectionStart, int selectionLength) throws CoreException {
if (workingCopy == null)
return null;
int options= ITranslationUnit.AST_SKIP_INDEXED_HEADERS;
IASTTranslationUnit ast = workingCopy.getAST(index, options);
return ast.getNodeSelector(null).findEnclosingName(selectionStart, selectionLength);
}
}