diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java index e608ce2d3ad..d25412ddcca 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java @@ -5531,4 +5531,44 @@ public class AST2Tests extends AST2BaseTest { return runtime.totalMemory()-runtime.freeMemory(); } + // void test() { + // const void* p = 1+2; + // } + public void testGetChildren_Bug256127() throws Exception { + final String code = getAboveComment(); + for (ParserLanguage lang : ParserLanguage.values()) { + IASTNode node= parseAndCheckBindings(code, lang); + + IASTNode[] children= node.getChildren(); + assertEquals(1, children.length); + assertInstance(children[0], IASTFunctionDefinition.class); + + children= children[0].getChildren(); + assertEquals(3, children.length); + assertInstance(children[0], IASTDeclSpecifier.class); + assertInstance(children[1], IASTDeclarator.class); + assertInstance(children[2], IASTCompoundStatement.class); + + children= children[2].getChildren(); + assertEquals(1, children.length); + assertInstance(children[0], IASTDeclarationStatement.class); + + children= children[0].getChildren()[0].getChildren(); // skip declaration + assertEquals(2, children.length); + assertInstance(children[0], IASTDeclSpecifier.class); + assertInstance(children[1], IASTDeclarator.class); + + children= children[1].getChildren(); + assertEquals(2, children.length); + assertInstance(children[0], IASTName.class); + assertInstance(children[1], IASTInitializer.class); + + children= children[1].getChildren()[0].getChildren(); // skip binary expression + assertEquals(2, children.length); + assertInstance(children[0], IASTLiteralExpression.class); + assertInstance(children[1], IASTLiteralExpression.class); + + assertEquals(0, children[0].getChildren().length); + } + } } 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 73623dde8a5..fef8fd81eee 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 @@ -83,6 +83,12 @@ public interface IASTNode { * @return the parent node of this node */ public IASTNode getParent(); + + /** + * Returns the children of this node. + * @since 5.1 + */ + IASTNode[] getChildren(); /** * Set the parent node of this node in the tree. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java index 538bfe82fa8..654cc157be7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java @@ -44,6 +44,11 @@ public abstract class ASTNode implements IASTNode { return parent; } + public IASTNode[] getChildren() { + ChildCollector collector= new ChildCollector(this); + return collector.getChildren(); + } + public void setParent(IASTNode node) { this.parent = node; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ChildCollector.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ChildCollector.java new file mode 100644 index 00000000000..8845bcdf83a --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ChildCollector.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * 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 java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTInitializer; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTProblem; +import org.eclipse.cdt.core.dom.ast.IASTStatement; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IASTTypeId; +import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; +import org.eclipse.cdt.core.dom.ast.c.ICASTDesignator; +import org.eclipse.cdt.core.dom.ast.c.ICASTVisitor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisitor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; + +/** + * Collector to find all children for an ast-node. + */ +class ChildCollector extends ASTVisitor implements ICPPASTVisitor, ICASTVisitor { + + private final IASTNode fNode; + private List fNodes; + + public ChildCollector(IASTNode node) { + super(true); + fNode= node; + } + + public IASTNode[] getChildren() { + fNode.accept(this); + if (fNodes == null) + return IASTNode.EMPTY_NODE_ARRAY; + + return fNodes.toArray(new IASTNode[fNodes.size()]); + } + + private int addChild(IASTNode child) { + if (fNodes == null) { + if (child == fNode) + return PROCESS_CONTINUE; + fNodes= new ArrayList(); + } + fNodes.add(child); + return PROCESS_SKIP; + } + + public int visit(ICPPASTBaseSpecifier baseSpecifier) { + return addChild(baseSpecifier); + } + + public int visit(ICPPASTNamespaceDefinition namespaceDefinition) { + return addChild(namespaceDefinition); + } + + public int visit(ICPPASTTemplateParameter templateParameter) { + return addChild(templateParameter); + } + + @Override + public int visit(IASTArrayModifier arrayModifier) { + return addChild(arrayModifier); + } + + @Override + public int visit(IASTDeclaration declaration) { + return addChild(declaration); + } + + @Override + public int visit(IASTDeclarator declarator) { + return addChild(declarator); + } + + @Override + public int visit(IASTDeclSpecifier declSpec) { + return addChild(declSpec); + } + + @Override + public int visit(IASTEnumerator enumerator) { + return addChild(enumerator); + } + + @Override + public int visit(IASTExpression expression) { + return addChild(expression); + } + + @Override + public int visit(IASTInitializer initializer) { + return addChild(initializer); + } + + @Override + public int visit(IASTName name) { + return addChild(name); + } + + @Override + public int visit(IASTParameterDeclaration parameterDeclaration) { + return addChild(parameterDeclaration); + } + + @Override + public int visit(IASTProblem problem) { + return addChild(problem); + } + + @Override + public int visit(IASTStatement statement) { + return addChild(statement); + } + + @Override + public int visit(IASTTranslationUnit tu) { + return addChild(tu); + } + + @Override + public int visit(IASTTypeId typeId) { + return addChild(typeId); + } + + public int visit(ICASTDesignator designator) { + return addChild(designator); + } + + public int leave(ICASTDesignator designator) { + return PROCESS_SKIP; + } + + public int leave(ICPPASTBaseSpecifier baseSpecifier) { + return PROCESS_SKIP; + } + + public int leave(ICPPASTNamespaceDefinition namespaceDefinition) { + return PROCESS_SKIP; + } + + public int leave(ICPPASTTemplateParameter templateParameter) { + return PROCESS_SKIP; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/ASTLiteralNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/ASTLiteralNode.java index 2663056893a..cbea0b9cb6e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/ASTLiteralNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/ASTLiteralNode.java @@ -61,6 +61,10 @@ public class ASTLiteralNode implements IASTNode { public IASTNode getParent() { return null; } + + public IASTNode[] getChildren() { + return IASTNode.EMPTY_NODE_ARRAY; + } public ASTNodeProperty getPropertyInParent() { return null; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java index 4561fcd5d61..55fdcf96f31 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java @@ -105,6 +105,10 @@ public class PDOMASTAdapter { return fDelegate.getParent(); } + public IASTNode[] getChildren() { + return fDelegate.getChildren(); + } + public ASTNodeProperty getPropertyInParent() { return fDelegate.getPropertyInParent(); }