mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Call Hierarchy: Avoid generating AST
This commit is contained in:
parent
96dc647bc7
commit
fb61bc0c35
17 changed files with 428 additions and 538 deletions
|
@ -13,7 +13,9 @@ package org.eclipse.cdt.internal.core.pdom.indexer;
|
|||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
||||
|
@ -23,8 +25,9 @@ abstract public class IndexerASTVisitor extends ASTVisitor {
|
|||
private IASTNode fDefinition;
|
||||
|
||||
public IndexerASTVisitor() {
|
||||
shouldVisitNames = true;
|
||||
shouldVisitDeclarations = true;
|
||||
shouldVisitNames= true;
|
||||
shouldVisitDeclarations= true;
|
||||
shouldVisitInitializers= true;
|
||||
}
|
||||
|
||||
abstract public void visit(IASTName name, IASTName definitionName);
|
||||
|
@ -56,4 +59,15 @@ abstract public class IndexerASTVisitor extends ASTVisitor {
|
|||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
||||
public int visit(IASTInitializer initializer) {
|
||||
if (fDefinition == null) {
|
||||
IASTNode cand= initializer.getParent();
|
||||
if (cand instanceof IASTDeclarator) {
|
||||
fDefinition= cand;
|
||||
fDefinitionName= ((IASTDeclarator) fDefinition).getName();
|
||||
}
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
}
|
|
@ -54,7 +54,7 @@ public class BasicCallHierarchyTest extends CallHierarchyBaseTest {
|
|||
private void doTestFunctions(String filename) throws IOException, Exception, PartInitException {
|
||||
String content = readTaggedComment("testFunctions");
|
||||
IFile file= createFile(getProject(), filename, content);
|
||||
waitForIndexer(fIndex, file, 1000);
|
||||
waitForIndexer(fIndex, file, INDEXER_WAIT_TIME);
|
||||
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
|
||||
CEditor editor= (CEditor) IDE.openEditor(page, file);
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.eclipse.cdt.internal.ui.callhierarchy.CallHierarchyUI;
|
|||
import org.eclipse.cdt.internal.ui.editor.CEditor;
|
||||
|
||||
public class CallHierarchyBaseTest extends BaseUITestCase {
|
||||
protected static final int INDEXER_WAIT_TIME = 8000;
|
||||
|
||||
private ICProject fCProject;
|
||||
protected IIndex fIndex;
|
||||
|
|
|
@ -37,7 +37,7 @@ public class InitializersInCallHierarchyTest extends CallHierarchyBaseTest {
|
|||
public void testCIntVarInitializer() throws Exception {
|
||||
String content = readTaggedComment("intvar");
|
||||
IFile file= createFile(getProject(), "intvar.c", content);
|
||||
waitForIndexer(fIndex, file, 1000);
|
||||
waitForIndexer(fIndex, file, INDEXER_WAIT_TIME);
|
||||
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
|
||||
CEditor editor= (CEditor) IDE.openEditor(page, file);
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
* Markus Schorn - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.internal.ui.missingapi;
|
||||
package org.eclipse.cdt.internal.ui.callhierarchy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
|
@ -12,31 +12,26 @@
|
|||
package org.eclipse.cdt.internal.ui.callhierarchy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||
import org.eclipse.jface.text.Region;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IEnumerator;
|
||||
import org.eclipse.cdt.core.index.IIndex;
|
||||
import org.eclipse.cdt.core.index.IIndexName;
|
||||
import org.eclipse.cdt.core.model.CoreModel;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
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.core.model.IVariable;
|
||||
import org.eclipse.cdt.ui.CUIPlugin;
|
||||
|
||||
import org.eclipse.cdt.internal.corext.util.CModelUtil;
|
||||
|
||||
import org.eclipse.cdt.internal.ui.missingapi.CElementSet;
|
||||
import org.eclipse.cdt.internal.ui.missingapi.CIndexQueries;
|
||||
import org.eclipse.cdt.internal.ui.missingapi.CIndexReference;
|
||||
import org.eclipse.cdt.internal.ui.missingapi.CalledByResult;
|
||||
import org.eclipse.cdt.internal.ui.missingapi.CallsToResult;
|
||||
import org.eclipse.cdt.internal.ui.viewsupport.AsyncTreeContentProvider;
|
||||
import org.eclipse.cdt.internal.ui.viewsupport.WorkingSetFilterUI;
|
||||
|
||||
|
@ -96,107 +91,45 @@ public class CHContentProvider extends AsyncTreeContentProvider {
|
|||
IProgressMonitor monitor) {
|
||||
if (parentElement instanceof CHNode) {
|
||||
CHNode node = (CHNode) parentElement;
|
||||
ICElement elem= node.getRepresentedDeclaration();
|
||||
if (elem != null) {
|
||||
try {
|
||||
if (fComputeReferencedBy) {
|
||||
return asyncronouslyComputeReferencedBy(node, elem);
|
||||
return asyncronouslyComputeReferencedBy(node);
|
||||
}
|
||||
else {
|
||||
return asyncronouslyComputeRefersTo(node, elem);
|
||||
return asyncronouslyComputeRefersTo(node);
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
} catch (DOMException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
return NO_CHILDREN;
|
||||
}
|
||||
|
||||
private Object[] asyncronouslyComputeReferencedBy(CHNode parent, ICElement elem) {
|
||||
private Object[] asyncronouslyComputeReferencedBy(CHNode parent) throws CoreException, InterruptedException, DOMException {
|
||||
ICProject[] scope= CoreModel.getDefault().getCModel().getCProjects();
|
||||
IIndex index= CCorePlugin.getIndexManager().getIndex(scope);
|
||||
index.acquireReadLock();
|
||||
try {
|
||||
ICProject[] scope= CoreModel.getDefault().getCModel().getCProjects();
|
||||
CalledByResult calledBy= CIndexQueries.getInstance().findCalledBy(scope, elem, NPM);
|
||||
ArrayList result= new ArrayList();
|
||||
|
||||
ICElement[] elements= calledBy.getElements();
|
||||
for (int i = 0; i < elements.length; i++) {
|
||||
ICElement element = elements[i];
|
||||
if (element != null) {
|
||||
if (fFilter == null || fFilter.isPartOfWorkingSet(element)) {
|
||||
CIndexReference[] refs= calledBy.getReferences(element);
|
||||
if (refs != null && refs.length > 0) {
|
||||
CHNode node = createRefbyNode(parent, element, refs);
|
||||
result.add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toArray();
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
return CHQueries.findCalledBy(this, parent, index, NPM);
|
||||
}
|
||||
finally {
|
||||
index.releaseReadLock();
|
||||
}
|
||||
return NO_CHILDREN;
|
||||
}
|
||||
|
||||
private CHNode createRefbyNode(CHNode parent, ICElement element, CIndexReference[] refs) {
|
||||
ITranslationUnit tu= CModelUtil.getTranslationUnit(element);
|
||||
CHNode node= new CHNode(parent, tu, refs[0].getTimestamp(), element);
|
||||
if (element instanceof IVariable || element instanceof IEnumerator) {
|
||||
node.setInitializer(true);
|
||||
}
|
||||
Arrays.sort(refs, CIndexReference.COMPARE_OFFSET);
|
||||
for (int i = 0; i < refs.length; i++) {
|
||||
CIndexReference reference = refs[i];
|
||||
node.addReference(new CHReferenceInfo(reference.getOffset(), reference.getLength()));
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
private CHNode createReftoNode(CHNode parent, ITranslationUnit tu, ICElement[] elements, CIndexReference[] references) {
|
||||
assert elements.length > 0;
|
||||
|
||||
CHNode node;
|
||||
long timestamp= references[0].getTimestamp();
|
||||
|
||||
if (elements.length == 1) {
|
||||
node= new CHNode(parent, tu, timestamp, elements[0]);
|
||||
}
|
||||
else {
|
||||
node= new CHMultiDefNode(parent, tu, timestamp, elements);
|
||||
}
|
||||
|
||||
Arrays.sort(references, CIndexReference.COMPARE_OFFSET);
|
||||
for (int i = 0; i < references.length; i++) {
|
||||
CIndexReference reference = references[i];
|
||||
node.addReference(new CHReferenceInfo(reference.getOffset(), reference.getLength()));
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
private Object[] asyncronouslyComputeRefersTo(CHNode parent, ICElement elem) {
|
||||
private Object[] asyncronouslyComputeRefersTo(CHNode parent) throws CoreException, InterruptedException, DOMException {
|
||||
ICProject[] scope= CoreModel.getDefault().getCModel().getCProjects();
|
||||
IIndex index= CCorePlugin.getIndexManager().getIndex(scope);
|
||||
index.acquireReadLock();
|
||||
try {
|
||||
if (elem instanceof ISourceReference) {
|
||||
ISourceReference sf= (ISourceReference) elem;
|
||||
ITranslationUnit tu= sf.getTranslationUnit();
|
||||
ISourceRange range= sf.getSourceRange();
|
||||
ICProject[] scope= CoreModel.getDefault().getCModel().getCProjects();
|
||||
CallsToResult callsTo= CIndexQueries.getInstance().findCallsInRange(scope, tu, new Region(range.getStartPos(), range.getLength()), NPM);
|
||||
ArrayList result= new ArrayList();
|
||||
CElementSet[] elementSets= callsTo.getElementSets();
|
||||
for (int i = 0; i < elementSets.length; i++) {
|
||||
CElementSet set = elementSets[i];
|
||||
if (!set.isEmpty()) {
|
||||
CIndexReference[] refs= callsTo.getReferences(set);
|
||||
ICElement[] elements= set.getElements(fFilter);
|
||||
if (elements.length > 0) {
|
||||
CHNode node = createReftoNode(parent, tu, elements, refs);
|
||||
result.add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toArray();
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
return CHQueries.findCalls(this, parent, index, NPM);
|
||||
}
|
||||
finally {
|
||||
index.releaseReadLock();
|
||||
}
|
||||
return NO_CHILDREN;
|
||||
}
|
||||
|
||||
public void setComputeReferencedBy(boolean value) {
|
||||
|
@ -211,4 +144,75 @@ public class CHContentProvider extends AsyncTreeContentProvider {
|
|||
fFilter= filterUI;
|
||||
recompute();
|
||||
}
|
||||
|
||||
CHNode[] createNodes(CHNode node, CalledByResult result) throws CoreException {
|
||||
ArrayList nodes= new ArrayList();
|
||||
ICElement[] elements= result.getElements();
|
||||
for (int i = 0; i < elements.length; i++) {
|
||||
ICElement element = elements[i];
|
||||
if (element != null) {
|
||||
if (fFilter == null || fFilter.isPartOfWorkingSet(element)) {
|
||||
IIndexName[] refs= result.getReferences(element);
|
||||
if (refs != null && refs.length > 0) {
|
||||
CHNode newNode = createRefbyNode(node, element, refs);
|
||||
nodes.add(newNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (CHNode[]) nodes.toArray(new CHNode[nodes.size()]);
|
||||
}
|
||||
|
||||
private CHNode createRefbyNode(CHNode parent, ICElement element, IIndexName[] refs) throws CoreException {
|
||||
ITranslationUnit tu= CModelUtil.getTranslationUnit(element);
|
||||
CHNode node= new CHNode(parent, tu, refs[0].getFile().getTimestamp(), element);
|
||||
if (element instanceof IVariable || element instanceof IEnumerator) {
|
||||
node.setInitializer(true);
|
||||
}
|
||||
for (int i = 0; i < refs.length; i++) {
|
||||
IIndexName reference = refs[i];
|
||||
node.addReference(new CHReferenceInfo(reference.getNodeOffset(), reference.getNodeLength()));
|
||||
}
|
||||
node.sortReferencesByOffset();
|
||||
return node;
|
||||
}
|
||||
|
||||
CHNode[] createNodes(CHNode node, CallsToResult callsTo) throws CoreException {
|
||||
ITranslationUnit tu= CModelUtil.getTranslationUnit(node.getRepresentedDeclaration());
|
||||
ArrayList result= new ArrayList();
|
||||
CElementSet[] elementSets= callsTo.getElementSets();
|
||||
for (int i = 0; i < elementSets.length; i++) {
|
||||
CElementSet set = elementSets[i];
|
||||
if (!set.isEmpty()) {
|
||||
IIndexName[] refs= callsTo.getReferences(set);
|
||||
ICElement[] elements= set.getElements(fFilter);
|
||||
if (elements.length > 0) {
|
||||
CHNode childNode = createReftoNode(node, tu, elements, refs);
|
||||
result.add(childNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (CHNode[]) result.toArray(new CHNode[result.size()]);
|
||||
}
|
||||
|
||||
private CHNode createReftoNode(CHNode parent, ITranslationUnit tu, ICElement[] elements, IIndexName[] references) throws CoreException {
|
||||
assert elements.length > 0;
|
||||
|
||||
CHNode node;
|
||||
long timestamp= references[0].getFile().getTimestamp();
|
||||
|
||||
if (elements.length == 1) {
|
||||
node= new CHNode(parent, tu, timestamp, elements[0]);
|
||||
}
|
||||
else {
|
||||
node= new CHMultiDefNode(parent, tu, timestamp, elements);
|
||||
}
|
||||
|
||||
for (int i = 0; i < references.length; i++) {
|
||||
IIndexName reference = references[i];
|
||||
node.addReference(new CHReferenceInfo(reference.getNodeOffset(), reference.getNodeLength()));
|
||||
}
|
||||
node.sortReferencesByOffset();
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ import org.eclipse.swt.widgets.Display;
|
|||
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
|
||||
import org.eclipse.cdt.internal.ui.missingapi.CIndexQueries;
|
||||
|
||||
public class CHDropTargetListener implements DropTargetListener {
|
||||
|
||||
|
@ -46,7 +45,7 @@ public class CHDropTargetListener implements DropTargetListener {
|
|||
if (event.detail != DND.DROP_NONE) {
|
||||
if (LocalSelectionTransfer.getTransfer().isSupportedType(event.currentDataType)) {
|
||||
fInput= checkLocalSelection();
|
||||
if (!CIndexQueries.isRelevantForCallHierarchy(fInput)) {
|
||||
if (!CallHierarchyUI.isRelevantForCallHierarchy(fInput)) {
|
||||
event.detail= DND.DROP_NONE;
|
||||
fInput= null;
|
||||
}
|
||||
|
|
|
@ -167,4 +167,10 @@ public class CHNode implements IAdaptable {
|
|||
public void setInitializer(boolean isInitializer) {
|
||||
fIsInitializer = isInitializer;
|
||||
}
|
||||
|
||||
public void sortReferencesByOffset() {
|
||||
if (fReferences.size() > 1) {
|
||||
Collections.sort(fReferences, CHReferenceInfo.COMPARE_OFFSET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,230 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 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
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.internal.ui.callhierarchy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.eclipse.jface.text.IRegion;
|
||||
import org.eclipse.jface.text.Region;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.IPositionConverter;
|
||||
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.IBinding;
|
||||
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.IIndexName;
|
||||
import org.eclipse.cdt.core.model.CModelException;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
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.ui.CUIPlugin;
|
||||
|
||||
import org.eclipse.cdt.internal.core.model.ext.CElementHandleFactory;
|
||||
import org.eclipse.cdt.internal.corext.util.CModelUtil;
|
||||
|
||||
|
||||
/**
|
||||
* Access to high level queries in the index.
|
||||
* @since 4.0
|
||||
*/
|
||||
public class CHQueries {
|
||||
private static final ICElement[] EMPTY_ELEMENTS = new ICElement[0];
|
||||
private static final CHNode[] EMPTY_NODES= new CHNode[0];
|
||||
|
||||
private CHQueries() {}
|
||||
|
||||
/**
|
||||
* Searches for functions and methods that call a given element.
|
||||
* @throws DOMException
|
||||
*/
|
||||
public static CHNode[] findCalledBy(CHContentProvider cp, CHNode node,
|
||||
IIndex index, IProgressMonitor pm) throws CoreException, DOMException {
|
||||
CalledByResult result= new CalledByResult();
|
||||
ICElement callee= node.getRepresentedDeclaration();
|
||||
if (! (callee instanceof ISourceReference)) {
|
||||
return EMPTY_NODES;
|
||||
}
|
||||
IBinding calleeBinding= elementToBinding(index, callee);
|
||||
findCalledBy(index, calleeBinding, callee.getCProject(), result);
|
||||
|
||||
return cp.createNodes(node, result);
|
||||
}
|
||||
|
||||
private static IIndexBinding elementToBinding(IIndex index, ICElement element) throws CoreException {
|
||||
IIndexName name= elementToName(index, element);
|
||||
if (name != null) {
|
||||
return index.findBinding(name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static IIndexName elementToName(IIndex index, ICElement element) throws CoreException {
|
||||
if (element instanceof ISourceReference) {
|
||||
ISourceReference sf = ((ISourceReference)element);
|
||||
ITranslationUnit tu= sf.getTranslationUnit();
|
||||
if (tu != null) {
|
||||
IPath location= tu.getLocation();
|
||||
if (location != null) {
|
||||
IIndexFile file= index.getFile(location);
|
||||
if (file != null) {
|
||||
String elementName= element.getElementName();
|
||||
int idx= elementName.lastIndexOf(":")+1; //$NON-NLS-1$
|
||||
ISourceRange pos= sf.getSourceRange();
|
||||
IRegion region= new Region(pos.getIdStartPos()+idx, pos.getIdLength());
|
||||
IPositionConverter converter= CCorePlugin.getPositionTrackerManager().findPositionConverter(tu, file.getTimestamp());
|
||||
if (converter != null) {
|
||||
region= converter.actualToHistoric(region);
|
||||
}
|
||||
IIndexName[] names= file.findNames(region.getOffset(), region.getLength());
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
IIndexName name = names[i];
|
||||
if (!name.isReference() && elementName.endsWith(new String(name.toCharArray()))) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void findCalledBy(IIndex index, IBinding callee, ICProject project, CalledByResult result) throws CoreException, DOMException {
|
||||
if (callee != null) {
|
||||
IIndexName[] names= index.findReferences(callee);
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
IIndexName rname = names[i];
|
||||
IIndexName caller= rname.getEnclosingDefinition();
|
||||
if (caller != null) {
|
||||
ICElement elem= getCElementForName(project, index, caller);
|
||||
if (elem != null) {
|
||||
result.add(elem, rname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ITranslationUnit getTranslationUnit(ICProject cproject, IName name) {
|
||||
IPath path= Path.fromOSString(name.getFileLocation().getFileName());
|
||||
try {
|
||||
return CModelUtil.findTranslationUnitForLocation(path, cproject);
|
||||
} catch (CModelException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for all calls that are made within a given range.
|
||||
* @throws DOMException
|
||||
*/
|
||||
public static CHNode[] findCalls(CHContentProvider cp, CHNode node, IIndex index, IProgressMonitor pm) throws CoreException, DOMException {
|
||||
ICElement caller= node.getRepresentedDeclaration();
|
||||
CallsToResult result= new CallsToResult();
|
||||
IIndexName callerName= elementToName(index, caller);
|
||||
if (callerName != null) {
|
||||
IIndexName[] refs= callerName.getEnclosedNames();
|
||||
for (int i = 0; i < refs.length; i++) {
|
||||
IIndexName name = refs[i];
|
||||
IBinding binding= index.findBinding(name);
|
||||
if (CallHierarchyUI.isRelevantForCallHierarchy(binding)) {
|
||||
ICElement[] defs = findAllDefinitions(index, binding);
|
||||
if (defs.length == 0) {
|
||||
ICElement elem = findAnyDeclaration(index, null, binding);
|
||||
if (elem != null) {
|
||||
defs = new ICElement[] { elem };
|
||||
}
|
||||
}
|
||||
if (defs != null && defs.length > 0) {
|
||||
result.add(defs, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return cp.createNodes(node, result);
|
||||
}
|
||||
|
||||
public static ICElement[] findAllDefinitions(IIndex index, IBinding binding) throws CoreException, DOMException {
|
||||
if (binding != null) {
|
||||
IIndexName[] defs= index.findDefinitions(binding);
|
||||
|
||||
ArrayList result= new ArrayList();
|
||||
for (int i = 0; i < defs.length; i++) {
|
||||
IIndexName in = defs[i];
|
||||
ICElement definition= getCElementForName(null, index, in);
|
||||
if (definition != null) {
|
||||
result.add(definition);
|
||||
}
|
||||
|
||||
}
|
||||
return (ICElement[]) result.toArray(new ICElement[result.size()]);
|
||||
}
|
||||
return EMPTY_ELEMENTS;
|
||||
}
|
||||
|
||||
static ICElement getCElementForName(ICProject preferProject, IIndex index, IASTName declName) throws CoreException, DOMException {
|
||||
assert !declName.isReference();
|
||||
IBinding binding= declName.resolveBinding();
|
||||
if (binding != null) {
|
||||
ITranslationUnit tu= getTranslationUnit(preferProject, declName);
|
||||
if (tu != null) {
|
||||
IFile file= (IFile) tu.getResource();
|
||||
long timestamp= file.getLocalTimeStamp();
|
||||
IASTFileLocation loc= declName.getFileLocation();
|
||||
IRegion region= new Region(loc.getNodeOffset(), loc.getNodeLength());
|
||||
IPositionConverter converter= CCorePlugin.getPositionTrackerManager().findPositionConverter(file, timestamp);
|
||||
if (converter != null) {
|
||||
region= converter.actualToHistoric(region);
|
||||
}
|
||||
return CElementHandleFactory.create(tu, binding, region, timestamp);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static ICElement getCElementForName(ICProject preferProject, IIndex index, IIndexName declName) throws CoreException, DOMException {
|
||||
assert !declName.isReference();
|
||||
ITranslationUnit tu= getTranslationUnit(preferProject, declName);
|
||||
if (tu != null) {
|
||||
IRegion region= new Region(declName.getNodeOffset(), declName.getNodeLength());
|
||||
long timestamp= declName.getFile().getTimestamp();
|
||||
return CElementHandleFactory.create(tu, index.findBinding(declName), region, timestamp);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ICElement findAnyDeclaration(IIndex index, ICProject preferProject, IBinding binding) throws CoreException, DOMException {
|
||||
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]);
|
||||
if (elem != null) {
|
||||
return elem;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -11,7 +11,16 @@
|
|||
|
||||
package org.eclipse.cdt.internal.ui.callhierarchy;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class CHReferenceInfo {
|
||||
public static final Comparator COMPARE_OFFSET = new Comparator() {
|
||||
public int compare(Object o1, Object o2) {
|
||||
CHReferenceInfo r1= (CHReferenceInfo) o1;
|
||||
CHReferenceInfo r2= (CHReferenceInfo) o2;
|
||||
return r1.fOffset - r2.fOffset;
|
||||
}
|
||||
};
|
||||
private int fOffset;
|
||||
private int fLength;
|
||||
|
||||
|
|
|
@ -23,9 +23,14 @@ import org.eclipse.ui.IWorkbenchPage;
|
|||
import org.eclipse.ui.IWorkbenchWindow;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
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.IEnumerator;
|
||||
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.IVariable;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICExternalBinding;
|
||||
import org.eclipse.cdt.core.index.IIndex;
|
||||
import org.eclipse.cdt.core.index.IIndexManager;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
|
@ -36,7 +41,6 @@ import org.eclipse.cdt.ui.CUIPlugin;
|
|||
|
||||
import org.eclipse.cdt.internal.ui.actions.OpenActionUtil;
|
||||
import org.eclipse.cdt.internal.ui.editor.CEditor;
|
||||
import org.eclipse.cdt.internal.ui.missingapi.CIndexQueries;
|
||||
import org.eclipse.cdt.internal.ui.util.ExceptionHandler;
|
||||
import org.eclipse.cdt.internal.ui.viewsupport.CElementLabels;
|
||||
import org.eclipse.cdt.internal.ui.viewsupport.FindNameForSelectionVisitor;
|
||||
|
@ -120,7 +124,6 @@ public class CallHierarchyUI {
|
|||
|
||||
private static ICElement[] findDefinitions(ICProject project, IEditorInput editorInput, ITextSelection sel) throws CoreException {
|
||||
try {
|
||||
CIndexQueries indexq= CIndexQueries.getInstance();
|
||||
IIndex index= CCorePlugin.getIndexManager().getIndex(project, IIndexManager.ADD_DEPENDENCIES | IIndexManager.ADD_DEPENDENT);
|
||||
|
||||
index.acquireReadLock();
|
||||
|
@ -128,19 +131,19 @@ public class CallHierarchyUI {
|
|||
IASTName name= getSelectedName(index, editorInput, sel);
|
||||
if (name != null) {
|
||||
IBinding binding= name.resolveBinding();
|
||||
if (CIndexQueries.isRelevantForCallHierarchy(binding)) {
|
||||
if (CallHierarchyUI.isRelevantForCallHierarchy(binding)) {
|
||||
if (name.isDefinition()) {
|
||||
ICElement elem= indexq.getCElementForName(project, name);
|
||||
ICElement elem= CHQueries.getCElementForName(project, index, name);
|
||||
if (elem != null) {
|
||||
return new ICElement[]{elem};
|
||||
}
|
||||
}
|
||||
else {
|
||||
ICElement[] elems= indexq.findAllDefinitions(index, name);
|
||||
ICElement[] elems= CHQueries.findAllDefinitions(index, binding);
|
||||
if (elems.length == 0) {
|
||||
elems= indexq.findAllDefinitions(index, name);
|
||||
elems= CHQueries.findAllDefinitions(index, binding);
|
||||
if (elems.length == 0) {
|
||||
ICElement elem= indexq.findAnyDeclaration(index, project, name);
|
||||
ICElement elem= CHQueries.findAnyDeclaration(index, project, binding);
|
||||
if (elems != null) {
|
||||
elems= new ICElement[]{elem};
|
||||
}
|
||||
|
@ -160,6 +163,9 @@ public class CallHierarchyUI {
|
|||
catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
}
|
||||
catch (DOMException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
}
|
||||
return null;
|
||||
|
@ -179,4 +185,39 @@ public class CallHierarchyUI {
|
|||
ast.accept(finder);
|
||||
return finder.getSelectedName();
|
||||
}
|
||||
|
||||
public static boolean isRelevantForCallHierarchy(IBinding binding) {
|
||||
if (binding instanceof ICExternalBinding ||
|
||||
binding instanceof IEnumerator ||
|
||||
binding instanceof IFunction ||
|
||||
binding instanceof IVariable) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isRelevantForCallHierarchy(ICElement elem) {
|
||||
if (elem == null) {
|
||||
return false;
|
||||
}
|
||||
switch (elem.getElementType()) {
|
||||
case ICElement.C_CLASS_CTOR:
|
||||
case ICElement.C_CLASS_DTOR:
|
||||
case ICElement.C_ENUMERATOR:
|
||||
case ICElement.C_FIELD:
|
||||
case ICElement.C_FUNCTION:
|
||||
case ICElement.C_FUNCTION_DECLARATION:
|
||||
case ICElement.C_METHOD:
|
||||
case ICElement.C_METHOD_DECLARATION:
|
||||
case ICElement.C_TEMPLATE_FUNCTION:
|
||||
case ICElement.C_TEMPLATE_FUNCTION_DECLARATION:
|
||||
case ICElement.C_TEMPLATE_METHOD:
|
||||
case ICElement.C_TEMPLATE_METHOD_DECLARATION:
|
||||
case ICElement.C_TEMPLATE_VARIABLE:
|
||||
case ICElement.C_VARIABLE:
|
||||
case ICElement.C_VARIABLE_DECLARATION:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
* Markus Schorn - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.internal.ui.missingapi;
|
||||
package org.eclipse.cdt.internal.ui.callhierarchy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -17,6 +17,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.cdt.core.index.IIndexName;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
|
||||
public class CalledByResult {
|
||||
|
@ -27,12 +28,12 @@ public class CalledByResult {
|
|||
return (ICElement[]) elements.toArray(new ICElement[elements.size()]);
|
||||
}
|
||||
|
||||
public CIndexReference[] getReferences(ICElement calledElement) {
|
||||
public IIndexName[] getReferences(ICElement calledElement) {
|
||||
List references= (List) fElementToReferences.get(calledElement);
|
||||
return (CIndexReference[]) references.toArray(new CIndexReference[references.size()]);
|
||||
return (IIndexName[]) references.toArray(new IIndexName[references.size()]);
|
||||
}
|
||||
|
||||
public void add(ICElement elem, CIndexReference ref) {
|
||||
public void add(ICElement elem, IIndexName ref) {
|
||||
List list= (List) fElementToReferences.get(elem);
|
||||
if (list == null) {
|
||||
list= new ArrayList();
|
|
@ -9,7 +9,7 @@
|
|||
* Markus Schorn - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.internal.ui.missingapi;
|
||||
package org.eclipse.cdt.internal.ui.callhierarchy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -17,6 +17,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.cdt.core.index.IIndexName;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
|
||||
public class CallsToResult {
|
||||
|
@ -27,12 +28,12 @@ public class CallsToResult {
|
|||
return (CElementSet[]) elementSets.toArray(new CElementSet[elementSets.size()]);
|
||||
}
|
||||
|
||||
public CIndexReference[] getReferences(CElementSet elementSet) {
|
||||
public IIndexName[] getReferences(CElementSet elementSet) {
|
||||
List references= (List) fElementSetsToReferences.get(elementSet);
|
||||
return (CIndexReference[]) references.toArray(new CIndexReference[references.size()]);
|
||||
return (IIndexName[]) references.toArray(new IIndexName[references.size()]);
|
||||
}
|
||||
|
||||
public void add(ICElement[] elems, CIndexReference ref) {
|
||||
public void add(ICElement[] elems, IIndexName ref) {
|
||||
CElementSet key= new CElementSet(elems);
|
||||
List list= (List) fElementSetsToReferences.get(key);
|
||||
if (list == null) {
|
|
@ -9,7 +9,7 @@
|
|||
* Markus Schorn - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.internal.ui.missingapi;
|
||||
package org.eclipse.cdt.internal.ui.callhierarchy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -1,370 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 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
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.internal.ui.missingapi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.eclipse.jface.text.IRegion;
|
||||
import org.eclipse.jface.text.Region;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.IPositionConverter;
|
||||
import org.eclipse.cdt.core.dom.IName;
|
||||
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.IEnumerator;
|
||||
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.IVariable;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICExternalBinding;
|
||||
import org.eclipse.cdt.core.index.IIndex;
|
||||
import org.eclipse.cdt.core.index.IIndexName;
|
||||
import org.eclipse.cdt.core.model.CModelException;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.model.ILanguage;
|
||||
import org.eclipse.cdt.core.model.IParent;
|
||||
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.ui.CUIPlugin;
|
||||
|
||||
import org.eclipse.cdt.internal.corext.util.CModelUtil;
|
||||
|
||||
/**
|
||||
* Access to high level queries in the index.
|
||||
* @since 4.0
|
||||
*/
|
||||
public class CIndexQueries {
|
||||
private static final int ASTTU_OPTIONS = ITranslationUnit.AST_SKIP_INDEXED_HEADERS;
|
||||
private static final ICElement[] EMPTY_ELEMENTS = new ICElement[0];
|
||||
private static final CIndexQueries sInstance= new CIndexQueries();
|
||||
|
||||
public static CIndexQueries getInstance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public static boolean isRelevantForCallHierarchy(IBinding binding) {
|
||||
if (binding instanceof ICExternalBinding ||
|
||||
binding instanceof IEnumerator ||
|
||||
binding instanceof IFunction ||
|
||||
binding instanceof IVariable) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isRelevantForCallHierarchy(ICElement elem) {
|
||||
if (elem == null) {
|
||||
return false;
|
||||
}
|
||||
switch (elem.getElementType()) {
|
||||
case ICElement.C_CLASS_CTOR:
|
||||
case ICElement.C_CLASS_DTOR:
|
||||
case ICElement.C_ENUMERATOR:
|
||||
case ICElement.C_FIELD:
|
||||
case ICElement.C_FUNCTION:
|
||||
case ICElement.C_FUNCTION_DECLARATION:
|
||||
case ICElement.C_METHOD:
|
||||
case ICElement.C_METHOD_DECLARATION:
|
||||
case ICElement.C_TEMPLATE_FUNCTION:
|
||||
case ICElement.C_TEMPLATE_FUNCTION_DECLARATION:
|
||||
case ICElement.C_TEMPLATE_METHOD:
|
||||
case ICElement.C_TEMPLATE_METHOD_DECLARATION:
|
||||
case ICElement.C_TEMPLATE_VARIABLE:
|
||||
case ICElement.C_VARIABLE:
|
||||
case ICElement.C_VARIABLE_DECLARATION:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Searches for functions and methods that call a given element.
|
||||
* @param scope the projects to be searched
|
||||
* @param callee a function, method, constant, variable or enumerator.
|
||||
* @param pm a monitor to report progress
|
||||
* @return a result object.
|
||||
* @since 4.0
|
||||
*/
|
||||
public CalledByResult findCalledBy(ICProject[] scope, ICElement callee, IProgressMonitor pm) {
|
||||
CalledByResult result= new CalledByResult();
|
||||
try {
|
||||
findCalledBy(scope, callee, pm, result);
|
||||
}
|
||||
catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void findCalledBy(ICProject[] scope, ICElement callee, IProgressMonitor pm, CalledByResult result)
|
||||
throws CoreException, InterruptedException {
|
||||
if (! (callee instanceof ISourceReference)) {
|
||||
return;
|
||||
}
|
||||
ISourceReference sf= (ISourceReference) callee;
|
||||
ISourceRange range;
|
||||
range = sf.getSourceRange();
|
||||
ITranslationUnit tu= sf.getTranslationUnit();
|
||||
IIndex index= CCorePlugin.getIndexManager().getIndex(scope);
|
||||
index.acquireReadLock();
|
||||
try {
|
||||
ILanguage language = tu.getLanguage();
|
||||
IASTTranslationUnit ast= tu.getAST(index, ASTTU_OPTIONS);
|
||||
if (ast == null) {
|
||||
return;
|
||||
}
|
||||
IASTName[] names = language.getSelectedNames(ast, range.getIdStartPos(), range.getIdLength());
|
||||
if (names == null || names.length == 0) {
|
||||
return;
|
||||
}
|
||||
IASTName name= names[names.length-1];
|
||||
for (int i = 0; i < scope.length; i++) {
|
||||
ICProject project = scope[i];
|
||||
findCalledBy(index, name, project, result);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
index.releaseReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
private void findCalledBy(IIndex index, IASTName name, ICProject project, CalledByResult result) throws CoreException {
|
||||
IBinding binding= name.resolveBinding();
|
||||
if (binding != null) {
|
||||
IName[] names= index.findReferences(binding);
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
IName rname = names[i];
|
||||
ITranslationUnit tu= getTranslationUnit(project, rname);
|
||||
CIndexReference ref= new CIndexReference(tu, rname);
|
||||
ICElement elem = findCalledBy(ref);
|
||||
if (elem != null) {
|
||||
result.add(elem, ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ICElement findCalledBy(CIndexReference reference) {
|
||||
ITranslationUnit tu= reference.getTranslationUnit();
|
||||
long timestamp= reference.getTimestamp();
|
||||
IPositionConverter pc= CCorePlugin.getPositionTrackerManager().findPositionConverter(tu.getPath(), timestamp);
|
||||
int offset= reference.getOffset();
|
||||
if (pc != null) {
|
||||
offset= pc.historicToActual(new Region(offset, 0)).getOffset();
|
||||
}
|
||||
return findEnclosingFunction(tu, offset);
|
||||
}
|
||||
|
||||
private ICElement findEnclosingFunction(ICElement element, int offset) {
|
||||
if (element == null || element instanceof org.eclipse.cdt.core.model.IFunctionDeclaration) {
|
||||
return element;
|
||||
}
|
||||
if (element instanceof org.eclipse.cdt.core.model.IVariable) {
|
||||
return element;
|
||||
}
|
||||
try {
|
||||
if (element instanceof IParent) {
|
||||
ICElement[] children= ((IParent) element).getChildren();
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
ICElement child = children[i];
|
||||
if (child instanceof ISourceReference) {
|
||||
ISourceRange sr= ((ISourceReference) child).getSourceRange();
|
||||
int startPos= sr.getStartPos();
|
||||
if (startPos <= offset && offset < startPos + sr.getLength()) {
|
||||
return findEnclosingFunction(child, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (CModelException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private ITranslationUnit getTranslationUnit(ICProject cproject, IName name) {
|
||||
IPath path= Path.fromOSString(name.getFileLocation().getFileName());
|
||||
try {
|
||||
return CModelUtil.findTranslationUnitForLocation(path, cproject);
|
||||
} catch (CModelException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for all calls that are made within a given range.
|
||||
* @param scope the scope in which the references can be resolved to elements
|
||||
* @param tu the translation unit where the calls are made
|
||||
* @param range the range in the translation unit where the calls are made
|
||||
* @param pm a monitor to report progress
|
||||
* @return a result object.
|
||||
* @since 4.0
|
||||
*/
|
||||
public CallsToResult findCallsInRange(ICProject[] scope, ITranslationUnit tu, IRegion range, IProgressMonitor pm) {
|
||||
CallsToResult result= new CallsToResult();
|
||||
try {
|
||||
findCallsInRange(scope, tu, range, pm, result);
|
||||
}
|
||||
catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void findCallsInRange(ICProject[] scope, ITranslationUnit tu, IRegion range, IProgressMonitor pm, CallsToResult result)
|
||||
throws CoreException, InterruptedException {
|
||||
IIndex index= CCorePlugin.getIndexManager().getIndex(scope);
|
||||
index.acquireReadLock();
|
||||
try {
|
||||
IASTTranslationUnit astTU= tu.getAST(index, ASTTU_OPTIONS);
|
||||
if (astTU != null) {
|
||||
ReferenceVisitor refVisitor= new ReferenceVisitor(astTU.getFilePath(), range.getOffset(), range.getLength());
|
||||
astTU.accept(refVisitor);
|
||||
|
||||
IASTName[] refs = refVisitor.getReferences();
|
||||
for (int i = 0; i < refs.length; i++) {
|
||||
IASTName name = refs[i];
|
||||
IBinding binding= name.resolveBinding();
|
||||
if (isRelevantForCallHierarchy(binding)) {
|
||||
ICElement[] defs = findAllDefinitions(index, name);
|
||||
if (defs.length == 0) {
|
||||
ICElement elem = findAnyDeclaration(index, null, name);
|
||||
if (elem != null) {
|
||||
defs = new ICElement[] { elem };
|
||||
}
|
||||
}
|
||||
if (defs != null && defs.length > 0) {
|
||||
CIndexReference ref = new CIndexReference(tu, name);
|
||||
result.add(defs, ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
index.releaseReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
public ICElement[] findAllDefinitions(IIndex index, IASTName name) throws CoreException {
|
||||
IBinding binding= name.resolveBinding();
|
||||
if (binding != null) {
|
||||
IIndexName[] defs= index.findDefinitions(binding);
|
||||
|
||||
ArrayList result= new ArrayList();
|
||||
for (int i = 0; i < defs.length; i++) {
|
||||
IIndexName in = defs[i];
|
||||
ICElement definition= getCElementForName(null, in);
|
||||
if (definition != null) {
|
||||
result.add(definition);
|
||||
}
|
||||
|
||||
}
|
||||
return (ICElement[]) result.toArray(new ICElement[result.size()]);
|
||||
}
|
||||
return EMPTY_ELEMENTS;
|
||||
}
|
||||
|
||||
public ICElement getCElementForName(ICProject preferProject, IName declName) {
|
||||
assert !declName.isReference();
|
||||
ITranslationUnit tu= getTranslationUnit(preferProject, declName);
|
||||
if (tu != null) {
|
||||
IRegion region= null;
|
||||
if (declName instanceof IIndexName) {
|
||||
IIndexName pname= (IIndexName) declName;
|
||||
region= new Region(pname.getNodeOffset(), pname.getNodeLength());
|
||||
try {
|
||||
long timestamp= pname.getFile().getTimestamp();
|
||||
IPositionConverter pc= CCorePlugin.getPositionTrackerManager().findPositionConverter(tu.getPath(), timestamp);
|
||||
if (pc != null) {
|
||||
region= pc.historicToActual(region);
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
IASTFileLocation loc= declName.getFileLocation();
|
||||
region= new Region(loc.getNodeOffset(), loc.getNodeLength());
|
||||
}
|
||||
return getCElementWithRangeOfID(tu, region.getOffset(), region.getLength());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ICElement getCElementWithRangeOfID(ICElement element, int offset, int length) {
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
if (element instanceof IParent) {
|
||||
ICElement[] children= ((IParent) element).getChildren();
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
ICElement child = children[i];
|
||||
if (child instanceof ISourceReference) {
|
||||
ISourceRange sr= ((ISourceReference) child).getSourceRange();
|
||||
if (surrounds(offset, length, sr.getIdStartPos(), sr.getIdLength())) {
|
||||
return child;
|
||||
}
|
||||
int childOffset= sr.getStartPos();
|
||||
if (childOffset > offset) {
|
||||
return null;
|
||||
}
|
||||
if (surrounds(childOffset, sr.getLength(), offset, length)) {
|
||||
ICElement result= getCElementWithRangeOfID(child, offset, length);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (CModelException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean surrounds(int offset1, int length1, int offset2, int length2) {
|
||||
int deltaOffset= offset2-offset1;
|
||||
int deltaEndoffset= deltaOffset + length2 - length1;
|
||||
return deltaOffset >= 0 && deltaEndoffset <= 0;
|
||||
}
|
||||
|
||||
public ICElement findAnyDeclaration(IIndex index, ICProject preferProject, IASTName name) throws CoreException {
|
||||
IBinding binding= name.resolveBinding();
|
||||
if (binding != null) {
|
||||
IIndexName[] names= index.findNames(binding, IIndex.FIND_DECLARATIONS);
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
ICElement elem= getCElementForName(preferProject, names[i]);
|
||||
if (elem != null) {
|
||||
return elem;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 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
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.internal.ui.missingapi;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.eclipse.cdt.core.dom.IName;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
|
||||
public class CIndexReference {
|
||||
public static final Comparator COMPARE_OFFSET = new Comparator() {
|
||||
public int compare(Object o1, Object o2) {
|
||||
CIndexReference r1= (CIndexReference) o1;
|
||||
CIndexReference r2= (CIndexReference) o2;
|
||||
return r1.fOffset - r2.fOffset;
|
||||
}
|
||||
};
|
||||
private int fOffset;
|
||||
private int fLength;
|
||||
private ITranslationUnit fTranslationUnit;
|
||||
|
||||
public CIndexReference(ITranslationUnit tu, IName name) {
|
||||
fTranslationUnit= tu;
|
||||
fOffset= name.getFileLocation().getNodeOffset();
|
||||
fLength= name.getFileLocation().getNodeLength();
|
||||
}
|
||||
public ITranslationUnit getTranslationUnit() {
|
||||
return fTranslationUnit;
|
||||
}
|
||||
public int getOffset() {
|
||||
return fOffset;
|
||||
}
|
||||
public long getTimestamp() {
|
||||
return 0;
|
||||
}
|
||||
public int getLength() {
|
||||
return fLength;
|
||||
}
|
||||
}
|
|
@ -33,6 +33,8 @@ import org.eclipse.cdt.core.model.ITranslationUnit;
|
|||
import org.eclipse.cdt.core.resources.FileStorage;
|
||||
import org.eclipse.cdt.ui.CUIPlugin;
|
||||
|
||||
import org.eclipse.cdt.internal.core.model.ext.ICElementHandle;
|
||||
|
||||
import org.eclipse.cdt.internal.ui.util.ExternalEditorInput;
|
||||
|
||||
/**
|
||||
|
@ -96,7 +98,7 @@ public class EditorOpener {
|
|||
ITranslationUnit tu= sr.getTranslationUnit();
|
||||
ISourceRange range= sr.getSourceRange();
|
||||
long timestamp= 0; // last modified of file.
|
||||
if (tu.isWorkingCopy()) {
|
||||
if (tu.isWorkingCopy() || element instanceof ICElementHandle) {
|
||||
timestamp= -1;
|
||||
}
|
||||
open(page, tu, new Region(range.getIdStartPos(), range.getIdLength()), timestamp);
|
||||
|
|
Loading…
Add table
Reference in a new issue