1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 02:06:01 +02:00

Bug 322750: Expanding selection with macro expansion.

This commit is contained in:
Markus Schorn 2010-08-26 11:21:21 +00:00
parent 45540144be
commit b25a75fc64
4 changed files with 43 additions and 37 deletions

View file

@ -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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -72,10 +72,18 @@ public interface IASTNodeSelector {
* <p> * <p>
* For nodes with the same location, macro-expansions ({@link IASTPreprocessorMacroExpansion}) are preferred * For nodes with the same location, macro-expansions ({@link IASTPreprocessorMacroExpansion}) are preferred
* over c/c++-nodes nodes and children are preferred over their parents. * over c/c++-nodes nodes and children are preferred over their parents.
* Prefers children over parents.
*/ */
IASTNode findEnclosingNode(int offset, int length); IASTNode findEnclosingNode(int offset, int length);
/**
* Returns the smallest node strictly enclosing the given range, or <code>null</code> if there is no such node.
* <p>
* 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 <code>null</code> if there is no such node. * Returns the first node contained in the given range, or <code>null</code> if there is no such node.
* <p> * <p>

View file

@ -108,7 +108,7 @@ public class ASTNodeSelector implements IASTNodeSelector {
expansion= nodeSpec.findTrailingMacroExpansion(this); expansion= nodeSpec.findTrailingMacroExpansion(this);
if (expansion != null) { if (expansion != null) {
IASTFileLocation floc= expansion.getFileLocation(); 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); nodeSpec.setRangeInSequence(seqbegin, seqend-seqbegin);
@ -131,6 +131,10 @@ public class ASTNodeSelector implements IASTNodeSelector {
return findNode(offset, length, Relation.ENCLOSING, IASTNode.class); 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) { public IASTNode findFirstContainedNodeInExpansion(int offset, int length) {
return findNode(offset, length, Relation.FIRST_CONTAINED, IASTNode.class, true); return findNode(offset, length, Relation.FIRST_CONTAINED, IASTNode.class, true);
} }

View file

@ -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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -23,7 +23,7 @@ import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion;
* @since 5.0 * @since 5.0
*/ */
public class ASTNodeSpecification<T extends IASTNode> { public class ASTNodeSpecification<T extends IASTNode> {
public enum Relation {FIRST_CONTAINED, EXACT_MATCH, ENCLOSING} public enum Relation {FIRST_CONTAINED, EXACT_MATCH, ENCLOSING, STRICTLY_ENCLOSING}
private final Class<T> fClass; private final Class<T> fClass;
private final Relation fRelation; private final Relation fRelation;
@ -105,10 +105,14 @@ public class ASTNodeSpecification<T extends IASTNode> {
return selOffset <= offset && endOffset <= selEndOffset; return selOffset <= offset && endOffset <= selEndOffset;
case ENCLOSING: case ENCLOSING:
return offset <= selOffset && selEndOffset <= endOffset; return offset <= selOffset && selEndOffset <= endOffset;
default: case STRICTLY_ENCLOSING:
assert false; if (offset <= selOffset && selEndOffset <= endOffset) {
return offset != selOffset || selEndOffset != endOffset;
}
return false; return false;
} }
assert false;
return false;
} }
public boolean isAcceptableNode(IASTNode astNode) { public boolean isAcceptableNode(IASTNode astNode) {
@ -134,12 +138,16 @@ public class ASTNodeSpecification<T extends IASTNode> {
case EXACT_MATCH: case EXACT_MATCH:
case ENCLOSING: case ENCLOSING:
return offset <= fSeqNumber && fSeqEndNumber <= endOffset; return offset <= fSeqNumber && fSeqEndNumber <= endOffset;
case STRICTLY_ENCLOSING:
if (offset <= fSeqNumber && fSeqEndNumber <= endOffset) {
return offset != fSeqNumber || fSeqEndNumber != endOffset;
}
return false;
case FIRST_CONTAINED: case FIRST_CONTAINED:
return offset <= fSeqEndNumber && fSeqNumber <= endOffset; return offset <= fSeqEndNumber && fSeqNumber <= endOffset;
default:
assert false;
return false;
} }
assert false;
return false;
} }
private void storeIfBest(IASTFileLocation loc, T astNode) { private void storeIfBest(IASTFileLocation loc, T astNode) {
@ -179,6 +187,7 @@ public class ASTNodeSpecification<T extends IASTNode> {
} }
return false; return false;
case ENCLOSING: case ENCLOSING:
case STRICTLY_ENCLOSING:
final int bestLength= fBestEndOffset-fBestOffset; final int bestLength= fBestEndOffset-fBestOffset;
if (length < bestLength) { if (length < bestLength) {
return true; return true;
@ -202,7 +211,7 @@ public class ASTNodeSpecification<T extends IASTNode> {
public IASTPreprocessorMacroExpansion findLeadingMacroExpansion(ASTNodeSelector nodeSelector) { public IASTPreprocessorMacroExpansion findLeadingMacroExpansion(ASTNodeSelector nodeSelector) {
IASTPreprocessorMacroExpansion exp= nodeSelector.findEnclosingMacroExpansion(fZeroToLeft ? fFileOffset-1 : fFileOffset, 1); IASTPreprocessorMacroExpansion exp= nodeSelector.findEnclosingMacroExpansion(fZeroToLeft ? fFileOffset-1 : fFileOffset, 1);
if (fRelation == Relation.ENCLOSING) if (fRelation == Relation.ENCLOSING || fRelation == Relation.STRICTLY_ENCLOSING)
return exp; return exp;
if (exp != null) { if (exp != null) {
@ -219,7 +228,7 @@ public class ASTNodeSpecification<T extends IASTNode> {
public IASTPreprocessorMacroExpansion findTrailingMacroExpansion(ASTNodeSelector nodeSelector) { public IASTPreprocessorMacroExpansion findTrailingMacroExpansion(ASTNodeSelector nodeSelector) {
IASTPreprocessorMacroExpansion exp= nodeSelector.findEnclosingMacroExpansion(fFileEndOffset==fFileOffset && !fZeroToLeft ? fFileEndOffset : fFileEndOffset-1, 1); 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; return exp;
if (exp != null) { if (exp != null) {

View file

@ -14,7 +14,9 @@ import java.util.ResourceBundle;
import org.eclipse.ui.texteditor.ITextEditor; 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.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.model.ISourceRange; 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 * Made public to serve as fallback for other expansions
*/ */
public static ISourceRange expandToEnclosing(IASTTranslationUnit ast, SourceRange current) { public static ISourceRange expandToEnclosing(IASTTranslationUnit ast, SourceRange current) {
IASTNode enclosingNode = ast.getNodeSelector(null).findEnclosingNode(current.getStartPos(), final IASTNodeSelector nodeSelector = ast.getNodeSelector(null);
current.getLength()); IASTNode node = nodeSelector.findStrictlyEnclosingNode(current.getStartPos(), current.getLength());
if (node == null)
return null;
int newOffset = enclosingNode.getFileLocation().getNodeOffset(); final IASTFileLocation fileLocation = node.getFileLocation();
int newLength = enclosingNode.getFileLocation().getNodeLength(); return new SourceRange(fileLocation.getNodeOffset(), fileLocation.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);
} }
} }