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