1
0
Fork 0
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:
Markus Schorn 2008-03-03 15:05:11 +00:00
parent cf7493d440
commit 4e91bb54ab
10 changed files with 280 additions and 37 deletions

View file

@ -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;
}
}
}
}

View file

@ -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;
}
/**

View file

@ -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;
}
}

View file

@ -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++) {

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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());
}
}

View file

@ -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() {

View file

@ -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;

View file

@ -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;