mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-03 14:25:37 +02:00
Navigating an argument of a macro-expansion, bug 208300.
This commit is contained in:
parent
cf7493d440
commit
4e91bb54ab
10 changed files with 280 additions and 37 deletions
|
@ -839,21 +839,23 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
|
|||
for (int i = 0; i < CTX_LINKAGES.length; i++) {
|
||||
IIndexFile context= null;
|
||||
final IIndexFileLocation ifl = IndexLocationFactory.getIFL(this);
|
||||
IIndexFile indexFile= index.getFile(CTX_LINKAGES[i], ifl);
|
||||
if (indexFile != null) {
|
||||
// bug 199412, when a source-file includes itself the context may recurse.
|
||||
HashSet<IIndexFile> visited= new HashSet<IIndexFile>();
|
||||
visited.add(indexFile);
|
||||
indexFile = getParsedInContext(indexFile);
|
||||
while (indexFile != null && visited.add(indexFile)) {
|
||||
context= indexFile;
|
||||
indexFile= getParsedInContext(indexFile);
|
||||
if (ifl != null) {
|
||||
IIndexFile indexFile= index.getFile(CTX_LINKAGES[i], ifl);
|
||||
if (indexFile != null) {
|
||||
// bug 199412, when a source-file includes itself the context may recurse.
|
||||
HashSet<IIndexFile> visited= new HashSet<IIndexFile>();
|
||||
visited.add(indexFile);
|
||||
indexFile = getParsedInContext(indexFile);
|
||||
while (indexFile != null && visited.add(indexFile)) {
|
||||
context= indexFile;
|
||||
indexFile= getParsedInContext(indexFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (context != null) {
|
||||
ITranslationUnit tu= CoreModelUtil.findTranslationUnitForLocation(context.getLocation(), getCProject());
|
||||
if (tu != null && tu.isSourceUnit()) {
|
||||
return tu;
|
||||
if (context != null) {
|
||||
ITranslationUnit tu= CoreModelUtil.findTranslationUnitForLocation(context.getLocation(), getCProject());
|
||||
if (tu != null && tu.isSourceUnit()) {
|
||||
return tu;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006, 2007 Symbian Software Ltd. and others.
|
||||
* Copyright (c) 2006, 2008 Symbian Software Ltd. 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
|
||||
|
@ -10,6 +10,8 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.index;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.internal.core.index.IndexFileLocation;
|
||||
|
@ -120,12 +122,17 @@ public class IndexLocationFactory {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns an IIndexFileLocation for the specified workspace file
|
||||
* Returns an IIndexFileLocation for the specified workspace file, or <code>null</code> if it does not
|
||||
* have a location.
|
||||
* @param file
|
||||
* @return an IIndexFileLocation for the specified workspace file
|
||||
*/
|
||||
public static IIndexFileLocation getWorkspaceIFL(IFile file) {
|
||||
return new IndexFileLocation(file.getLocationURI(), file.getFullPath().toString());
|
||||
final URI locationURI = file.getLocationURI();
|
||||
if (locationURI != null) {
|
||||
return new IndexFileLocation(locationURI, file.getFullPath().toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -48,12 +48,18 @@ public class ASTNodeMatchKind {
|
|||
* Returns whether the node matches the selection.
|
||||
*/
|
||||
public boolean matches(ASTNode node, int selOffset, int selLength) {
|
||||
if (fNamesOnly && node instanceof IASTName == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int nodeOffset= node.getOffset();
|
||||
final int nodeLength= node.getLength();
|
||||
return isAcceptableNode(node) && rangeMatches(node.getOffset(), node.getLength(), selOffset, selLength);
|
||||
}
|
||||
|
||||
public boolean isAcceptableNode(ASTNode astNode) {
|
||||
return !fNamesOnly || astNode instanceof IASTName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the node range matches the selection.
|
||||
*/
|
||||
public boolean rangeMatches(final int nodeOffset, final int nodeLength, int selOffset,
|
||||
int selLength) {
|
||||
switch(fRelation) {
|
||||
case EXACT:
|
||||
return selOffset == nodeOffset && selLength == nodeLength;
|
||||
|
@ -63,7 +69,7 @@ public class ASTNodeMatchKind {
|
|||
return nodeOffset <= selOffset && selOffset+selLength <= nodeOffset+nodeLength;
|
||||
default:
|
||||
assert false;
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -187,6 +187,9 @@ public class CIndex implements IIndex {
|
|||
}
|
||||
|
||||
public IIndexFile[] getFiles(IIndexFileLocation location) throws CoreException {
|
||||
if (location == null) {
|
||||
return IIndexFile.EMPTY_FILE_ARRAY;
|
||||
}
|
||||
ArrayList<IIndexFragmentFile> result= new ArrayList<IIndexFragmentFile>();
|
||||
BitSet linkages= new BitSet();
|
||||
for (int i = 0; i < fPrimaryFragmentCount; i++) {
|
||||
|
|
|
@ -413,7 +413,7 @@ class ASTUndef extends ASTPreprocessorNode implements IASTPreprocessorUndefState
|
|||
fName= new ASTPreprocessorName(this, IASTPreprocessorUndefStatement.MACRO_NAME, nameNumber, nameEndNumber, name, binding);
|
||||
}
|
||||
|
||||
public IASTName getMacroName() {
|
||||
public ASTPreprocessorName getMacroName() {
|
||||
return fName;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008 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.core.parser.scanner;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTImageLocation;
|
||||
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.IASTParameterDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTProblem;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICASTDesignator;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind;
|
||||
|
||||
public class FindNodeByImageLocation extends CPPASTVisitor implements ICASTVisitor, ICPPASTVisitor {
|
||||
private ASTNode fCandidate= null;
|
||||
private final int fOffset;
|
||||
private final int fLength;
|
||||
private final ASTNodeMatchKind fMatchKind;
|
||||
private int fImageOffset;
|
||||
private int fImageLength;
|
||||
|
||||
public FindNodeByImageLocation(int offset, int length, int imgOffset, int imgLength, ASTNodeMatchKind matchKind) {
|
||||
fMatchKind= matchKind;
|
||||
fOffset = offset;
|
||||
fLength = length;
|
||||
fImageOffset= imgOffset;
|
||||
fImageLength= imgLength;
|
||||
|
||||
shouldVisitNames = true;
|
||||
shouldVisitDeclarations= true;
|
||||
|
||||
shouldVisitInitializers=
|
||||
shouldVisitParameterDeclarations=
|
||||
shouldVisitDeclarators=
|
||||
shouldVisitDeclSpecifiers=
|
||||
shouldVisitDesignators=
|
||||
shouldVisitEnumerators=
|
||||
shouldVisitExpressions=
|
||||
shouldVisitStatements=
|
||||
shouldVisitTypeIds=
|
||||
shouldVisitEnumerators=
|
||||
shouldVisitBaseSpecifiers=
|
||||
shouldVisitNamespaces=
|
||||
shouldVisitTemplateParameters=
|
||||
shouldVisitTranslationUnit= !matchKind.matchNamesOnly();
|
||||
}
|
||||
|
||||
public int processNode(IASTNode node) {
|
||||
if (node instanceof ASTNode) {
|
||||
final ASTNode astNode = (ASTNode) node;
|
||||
if (astNode.getOffset() > fOffset+fLength || astNode.getOffset() + astNode.getLength() < fOffset) {
|
||||
return PROCESS_SKIP;
|
||||
}
|
||||
|
||||
if (fMatchKind.isAcceptableNode(astNode)) {
|
||||
IASTImageLocation imageLocation= astNode.getImageLocation();
|
||||
if (imageLocation != null && imageLocation.getLocationKind() == IASTImageLocation.ARGUMENT_TO_MACRO_EXPANSION) {
|
||||
if (fMatchKind.rangeMatches(imageLocation.getNodeOffset(), imageLocation.getNodeLength(), fImageOffset, fImageLength)) {
|
||||
if (fCandidate == null || !fMatchKind.isBetterMatch(fCandidate, astNode)) {
|
||||
fCandidate= astNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTDeclaration declaration) {
|
||||
// use declarations to determine if the search has gone past the
|
||||
// offset (i.e. don't know the order the visitor visits the nodes)
|
||||
if (declaration instanceof ASTNode && ((ASTNode) declaration).getOffset() > fOffset + fLength)
|
||||
return PROCESS_ABORT;
|
||||
|
||||
return processNode(declaration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTDeclarator declarator) {
|
||||
return processNode(declarator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTDeclSpecifier declSpec) {
|
||||
return processNode(declSpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTEnumerator enumerator) {
|
||||
return processNode(enumerator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTExpression expression) {
|
||||
return processNode(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTInitializer initializer) {
|
||||
return processNode(initializer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTName name) {
|
||||
if (name.toString() != null)
|
||||
return processNode(name);
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTParameterDeclaration parameterDeclaration) {
|
||||
return processNode(parameterDeclaration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTStatement statement) {
|
||||
return processNode(statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTTypeId typeId) {
|
||||
return processNode(typeId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(ICPPASTBaseSpecifier baseSpecifier) {
|
||||
return processNode(baseSpecifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(ICPPASTNamespaceDefinition namespaceDefinition) {
|
||||
return processNode(namespaceDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(ICPPASTTemplateParameter templateParameter) {
|
||||
return processNode(templateParameter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTProblem problem) {
|
||||
return processNode(problem);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processDesignator(org.eclipse.cdt.core.dom.ast.c.ICASTDesignator)
|
||||
*/
|
||||
public int visit(ICASTDesignator designator) {
|
||||
return processNode(designator);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.c.ICASTVisitor#leave(org.eclipse.cdt.core.dom.ast.c.ICASTDesignator)
|
||||
*/
|
||||
public int leave(ICASTDesignator designator) {
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTTranslationUnit tu) {
|
||||
return processNode(tu);
|
||||
}
|
||||
|
||||
public ASTNode getNode() {
|
||||
return fCandidate;
|
||||
}
|
||||
}
|
|
@ -13,7 +13,6 @@ package org.eclipse.cdt.internal.core.parser.scanner;
|
|||
import java.util.ArrayList;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTImageLocation;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
|
||||
|
@ -130,7 +129,7 @@ class LocationCtxMacroExpansion extends LocationCtx {
|
|||
return null;
|
||||
}
|
||||
|
||||
public IASTName[] getNestedMacroReferences() {
|
||||
public ASTPreprocessorName[] getNestedMacroReferences() {
|
||||
return fLocationMap.getNestedMacroReferences((ASTMacroExpansion) fExpansionName.getParent());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ public class LocationMap implements ILocationResolver {
|
|||
private ArrayList<ASTProblem> fProblems= new ArrayList<ASTProblem>();
|
||||
private ArrayList<ASTComment> fComments= new ArrayList<ASTComment>();
|
||||
private ArrayList<ASTMacroDefinition> fBuiltinMacros= new ArrayList<ASTMacroDefinition>();
|
||||
private ArrayList<IASTName> fMacroReferences= new ArrayList<IASTName>();
|
||||
private ArrayList<ASTPreprocessorName> fMacroReferences= new ArrayList<ASTPreprocessorName>();
|
||||
|
||||
private LocationCtxFile fRootContext= null;
|
||||
private LocationCtx fCurrentContext= null;
|
||||
|
@ -176,7 +176,7 @@ public class LocationMap implements ILocationResolver {
|
|||
return fCurrentContext;
|
||||
}
|
||||
|
||||
private void addMacroReference(IASTName name) {
|
||||
private void addMacroReference(ASTPreprocessorName name) {
|
||||
fMacroReferences.add(name);
|
||||
}
|
||||
|
||||
|
@ -460,7 +460,28 @@ public class LocationMap implements ILocationResolver {
|
|||
// search for a macro-expansion
|
||||
LocationCtxMacroExpansion ctx= fRootContext.findSurroundingMacroExpansion(sequenceNumber, length);
|
||||
if (ctx != null) {
|
||||
return ctx.findNode(sequenceNumber, length, matchKind);
|
||||
ASTNode candidate= ctx.findNode(sequenceNumber, length, matchKind);
|
||||
int imageOffset= ctx.fEndOffsetInParent + sequenceNumber - ctx.fSequenceNumber;
|
||||
if (fTranslationUnit != null) {
|
||||
FindNodeByImageLocation visitor= new FindNodeByImageLocation(ctx.fSequenceNumber, ctx.getSequenceLength(), imageOffset, length, matchKind);
|
||||
fTranslationUnit.accept(visitor);
|
||||
ASTNode candidate2= visitor.getNode();
|
||||
if (matchKind.isBetterMatch(candidate2, candidate)) {
|
||||
candidate= candidate2;
|
||||
}
|
||||
}
|
||||
ASTPreprocessorName[] nested= ctx.getNestedMacroReferences();
|
||||
for (ASTPreprocessorName name : nested) {
|
||||
IASTImageLocation imageLoc= name.getImageLocation();
|
||||
if (imageLoc != null && imageLoc.getLocationKind() == IASTImageLocation.ARGUMENT_TO_MACRO_EXPANSION) {
|
||||
if (matchKind.rangeMatches(imageLoc.getNodeOffset(), imageLoc.getNodeLength(), imageOffset, length)) {
|
||||
if (matchKind.isBetterMatch(name, candidate)) {
|
||||
candidate= name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -590,15 +611,15 @@ public class LocationMap implements ILocationResolver {
|
|||
return result.toArray(new IASTName[result.size()]);
|
||||
}
|
||||
|
||||
public IASTName[] getNestedMacroReferences(ASTMacroExpansion expansion) {
|
||||
public ASTPreprocessorName[] getNestedMacroReferences(ASTMacroExpansion expansion) {
|
||||
final IASTName explicitRef= expansion.getMacroReference();
|
||||
List<IASTName> result= new ArrayList<IASTName>();
|
||||
for (IASTName name : fMacroReferences) {
|
||||
List<ASTPreprocessorName> result= new ArrayList<ASTPreprocessorName>();
|
||||
for (ASTPreprocessorName name : fMacroReferences) {
|
||||
if (name.getParent() == expansion && name != explicitRef) {
|
||||
result.add(name);
|
||||
}
|
||||
}
|
||||
return result.toArray(new IASTName[result.size()]);
|
||||
return result.toArray(new ASTPreprocessorName[result.size()]);
|
||||
}
|
||||
|
||||
public IDependencyTree getDependencyTree() {
|
||||
|
|
|
@ -249,6 +249,9 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
|
|||
|
||||
final Object tu= fFilesToUpdate[i];
|
||||
final IIndexFileLocation ifl= fResolver.resolveFile(tu);
|
||||
if (ifl == null)
|
||||
continue;
|
||||
|
||||
final boolean isSourceUnit= fResolver.isSourceUnit(tu);
|
||||
final boolean isExcludedSource= isSourceUnit && !fIndexFilesWithoutConfiguration && !fResolver.isFileBuildConfigured(tu);
|
||||
final IIndexFragmentFile[] indexFiles= fIndex.getWritableFiles(ifl);
|
||||
|
@ -393,6 +396,8 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
|
|||
}
|
||||
final Object tu = iterator.next();
|
||||
IIndexFileLocation ifl= fResolver.resolveFile(tu);
|
||||
if (ifl == null)
|
||||
continue;
|
||||
IIndexFragmentFile[] ifiles= fIndex.getWritableFiles(ifl);
|
||||
for (int i = 0; i < ifiles.length; i++) {
|
||||
IIndexFragmentFile ifile = ifiles[i];
|
||||
|
@ -470,6 +475,8 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
|
|||
return;
|
||||
final Object tu= iter.next();
|
||||
final IIndexFileLocation ifl = fResolver.resolveFile(tu);
|
||||
if (ifl == null)
|
||||
continue;
|
||||
final FileContent info= getFileInfo(linkageID, ifl);
|
||||
if (info != null && info.fRequestUpdate && !info.fIsUpdated) {
|
||||
info.fRequestIsCounted= false;
|
||||
|
|
|
@ -943,14 +943,16 @@ public abstract class CPPSelectionTestsAnyIndexer extends BaseSelectionTestsInde
|
|||
assertNode("MY_PAR", offset0, decl);
|
||||
}
|
||||
|
||||
// #define MY_MACRO 0xDEADBEEF
|
||||
// #define MY_PAR( aRef );
|
||||
// #define MY_MACRO 0xDEADBEEF
|
||||
// #define MY_PAR( aRef ) aRef;
|
||||
// int gvar;
|
||||
|
||||
// #include "macrodef.h"
|
||||
// int basictest(void){
|
||||
// int tester = MY_PAR(MY_MACRO);
|
||||
// tester= MY_PAR(gvar);
|
||||
// }
|
||||
public void _testMacroNavigation_Bug208300() throws Exception {
|
||||
public void testMacroNavigation_Bug208300() throws Exception {
|
||||
StringBuffer[] buffers= getContents(2);
|
||||
String hcode= buffers[0].toString();
|
||||
String scode= buffers[1].toString();
|
||||
|
@ -969,6 +971,11 @@ public abstract class CPPSelectionTestsAnyIndexer extends BaseSelectionTestsInde
|
|||
offset1 = scode.indexOf("MY_MACRO");
|
||||
decl = testF3(file, offset1);
|
||||
assertNode("MY_MACRO", offset0, decl);
|
||||
|
||||
offset0 = hcode.indexOf("gvar");
|
||||
offset1 = scode.indexOf("gvar");
|
||||
decl = testF3(file, offset1);
|
||||
assertNode("gvar", offset0, decl);
|
||||
}
|
||||
|
||||
// int wurscht;
|
||||
|
|
Loading…
Add table
Reference in a new issue