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 index 3ff6ebfe195..fea86d7c702 100644 --- 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2009 Wind River Systems, Inc. and others. + * Copyright (c) 2008, 2010 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 @@ -72,9 +72,17 @@ public interface IASTNodeSelector { *

* For nodes with the same location, macro-expansions ({@link IASTPreprocessorMacroExpansion}) are preferred * over c/c++-nodes nodes and children are preferred over their parents. - * Prefers children over parents. */ IASTNode findEnclosingNode(int offset, int length); + + /** + * Returns the smallest node strictly enclosing the given range, or null if there is no such node. + *

+ * For nodes with the same location, macro-expansions ({@link IASTPreprocessorMacroExpansion}) are preferred + * over c/c++-nodes nodes and children are preferred over their parents. + * @since 5.3 + */ + IASTNode findStrictlyEnclosingNode(int offset, int length); /** * Returns the first node contained in the given range, or null if there is no such node. 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 index 57fdf198a1d..ad7512b0d2e 100644 --- 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 @@ -108,7 +108,7 @@ public class ASTNodeSelector implements IASTNodeSelector { expansion= nodeSpec.findTrailingMacroExpansion(this); if (expansion != null) { IASTFileLocation floc= expansion.getFileLocation(); - seqend= fLocationResolver.getSequenceNumberForFileOffset(fFilePath, floc.getNodeOffset() + floc.getNodeLength())-1; + seqend= fLocationResolver.getSequenceNumberForFileOffset(fFilePath, floc.getNodeOffset() + floc.getNodeLength()); } nodeSpec.setRangeInSequence(seqbegin, seqend-seqbegin); @@ -130,6 +130,10 @@ public class ASTNodeSelector implements IASTNodeSelector { public IASTNode findEnclosingNode(int offset, int length) { return findNode(offset, length, Relation.ENCLOSING, IASTNode.class); } + + public IASTNode findStrictlyEnclosingNode(int offset, int length) { + return findNode(offset, length, Relation.STRICTLY_ENCLOSING, IASTNode.class); + } public IASTNode findFirstContainedNodeInExpansion(int offset, int length) { return findNode(offset, length, Relation.FIRST_CONTAINED, IASTNode.class, true); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSpecification.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSpecification.java index 4e3ebfd1f48..a269c788ed2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSpecification.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSpecification.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2008, 2010 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 @@ -23,7 +23,7 @@ import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion; * @since 5.0 */ public class ASTNodeSpecification { - public enum Relation {FIRST_CONTAINED, EXACT_MATCH, ENCLOSING} + public enum Relation {FIRST_CONTAINED, EXACT_MATCH, ENCLOSING, STRICTLY_ENCLOSING} private final Class fClass; private final Relation fRelation; @@ -105,10 +105,14 @@ public class ASTNodeSpecification { return selOffset <= offset && endOffset <= selEndOffset; case ENCLOSING: return offset <= selOffset && selEndOffset <= endOffset; - default: - assert false; - return false; + case STRICTLY_ENCLOSING: + if (offset <= selOffset && selEndOffset <= endOffset) { + return offset != selOffset || selEndOffset != endOffset; + } + return false; } + assert false; + return false; } public boolean isAcceptableNode(IASTNode astNode) { @@ -134,12 +138,16 @@ public class ASTNodeSpecification { case EXACT_MATCH: case ENCLOSING: return offset <= fSeqNumber && fSeqEndNumber <= endOffset; + case STRICTLY_ENCLOSING: + if (offset <= fSeqNumber && fSeqEndNumber <= endOffset) { + return offset != fSeqNumber || fSeqEndNumber != endOffset; + } + return false; case FIRST_CONTAINED: return offset <= fSeqEndNumber && fSeqNumber <= endOffset; - default: - assert false; - return false; } + assert false; + return false; } private void storeIfBest(IASTFileLocation loc, T astNode) { @@ -179,6 +187,7 @@ public class ASTNodeSpecification { } return false; case ENCLOSING: + case STRICTLY_ENCLOSING: final int bestLength= fBestEndOffset-fBestOffset; if (length < bestLength) { return true; @@ -202,7 +211,7 @@ public class ASTNodeSpecification { public IASTPreprocessorMacroExpansion findLeadingMacroExpansion(ASTNodeSelector nodeSelector) { IASTPreprocessorMacroExpansion exp= nodeSelector.findEnclosingMacroExpansion(fZeroToLeft ? fFileOffset-1 : fFileOffset, 1); - if (fRelation == Relation.ENCLOSING) + if (fRelation == Relation.ENCLOSING || fRelation == Relation.STRICTLY_ENCLOSING) return exp; if (exp != null) { @@ -219,7 +228,7 @@ public class ASTNodeSpecification { public IASTPreprocessorMacroExpansion findTrailingMacroExpansion(ASTNodeSelector nodeSelector) { IASTPreprocessorMacroExpansion exp= nodeSelector.findEnclosingMacroExpansion(fFileEndOffset==fFileOffset && !fZeroToLeft ? fFileEndOffset : fFileEndOffset-1, 1); - if (fRelation == Relation.ENCLOSING) + if (fRelation == Relation.ENCLOSING || fRelation == Relation.STRICTLY_ENCLOSING) return exp; if (exp != null) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/StructureSelectEnclosingAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/StructureSelectEnclosingAction.java index 21cd82545e3..a9628e4e7e2 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/StructureSelectEnclosingAction.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/StructureSelectEnclosingAction.java @@ -14,7 +14,9 @@ import java.util.ResourceBundle; import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNodeSelector; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.model.ISourceRange; @@ -44,29 +46,12 @@ public class StructureSelectEnclosingAction extends StructureSelectionAction { * Made public to serve as fallback for other expansions */ public static ISourceRange expandToEnclosing(IASTTranslationUnit ast, SourceRange current) { - IASTNode enclosingNode = ast.getNodeSelector(null).findEnclosingNode(current.getStartPos(), - current.getLength()); - - int newOffset = enclosingNode.getFileLocation().getNodeOffset(); - int newLength = enclosingNode.getFileLocation().getNodeLength(); - - // we can have some nested nodes with same position, so traverse until we have a new position. - while (newOffset == current.getStartPos() && newLength == current.getLength()) { - IASTNode toBeSelected = enclosingNode.getParent(); - // if we can't traverse further, give up - if (toBeSelected == null - || toBeSelected.getFileLocation().getFileName() != enclosingNode.getFileLocation() - .getFileName()) { - return null; - } - newOffset = toBeSelected.getFileLocation().getNodeOffset(); - newLength = toBeSelected.getFileLocation().getNodeLength(); - - enclosingNode = toBeSelected; - } - - return new SourceRange(newOffset, newLength); + final IASTNodeSelector nodeSelector = ast.getNodeSelector(null); + IASTNode node = nodeSelector.findStrictlyEnclosingNode(current.getStartPos(), current.getLength()); + if (node == null) + return null; + + final IASTFileLocation fileLocation = node.getFileLocation(); + return new SourceRange(fileLocation.getNodeOffset(), fileLocation.getNodeLength()); } - - }