From 4e91bb54ab7237c04102517236b80178a83f8899 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Mon, 3 Mar 2008 15:05:11 +0000 Subject: Navigating an argument of a macro-expansion, bug 208300. --- .../cdt/core/index/IndexLocationFactory.java | 13 +- .../internal/core/dom/parser/ASTNodeMatchKind.java | 20 ++- .../eclipse/cdt/internal/core/index/CIndex.java | 3 + .../core/parser/scanner/ASTPreprocessorNode.java | 2 +- .../parser/scanner/FindNodeByImageLocation.java | 191 +++++++++++++++++++++ .../parser/scanner/LocationCtxMacroExpansion.java | 3 +- .../internal/core/parser/scanner/LocationMap.java | 35 +++- .../internal/core/pdom/AbstractIndexerTask.java | 7 + 8 files changed, 254 insertions(+), 20 deletions(-) create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/FindNodeByImageLocation.java (limited to 'core/org.eclipse.cdt.core/parser') diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IndexLocationFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IndexLocationFactory.java index a47f2301d21..a8bdaed3f8e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IndexLocationFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IndexLocationFactory.java @@ -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 null 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; } /** diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeMatchKind.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeMatchKind.java index ff4a186f9d3..20acf3266c5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeMatchKind.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeMatchKind.java @@ -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; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java index d799499567d..f9784997b44 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java @@ -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 result= new ArrayList(); BitSet linkages= new BitSet(); for (int i = 0; i < fPrimaryFragmentCount; i++) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java index 3563065d0c8..fa8f7cbdae1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java @@ -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; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/FindNodeByImageLocation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/FindNodeByImageLocation.java new file mode 100644 index 00000000000..189b092f6aa --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/FindNodeByImageLocation.java @@ -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; + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java index 0dc39f5a8c0..753203b6b44 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java @@ -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()); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java index b0b54f63ce2..9b300aa3e09 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java @@ -51,7 +51,7 @@ public class LocationMap implements ILocationResolver { private ArrayList fProblems= new ArrayList(); private ArrayList fComments= new ArrayList(); private ArrayList fBuiltinMacros= new ArrayList(); - private ArrayList fMacroReferences= new ArrayList(); + private ArrayList fMacroReferences= new ArrayList(); 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 result= new ArrayList(); - for (IASTName name : fMacroReferences) { + List result= new ArrayList(); + 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() { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java index a38c15f5111..3974161d378 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java @@ -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; -- cgit v1.2.3