/*******************************************************************************
* Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences 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:
* Institute for Software - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.utils;
import java.util.ArrayList;
import java.util.Collection;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
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.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
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.IASTPointerOperator;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
import org.eclipse.cdt.internal.ui.refactoring.extractfunction.TrailNodeEqualityChecker;
public class ASTHelper {
private ASTHelper() {
}
static public IASTNode getDeclarationForNode(IASTNode tmpNode) {
while (tmpNode != null && !(tmpNode instanceof IASTSimpleDeclaration) && !(tmpNode instanceof IASTParameterDeclaration)) {
tmpNode = tmpNode.getParent();
}
return tmpNode;
}
static public IASTDeclarator getDeclaratorForNode(IASTNode aNode) {
IASTNode tmpNode = getDeclarationForNode(aNode);
IASTDeclarator declarator = null;
if (tmpNode instanceof IASTSimpleDeclaration) {
IASTSimpleDeclaration decl = (IASTSimpleDeclaration) tmpNode;
if (decl.getDeclarators().length > 0) {
declarator = decl.getDeclarators()[0];
}
} else if (tmpNode instanceof IASTParameterDeclaration) {
IASTParameterDeclaration decl = (IASTParameterDeclaration) tmpNode;
declarator = decl.getDeclarator();
}
return declarator;
}
static public IASTDeclSpecifier getDeclarationSpecifier(IASTNode declaration) {
if (declaration != null) {
if (declaration instanceof IASTSimpleDeclaration) {
IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) declaration;
return simpleDecl.getDeclSpecifier();
} else if (declaration instanceof ICPPASTParameterDeclaration) {
ICPPASTParameterDeclaration paramDecl = (ICPPASTParameterDeclaration) declaration;
return paramDecl.getDeclSpecifier();
}
}
return null;
}
public static boolean samePointers(IASTPointerOperator[] pointerOperators1, IASTPointerOperator[] pointerOperators2, TrailNodeEqualityChecker checker) {
if (pointerOperators2.length == pointerOperators1.length) {
for (int i = 0; i < pointerOperators2.length; i++) {
IASTPointerOperator operator1 = pointerOperators1[i];
IASTPointerOperator operator2 = pointerOperators2[i];
if (!checker.isEquals(operator1, operator2)) {
return false;
}
}
} else {
return false;
}
return true;
}
public static boolean isClassDeclarationName(IASTName astName) {
if (astName == null)
return false;
IASTNode parent = astName.getParent();
if (parent instanceof ICPPASTCompositeTypeSpecifier) {
ICPPASTCompositeTypeSpecifier typeSpecifier = (ICPPASTCompositeTypeSpecifier) parent;
return typeSpecifier.getKey() == ICPPASTCompositeTypeSpecifier.k_class;
}
return false;
}
public static ArrayList<ICPPASTNamespaceDefinition> getNamespaces(IASTNode node) {
ArrayList<ICPPASTNamespaceDefinition> namespaces = new ArrayList<ICPPASTNamespaceDefinition>();
for (IASTNode aktNode = node; aktNode != null; aktNode = aktNode.getParent()) {
if (aktNode instanceof ICPPASTNamespaceDefinition) {
namespaces.add(0, (ICPPASTNamespaceDefinition) aktNode);
} else if(aktNode instanceof ICPPASTQualifiedName) {
namespaces.addAll(getNamespaces((ICPPASTQualifiedName) aktNode));
}
}
return namespaces;
}
public static ArrayList<ICPPASTNamespaceDefinition> getNamespaces(ICPPASTQualifiedName qualifiedName) {
ArrayList<ICPPASTNamespaceDefinition> namespaces = new ArrayList<ICPPASTNamespaceDefinition>();
for(IASTName aktQualifiedPartName : qualifiedName.getNames()) {
IBinding binding = aktQualifiedPartName.resolveBinding();
for(IASTName aktResolvedName : qualifiedName.getTranslationUnit().getDefinitionsInAST(binding)) {
if(aktResolvedName.getParent() instanceof ICPPASTNamespaceDefinition) {
namespaces.add((ICPPASTNamespaceDefinition) aktResolvedName.getParent());
break;
}
}
}
return namespaces;
}
public static Collection<IASTDeclSpecifier> getCompositTypeSpecifiers(IASTNode baseNode) {
final Collection<IASTDeclSpecifier> specifiers = new ArrayList<IASTDeclSpecifier>();
ASTVisitor visitor = new ASTVisitor() {
@Override
public int visit(IASTDeclSpecifier declSpec) {
specifiers.add(declSpec);
return super.visit(declSpec);
}
};
visitor.shouldVisitDeclSpecifiers = true;
baseNode.accept(visitor);
return specifiers;
}
public static Collection<IASTPreprocessorStatement> getAllInFilePreprocessorStatements(IASTTranslationUnit unit, String aktFileName) {
Collection<IASTPreprocessorStatement> statements = new ArrayList<IASTPreprocessorStatement>();
for(IASTPreprocessorStatement aktStatement : unit.getAllPreprocessorStatements()) {
if(aktStatement.getFileLocation() == null) {
continue;
} else if (aktStatement.getFileLocation().getFileName().equals(aktFileName)) {
statements.add(aktStatement);
}
}
return statements;
}
public static Collection<IASTDeclaration> getAllInFileDeclarations(IASTTranslationUnit unit, String aktFileName) {
Collection<IASTDeclaration> decls = new ArrayList<IASTDeclaration>();
for(IASTDeclaration aktDecl: unit.getDeclarations()) {
if(aktDecl.getFileLocation() == null) {
continue;
} else if(aktDecl.getFileLocation().getFileName().equals(aktFileName)) {
decls.add(aktDecl);
}
}
return decls;
}
public static ICPPASTUsingDirective getActiveUsingDirecitveForNode(IASTNode node, IASTTranslationUnit unit) {
ICPPASTUsingDirective activeDirective = null;
for(IASTDeclaration aktDeclaration : getAllInFileDeclarations(unit, node.getFileLocation().getFileName())) {
if(aktDeclaration.getFileLocation().getNodeOffset() >= node.getFileLocation().getNodeOffset()) {
break;
}
if(aktDeclaration instanceof ICPPASTUsingDirective) {
activeDirective = (ICPPASTUsingDirective) aktDeclaration;
}
}
return activeDirective;
}
public static Collection<ICPPASTUsingDeclaration> getUsingDeclarations(IASTTranslationUnit unit) {
Collection<ICPPASTUsingDeclaration> usingDecls = new ArrayList<ICPPASTUsingDeclaration>();
for(IASTDeclaration aktDecl : unit.getDeclarations()) {
if (aktDecl instanceof ICPPASTUsingDeclaration) {
usingDecls.add((ICPPASTUsingDeclaration) aktDecl);
}
}
return usingDecls;
}
public static boolean isClassDefinitionName(IASTName name) {
try {
if(!(name.getParent().getParent().getParent() instanceof IASTFunctionDefinition)) {
return false;
}
ICPPASTQualifiedName qName = (ICPPASTQualifiedName) name.getParent();
IASTName secondLastName = qName.getNames()[qName.getNames().length-2];
if(!(name.equals(secondLastName))) {
return false;
}
IBinding binding = name.resolveBinding();
for(IASTName aktName : name.getTranslationUnit().getDeclarationsInAST(binding)) {
if(!isClassDeclarationName(aktName)) {
return false;
}
}
} catch (NullPointerException e) {
return false;
}
return true;
}
public static IASTCompositeTypeSpecifier getCompositeTypeSpecifierForName(IASTName name) {
IBinding binding = name.resolveBinding();
for(IASTName aktName : name.getTranslationUnit().getDefinitionsInAST(binding)) {
if(aktName.getParent() instanceof IASTCompositeTypeSpecifier) {
return (IASTCompositeTypeSpecifier) aktName.getParent();
}
}
return null;
}
public static Collection<IASTFunctionDeclarator> getFunctionDeclaratorsForClass(IASTCompositeTypeSpecifier klass) {
Collection<IASTFunctionDeclarator> declarators = new ArrayList<IASTFunctionDeclarator>();
for(IASTDeclaration aktDeclaration : klass.getMembers()) {
if(aktDeclaration instanceof IASTSimpleDeclaration) {
for(IASTDeclarator aktDeclarator : ((IASTSimpleDeclaration) aktDeclaration).getDeclarators()) {
if(aktDeclarator instanceof IASTFunctionDeclarator) {
declarators.add((IASTFunctionDeclarator) aktDeclarator);
}
}
}
}
return declarators;
}
public static Collection<IASTFunctionDefinition> getFunctionDefinitionsForClass(IASTCompositeTypeSpecifier klass) {
Collection<IASTFunctionDefinition> definitions = new ArrayList<IASTFunctionDefinition>();
for(IASTFunctionDeclarator aktDeclarator : getFunctionDeclaratorsForClass(klass)) {
IBinding binding = aktDeclarator.getName().resolveBinding();
for(IASTName aktName : aktDeclarator.getTranslationUnit().getDefinitionsInAST(binding)) {
if(aktName.getParent().getParent().getParent() instanceof IASTFunctionDefinition) {
definitions.add((IASTFunctionDefinition) aktName.getParent().getParent().getParent());
}
}
}
return definitions;
}
}