diff options
Diffstat (limited to 'core/org.eclipse.cdt.core/parser')
18 files changed, 650 insertions, 158 deletions
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTMacroExpansion.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTMacroExpansion.java index a650c2c3fee..d4d7270b5ee 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTMacroExpansion.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTMacroExpansion.java @@ -12,12 +12,9 @@ package org.eclipse.cdt.core.dom.ast; /** - * A Macro expansion is a node location. Nodes that have locations that arrive - * through the expansion of preprocessor macros will refer to these type of - * objects. - * - * @author Doug Schaefer + * @deprecated, use IASTMacroExpansionLocation instead */ +@Deprecated public interface IASTMacroExpansion extends IASTNodeLocation { /** @@ -54,5 +51,6 @@ public interface IASTMacroExpansion extends IASTNodeLocation { * @return * @deprecated use {@link IASTNodeLocation#asFileLocation()}. */ + @Deprecated public IASTNodeLocation[] getExpansionLocations(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTMacroExpansionLocation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTMacroExpansionLocation.java new file mode 100644 index 00000000000..d6808040620 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTMacroExpansionLocation.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * 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.core.dom.ast; + +/** + * Node location inside of a macro expansion. + * @since 5.0 + */ +public interface IASTMacroExpansionLocation extends IASTNodeLocation { + + /** + * Returns the expansion node enclosing this location. This will be the outermost + * macro expansion that can actually be found in the code. + */ + public IASTPreprocessorMacroExpansion getExpansion(); + + /** + * Returns an offset within the macro-expansion. The offset can be used to compare + * nodes within the same macro-expansion. However, it does not serve as an offset + * into a file. + */ + public int getNodeOffset(); + + /** + * Returns the length of this location. The length can be used to compare this location + * with others from within the same macro-expansion. However, the length does not neccessarily + * relate to a length in terms of characters. + */ + public int getNodeLength(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java index 1ddd1cbd6e8..0e6d288390d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2007 IBM Corporation and others. + * Copyright (c) 2004, 2008 IBM Corporation 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 @@ -36,7 +36,7 @@ public interface IASTNode { * * Where the node is completely generated within a macro expansion, * IASTNodeLocation [] result will have one element in it, and it will be an - * IASTMacroExpansion. + * {@link IASTMacroExpansionLocation}. * * Nodes that span file context into a macro expansion (and potentially out * of the macro expansion again) result in an IASTNodeLocation [] result diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNodeSelector.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNodeSelector.java new file mode 100644 index 00000000000..636ee3cf6b4 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNodeSelector.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * 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.core.dom.ast; + +/** + * Interface for searching nodes of a file in a translation unit. An instance of this interface can + * be obtained via {@link IASTTranslationUnit#getNodeSelector(String)}. + * @since 5.0 + */ +public interface IASTNodeSelector { + + /** + * Returns the name for the exact given range, or <code>null</code> if there is no such node. + */ + IASTName findName(int offset, int length); + + /** + * Returns the smallest name surrounding the given range, or <code>null</code> if there is no such node. + */ + IASTName findSurroundingName(int offset, int length); + + /** + * Returns the first name contained in the given range, or <code>null</code> if there is no such node. + */ + IASTName findFirstContainedName(int offset, int length); + + /** + * Returns the node for the exact given range, or <code>null</code> if there is no such node. + */ + IASTNode findNode(int offset, int length); + + /** + * Returns the smallest node surrounding the given range, or <code>null</code> if there is no such node. + */ + IASTNode findSurroundingNode(int offset, int length); + + /** + * Returns the first node contained in the given range, or <code>null</code> if there is no such node. + */ + IASTNode findFirstContainedNode(int offset, int length); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorMacroExpansion.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorMacroExpansion.java new file mode 100644 index 00000000000..84028700725 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorMacroExpansion.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * 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.core.dom.ast; + +/** + * Models macro expansion found in the source code that is not nested inside another expansion. + * @since 5.0 + */ +public interface IASTPreprocessorMacroExpansion extends IASTNode { + public static final IASTPreprocessorMacroExpansion[] EMPTY_ARRAY = {}; + public static final ASTNodeProperty EXPANSION_NAME= + new ASTNodeProperty("IASTPreprocessorMacroExpansion.EXPANSION_NAME - macro name"); //$NON-NLS-1$ + + /** + * Returns the macro definition used for the expansion. + */ + public IASTPreprocessorMacroDefinition getMacroDefinition(); + + /** + * Returns the reference to the macro that causes this expansion. + */ + public IASTName getMacroReference(); + + /** + * Returns an array of nested macro expansions. + */ + public IASTName[] getNestedMacroReferences(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java index 7c909837577..f2929181935 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java @@ -115,15 +115,23 @@ public interface IASTTranslationUnit extends IASTNode, IAdaptable { * @return List of IASTName nodes representing uses of the binding */ public IASTName[] getReferences(IBinding binding); + + + /** + * Returns an IASTNodeSelector object for finding nodes by file offsets. + * The object is suitable for working in one of the files that is part of + * the translation unit. + * @param filePath file of interest, as returned by {@link IASTFileLocation#getFileName()}, + * or <code>null</code> to specify the root source of the translation-unit. + * @return an IASTNodeSelector. + * @since 5.0 + */ + public IASTNodeSelector getNodeSelector(String filePath); /** - * Select the node in the treat that best fits the offset/length/file path. - * - * @param path - file name specified through path - * @param offset - location in the file as an offset - * @param length - length of selection - * @return <code>IASTNode</code> that best fits + * @deprecated use {@link #getNodeSelector(String)}, instead. */ + @Deprecated public IASTNode selectNodeForLocation(String path, int offset, int length); /** @@ -158,6 +166,11 @@ public interface IASTTranslationUnit extends IASTNode, IAdaptable { public IASTPreprocessorStatement[] getAllPreprocessorStatements(); /** + * Returns an array with all macro expansions of this translation unit. + */ + public IASTPreprocessorMacroExpansion[] getMacroExpansions(); + + /** * Get all preprocessor and scanner problems. * @return <code>IASTProblem[]</code> */ @@ -182,9 +195,16 @@ public interface IASTTranslationUnit extends IASTNode, IAdaptable { */ public IASTFileLocation flattenLocationsToFile( IASTNodeLocation [] nodeLocations ); - public static final ASTNodeProperty EXPANSION_NAME = new ASTNodeProperty( + /** + * @deprecated names for macro expansions are nested inside of {@link IASTPreprocessorMacroExpansion}. + */ + @Deprecated + public static final ASTNodeProperty EXPANSION_NAME = new ASTNodeProperty( "IASTTranslationUnit.EXPANSION_NAME - IASTName generated for macro expansions."); //$NON-NLS-1$ - + + public static final ASTNodeProperty MACRO_EXPANSION = new ASTNodeProperty( + "IASTTranslationUnit.MACRO_EXPANSION - IASTPreprocessorMacroExpansion node for macro expansions."); //$NON-NLS-1$ + public static interface IDependencyTree { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/AbstractCLikeLanguage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/AbstractCLikeLanguage.java index 3bc79dd7596..b7b34d7c914 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/AbstractCLikeLanguage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/AbstractCLikeLanguage.java @@ -23,6 +23,7 @@ import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTCompletionNode; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.model.AbstractLanguage; @@ -180,13 +181,17 @@ public abstract class AbstractCLikeLanguage extends AbstractLanguage implements public IASTName[] getSelectedNames(IASTTranslationUnit ast, int start, int length) { - IASTNode selectedNode= ast.selectNodeForLocation(ast.getFilePath(), start, length); + IASTNode selectedNode= ast.getNodeSelector(null).findNode(start, length); if (selectedNode == null) return new IASTName[0]; if (selectedNode instanceof IASTName) return new IASTName[] { (IASTName) selectedNode }; + + if (selectedNode instanceof IASTPreprocessorMacroExpansion) { + return new IASTName[] {((IASTPreprocessorMacroExpansion) selectedNode).getMacroReference()}; + } NameCollector collector = new NameCollector(); selectedNode.accept(collector); 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 new file mode 100644 index 00000000000..ff4a186f9d3 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeMatchKind.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * 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.dom.parser; + +import org.eclipse.cdt.core.dom.ast.IASTName; + +/** + * For searching ast-nodes by offset and length, instances of this class can be used to + * determine whether a node matches or not. + * + * @since 5.0 + */ +public class ASTNodeMatchKind { + public enum Relation {FIRST_CONTAINED, EXACT, SURROUNDING} + + static final ASTNodeMatchKind MATCH_EXACT= new ASTNodeMatchKind(Relation.EXACT, false); + static final ASTNodeMatchKind MATCH_EXACT_NAME= new ASTNodeMatchKind(Relation.EXACT, true); + static final ASTNodeMatchKind MATCH_FIRST_CONTAINED= new ASTNodeMatchKind(Relation.FIRST_CONTAINED, false); + static final ASTNodeMatchKind MATCH_FIRST_NAME_CONTAINED= new ASTNodeMatchKind(Relation.FIRST_CONTAINED, true); + static final ASTNodeMatchKind MATCH_SURROUNDING= new ASTNodeMatchKind(Relation.SURROUNDING, false); + static final ASTNodeMatchKind MATCH_SURROUNDING_NAME= new ASTNodeMatchKind(Relation.SURROUNDING, true); + + private boolean fNamesOnly; + private Relation fRelation; + + private ASTNodeMatchKind(Relation relation, boolean namesOnly) { + fRelation= relation; + fNamesOnly= namesOnly; + } + + public Relation getRelationToSelection() { + return fRelation; + } + + public boolean matchNamesOnly() { + return fNamesOnly; + } + + /** + * 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(); + switch(fRelation) { + case EXACT: + return selOffset == nodeOffset && selLength == nodeLength; + case FIRST_CONTAINED: + return selOffset <= nodeOffset && nodeOffset+nodeLength <= selOffset+selLength; + case SURROUNDING: + return nodeOffset <= selOffset && selOffset+selLength <= nodeOffset+nodeLength; + default: + assert false; + return false; + } + } + + /** + * Returns whether the node is a lower bound for matching the selection. A node is a lower + * bound when a node to the left of the given one cannot match the selection. + */ + public boolean isLowerBound(ASTNode node, int selOffset, int selLength) { + final int nodeOffset= node.getOffset(); + switch(fRelation) { + case SURROUNDING: + case EXACT: + return nodeOffset < selOffset+selLength; + case FIRST_CONTAINED: + return nodeOffset <= selOffset; + default: + assert false; + return false; + } + } + + /** + * Returns whether cand1 is a better match than cand2, prefers cand1 in case of doubt. + */ + public boolean isBetterMatch(ASTNode cand1, ASTNode cand2) { + if (cand1 == null) + return false; + if (cand2 == null) + return true; + + final int nodeOffset1= cand1.getOffset(); + final int nodeLength1= cand1.getLength(); + final int nodeOffset2= cand2.getOffset(); + final int nodeLength2= cand2.getLength(); + switch(fRelation) { + case EXACT: + return true; + case FIRST_CONTAINED: + return nodeOffset1 < nodeOffset2 || (nodeOffset1 == nodeOffset2 && nodeLength1 <= nodeLength2); + case SURROUNDING: + return nodeLength1 <= nodeLength2; + default: + assert false; + return false; + } + } +}
\ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSelector.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSelector.java new file mode 100644 index 00000000000..75b1fbe130f --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSelector.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * 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.dom.parser; + +import org.eclipse.cdt.core.dom.ast.IASTMacroExpansionLocation; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; +import org.eclipse.cdt.core.dom.ast.IASTNodeSelector; +import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind.Relation; +import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver; + +/** + * Class to support searching for nodes by offsets. + * @since 5.0 + */ +public class ASTNodeSelector implements IASTNodeSelector { + + private ASTTranslationUnit fTu; + private ILocationResolver fLocationResolver; + private String fFilePath; + private final boolean fIsValid; + + public ASTNodeSelector(ASTTranslationUnit tu, ILocationResolver locationResolver, String filePath) { + fTu= tu; + fLocationResolver= locationResolver; + fFilePath= filePath; + fIsValid= verify(); + } + + private boolean verify() { + if (fLocationResolver != null) { + if (fFilePath == null) { + fFilePath= fLocationResolver.getTranslationUnitPath(); + } + return true; + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getNode(int, int) + */ + private IASTNode getNode(int offset, int length, ASTNodeMatchKind matchKind) { + if (!fIsValid) { + return null; + } + + final int sequenceNumber= fLocationResolver.getSequenceNumberForFileOffset(fFilePath, offset); + if (sequenceNumber < 0) { + return null; + } + final int sequenceLength= length <= 0 ? 0 : + fLocationResolver.getSequenceNumberForFileOffset(fFilePath, offset+length-1) + 1 - sequenceNumber; + + ASTNode preCand= searchPreprocessor(sequenceNumber, sequenceLength, matchKind); + if (preCand != null && matchKind.getRelationToSelection() != Relation.FIRST_CONTAINED) { + return preCand; + } + ASTNode astCand= searchAST(sequenceNumber, sequenceLength, matchKind); + return matchKind.isBetterMatch(preCand, astCand) ? preCand : astCand; + } + + private ASTNode searchPreprocessor(int sequenceNumber, int sequenceLength, ASTNodeMatchKind matchKind) { + return fLocationResolver.findPreprocessorNode(sequenceNumber, sequenceLength, matchKind); + } + + private ASTNode searchAST(int sequenceNumber, int length, ASTNodeMatchKind matchKind) { + FindNodeForOffsetAction nodeFinder= new FindNodeForOffsetAction(sequenceNumber, length, matchKind); + fTu.accept(nodeFinder); + ASTNode result= nodeFinder.getNode(); + // don't accept matches from the ast enclosed in a macro expansion (possible for contained matches, only) + if (result != null && + matchKind.getRelationToSelection() == Relation.FIRST_CONTAINED) { + IASTNodeLocation[] loc= result.getNodeLocations(); + if (loc.length > 0 && loc[0] instanceof IASTMacroExpansionLocation) { + return null; + } + } + return result; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getFirstContainedNode(int, int) + */ + public IASTNode findFirstContainedNode(int offset, int length) { + return getNode(offset, length, ASTNodeMatchKind.MATCH_FIRST_CONTAINED); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getNode(int, int) + */ + public IASTNode findNode(int offset, int length) { + return getNode(offset, length, ASTNodeMatchKind.MATCH_EXACT); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getSurroundingNode(int, int) + */ + public IASTNode findSurroundingNode(int offset, int length) { + return getNode(offset, length, ASTNodeMatchKind.MATCH_SURROUNDING); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getFirstContainedNode(int, int) + */ + public IASTName findFirstContainedName(int offset, int length) { + return (IASTName) getNode(offset, length, ASTNodeMatchKind.MATCH_FIRST_NAME_CONTAINED); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getNode(int, int) + */ + public IASTName findName(int offset, int length) { + return (IASTName) getNode(offset, length, ASTNodeMatchKind.MATCH_EXACT_NAME); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getSurroundingNode(int, int) + */ + public IASTName findSurroundingName(int offset, int length) { + return (IASTName) getNode(offset, length, ASTNodeMatchKind.MATCH_SURROUNDING_NAME); + } + +}
\ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java index caa28508919..4cdf3a28a88 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java @@ -21,8 +21,10 @@ import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; +import org.eclipse.cdt.core.dom.ast.IASTNodeSelector; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; import org.eclipse.cdt.core.dom.ast.IASTProblem; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; @@ -139,11 +141,20 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat return EMPTY_PREPROCESSOR_MACRODEF_ARRAY; return fLocationResolver.getMacroDefinitions(); } - + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.IASTTranslationUnit#getMacroExpansions() + */ + public IASTPreprocessorMacroExpansion[] getMacroExpansions() { + if (fLocationResolver == null) + return IASTPreprocessorMacroExpansion.EMPTY_ARRAY; + return fLocationResolver.getMacroExpansions(getFileLocation()); + } + /* * (non-Javadoc) * - * @see org.eclipse.cdt.core.dom.ast.IASTTranslationUnit#getMacroDefinitions() + * @see org.eclipse.cdt.core.dom.ast.IASTTranslationUnit#getBuiltinMacroDefinitions() */ public final IASTPreprocessorMacroDefinition[] getBuiltinMacroDefinitions() { if (fLocationResolver == null) @@ -316,20 +327,10 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat * @see org.eclipse.cdt.core.dom.ast.IASTTranslationUnit#getNodeForLocation(org.eclipse.cdt.core.dom.ast.IASTNodeLocation) */ public final IASTNode selectNodeForLocation(String path, int realOffset, int realLength) { - IASTNode result= null; - if (fLocationResolver != null) { - int start= fLocationResolver.getSequenceNumberForFileOffset(path, realOffset); - if (start >= 0) { - int length= realLength < 1 ? 0 : - fLocationResolver.getSequenceNumberForFileOffset(path, realOffset+realLength-1) + 1 - start; - result= fLocationResolver.findSurroundingPreprocessorNode(start, length); - if (result == null) { - FindNodeForOffsetAction nodeFinder = new FindNodeForOffsetAction(start, length); - accept(nodeFinder); - result = nodeFinder.getNode(); - } - } - } - return result; + return getNodeSelector(path).findNode(realOffset, realLength); + } + + public final IASTNodeSelector getNodeSelector(String filePath) { + return new ASTNodeSelector(this, fLocationResolver, filePath); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FindNodeForOffsetAction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FindNodeForOffsetAction.java index a42d41926e6..143d932905d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FindNodeForOffsetAction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FindNodeForOffsetAction.java @@ -39,49 +39,47 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisitor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; public class FindNodeForOffsetAction extends CPPASTVisitor implements ICASTVisitor, ICPPASTVisitor { - private IASTNode fFoundNode = null; - private int fOffset = 0; - private int fLength = 0; + private ASTNode fCandidate= null; + private final int fOffset; + private final int fLength; + private final ASTNodeMatchKind fMatchKind; - public FindNodeForOffsetAction(int offset, int length) { + public FindNodeForOffsetAction(int offset, int length, ASTNodeMatchKind matchKind) { + fMatchKind= matchKind; fOffset = offset; fLength = length; shouldVisitNames = true; - shouldVisitDeclarations = true; - shouldVisitInitializers = true; - shouldVisitParameterDeclarations = true; - shouldVisitDeclarators = true; - shouldVisitDeclSpecifiers = true; - shouldVisitDesignators = true; - shouldVisitEnumerators = true; - shouldVisitExpressions = true; - shouldVisitStatements = true; - shouldVisitTypeIds = true; - shouldVisitEnumerators = true; - shouldVisitBaseSpecifiers = true; - shouldVisitNamespaces = true; - shouldVisitTemplateParameters= true; - shouldVisitTranslationUnit= 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 (fFoundNode != null) - return PROCESS_ABORT; - if (node instanceof ASTNode) { - final int offset = ((ASTNode) node).getOffset(); - final int length = ((ASTNode) node).getLength(); - - if (offset == fOffset && length == fLength) { - fFoundNode = node; - return PROCESS_ABORT; + final ASTNode astNode = (ASTNode) node; + if (astNode.getOffset() > fOffset+fLength || astNode.getOffset() + astNode.getLength() < fOffset) { + return PROCESS_SKIP; } - // skip the rest of this node if the selection is outside of its - // bounds - if (fOffset > offset + length) - return PROCESS_SKIP; + if (fMatchKind.matches(astNode, fOffset, fLength)) { + if (fCandidate == null || !fMatchKind.isBetterMatch(fCandidate, astNode)) { + fCandidate= astNode; + } + } } return PROCESS_CONTINUE; } @@ -90,8 +88,7 @@ public class FindNodeForOffsetAction extends CPPASTVisitor implements ICASTVisit 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) + if (declaration instanceof ASTNode && ((ASTNode) declaration).getOffset() > fOffset + fLength) return PROCESS_ABORT; return processNode(declaration); @@ -208,7 +205,7 @@ public class FindNodeForOffsetAction extends CPPASTVisitor implements ICASTVisit return processNode(tu); } - public IASTNode getNode() { - return fFoundNode; + 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/ASTPreprocessorName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java index 59198c3b1af..8c97b1d4814 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java @@ -18,6 +18,7 @@ import org.eclipse.cdt.core.dom.ast.IASTImageLocation; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IMacroBinding; @@ -60,6 +61,7 @@ class ASTPreprocessorName extends ASTPreprocessorNode implements IASTName { public char[] toCharArray() { return fName; } + @Override public String toString() { return new String(fName); } @@ -72,6 +74,7 @@ class ASTPreprocessorDefinition extends ASTPreprocessorName { super(parent, property, startNumber, endNumber, name, binding); } + @Override public boolean isDefinition() { return true; } @@ -86,10 +89,12 @@ class ASTBuiltinName extends ASTPreprocessorDefinition { fFileLocation= floc; } + @Override public boolean contains(IASTNode node) { return node==this; } + @Override public String getContainingFilename() { if (fFileLocation == null) { return ""; //$NON-NLS-1$ @@ -97,10 +102,12 @@ class ASTBuiltinName extends ASTPreprocessorDefinition { return fFileLocation.getFileName(); } + @Override public IASTFileLocation getFileLocation() { return fFileLocation; } + @Override public IASTNodeLocation[] getNodeLocations() { if (fFileLocation == null) { return new IASTNodeLocation[0]; @@ -108,6 +115,7 @@ class ASTBuiltinName extends ASTPreprocessorDefinition { return new IASTNodeLocation[]{fFileLocation}; } + @Override public String getRawSignature() { if (fFileLocation == null) { return ""; //$NON-NLS-1$ @@ -119,8 +127,8 @@ class ASTBuiltinName extends ASTPreprocessorDefinition { class ASTMacroReferenceName extends ASTPreprocessorName { private ImageLocationInfo fImageLocationInfo; - public ASTMacroReferenceName(IASTNode parent, int offset, int endOffset, IMacroBinding macro, ImageLocationInfo imgLocationInfo) { - super(parent, IASTTranslationUnit.EXPANSION_NAME, offset, endOffset, macro.getNameCharArray(), macro); + public ASTMacroReferenceName(IASTPreprocessorMacroExpansion parent, int offset, int endOffset, IMacroBinding macro, ImageLocationInfo imgLocationInfo) { + super(parent, IASTPreprocessorMacroExpansion.EXPANSION_NAME, offset, endOffset, macro.getNameCharArray(), macro); fImageLocationInfo= imgLocationInfo; } 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 ab61429754a..3563065d0c8 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 @@ -17,7 +17,7 @@ import org.eclipse.cdt.core.dom.ast.IASTComment; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTFunctionStyleMacroParameter; import org.eclipse.cdt.core.dom.ast.IASTImageLocation; -import org.eclipse.cdt.core.dom.ast.IASTMacroExpansion; +import org.eclipse.cdt.core.dom.ast.IASTMacroExpansionLocation; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; @@ -31,6 +31,7 @@ import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfdefStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfndefStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorObjectStyleMacroDefinition; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorPragmaStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorUndefStatement; @@ -41,6 +42,8 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree.IASTInclusionNode; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; +import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind; +import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind.Relation; /** * Models various AST-constructs obtained from the preprocessor. @@ -69,10 +72,36 @@ abstract class ASTPreprocessorNode extends ASTNode { } /** - * Returns a subnode surrounding the given range or this. + * Returns a matching node or null. */ - IASTNode findSurroundingNode(int sequenceNumber, int length) { - return this; + ASTNode findNode(int sequenceNumber, int length, ASTNodeMatchKind matchKind) { + if (matchKind.matches(this, sequenceNumber, length)) { + return this; + } + return null; + } + + /** + * Helper method for preprocessor nodes containing a name + */ + protected ASTNode findNode(int sequenceNumber, int length, ASTPreprocessorName name, ASTNodeMatchKind matchKind) { + ASTNode n1, n2; + if (matchKind.getRelationToSelection() == Relation.SURROUNDING) { + n1= name; + n2= this; + } + else { + n1= this; + n2= name; + } + + if (matchKind.matches(n1, sequenceNumber, length)) { + return n1; + } + if (matchKind.matches(n2, sequenceNumber, length)) { + return n2; + } + return null; } } @@ -221,13 +250,8 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces } @Override - IASTNode findSurroundingNode(int sequenceNumber, int length) { - final int nameSequencNumber= fName.getOffset(); - final int nameEndSequencNumber= nameSequencNumber + fName.getLength(); - if (nameSequencNumber <= sequenceNumber && sequenceNumber+length <= nameEndSequencNumber) { - return fName; - } - return this; + ASTNode findNode(int sequenceNumber, int length, ASTNodeMatchKind matchKind) { + return findNode(sequenceNumber, length, fName, matchKind); } } @@ -284,13 +308,8 @@ class ASTMacroDefinition extends ASTPreprocessorNode implements IASTPreprocessor } @Override - IASTNode findSurroundingNode(int sequenceNumber, int length) { - final int nameSequencNumber= fName.getOffset(); - final int nameEndSequencNumber= nameSequencNumber + fName.getLength(); - if (nameSequencNumber <= sequenceNumber && sequenceNumber+length <= nameEndSequencNumber) { - return fName; - } - return this; + ASTNode findNode(int sequenceNumber, int length, ASTNodeMatchKind matchKind) { + return findNode(sequenceNumber, length, fName, matchKind); } public void setExpansion(String exp) {assert false;} @@ -399,13 +418,8 @@ class ASTUndef extends ASTPreprocessorNode implements IASTPreprocessorUndefState } @Override - IASTNode findSurroundingNode(int sequenceNumber, int length) { - final int nameSequencNumber= fName.getOffset(); - final int nameEndSequencNumber= nameSequencNumber + fName.getLength(); - if (nameSequencNumber <= sequenceNumber && sequenceNumber+length <= nameEndSequencNumber) { - return fName; - } - return this; + ASTNode findNode(int sequenceNumber, int length, ASTNodeMatchKind matchKind) { + return findNode(sequenceNumber, length, fName, matchKind); } } @@ -503,7 +517,42 @@ class ASTFileLocation implements IASTFileLocation { } } -class ASTMacroExpansionLocation implements IASTMacroExpansion { +class ASTMacroExpansion extends ASTPreprocessorNode implements IASTPreprocessorMacroExpansion { + + private LocationCtxMacroExpansion fContext; + + public ASTMacroExpansion(IASTNode parent, int startNumber, int endNumber) { + super(parent, IASTTranslationUnit.MACRO_EXPANSION, startNumber, endNumber); + } + + void setContext(LocationCtxMacroExpansion expansionCtx) { + fContext= expansionCtx; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion#getName() + */ + public ASTMacroReferenceName getMacroReference() { + return fContext.getMacroReference(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion#getMacroDefinition() + */ + public IASTPreprocessorMacroDefinition getMacroDefinition() { + return fContext.getMacroDefinition(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion#getNestedExpansions() + */ + public IASTName[] getNestedMacroReferences() { + return fContext.getNestedMacroReferences(); + } +} + +@SuppressWarnings("deprecation") +class ASTMacroExpansionLocation implements IASTMacroExpansionLocation, org.eclipse.cdt.core.dom.ast.IASTMacroExpansion { private LocationCtxMacroExpansion fContext; private int fOffset; @@ -515,6 +564,13 @@ class ASTMacroExpansionLocation implements IASTMacroExpansion { fLength= length; } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.IASTMacroExpansionLocation#getExpansion() + */ + public IASTPreprocessorMacroExpansion getExpansion() { + return fContext.getExpansion(); + } + public IASTNodeLocation[] getExpansionLocations() { final IASTFileLocation fl= asFileLocation(); return fl == null ? new IASTNodeLocation[0] : new IASTNodeLocation[] {fl}; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java index 3a240b850f0..25e1bcebd21 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java @@ -14,25 +14,25 @@ package org.eclipse.cdt.internal.core.parser.scanner; import org.eclipse.cdt.core.dom.ast.IASTComment; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTImageLocation; -import org.eclipse.cdt.core.dom.ast.IASTMacroExpansion; import org.eclipse.cdt.core.dom.ast.IASTName; -import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; import org.eclipse.cdt.core.dom.ast.IASTProblem; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IMacroBinding; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree; +import org.eclipse.cdt.internal.core.dom.parser.ASTNode; +import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind; /** * Interface between the ast and the location-resolver for resolving offsets. * @since 5.0 */ -public interface ILocationResolver { - +public interface ILocationResolver { /** * Introduces the ast translation unit to the location resolver. Must be called before any tokens from the * scanner are obtained. @@ -126,7 +126,7 @@ public interface ILocationResolver { * Returns the sequence-number for the given file-path and offset, or <code>-1</code> if this file * is not part of the translation-unit. * @param filePath a file path or <code>null</code> to specify the root of the translation unit. - * @param fileOffset an offset into the source of the file. + * @param fileOffset an offset into the source of the file, or <code>-1</code>. */ int getSequenceNumberForFileOffset(String filePath, int fileOffset); @@ -139,8 +139,12 @@ public interface ILocationResolver { * Returns a preprocessor node surrounding the given range, or <code>null</code>. The result is either a * preprocessing directive ({@link IASTPreprocessorStatement}) or a name contained therein {@link IASTName} or * a macro expansion ({@link IASTName}). + * + * @param sequenceNumber the sequence number of the start of the interesting region. + * @param length the sequence length of the interesting region. + * @param matchOption the kind of the desired match. */ - IASTNode findSurroundingPreprocessorNode(int sequenceNumber, int length); + ASTNode findPreprocessorNode(int sequenceNumber, int length, ASTNodeMatchKind matchOption); /** * Returns whether the specified sequence number points into the root file of the @@ -161,13 +165,5 @@ public interface ILocationResolver { * @return an array of macro expansions. * @since 5.0 */ - IASTMacroExpansion[] getMacroExpansions(IASTFileLocation loc); - - /** - * Returns all implicit macro references related to an explicit one. - * @param ref an explicit macro expansion. - * @return an array of names representing implicit macro expansions. - * @since 5.0 - */ - IASTName[] getImplicitMacroReferences(IASTName ref); + IASTPreprocessorMacroExpansion[] getMacroExpansions(IASTFileLocation loc); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java index 0963ddadde0..b3110958bba 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java @@ -13,7 +13,7 @@ package org.eclipse.cdt.internal.core.parser.scanner; import java.util.ArrayList; import java.util.Collection; -import org.eclipse.cdt.core.dom.ast.IASTMacroExpansion; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion; /** * A location context representing a file. @@ -105,7 +105,7 @@ class LocationCtxFile extends LocationCtxContainer { return sequenceNumber >= child.fSequenceNumber + child.getSequenceLength(); } - public void collectExplicitMacroExpansions(int offset, int length, ArrayList<IASTMacroExpansion> result) { + public void collectMacroExpansions(int offset, int length, ArrayList<IASTPreprocessorMacroExpansion> list) { Collection<LocationCtx> children= getChildren(); for (LocationCtx ctx : children) { // context must start before the end of the search range @@ -115,7 +115,7 @@ class LocationCtxFile extends LocationCtxContainer { if (ctx instanceof LocationCtxMacroExpansion) { // expansion must end after the search start if (ctx.fEndOffsetInParent > offset) { - result.add(new ASTMacroExpansionLocation(((LocationCtxMacroExpansion) ctx), 0, ctx.getSequenceLength())); + list.add((IASTPreprocessorMacroExpansion) ((LocationCtxMacroExpansion)ctx).getMacroReference().getParent()); } } } 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 5c47a497076..0dc39f5a8c0 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,9 +13,13 @@ 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; +import org.eclipse.cdt.internal.core.dom.parser.ASTNode; +import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind; +import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind.Relation; /** * A location context representing macro expansions. @@ -24,22 +28,27 @@ import org.eclipse.cdt.core.dom.ast.IMacroBinding; class LocationCtxMacroExpansion extends LocationCtx { private final LocationMap fLocationMap; private final int fLength; - private final ASTMacroReferenceName fName; private final ImageLocationInfo[] fLocationInfos; + private ASTMacroReferenceName fExpansionName; public LocationCtxMacroExpansion(LocationMap map, LocationCtxContainer parent, int parentOffset, int parentEndOffset, - int sequenceNumber, int length, ImageLocationInfo[] imageLocations, ASTMacroReferenceName expansion) { + int sequenceNumber, int length, ImageLocationInfo[] imageLocations, ASTMacroReferenceName expansionName) { super(parent, parentOffset, parentEndOffset, sequenceNumber); fLocationMap= map; fLength= length; - fName= expansion; fLocationInfos= imageLocations; + fExpansionName= expansionName; + if (expansionName.getParent() instanceof ASTMacroExpansion == false) { + throw new IllegalArgumentException(expansionName.toString() + " is not a macro expansion name"); //$NON-NLS-1$ + } } + @Override public int getSequenceLength() { return fLength; } + @Override public boolean collectLocations(int start, int length, ArrayList<IASTNodeLocation> locations) { final int offset= start-fSequenceNumber; assert offset >= 0 && length >= 0; @@ -53,14 +62,19 @@ class LocationCtxMacroExpansion extends LocationCtx { return false; } + public ASTMacroExpansion getExpansion() { + return (ASTMacroExpansion) fExpansionName.getParent(); + } + public ASTMacroReferenceName getMacroReference() { - return fName; + return fExpansionName; } public IASTPreprocessorMacroDefinition getMacroDefinition() { - return fLocationMap.getMacroDefinition((IMacroBinding) fName.getBinding()); + return fLocationMap.getMacroDefinition((IMacroBinding) fExpansionName.getBinding()); } + @Override public LocationCtxMacroExpansion findSurroundingMacroExpansion(int sequenceNumber, int length) { return this; } @@ -95,6 +109,30 @@ class LocationCtxMacroExpansion extends LocationCtx { } return null; } + + public ASTNode findNode(int sequenceNumber, int length, ASTNodeMatchKind matchKind) { + ASTNode n1, n2; + if (matchKind.getRelationToSelection() == Relation.SURROUNDING) { + n1= fExpansionName; + n2= (ASTNode) fExpansionName.getParent(); + } + else { + n1= (ASTNode) fExpansionName.getParent(); + n2= fExpansionName; + } + + if (matchKind.matches(n1, sequenceNumber, length)) { + return n1; + } + if (matchKind.matches(n2, sequenceNumber, length)) { + return n2; + } + return null; + } + + public IASTName[] 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 50f0be27aab..b0b54f63ce2 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 @@ -19,12 +19,11 @@ import java.util.List; import org.eclipse.cdt.core.dom.ast.IASTComment; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTImageLocation; -import org.eclipse.cdt.core.dom.ast.IASTMacroExpansion; import org.eclipse.cdt.core.dom.ast.IASTName; -import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; import org.eclipse.cdt.core.dom.ast.IASTProblem; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; @@ -32,7 +31,10 @@ import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IMacroBinding; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree; import org.eclipse.cdt.core.parser.util.CharArrayUtils; +import org.eclipse.cdt.internal.core.dom.parser.ASTNode; +import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind; import org.eclipse.cdt.internal.core.dom.parser.ASTProblem; +import org.eclipse.cdt.internal.core.dom.parser.ASTNodeMatchKind.Relation; /** * Converts the offsets relative to various contexts to the global sequence number. Also creates and stores @@ -136,7 +138,7 @@ public class LocationMap implements ILocationResolver { * @param imageLocationInfo the image-location for the name of the macro. */ public IASTName encounterImplicitMacroExpansion(IMacroBinding macro, ImageLocationInfo imageLocationInfo) { - return new ASTMacroReferenceName(fTranslationUnit, 0, 0, macro, imageLocationInfo); + return new ASTMacroReferenceName(null, 0, 0, macro, imageLocationInfo); } /** @@ -157,16 +159,19 @@ public class LocationMap implements ILocationResolver { int endNumber= getSequenceNumberForOffset(endOffset); final int length= endNumber-nameNumber; - ASTMacroReferenceName expansion= new ASTMacroReferenceName(fTranslationUnit, nameNumber, nameEndNumber, macro, null); + ASTMacroExpansion expansion= new ASTMacroExpansion(fTranslationUnit, nameNumber, endNumber); + ASTMacroReferenceName explicitRef= new ASTMacroReferenceName(expansion, nameNumber, nameEndNumber, macro, null); for (int i = 0; i < implicitMacroReferences.length; i++) { ASTMacroReferenceName name = (ASTMacroReferenceName) implicitMacroReferences[i]; - name.setOffsetAndLength(nameNumber, length); name.setParent(expansion); + name.setOffsetAndLength(nameNumber, length); addMacroReference(name); } - addMacroReference(expansion); + addMacroReference(explicitRef); - fCurrentContext= new LocationCtxMacroExpansion(this, (LocationCtxContainer) fCurrentContext, nameOffset, endOffset, endNumber, contextLength, imageLocations, expansion); + LocationCtxMacroExpansion expansionCtx= new LocationCtxMacroExpansion(this, (LocationCtxContainer) fCurrentContext, nameOffset, endOffset, endNumber, contextLength, imageLocations, explicitRef); + expansion.setContext(expansionCtx); + fCurrentContext= expansionCtx; fLastChildInsertionOffset= 0; return fCurrentContext; } @@ -361,17 +366,17 @@ public class LocationMap implements ILocationResolver { return floc.getSource(); } - public IASTMacroExpansion[] getMacroExpansions(IASTFileLocation loc) { + public IASTPreprocessorMacroExpansion[] getMacroExpansions(IASTFileLocation loc) { ASTFileLocation floc= convertFileLocation(loc); if (floc == null) { - return new IASTMacroExpansion[0]; + return IASTPreprocessorMacroExpansion.EMPTY_ARRAY; } LocationCtxFile ctx= floc.getLocationContext(); - ArrayList<IASTMacroExpansion> list= new ArrayList<IASTMacroExpansion>(); + ArrayList<IASTPreprocessorMacroExpansion> list= new ArrayList<IASTPreprocessorMacroExpansion>(); - ctx.collectExplicitMacroExpansions(floc.getNodeOffset(), floc.getNodeLength(), list); - return list.toArray(new IASTMacroExpansion[list.size()]); + ctx.collectMacroExpansions(floc.getNodeOffset(), floc.getNodeLength(), list); + return list.toArray(new IASTPreprocessorMacroExpansion[list.size()]); } private ASTFileLocation convertFileLocation(IASTFileLocation loc) { @@ -429,21 +434,24 @@ public class LocationMap implements ILocationResolver { return null; } - public IASTNode findSurroundingPreprocessorNode(int sequenceNumber, int length) { + public ASTNode findPreprocessorNode(int sequenceNumber, int length, ASTNodeMatchKind matchKind) { int lower=0; int upper= fDirectives.size()-1; while(lower <= upper) { int middle= (lower+upper)/2; - ASTPreprocessorNode node= fDirectives.get(middle); - final int nodeSequenceNumber= node.getOffset(); - if (nodeSequenceNumber <= sequenceNumber) { - final int nodeEndSequenceNumber= nodeSequenceNumber + node.getLength(); - if (sequenceNumber+length <= nodeEndSequenceNumber) { - return node.findSurroundingNode(sequenceNumber, length); - } - else { - lower= middle+1; + ASTPreprocessorNode candidate= fDirectives.get(middle); + ASTNode result= candidate.findNode(sequenceNumber, length, matchKind); + if (result != null) { + if (matchKind.getRelationToSelection() == Relation.FIRST_CONTAINED) { + if (middle>lower) { + upper= middle; // if (upper-lower == 1) then middle==lower + continue; + } } + return result; + } + if (matchKind.isLowerBound(candidate, sequenceNumber, length)) { + lower= middle+1; } else { upper= middle-1; @@ -452,12 +460,7 @@ public class LocationMap implements ILocationResolver { // search for a macro-expansion LocationCtxMacroExpansion ctx= fRootContext.findSurroundingMacroExpansion(sequenceNumber, length); if (ctx != null) { - ASTMacroReferenceName candidate= ctx.getMacroReference(); - final int candSequenceNumber = candidate.getOffset(); - final int candEndSequenceNumber = candSequenceNumber + candidate.getLength(); - if (candSequenceNumber <= sequenceNumber && sequenceNumber + length <= candEndSequenceNumber) { - return candidate; - } + return ctx.findNode(sequenceNumber, length, matchKind); } return null; @@ -587,10 +590,11 @@ public class LocationMap implements ILocationResolver { return result.toArray(new IASTName[result.size()]); } - public IASTName[] getImplicitMacroReferences(IASTName ref) { + public IASTName[] getNestedMacroReferences(ASTMacroExpansion expansion) { + final IASTName explicitRef= expansion.getMacroReference(); List<IASTName> result= new ArrayList<IASTName>(); for (IASTName name : fMacroReferences) { - if (name.getParent() == ref) { + if (name.getParent() == expansion && name != explicitRef) { result.add(name); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MultiMacroExpansionExplorer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MultiMacroExpansionExplorer.java index 5a7d4b5a535..45fa127d5eb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MultiMacroExpansionExplorer.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MultiMacroExpansionExplorer.java @@ -17,9 +17,9 @@ import java.util.List; import java.util.Map; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; -import org.eclipse.cdt.core.dom.ast.IASTMacroExpansion; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IMacroBinding; @@ -65,7 +65,7 @@ public class MultiMacroExpansionExplorer extends MacroExpansionExplorer { throw new IllegalArgumentException(); } final ILocationResolver resolver = getResolver(tu); - final IASTMacroExpansion[] expansions= resolver.getMacroExpansions(loc); + final IASTPreprocessorMacroExpansion[] expansions= resolver.getMacroExpansions(loc); final int count= expansions.length; loc = extendLocation(loc, expansions); @@ -78,13 +78,13 @@ public class MultiMacroExpansionExplorer extends MacroExpansionExplorer { final int firstOffset= loc.getNodeOffset(); int bidx= -1; int didx= -1; - for (IASTMacroExpansion expansion : expansions) { + for (IASTPreprocessorMacroExpansion expansion : expansions) { IASTName ref= expansion.getMacroReference(); if (ref != null) { ArrayList<IASTName> refs= new ArrayList<IASTName>(); refs.add(ref); - refs.addAll(Arrays.asList(resolver.getImplicitMacroReferences(ref))); - IASTFileLocation refLoc= expansion.asFileLocation(); + refs.addAll(Arrays.asList(expansion.getNestedMacroReferences())); + IASTFileLocation refLoc= expansion.getFileLocation(); int from= refLoc.getNodeOffset()-firstOffset; int to= from+refLoc.getNodeLength(); fBoundaries[++bidx]= from; @@ -105,14 +105,14 @@ public class MultiMacroExpansionExplorer extends MacroExpansionExplorer { return resolver; } - private IASTFileLocation extendLocation(IASTFileLocation loc, final IASTMacroExpansion[] expansions) { + private IASTFileLocation extendLocation(IASTFileLocation loc, final IASTPreprocessorMacroExpansion[] expansions) { final int count= expansions.length; if (count > 0) { int from= loc.getNodeOffset(); int to= from+loc.getNodeLength(); - final int lfrom = expansions[0].asFileLocation().getNodeOffset(); - final IASTFileLocation l= expansions[count-1].asFileLocation(); + final int lfrom = expansions[0].getFileLocation().getNodeOffset(); + final IASTFileLocation l= expansions[count-1].getFileLocation(); final int lto= l.getNodeOffset() + l.getNodeLength(); if (lfrom < from || lto > to) { |