mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-28 19:35:36 +02:00
Call Hierarchy: support for hierarchies across project boundaries.
This commit is contained in:
parent
1eceeb0258
commit
6b2a7a5842
6 changed files with 550 additions and 246 deletions
|
@ -6,7 +6,8 @@
|
|||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* QNX - Initial API and implementation
|
||||
* QNX - Initial API and implementation
|
||||
* Markus Schorn (Wind River Systems)
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
|
||||
|
@ -283,8 +284,14 @@ public class PDOMCPPLinkage extends PDOMLinkage {
|
|||
if (binding == null || binding instanceof IProblemBinding)
|
||||
return null;
|
||||
|
||||
if (binding instanceof PDOMBinding)
|
||||
return (PDOMBinding)binding;
|
||||
if (binding instanceof PDOMBinding) {
|
||||
// there is no guarantee, that the binding is from the same PDOM object.
|
||||
PDOMBinding pdomBinding = (PDOMBinding) binding;
|
||||
if (pdomBinding.getPDOM() == getPDOM()) {
|
||||
return pdomBinding;
|
||||
}
|
||||
// so if the binding is from another pdom it has to be adapted.
|
||||
}
|
||||
|
||||
PDOMNode parent = getParent(binding);
|
||||
if (parent == this) {
|
||||
|
|
|
@ -20,7 +20,9 @@ import org.eclipse.core.runtime.NullProgressMonitor;
|
|||
import org.eclipse.jface.text.Region;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
|
||||
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;
|
||||
|
@ -101,7 +103,8 @@ public class CHContentProvider extends AsyncTreeContentProvider {
|
|||
|
||||
private Object[] asyncronouslyComputeReferencedBy(CHNode parent, ICElement elem) {
|
||||
try {
|
||||
CalledByResult calledBy= CIndexQueries.getInstance().findCalledBy(elem, NPM);
|
||||
ICProject[] scope= CoreModel.getDefault().getCModel().getCProjects();
|
||||
CalledByResult calledBy= CIndexQueries.getInstance().findCalledBy(scope, elem, NPM);
|
||||
ArrayList result= new ArrayList();
|
||||
|
||||
ICElement[] elements= calledBy.getElements();
|
||||
|
@ -120,7 +123,6 @@ public class CHContentProvider extends AsyncTreeContentProvider {
|
|||
return result.toArray();
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
return NO_CHILDREN;
|
||||
}
|
||||
|
@ -163,7 +165,8 @@ public class CHContentProvider extends AsyncTreeContentProvider {
|
|||
ISourceReference sf= (ISourceReference) elem;
|
||||
ITranslationUnit tu= sf.getTranslationUnit();
|
||||
ISourceRange range= sf.getSourceRange();
|
||||
CallsToResult callsTo= CIndexQueries.getInstance().findCallsToInRange(tu, new Region(range.getStartPos(), range.getLength()), NPM);
|
||||
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++) {
|
||||
|
@ -181,7 +184,6 @@ public class CHContentProvider extends AsyncTreeContentProvider {
|
|||
}
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
return NO_CHILDREN;
|
||||
}
|
||||
|
|
|
@ -11,16 +11,20 @@
|
|||
|
||||
package org.eclipse.cdt.internal.ui.includebrowser;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
|
||||
import org.eclipse.cdt.core.model.CModelException;
|
||||
import org.eclipse.cdt.core.model.CoreModel;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.ui.CUIPlugin;
|
||||
|
||||
import org.eclipse.cdt.internal.ui.missingapi.CIndexQueries;
|
||||
import org.eclipse.cdt.internal.ui.missingapi.CIndexQueries.IPDOMInclude;
|
||||
import org.eclipse.cdt.internal.ui.missingapi.CIndexIncludeRelation;
|
||||
import org.eclipse.cdt.internal.ui.viewsupport.AsyncTreeContentProvider;
|
||||
|
||||
/**
|
||||
|
@ -61,48 +65,53 @@ public class IBContentProvider extends AsyncTreeContentProvider {
|
|||
return null;
|
||||
}
|
||||
|
||||
protected Object[] asyncronouslyComputeChildren(Object parentElement,
|
||||
IProgressMonitor monitor) {
|
||||
protected Object[] asyncronouslyComputeChildren(Object parentElement, IProgressMonitor monitor) {
|
||||
if (parentElement instanceof IBNode) {
|
||||
IBNode node = (IBNode) parentElement;
|
||||
ITranslationUnit tu= node.getRepresentedTranslationUnit();
|
||||
if (tu != null) {
|
||||
try {
|
||||
IPDOMInclude[] includes;
|
||||
IBFile directiveFile= null;
|
||||
IBFile targetFile= null;
|
||||
if (fComputeIncludedBy) {
|
||||
includes= CIndexQueries.getInstance().findIncludedBy(tu, NPM);
|
||||
CIndexIncludeRelation[] includes;
|
||||
IBFile directiveFile= null;
|
||||
IBFile targetFile= null;
|
||||
if (fComputeIncludedBy) {
|
||||
ICProject[] projects;
|
||||
try {
|
||||
projects = CoreModel.getDefault().getCModel().getCProjects();
|
||||
} catch (CModelException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
return NO_CHILDREN;
|
||||
}
|
||||
else {
|
||||
includes= CIndexQueries.getInstance().findIncludesTo(tu, NPM);
|
||||
directiveFile= node.getRepresentedFile();
|
||||
}
|
||||
if (includes.length > 0) {
|
||||
IBNode[] result = new IBNode[includes.length];
|
||||
for (int i = 0; i < includes.length; i++) {
|
||||
IPDOMInclude include = includes[i];
|
||||
includes= CIndexQueries.getInstance().findIncludedBy(projects, tu, NPM);
|
||||
}
|
||||
else {
|
||||
includes= CIndexQueries.getInstance().findIncludesTo(tu, NPM);
|
||||
directiveFile= node.getRepresentedFile();
|
||||
}
|
||||
if (includes.length > 0) {
|
||||
ArrayList result= new ArrayList(includes.length);
|
||||
for (int i = 0; i < includes.length; i++) {
|
||||
CIndexIncludeRelation include = includes[i];
|
||||
try {
|
||||
if (fComputeIncludedBy) {
|
||||
directiveFile= targetFile= new IBFile(tu.getCProject(), include.getIncludedBy());
|
||||
}
|
||||
else {
|
||||
targetFile= new IBFile(tu.getCProject(), include.getIncludes());
|
||||
}
|
||||
|
||||
} catch (CModelException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
targetFile= null;
|
||||
}
|
||||
|
||||
if (targetFile != null) {
|
||||
IBNode newnode= new IBNode(node, targetFile, directiveFile,
|
||||
include.getName(), include.getOffset(), include.getTimestamp());
|
||||
newnode.setIsActiveCode(include.isActiveCode());
|
||||
newnode.setIsSystemInclude(include.isSystemInclude());
|
||||
result[i]= newnode;
|
||||
result.add(newnode);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e.getStatus());
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
return result.toArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*******************************************************************************
|
||||
* 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 org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMInclude;
|
||||
|
||||
/**
|
||||
* Represents an include relation found in the index.
|
||||
* @since 4.0
|
||||
*/
|
||||
public class CIndexIncludeRelation {
|
||||
private IPath fIncludedBy;
|
||||
private IPath fIncludes;
|
||||
|
||||
CIndexIncludeRelation(PDOMInclude include) throws CoreException {
|
||||
fIncludedBy= Path.fromOSString(include.getIncludedBy().getFileName().getString());
|
||||
fIncludes= Path.fromOSString(include.getIncludes().getFileName().getString());
|
||||
}
|
||||
public boolean isSystemInclude() {
|
||||
return false;
|
||||
}
|
||||
public boolean isActiveCode() {
|
||||
return true;
|
||||
}
|
||||
public IPath getIncludedBy() {
|
||||
return fIncludedBy;
|
||||
}
|
||||
public IPath getIncludes() {
|
||||
return fIncludes;
|
||||
}
|
||||
public String getName() {
|
||||
return fIncludes.lastSegment();
|
||||
}
|
||||
public int getOffset() {
|
||||
return 9;
|
||||
}
|
||||
public long getTimestamp() {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -15,8 +15,6 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
@ -28,12 +26,10 @@ import org.eclipse.jface.text.Region;
|
|||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.IPositionConverter;
|
||||
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.model.CModelException;
|
||||
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.IFunctionDeclaration;
|
||||
|
@ -43,99 +39,97 @@ 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.IVariableDeclaration;
|
||||
import org.eclipse.cdt.ui.CUIPlugin;
|
||||
|
||||
import org.eclipse.cdt.internal.core.pdom.PDOM;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMFile;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMInclude;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
|
||||
import org.eclipse.cdt.internal.corext.util.CModelUtil;
|
||||
|
||||
/**
|
||||
* Access to high level queries in the index.
|
||||
* @since 4.0
|
||||
*/
|
||||
public class CIndexQueries {
|
||||
public static class IPDOMInclude {
|
||||
private PDOMInclude fInclude;
|
||||
|
||||
public IPDOMInclude(PDOMInclude include) {
|
||||
fInclude= include;
|
||||
}
|
||||
public boolean isSystemInclude() {
|
||||
return false;
|
||||
}
|
||||
public boolean isActiveCode() {
|
||||
return true;
|
||||
}
|
||||
public IPath getIncludedBy() throws CoreException {
|
||||
return Path.fromOSString(fInclude.getIncludedBy().getFileName().getString());
|
||||
}
|
||||
public IPath getIncludes() throws CoreException {
|
||||
return Path.fromOSString(fInclude.getIncludes().getFileName().getString());
|
||||
}
|
||||
public String getName() throws CoreException {
|
||||
return Path.fromOSString(fInclude.getIncludes().getFileName().getString()).lastSegment();
|
||||
}
|
||||
public int getOffset() {
|
||||
return 9;
|
||||
}
|
||||
public long getTimestamp() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static final IPDOMInclude[] EMPTY_INCLUDES = new IPDOMInclude[0];
|
||||
private static final ICElement[] EMPTY_ELEMENTS = new ICElement[0];
|
||||
private static final CIndexIncludeRelation[] EMPTY_INCLUDES = new CIndexIncludeRelation[0];
|
||||
private static final CIndexQueries sInstance= new CIndexQueries();
|
||||
|
||||
public static CIndexQueries getInstance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public static ITranslationUnit toTranslationUnit(ICProject cproject, PDOMFile includedBy) throws CoreException {
|
||||
String name= includedBy.getFileName().getString();
|
||||
return toTranslationUnit(cproject, name);
|
||||
}
|
||||
|
||||
public static ITranslationUnit toTranslationUnit(ICProject cproject, IASTName name) throws CoreException {
|
||||
return toTranslationUnit(cproject, name.getFileLocation().getFileName());
|
||||
}
|
||||
|
||||
private static ITranslationUnit toTranslationUnit(ICProject cproject, String pathStr) throws CModelException {
|
||||
IPath path= Path.fromOSString(pathStr);
|
||||
return CModelUtil.findTranslationUnitForLocation(path, cproject);
|
||||
}
|
||||
|
||||
|
||||
public IPDOMInclude[] findIncludedBy(ITranslationUnit tu, IProgressMonitor pm) throws CoreException, InterruptedException {
|
||||
/**
|
||||
* Searches for all include-relations that include the given translation unit.
|
||||
* @param scope the projects to be searched.
|
||||
* @param tu a translation unit
|
||||
* @param pm a monitor for reporting progress.
|
||||
* @return an array of include relations.
|
||||
* @since 4.0
|
||||
*/
|
||||
public CIndexIncludeRelation[] findIncludedBy(ICProject[] scope, ITranslationUnit tu, IProgressMonitor pm) {
|
||||
HashMap result= new HashMap();
|
||||
LinkedList projects= new LinkedList(Arrays.asList(CoreModel.getDefault().getCModel().getCProjects()));
|
||||
ICProject cproject= tu.getCProject();
|
||||
if (cproject != null) {
|
||||
projects.remove(cproject);
|
||||
projects.addLast(cproject);
|
||||
ICProject projectOfTU= tu.getCProject();
|
||||
|
||||
// mstodo progress monitor
|
||||
for (int i = scope.length-1; i >= 0; i--) {
|
||||
ICProject cproject = scope[i];
|
||||
// prefer the project of the translation unit.
|
||||
if (i != 0) {
|
||||
if (cproject.equals(projectOfTU)) {
|
||||
System.arraycopy(scope, 0, scope, 1, i);
|
||||
scope[0]= projectOfTU;
|
||||
cproject= scope[i];
|
||||
}
|
||||
}
|
||||
CIndexIncludeRelation[] includes= findIncludedBy(cproject, tu);
|
||||
for (int j = 0; j < includes.length; j++) {
|
||||
CIndexIncludeRelation include = includes[j];
|
||||
result.put(include.getIncludedBy(), include);
|
||||
}
|
||||
}
|
||||
|
||||
for (Iterator iter = projects.iterator(); iter.hasNext();) {
|
||||
cproject = (ICProject) iter.next();
|
||||
PDOM pdom= (PDOM) CCorePlugin.getPDOMManager().getPDOM(cproject);
|
||||
Collection includes= result.values();
|
||||
return (CIndexIncludeRelation[]) includes.toArray(new CIndexIncludeRelation[includes.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for all include-relations in a project that include the given translation unit.
|
||||
* @param project the project to be searched.
|
||||
* @param tu a translation unit
|
||||
* @return an array of include relations.
|
||||
* @since 4.0
|
||||
*/
|
||||
public CIndexIncludeRelation[] findIncludedBy(ICProject project, ITranslationUnit tu) {
|
||||
try {
|
||||
PDOM pdom= (PDOM) CCorePlugin.getPDOMManager().getPDOM(project);
|
||||
if (pdom != null) {
|
||||
pdom.acquireReadLock();
|
||||
try {
|
||||
PDOMFile fileTarget= pdom.getFile(locationForTU(tu));
|
||||
if (fileTarget != null) {
|
||||
ArrayList result= new ArrayList();
|
||||
PDOMInclude include= fileTarget.getFirstIncludedBy();
|
||||
while (include != null) {
|
||||
PDOMFile file= include.getIncludedBy();
|
||||
String path= file.getFileName().getString();
|
||||
result.put(path, new IPDOMInclude(include));
|
||||
try {
|
||||
result.add(new CIndexIncludeRelation(include));
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
}
|
||||
include= include.getNextInIncludedBy();
|
||||
}
|
||||
return (CIndexIncludeRelation[]) result.toArray(new CIndexIncludeRelation[result.size()]);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
pdom.releaseReadLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
Collection includes= result.values();
|
||||
return (IPDOMInclude[]) includes.toArray(new IPDOMInclude[includes.size()]);
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
return EMPTY_INCLUDES;
|
||||
}
|
||||
|
||||
private IPath locationForTU(ITranslationUnit tu) {
|
||||
|
@ -146,165 +140,270 @@ public class CIndexQueries {
|
|||
return tu.getPath();
|
||||
}
|
||||
|
||||
public IPDOMInclude[] findIncludesTo(ITranslationUnit tu, IProgressMonitor pm) throws CoreException, InterruptedException {
|
||||
/**
|
||||
* Searches for all include-relations defined in the given translation unit.
|
||||
* @param tu a translation unit.
|
||||
* @param pm a monitor to report progress.
|
||||
* @return an array of include relations.
|
||||
* @since 4.0
|
||||
*/
|
||||
public CIndexIncludeRelation[] findIncludesTo(ITranslationUnit tu, IProgressMonitor pm) {
|
||||
ICProject cproject= tu.getCProject();
|
||||
if (cproject != null) {
|
||||
PDOM pdom= (PDOM) CCorePlugin.getPDOMManager().getPDOM(cproject);
|
||||
if (pdom != null) {
|
||||
pdom.acquireReadLock();
|
||||
try {
|
||||
PDOMFile fileTarget= pdom.getFile(locationForTU(tu));
|
||||
if (fileTarget != null) {
|
||||
ArrayList result= new ArrayList();
|
||||
PDOMInclude include= fileTarget.getFirstInclude();
|
||||
while (include != null) {
|
||||
result.add(new IPDOMInclude(include));
|
||||
include= include.getNextInIncludes();
|
||||
try {
|
||||
PDOM pdom= (PDOM) CCorePlugin.getPDOMManager().getPDOM(cproject);
|
||||
if (pdom != null) {
|
||||
pdom.acquireReadLock();
|
||||
try {
|
||||
PDOMFile fileTarget= pdom.getFile(locationForTU(tu));
|
||||
if (fileTarget != null) {
|
||||
ArrayList result= new ArrayList();
|
||||
PDOMInclude include= fileTarget.getFirstInclude();
|
||||
while (include != null) {
|
||||
try {
|
||||
result.add(new CIndexIncludeRelation(include));
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
}
|
||||
include= include.getNextInIncludes();
|
||||
}
|
||||
return (CIndexIncludeRelation[]) result.toArray(new CIndexIncludeRelation[result.size()]);
|
||||
}
|
||||
return (IPDOMInclude[]) result.toArray(new IPDOMInclude[result.size()]);
|
||||
}
|
||||
finally {
|
||||
pdom.releaseReadLock();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
pdom.releaseReadLock();
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
return EMPTY_INCLUDES;
|
||||
}
|
||||
|
||||
public CalledByResult findCalledBy(ICElement callee, IProgressMonitor pm) throws CoreException, InterruptedException {
|
||||
LinkedList projects= new LinkedList(Arrays.asList(CoreModel.getDefault().getCModel().getCProjects()));
|
||||
IASTName name= toASTName(callee);
|
||||
/**
|
||||
* 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) {
|
||||
IASTName name= astNameForElement(callee);
|
||||
|
||||
CalledByResult result= new CalledByResult();
|
||||
if (name != null) {
|
||||
// resolve the binding.
|
||||
name.resolveBinding();
|
||||
|
||||
for (Iterator iter = projects.iterator(); iter.hasNext();) {
|
||||
findCalledBy(name, (ICProject) iter.next(), result);
|
||||
for (int i = 0; i < scope.length; i++) {
|
||||
ICProject project = scope[i];
|
||||
findCalledBy(name, project, result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private IASTName toASTName(ICElement elem) throws CoreException {
|
||||
if (elem instanceof ISourceReference) {
|
||||
ISourceReference sf= (ISourceReference) elem;
|
||||
ISourceRange range = sf.getSourceRange();
|
||||
ITranslationUnit tu = sf.getTranslationUnit();
|
||||
private IASTName astNameForElement(ICElement elem) {
|
||||
try {
|
||||
if (elem instanceof ISourceReference) {
|
||||
ISourceReference sf= (ISourceReference) elem;
|
||||
ISourceRange range= sf.getSourceRange();
|
||||
ITranslationUnit tu= sf.getTranslationUnit();
|
||||
IASTTranslationUnit ast= astUnitForTU(tu);
|
||||
if (ast != null) {
|
||||
ILanguage language = tu.getLanguage();
|
||||
IASTName[] names = language.getSelectedNames(ast, range.getIdStartPos(), range.getIdLength());
|
||||
if (names.length > 0) {
|
||||
return names[names.length-1];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private IASTTranslationUnit astUnitForTU(ITranslationUnit tu) {
|
||||
try {
|
||||
if (tu != null) {
|
||||
ILanguage language = tu.getLanguage();
|
||||
IASTTranslationUnit ast = language.getASTTranslationUnit(tu, ILanguage.AST_SKIP_ALL_HEADERS | ILanguage.AST_USE_INDEX);
|
||||
return getASTName(language, ast, range);
|
||||
return language.getASTTranslationUnit(tu, ILanguage.AST_SKIP_ALL_HEADERS | ILanguage.AST_USE_INDEX);
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static IASTName getASTName(ILanguage language, IASTTranslationUnit ast, ISourceRange range) {
|
||||
IASTName[] names = language.getSelectedNames(ast, range.getIdStartPos(), range.getIdLength());
|
||||
if (names.length > 0) {
|
||||
return names[names.length-1];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void findCalledBy(IASTName name, ICProject project, CalledByResult result) throws InterruptedException, CoreException {
|
||||
PDOM pdom= (PDOM) CCorePlugin.getPDOMManager().getPDOM(project);
|
||||
if (pdom != null) {
|
||||
pdom.acquireReadLock();
|
||||
try {
|
||||
IBinding binding= pdom.resolveBinding(name);
|
||||
if (binding != null) {
|
||||
IASTName[] names= pdom.getReferences(binding);
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
IASTName rname = names[i];
|
||||
ITranslationUnit tu= toTranslationUnit(project, rname);
|
||||
CIndexReference ref= new CIndexReference(tu, rname);
|
||||
ICElement elem= findCaller(ref);
|
||||
result.add(elem, ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
pdom.releaseReadLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public CallsToResult findCallsToInRange(ITranslationUnit tu, IRegion range, IProgressMonitor pm) throws CoreException, InterruptedException {
|
||||
CallsToResult result= new CallsToResult();
|
||||
ICProject project = tu.getCProject();
|
||||
PDOM pdom= (PDOM) CCorePlugin.getPDOMManager().getPDOM(project);
|
||||
if (pdom != null) {
|
||||
pdom.acquireReadLock();
|
||||
try {
|
||||
IPath location= locationForTU(tu);
|
||||
PDOMFile file= pdom.getFile(location);
|
||||
if (file != null) {
|
||||
// mstodo use correct timestamp
|
||||
long timestamp= location.toFile().lastModified();
|
||||
IPositionConverter pc= CCorePlugin.getPositionTrackerManager().findPositionConverter(tu.getPath(), timestamp);
|
||||
if (pc != null) {
|
||||
range= pc.historicToActual(range);
|
||||
}
|
||||
PDOMName name= file.getFirstName();
|
||||
while (name != null) {
|
||||
if (name.isReference()) {
|
||||
IASTFileLocation loc= name.getFileLocation();
|
||||
if (encloses(range, loc.getNodeOffset(), loc.getNodeLength())) {
|
||||
ICElement[] defs= findDefinitions(project, name);
|
||||
if (defs != null && defs.length > 0) {
|
||||
CIndexReference ref= new CIndexReference(tu, name);
|
||||
result.add(defs, ref);
|
||||
}
|
||||
}
|
||||
private void findCalledBy(IASTName name, ICProject project, CalledByResult result) {
|
||||
try {
|
||||
PDOM pdom= (PDOM) CCorePlugin.getPDOMManager().getPDOM(project);
|
||||
if (pdom != null) {
|
||||
pdom.acquireReadLock();
|
||||
try {
|
||||
IBinding binding= pdom.resolveBinding(name);
|
||||
if (binding != null) {
|
||||
IASTName[] names= pdom.getReferences(binding);
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
IASTName rname = names[i];
|
||||
ITranslationUnit tu= toTranslationUnit(project, rname);
|
||||
CIndexReference ref= new CIndexReference(tu, rname);
|
||||
ICElement elem = findCalledBy(ref);
|
||||
if (elem != null) {
|
||||
result.add(elem, ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
pdom.releaseReadLock();
|
||||
}
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
|
||||
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 findElement(tu, offset, false);
|
||||
}
|
||||
|
||||
private ICElement findElement(ICElement element, int offset, boolean allowVars) {
|
||||
if (element == null || (element instanceof IFunctionDeclaration) ||
|
||||
(allowVars && element instanceof IVariableDeclaration)) {
|
||||
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 findElement(child, offset, allowVars);
|
||||
}
|
||||
name= name.getNextInFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
pdom.releaseReadLock();
|
||||
} catch (CModelException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ITranslationUnit toTranslationUnit(ICProject cproject, IASTName 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();
|
||||
IASTTranslationUnit astTU= astUnitForTU(tu);
|
||||
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];
|
||||
ICElement[] defs = findAllDefinitions(scope, name);
|
||||
if (defs.length == 0) {
|
||||
ICElement elem = findAnyDeclaration(scope, name);
|
||||
if (elem != null) {
|
||||
defs = new ICElement[] { elem };
|
||||
}
|
||||
}
|
||||
if (defs != null && defs.length > 0) {
|
||||
CIndexReference ref = new CIndexReference(tu, name);
|
||||
result.add(defs, ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private ICElement[] findDefinitions(ICProject project, PDOMName name) throws CoreException {
|
||||
ArrayList defs= new ArrayList();
|
||||
PDOMBinding binding= name.getPDOMBinding();
|
||||
if (binding != null) {
|
||||
PDOMName declName= binding.getFirstDefinition();
|
||||
while (declName != null) {
|
||||
ICElement elem= findEnclosingElement(project, declName);
|
||||
if (elem != null) {
|
||||
defs.add(elem);
|
||||
}
|
||||
declName= declName.getNextInBinding();
|
||||
}
|
||||
if (defs.isEmpty()) {
|
||||
declName= binding.getFirstDeclaration();
|
||||
while (declName != null) {
|
||||
ICElement elem= findEnclosingElement(project, declName);
|
||||
if (elem != null) {
|
||||
defs.add(elem);
|
||||
}
|
||||
declName= declName.getNextInBinding();
|
||||
}
|
||||
}
|
||||
}
|
||||
return (ICElement[]) defs.toArray(new ICElement[defs.size()]);
|
||||
}
|
||||
|
||||
private boolean encloses(IRegion range, int nodeOffset, int nodeLength) {
|
||||
int d1= nodeOffset - range.getOffset();
|
||||
int d2= range.getLength() - nodeLength - d1;
|
||||
return d1 >= 0 && d2 >= 0;
|
||||
}
|
||||
|
||||
private ICElement findEnclosingElement(ICProject project, PDOMName declName) throws CoreException {
|
||||
public ICElement[] findAllDefinitions(ICProject[] projectsToSearch, IASTName name) {
|
||||
name.resolveBinding();
|
||||
ArrayList result= new ArrayList();
|
||||
for (int i = 0; i < projectsToSearch.length; i++) {
|
||||
ICProject project = projectsToSearch[i];
|
||||
ICElement[] definitions= findAllDefinitions(project, name);
|
||||
if (definitions != null && definitions.length > 0) {
|
||||
result.addAll(Arrays.asList(definitions));
|
||||
}
|
||||
}
|
||||
return (ICElement[]) result.toArray(new ICElement[result.size()]);
|
||||
}
|
||||
|
||||
public ICElement[] findAllDefinitions(ICProject project, IASTName name) {
|
||||
PDOM pdom;
|
||||
try {
|
||||
pdom = (PDOM) CCorePlugin.getPDOMManager().getPDOM(project);
|
||||
if (pdom != null) {
|
||||
pdom.acquireReadLock();
|
||||
try {
|
||||
IBinding binding= pdom.resolveBinding(name);
|
||||
if (binding != null) {
|
||||
return allEnclosingElements(project, pdom.getDefinitions(binding));
|
||||
}
|
||||
}
|
||||
finally {
|
||||
pdom.releaseReadLock();
|
||||
}
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
return EMPTY_ELEMENTS;
|
||||
}
|
||||
|
||||
private ICElement[] allEnclosingElements(ICProject project, IASTName[] defs) {
|
||||
if (defs != null && defs.length > 0) {
|
||||
ArrayList result= new ArrayList(defs.length);
|
||||
for (int i = 0; i < defs.length; i++) {
|
||||
IASTName defName = defs[i];
|
||||
ICElement elem= findEnclosingElement(project, (PDOMName) defName);
|
||||
if (elem != null) {
|
||||
result.add(elem);
|
||||
}
|
||||
}
|
||||
return (ICElement[]) result.toArray(new ICElement[result.size()]);
|
||||
}
|
||||
return EMPTY_ELEMENTS;
|
||||
}
|
||||
|
||||
private ICElement findEnclosingElement(ICProject project, PDOMName declName) {
|
||||
ITranslationUnit tu= toTranslationUnit(project, declName);
|
||||
if (tu != null) {
|
||||
// mstodo use correct timestamp
|
||||
|
@ -320,35 +419,100 @@ public class CIndexQueries {
|
|||
return null;
|
||||
}
|
||||
|
||||
private ICElement findCaller(CIndexReference reference) throws CoreException {
|
||||
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();
|
||||
public ICElement findDefinition(ICProject[] projectsToSearch, IASTName name) {
|
||||
name.resolveBinding();
|
||||
|
||||
for (int i = 0; i < projectsToSearch.length; i++) {
|
||||
ICProject project = projectsToSearch[i];
|
||||
ICElement definition= findDefinition(project, name);
|
||||
if (definition != null) {
|
||||
return definition;
|
||||
}
|
||||
}
|
||||
return findElement(tu, offset, false);
|
||||
return null;
|
||||
}
|
||||
|
||||
public ICElement findDefinition(ICProject project, IASTName name) {
|
||||
PDOM pdom;
|
||||
try {
|
||||
pdom = (PDOM) CCorePlugin.getPDOMManager().getPDOM(project);
|
||||
if (pdom != null) {
|
||||
pdom.acquireReadLock();
|
||||
try {
|
||||
IBinding binding= pdom.resolveBinding(name);
|
||||
if (binding != null) {
|
||||
ICElement elem= firstEnclosingElement(project, pdom.getDefinitions(binding));
|
||||
if (elem != null) {
|
||||
return elem;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
pdom.releaseReadLock();
|
||||
}
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private ICElement findElement(ICElement element, int offset, boolean allowVars) throws CModelException {
|
||||
if (element == null || (element instanceof IFunctionDeclaration) ||
|
||||
(allowVars && element instanceof IVariableDeclaration)) {
|
||||
return element;
|
||||
}
|
||||
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 findElement(child, offset, allowVars);
|
||||
}
|
||||
private ICElement firstEnclosingElement(ICProject project, IASTName[] defs) {
|
||||
if (defs != null) {
|
||||
for (int i = 0; i < defs.length; i++) {
|
||||
IASTName defName = defs[i];
|
||||
ICElement elem= findEnclosingElement(project, (PDOMName) defName);
|
||||
if (elem != null) {
|
||||
return elem;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ICElement findAnyDeclaration(ICProject[] projectsToSearch, IASTName name) {
|
||||
name.resolveBinding();
|
||||
|
||||
for (int i = 0; i < projectsToSearch.length; i++) {
|
||||
ICProject project = projectsToSearch[i];
|
||||
ICElement declaration= findAnyDeclaration(project, name);
|
||||
if (declaration != null) {
|
||||
return declaration;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ICElement findAnyDeclaration(ICProject project, IASTName name) {
|
||||
PDOM pdom;
|
||||
try {
|
||||
pdom = (PDOM) CCorePlugin.getPDOMManager().getPDOM(project);
|
||||
if (pdom != null) {
|
||||
pdom.acquireReadLock();
|
||||
try {
|
||||
IBinding binding= pdom.resolveBinding(name);
|
||||
if (binding != null) {
|
||||
ICElement elem= firstEnclosingElement(project, pdom.getDefinitions(binding));
|
||||
if (elem != null) {
|
||||
return elem;
|
||||
}
|
||||
elem= firstEnclosingElement(project, pdom.getDeclarations(binding));
|
||||
if (elem != null) {
|
||||
return elem;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
pdom.releaseReadLock();
|
||||
}
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.getDefault().log(e);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*******************************************************************************
|
||||
* 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.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
|
||||
/**
|
||||
* Visitor to find references in a given range of the source code.
|
||||
* @since 4.0
|
||||
*/
|
||||
class ReferenceVisitor extends ASTVisitor {
|
||||
private ArrayList fReferences= new ArrayList();
|
||||
private int fOffset;
|
||||
private int fEndOffset;
|
||||
private String fFileName;
|
||||
|
||||
ReferenceVisitor(String fileName, int offset, int length) {
|
||||
shouldVisitNames= true;
|
||||
shouldVisitDeclarations= true;
|
||||
|
||||
fFileName= fileName;
|
||||
fOffset= offset;
|
||||
fEndOffset= offset+length;
|
||||
}
|
||||
|
||||
public IASTName[] getReferences() {
|
||||
return (IASTName[]) fReferences.toArray(new IASTName[fReferences.size()]);
|
||||
}
|
||||
|
||||
public int visit(IASTName name) {
|
||||
if (name.isReference()) {
|
||||
IASTFileLocation loc= name.getFileLocation();
|
||||
if (!loc.getFileName().equals(fFileName)) {
|
||||
return PROCESS_SKIP;
|
||||
}
|
||||
int offset= loc.getNodeOffset();
|
||||
if (fOffset <= offset && offset+loc.getNodeLength() <= fEndOffset) {
|
||||
fReferences.add(name);
|
||||
}
|
||||
}
|
||||
return super.visit(name);
|
||||
}
|
||||
|
||||
public int visit(IASTDeclaration declaration) {
|
||||
IASTFileLocation loc= declaration.getFileLocation();
|
||||
if (!loc.getFileName().equals(fFileName)) {
|
||||
return PROCESS_SKIP;
|
||||
}
|
||||
int offset= loc.getNodeOffset();
|
||||
if (offset + loc.getNodeLength() <= fOffset || fEndOffset <= offset) {
|
||||
return PROCESS_SKIP;
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue