Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser')
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeMatchKind.java113
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSelector.java133
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java35
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FindNodeForOffsetAction.java69
4 files changed, 297 insertions, 53 deletions
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

Back to the top